9899d70
2007-09-21  Jakub Jelinek  <jakub@redhat.com>
9899d70
9899d70
	PR c++/33506
9899d70
	* langhooks.h (struct lang_hooks_for_types): Add type_hash_eq
9899d70
	field.
9899d70
	* langhooks.c (lhd_type_hash_eq): New function.
9899d70
	* langhooks-def.h (lhd_type_hash_eq): New prototype.
9899d70
	(LANG_HOOKS_TYPE_HASH_EQ): Define.
9899d70
	(LANG_HOOKS_FOR_TYPES_INITIALIZER): Add LANG_HOOKS_TYPE_HASH_EQ.
9899d70
	* tree.c (type_hash_eq): For FUNCTION_TYPE use
9899d70
	lang_hooks.type.type_hash_eq in addition to generic tests.
9899d70
9899d70
	* cp-tree.h (cxx_type_hash_eq): New prototype.
9899d70
	* cp-objcp-common.h (LANG_HOOKS_TYPE_HASH_EQ): Redefine.
9899d70
	* tree.c (cxx_type_hash_eq): New function.
9899d70
9899d70
	* g++.dg/ext/attrib29.C: New test.
9899d70
9899d70
--- gcc/langhooks.h.jj	2007-02-20 16:39:12.000000000 -0500
9899d70
+++ gcc/langhooks.h	2007-09-22 03:46:10.000000000 -0400
9899d70
@@ -148,6 +148,10 @@ struct lang_hooks_for_types
9899d70
      firstprivate variables.  */
9899d70
   void (*omp_firstprivatize_type_sizes) (struct gimplify_omp_ctx *, tree);
9899d70
 
9899d70
+  /* Return TRUE if TYPE1 and TYPE2 are identical for type hashing purposes.
9899d70
+     Called only after doing all language independent checks.  */
9899d70
+  bool (*type_hash_eq) (tree, tree);
9899d70
+
9899d70
   /* Nonzero if types that are identical are to be hashed so that only
9899d70
      one copy is kept.  If a language requires unique types for each
9899d70
      user-specified type, such as Ada, this should be set to TRUE.  */
9899d70
--- gcc/langhooks.c.jj	2007-02-20 16:39:12.000000000 -0500
9899d70
+++ gcc/langhooks.c	2007-09-22 03:46:10.000000000 -0400
9899d70
@@ -411,6 +411,16 @@ lhd_tree_dump_type_quals (tree t)
9899d70
 /* lang_hooks.expr_size: Determine the size of the value of an expression T
9899d70
    in a language-specific way.  Returns a tree for the size in bytes.  */
9899d70
 
9899d70
+/* Return TRUE if TYPE1 and TYPE2 are identical for type hashing purposes.
9899d70
+   Called only after doing all language independent checks.  */
9899d70
+
9899d70
+bool
9899d70
+lhd_type_hash_eq (tree typea ATTRIBUTE_UNUSED,
9899d70
+		  tree typeb ATTRIBUTE_UNUSED)
9899d70
+{
9899d70
+  return true;
9899d70
+}
9899d70
+
9899d70
 tree
9899d70
 lhd_expr_size (tree exp)
9899d70
 {
9899d70
--- gcc/langhooks-def.h.jj	2007-02-20 16:39:13.000000000 -0500
9899d70
+++ gcc/langhooks-def.h	2007-09-22 03:46:56.000000000 -0400
9899d70
@@ -70,6 +70,7 @@ extern tree lhd_expr_size (tree);
9899d70
 extern size_t lhd_tree_size (enum tree_code);
9899d70
 extern HOST_WIDE_INT lhd_to_target_charset (HOST_WIDE_INT);
9899d70
 extern tree lhd_expr_to_decl (tree, bool *, bool *, bool *);
9899d70
+extern bool lhd_type_hash_eq (tree, tree);
9899d70
 
9899d70
 /* Declarations of default tree inlining hooks.  */
9899d70
 extern tree lhd_tree_inlining_walk_subtrees (tree *, int *, walk_tree_fn,
9899d70
@@ -220,6 +221,7 @@ extern tree lhd_make_node (enum tree_cod
9899d70
 #define LANG_HOOKS_TYPE_MAX_SIZE	lhd_return_null_tree
9899d70
 #define LANG_HOOKS_OMP_FIRSTPRIVATIZE_TYPE_SIZES \
9899d70
   lhd_omp_firstprivatize_type_sizes
9899d70
+#define LANG_HOOKS_TYPE_HASH_EQ		lhd_type_hash_eq
9899d70
 #define LANG_HOOKS_HASH_TYPES		true
9899d70
 
9899d70
 #define LANG_HOOKS_FOR_TYPES_INITIALIZER { \
9899d70
@@ -234,6 +236,7 @@ extern tree lhd_make_node (enum tree_cod
9899d70
   LANG_HOOKS_INCOMPLETE_TYPE_ERROR, \
9899d70
   LANG_HOOKS_TYPE_MAX_SIZE, \
9899d70
   LANG_HOOKS_OMP_FIRSTPRIVATIZE_TYPE_SIZES, \
9899d70
+  LANG_HOOKS_TYPE_HASH_EQ, \
9899d70
   LANG_HOOKS_HASH_TYPES \
9899d70
 }
9899d70
 
9899d70
--- gcc/tree.c.jj	2007-04-03 07:18:26.000000000 -0400
9899d70
+++ gcc/tree.c	2007-09-22 03:46:10.000000000 -0400
9899d70
@@ -4168,17 +4168,21 @@ type_hash_eq (const void *va, const void
9899d70
 				      TYPE_FIELDS (b->type))));
9899d70
 
9899d70
     case FUNCTION_TYPE:
9899d70
-      return (TYPE_ARG_TYPES (a->type) == TYPE_ARG_TYPES (b->type)
9899d70
-	      || (TYPE_ARG_TYPES (a->type)
9899d70
-		  && TREE_CODE (TYPE_ARG_TYPES (a->type)) == TREE_LIST
9899d70
-		  && TYPE_ARG_TYPES (b->type)
9899d70
-		  && TREE_CODE (TYPE_ARG_TYPES (b->type)) == TREE_LIST
9899d70
-		  && type_list_equal (TYPE_ARG_TYPES (a->type),
9899d70
-				      TYPE_ARG_TYPES (b->type))));
9899d70
+      if (TYPE_ARG_TYPES (a->type) == TYPE_ARG_TYPES (b->type)
9899d70
+	  || (TYPE_ARG_TYPES (a->type)
9899d70
+	      && TREE_CODE (TYPE_ARG_TYPES (a->type)) == TREE_LIST
9899d70
+	      && TYPE_ARG_TYPES (b->type)
9899d70
+	      && TREE_CODE (TYPE_ARG_TYPES (b->type)) == TREE_LIST
9899d70
+	      && type_list_equal (TYPE_ARG_TYPES (a->type),
9899d70
+				  TYPE_ARG_TYPES (b->type))))
9899d70
+	break;
9899d70
+      return 0;
9899d70
 
9899d70
     default:
9899d70
       return 0;
9899d70
     }
