[PATCH] Remove NOTHROW from {,v}{,f}{print,scan}f, {,f}printf_unlocked and __{,v}{,f}printf_chk builtins
Jakub Jelinek
jakub@redhat.com
Tue Sep 4 20:23:00 GMT 2007
- Previous message (by thread): [PATCH] Remove NOTHROW from {,v}{,f}{print,scan}f, {,f}printf_unlocked and __{,v}{,f}printf_chk builtins
- Next message (by thread): [PATCH] Remove NOTHROW from {,v}{,f}{print,scan}f, {,f}printf_unlocked and __{,v}{,f}printf_chk builtins
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
On Tue, Sep 04, 2007 at 10:07:00AM -0700, Mark Mitchell wrote:
> > What we could do is when we see a prototype, update the NOTHROW state
> > not only of the DECL_ANTICIPATED builtin, but also its __builtin_* variant.
>
> That seems like it might be an improvement. I guess the problem is if
> __builtin_printf decides to go call "puts", and "puts" is declared to
> throw exceptions, even though "printf" is not. So, presumably we don't
> set the bit on the builtin because we can't be sure it's safe.
Well, TREE_NOTHROW __builtin_printf and __builtin_puts with !TREE_NOTHROW
is what we had for the last 3 years, I don't remember any ICEs with it.
I tried e.g.:
struct A { A (); ~A (); };
inline int foo (const char *f)
{
A a;
__builtin_printf (f);
return 0;
}
int bar ()
{
return foo ("foo\n");
}
or just
int bar ()
{
A a;
__builtin_printf ("foo\n");
return 0;
}
As long as we don't ICE here, I think we are fine, libraries that
have puts that can throw and printf that can't are IMHO broken.
Either both of them can throw, or neither can.
> > BTW, several other functions are already not NOTHROW for years:
> > http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02897.html
> > it is just that the NOTHROW for the *printf has been not explicit
> > in builtins.def and therefore missed in the above patch.
>
> Yes, I understand. It might mean that we should do your patch, just to
> get everything into a consistent state -- but we still have a
> longer-term problem: how to avoid pessimizing code on all systems
> because, on some systems, thread cancellation is implemented as an
> exception. I'd like to at least have a strategy here, unless it's the
> case that the builtins being nothrow doesn't offer us any advantage.
Ok, so how about following patch together with the earlier posted
builtins.def fix (http://gcc.gnu.org/ml/gcc-patches/2007-09/msg00103.html).
Jakub
-------------- next part --------------
2007-09-04 Jakub Jelinek <jakub@redhat.com>
* decl.c (duplicate_decls): Set TREE_NOTHROW on __builtin_XX
decl if a prototype for XX is provided with throw().
PR c++/33289
* decl.c (builtin_function_1): Set DECL_ANTICIPATED also
on __*_chk non-__builtin_* decls.
* g++.dg/eh/builtin1.C: New test.
* g++.dg/eh/builtin2.C: New test.
* g++.dg/eh/builtin3.C: New test.
PR c++/33289
* g++.dg/eh/builtin4.C: New test.
--- gcc/cp/decl.c.jj 2007-08-31 14:28:19.000000000 +0200
+++ gcc/cp/decl.c 2007-09-04 21:28:06.000000000 +0200
@@ -1280,6 +1280,18 @@ duplicate_decls (tree newdecl, tree oldd
TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = type;
}
+ /* When there is explicit declaration of builtin with throw(),
+ say printf, propagate TREE_NOTHROW even to the __builtin
+ variant (__builtin_printf in this case). */
+ if (DECL_BUILT_IN_CLASS (olddecl) == BUILT_IN_NORMAL
+ && DECL_ANTICIPATED (olddecl)
+ && TREE_NOTHROW (newdecl)
+ && !TREE_NOTHROW (olddecl)
+ && built_in_decls [DECL_FUNCTION_CODE (olddecl)] != NULL_TREE
+ && built_in_decls [DECL_FUNCTION_CODE (olddecl)] != olddecl
+ && types_match)
+ TREE_NOTHROW (built_in_decls [DECL_FUNCTION_CODE (olddecl)]) = 1;
+
/* Whether or not the builtin can throw exceptions has no
bearing on this declarator. */
TREE_NOTHROW (olddecl) = 0;
@@ -3517,6 +3529,17 @@ builtin_function_1 (tree decl, tree cont
anticipated but not actually declared. */
if (name[0] != '_' || name[1] != '_')
DECL_ANTICIPATED (decl) = 1;
+ else if (strncmp (name + 2, "builtin_", sizeof ("builtin_") - 1) != 0)
+ {
+ size_t len = strlen (name);
+
+ /* Treat __*_chk fortification functions as anticipated as well,
+ unless they are __builtin_*. */
+ if (len >= sizeof ("___chk")
+ && memcmp (name + len - sizeof ("_chk") + 1,
+ "_chk", sizeof ("_chk")) == 0)
+ DECL_ANTICIPATED (decl) = 1;
+ }
return decl;
}
--- gcc/testsuite/g++.dg/eh/builtin1.C.jj 2007-09-04 22:02:08.000000000 +0200
+++ gcc/testsuite/g++.dg/eh/builtin1.C 2007-09-04 22:02:04.000000000 +0200
@@ -0,0 +1,26 @@
+// Verify that if explicit prototype for builtin is present without throw(),
+// both the normal builtin and __builtin_* variant are expected to be
+// able to throw exceptions.
+// { dg-do compile }
+// { dg-options "-fdump-tree-eh" }
+
+extern "C" int printf (const char *, ...);
+
+struct A { A (); ~A (); int i; };
+
+int
+foo ()
+{
+ A a;
+ printf ("foo %d\n", a.i);
+}
+
+int
+bar ()
+{
+ A a;
+ __builtin_printf ("foo %d\n", a.i);
+}
+
+/* { dg-final { scan-tree-dump-times "resx 1" 2 "eh" } } */
+/* { dg-final { cleanup-tree-dump "eh" } } */
--- gcc/testsuite/g++.dg/eh/builtin2.C.jj 2007-09-04 22:02:59.000000000 +0200
+++ gcc/testsuite/g++.dg/eh/builtin2.C 2007-09-04 22:04:07.000000000 +0200
@@ -0,0 +1,25 @@
+// Verify that if explicit prototype for builtin is present with throw(),
+// neither the normal builtin nor __builtin_* variant can throw exceptions.
+// { dg-do compile }
+// { dg-options "-fdump-tree-eh" }
+
+extern "C" int printf (const char *, ...) throw();
+
+struct A { A (); ~A (); int i; };
+
+int
+foo ()
+{
+ A a;
+ printf ("foo %d\n", a.i);
+}
+
+int
+bar ()
+{
+ A a;
+ __builtin_printf ("foo %d\n", a.i);
+}
+
+/* { dg-final { scan-tree-dump-times "resx 1" 0 "eh" } } */
+/* { dg-final { cleanup-tree-dump "eh" } } */
--- gcc/testsuite/g++.dg/eh/builtin3.C.jj 2007-09-04 22:03:07.000000000 +0200
+++ gcc/testsuite/g++.dg/eh/builtin3.C 2007-09-04 22:03:56.000000000 +0200
@@ -0,0 +1,16 @@
+// Without explicit prototype, we need to assume the builtin can
+// throw for builtins that at least on one platform can throw.
+// { dg-do compile }
+// { dg-options "-fdump-tree-eh" }
+
+struct A { A (); ~A (); int i; };
+
+int
+bar ()
+{
+ A a;
+ __builtin_printf ("foo %d\n", a.i);
+}
+
+/* { dg-final { scan-tree-dump-times "resx 1" 1 "eh" } } */
+/* { dg-final { cleanup-tree-dump "eh" } } */
--- gcc/testsuite/g++.dg/eh/builtin4.C.jj 2007-09-04 22:06:06.000000000 +0200
+++ gcc/testsuite/g++.dg/eh/builtin4.C 2007-09-04 22:07:03.000000000 +0200
@@ -0,0 +1,6 @@
+// PR c++/33289
+// { dg-do compile }
+
+typedef __SIZE_TYPE__ size_t;
+extern "C" int __sprintf_chk (char *__restrict, int, size_t, const char *, ...) throw ();
+extern "C" int __sprintf_chk (char *__restrict, int, size_t, const char *, ...) throw ();
- Previous message (by thread): [PATCH] Remove NOTHROW from {,v}{,f}{print,scan}f, {,f}printf_unlocked and __{,v}{,f}printf_chk builtins
- Next message (by thread): [PATCH] Remove NOTHROW from {,v}{,f}{print,scan}f, {,f}printf_unlocked and __{,v}{,f}printf_chk builtins
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the Gcc-patches
mailing list