[C++ PATCH] Fix FUNCTION_TYPE hashing problem (PR c++/33506)
Jakub Jelinek
jakub@redhat.com
Thu Sep 20 04:02:00 GMT 2007
Hi!
The attached testcase issues incorrect diagnostics on valid code.
The problem seems to be caused by type hashing.
For attributes that require function type (nonnull, warn_unused_result,
sentinel, regparm, ...) decl_attributes changes the type (either
*decl itself or TREE_TYPE (*decl)) to one returned from
build_type_attribute_variant, which uses a hash table. Unfortunately,
TYPE_LANG_SLOT_1 is not hashed (the generic code doesn't know how to
hash it anyway), so if there has been the same FUNCTION_TYPE already
with the same arguments and same attributes, but different
TYPE_RAISES_EXCEPTIONS, during attribute additions suddenly throw ()
is lost or we get some unrelated throw list from some other prototype.
One possibility to fix this is to compare TYPE_LANG_SLOT_1 (just
as a pointer) in type_hash_eq (but we risk creating too much garbage
in that case), another is to use a langhook in attribs.c, which
for C++ would be cp_build_type_attribute_variant, below is implemented
another approach, which in cplus_decl_attributes remembers the type
and if TYPE_RAISES_EXCEPTIONS changed, fix it up using
build_exception_variant.
Testing in progress on x86_64-linux, ok for trunk/4.2 if that succeeds?
2007-09-20 Jakub Jelinek <jakub@redhat.com>
PR c++/33506
* decl2.c (cplus_decl_attributes): Restore TYPE_RAISES_EXCEPTIONS
if decl_attributes changed it.
* g++.dg/ext/attrib29.C: New test.
--- gcc/cp/decl2.c.jj 2007-09-19 12:23:29.000000000 +0200
+++ gcc/cp/decl2.c 2007-09-20 01:43:26.000000000 +0200
@@ -1070,6 +1070,8 @@ save_template_attributes (tree *attr_p,
void
cplus_decl_attributes (tree *decl, tree attributes, int flags)
{
+ tree oldfntype = NULL_TREE;
+
if (*decl == NULL_TREE || *decl == void_type_node
|| *decl == error_mark_node
|| attributes == NULL_TREE)
@@ -1085,8 +1087,28 @@ cplus_decl_attributes (tree *decl, tree
if (TREE_CODE (*decl) == TEMPLATE_DECL)
decl = &DECL_TEMPLATE_RESULT (*decl);
+ if (TREE_CODE (*decl) == FUNCTION_TYPE)
+ oldfntype = *decl;
+ else if (DECL_P (*decl) && TREE_CODE (TREE_TYPE (*decl)) == FUNCTION_TYPE)
+ oldfntype = TREE_TYPE (*decl);
+
decl_attributes (decl, attributes, flags);
+ if (oldfntype)
+ {
+ if (TREE_CODE (*decl) == FUNCTION_TYPE
+ && TYPE_RAISES_EXCEPTIONS (*decl)
+ != TYPE_RAISES_EXCEPTIONS (oldfntype))
+ *decl
+ = build_exception_variant (*decl,
+ TYPE_RAISES_EXCEPTIONS (oldfntype));
+ else if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (*decl))
+ != TYPE_RAISES_EXCEPTIONS (oldfntype))
+ TREE_TYPE (*decl)
+ = build_exception_variant (TREE_TYPE (*decl),
+ TYPE_RAISES_EXCEPTIONS (oldfntype));
+ }
+
if (TREE_CODE (*decl) == TYPE_DECL)
SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (*decl), TREE_TYPE (*decl));
}
--- gcc/testsuite/g++.dg/ext/attrib29.C.jj 2007-09-20 01:46:45.000000000 +0200
+++ gcc/testsuite/g++.dg/ext/attrib29.C 2007-09-20 01:46:13.000000000 +0200
@@ -0,0 +1,10 @@
+// PR c++/33506
+// { dg-do compile }
+
+extern int f1 (char *) __attribute__ ((warn_unused_result));
+extern int f2 (char *) throw () __attribute__ ((warn_unused_result));
+extern int f2 (char *) throw ();
+
+extern int f3 (char *) __attribute__ ((nonnull (1)));
+extern int f4 (char *) throw () __attribute__ ((nonnull (1)));
+extern int f4 (char *) throw ();
Jakub
More information about the Gcc-patches
mailing list