9899d70
+
9899d70
+  return lang_hooks.types.type_hash_eq (a->type, b->type);
9899d70
 }
9899d70
 
9899d70
 /* Return the cached hash value.  */
9899d70
--- gcc/cp/cp-tree.h.jj	2007-06-26 07:57:09.000000000 -0400
9899d70
+++ gcc/cp/cp-tree.h	2007-09-22 03:50:22.000000000 -0400
9899d70
@@ -4421,7 +4421,8 @@ extern tree cp_add_pending_fn_decls		(vo
9899d70
 extern int cp_auto_var_in_fn_p			(tree,tree);
9899d70
 extern tree fold_if_not_in_template		(tree);
9899d70
 extern tree rvalue                              (tree);
9899d70
-   
9899d70
+extern bool cxx_type_hash_eq			(tree, tree);
9899d70
+
9899d70
 /* in typeck.c */
9899d70
 extern int string_conv_p			(tree, tree, int);
9899d70
 extern tree cp_truthvalue_conversion		(tree);
9899d70
--- gcc/cp/cp-objcp-common.h.jj	2007-02-20 16:37:34.000000000 -0500
9899d70
+++ gcc/cp/cp-objcp-common.h	2007-09-22 03:49:38.000000000 -0400
9899d70
@@ -85,6 +85,8 @@ extern tree objcp_tsubst_copy_and_build 
9899d70
 #define LANG_HOOKS_WRITE_GLOBALS lhd_do_nothing
9899d70
 #undef LANG_HOOKS_COMDAT_GROUP
9899d70
 #define LANG_HOOKS_COMDAT_GROUP cxx_comdat_group
9899d70
+#undef LANG_HOOKS_TYPE_HASH_EQ                                                                                          
9899d70
+#define LANG_HOOKS_TYPE_HASH_EQ cxx_type_hash_eq
9899d70
 
9899d70
 #undef LANG_HOOKS_FUNCTION_INIT
9899d70
 #define LANG_HOOKS_FUNCTION_INIT cxx_push_function_context
9899d70
--- gcc/cp/tree.c.jj	2007-03-12 03:28:01.000000000 -0400
9899d70
+++ gcc/cp/tree.c	2007-09-22 03:46:10.000000000 -0400
9899d70
@@ -1959,6 +1959,22 @@ cp_build_type_attribute_variant (tree ty
9899d70
   return new_type;
9899d70
 }
9899d70
 
9899d70
+/* Return TRUE if TYPE1 and TYPE2 are identical for type hashing purposes.
9899d70
+   Called only after doing all language independent checks.  Only
9899d70
+   to check TYPE_RAISES_EXCEPTIONS for FUNCTION_TYPE, the rest is already
9899d70
+   compared in type_hash_eq.  */
9899d70
+
9899d70
+bool
9899d70
+cxx_type_hash_eq (tree typea, tree typeb)
9899d70
+{
9899d70
+  if (TREE_CODE (typea) != FUNCTION_TYPE
9899d70
+      || TYPE_RAISES_EXCEPTIONS (typea) == TYPE_RAISES_EXCEPTIONS (typeb))
9899d70
+    return true;
9899d70
+
9899d70
+  return comp_except_specs (TYPE_RAISES_EXCEPTIONS (typea),
9899d70
+			    TYPE_RAISES_EXCEPTIONS (typeb), 1);
9899d70
+}
9899d70
+
9899d70
 /* Apply FUNC to all language-specific sub-trees of TP in a pre-order
9899d70
    traversal.  Called from walk_tree.  */
9899d70
 
9899d70
--- gcc/testsuite/g++.dg/ext/attrib29.C.jj	2007-09-22 03:46:10.000000000 -0400
9899d70
+++ gcc/testsuite/g++.dg/ext/attrib29.C	2007-09-22 03:46:10.000000000 -0400
9899d70
@@ -0,0 +1,10 @@
9899d70
+// PR c++/33506
9899d70
+// { dg-do compile }
9899d70
+
9899d70
+extern int f1 (char *) __attribute__ ((warn_unused_result));
9899d70
+extern int f2 (char *) throw () __attribute__ ((warn_unused_result));
9899d70
+extern int f2 (char *) throw ();
9899d70
+
9899d70
+extern int f3 (char *) __attribute__ ((nonnull (1)));
9899d70
+extern int f4 (char *) throw () __attribute__ ((nonnull (1)));
9899d70
+extern int f4 (char *) throw ();