[C++ PATCH] Fix FUNCTION_TYPE hashing problem (PR c++/33506, take 2)

Jakub Jelinek jakub@redhat.com
Fri Sep 21 09:49:00 GMT 2007


On Thu, Sep 20, 2007 at 05:51:32PM -0400, Mark Mitchell wrote:
> I think you have the right idea with a hook, but I don't think it's in
> the right place.  In particular, decl_attributes should be taught not to
> corrupt the type in this way.  Instead, I think type_hash_eq should have
> a language hook to allow the C++ front end to say that for a
> FUNCTION_TYPE the TYPE_RAISES_EXCEPTION matters for equality.

Here it is (regtested on x86_64-linux), but there are many variants
where exactly this can be put, so if you prefer something else, just
tell me and I'll regtest another variant.

I wanted to keep the generic type_hash_eq as the hashtab comparison
function rather than creating the hash table with a langhook fnptr
which would need to call the generic type_hash_eq, because that
would mean exposing the so far tree.c local struct type_hash
and in what I think is a fast path would mean another call layer.
The patch ATM only calls the langhook for FUNCTION_TYPE, but it is easy to
change that for other types, just replace the return (condition)
for those types with if (condition) break; return 0;
But I'm not sure it is necessary to do so until we find real uses for it.

2007-09-21  Jakub Jelinek  <jakub@redhat.com>

	PR c++/33506
	* langhooks.h (struct lang_hooks_for_types): Add type_hash_eq
	field.
	* langhooks.c (lhd_type_hash_eq): New function.
	* langhooks-def.h (lhd_type_hash_eq): New prototype.
	(LANG_HOOKS_TYPE_HASH_EQ): Define.
	(LANG_HOOKS_FOR_TYPES_INITIALIZER): Add LANG_HOOKS_TYPE_HASH_EQ.
	* tree.c (type_hash_eq): For FUNCTION_TYPE use
	lang_hooks.type.type_hash_eq in addition to generic tests.

	* cp-tree.h (cxx_type_hash_eq): New prototype.
	* cp-objcp-common.h (LANG_HOOKS_TYPE_HASH_EQ): Redefine.
	* tree.c (cxx_type_hash_eq): New function.

	* g++.dg/ext/attrib29.C: New test.

--- gcc/langhooks.h.jj	2007-09-11 12:43:43.000000000 +0200
+++ gcc/langhooks.h	2007-09-21 10:04:09.000000000 +0200
@@ -129,6 +129,10 @@ struct lang_hooks_for_types
      firstprivate variables.  */
   void (*omp_firstprivatize_type_sizes) (struct gimplify_omp_ctx *, tree);
 
+  /* Return TRUE if TYPE1 and TYPE2 are identical for type hashing purposes.
+     Called only after doing all language independent checks.  */
+  bool (*type_hash_eq) (const_tree, const_tree);
+
   /* Nonzero if types that are identical are to be hashed so that only
      one copy is kept.  If a language requires unique types for each
      user-specified type, such as Ada, this should be set to TRUE.  */
--- gcc/langhooks.c.jj	2007-09-11 12:43:28.000000000 +0200
+++ gcc/langhooks.c	2007-09-21 10:42:14.000000000 +0200
@@ -466,6 +466,16 @@ lhd_omp_firstprivatize_type_sizes (struc
 {
 }
 
+/* Return TRUE if TYPE1 and TYPE2 are identical for type hashing purposes.
+   Called only after doing all language independent checks.  */
+
+bool
+lhd_type_hash_eq (const_tree typea ATTRIBUTE_UNUSED,
+		  const_tree typeb ATTRIBUTE_UNUSED)
+{
+  return true;
+}
+
 tree
 add_builtin_function (const char *name,
 		      tree type,
--- gcc/langhooks-def.h.jj	2007-09-11 12:43:43.000000000 +0200
+++ gcc/langhooks-def.h	2007-09-21 10:18:17.000000000 +0200
@@ -66,6 +66,7 @@ extern size_t lhd_tree_size (enum tree_c
 extern HOST_WIDE_INT lhd_to_target_charset (HOST_WIDE_INT);
 extern tree lhd_expr_to_decl (tree, bool *, bool *, bool *);
 extern tree lhd_builtin_function (tree decl);
+extern bool lhd_type_hash_eq (const_tree, const_tree);
 
 /* Declarations of default tree inlining hooks.  */
 extern void lhd_initialize_diagnostics (struct diagnostic_context *);
@@ -180,6 +181,7 @@ extern tree lhd_make_node (enum tree_cod
 #define LANG_HOOKS_TYPE_MAX_SIZE	lhd_return_null_const_tree
 #define LANG_HOOKS_OMP_FIRSTPRIVATIZE_TYPE_SIZES \
   lhd_omp_firstprivatize_type_sizes
+#define LANG_HOOKS_TYPE_HASH_EQ		lhd_type_hash_eq
 #define LANG_HOOKS_HASH_TYPES		true
 
 #define LANG_HOOKS_FOR_TYPES_INITIALIZER { \
@@ -192,6 +194,7 @@ extern tree lhd_make_node (enum tree_cod
   LANG_HOOKS_INCOMPLETE_TYPE_ERROR, \
   LANG_HOOKS_TYPE_MAX_SIZE, \
   LANG_HOOKS_OMP_FIRSTPRIVATIZE_TYPE_SIZES, \
+  LANG_HOOKS_TYPE_HASH_EQ, \
   LANG_HOOKS_HASH_TYPES \
 }
 
--- gcc/tree.c.jj	2007-09-14 11:54:35.000000000 +0200
+++ gcc/tree.c	2007-09-21 10:44:00.000000000 +0200
@@ -4608,17 +4608,21 @@ type_hash_eq (const void *va, const void
 				      TYPE_FIELDS (b->type))));
 
     case FUNCTION_TYPE:
-      return (TYPE_ARG_TYPES (a->type) == TYPE_ARG_TYPES (b->type)
-	      || (TYPE_ARG_TYPES (a->type)
-		  && TREE_CODE (TYPE_ARG_TYPES (a->type)) == TREE_LIST
-		  && TYPE_ARG_TYPES (b->type)
-		  && TREE_CODE (TYPE_ARG_TYPES (b->type)) == TREE_LIST
-		  && type_list_equal (TYPE_ARG_TYPES (a->type),
-				      TYPE_ARG_TYPES (b->type))));
+      if (TYPE_ARG_TYPES (a->type) == TYPE_ARG_TYPES (b->type)
+	  || (TYPE_ARG_TYPES (a->type)
+	      && TREE_CODE (TYPE_ARG_TYPES (a->type)) == TREE_LIST
+	      && TYPE_ARG_TYPES (b->type)
+	      && TREE_CODE (TYPE_ARG_TYPES (b->type)) == TREE_LIST
+	      && type_list_equal (TYPE_ARG_TYPES (a->type),
+				  TYPE_ARG_TYPES (b->type))))
+	break;
+      return 0;
 
     default:
       return 0;
     }
+
+  return lang_hooks.types.type_hash_eq (a->type, b->type);
 }
 
 /* Return the cached hash value.  */
--- gcc/cp/cp-tree.h.jj	2007-09-20 21:26:48.000000000 +0200
+++ gcc/cp/cp-tree.h	2007-09-21 10:36:05.000000000 +0200
@@ -4752,6 +4752,7 @@ extern tree rvalue				(tree);
 extern tree convert_bitfield_to_declared_type   (tree);
 extern tree cp_save_expr			(tree);
 extern bool cast_valid_in_integral_constant_expression_p (tree);
+extern bool cxx_type_hash_eq			(const_tree, const_tree);
 
 /* in typeck.c */
 extern int string_conv_p			(const_tree, const_tree, int);
--- gcc/cp/cp-objcp-common.h.jj	2007-09-11 12:43:32.000000000 +0200
+++ gcc/cp/cp-objcp-common.h	2007-09-21 10:23:16.000000000 +0200
@@ -88,6 +88,8 @@ extern tree objcp_tsubst_copy_and_build 
 #define LANG_HOOKS_COMDAT_GROUP cxx_comdat_group
 #undef  LANG_HOOKS_BUILTIN_FUNCTION
 #define LANG_HOOKS_BUILTIN_FUNCTION cxx_builtin_function
+#undef	LANG_HOOKS_TYPE_HASH_EQ
+#define LANG_HOOKS_TYPE_HASH_EQ	cxx_type_hash_eq
 
 #undef LANG_HOOKS_FUNCTION_INIT
 #define LANG_HOOKS_FUNCTION_INIT cxx_push_function_context
--- gcc/cp/tree.c.jj	2007-09-04 23:09:22.000000000 +0200
+++ gcc/cp/tree.c	2007-09-21 10:44:00.000000000 +0200
@@ -2281,6 +2281,22 @@ cp_build_type_attribute_variant (tree ty
   return new_type;
 }
 
+/* Return TRUE if TYPE1 and TYPE2 are identical for type hashing purposes.
+   Called only after doing all language independent checks.  Only
+   to check TYPE_RAISES_EXCEPTIONS for FUNCTION_TYPE, the rest is already
+   compared in type_hash_eq.  */
+
+bool
+cxx_type_hash_eq (const_tree typea, const_tree typeb)
+{
+  if (TREE_CODE (typea) != FUNCTION_TYPE
+      || TYPE_RAISES_EXCEPTIONS (typea) == TYPE_RAISES_EXCEPTIONS (typeb))
+    return true;
+
+  return comp_except_specs (TYPE_RAISES_EXCEPTIONS (typea),
+			    TYPE_RAISES_EXCEPTIONS (typeb), 1);
+}
+
 /* Apply FUNC to all language-specific sub-trees of TP in a pre-order
    traversal.  Called from walk_tree.  */
 
--- gcc/testsuite/g++.dg/ext/attrib29.C.jj	2007-09-20 21:28:35.000000000 +0200
+++ gcc/testsuite/g++.dg/ext/attrib29.C	2007-09-20 21:28:35.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