re PR c++/56247 (internal compiler error: in tsubst_copy, at cp/pt.c:12131)
authorJason Merrill <jason@redhat.com>
Sat, 9 Feb 2013 20:39:13 +0000 (15:39 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Sat, 9 Feb 2013 20:39:13 +0000 (15:39 -0500)
PR c++/56247
* pt.c (eq_specializations): Set comparing_specializations.
* tree.c (cp_tree_equal): Check it.
* cp-tree.h: Declare it.

From-SVN: r195922

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/pt.c
gcc/cp/tree.c
gcc/testsuite/g++.dg/template/ptrmem23.C [new file with mode: 0644]

index 26e130c..c1fc4bc 100644 (file)
@@ -1,5 +1,10 @@
 2013-02-09  Jason Merrill  <jason@redhat.com>
 
+       PR c++/56247
+       * pt.c (eq_specializations): Set comparing_specializations.
+       * tree.c (cp_tree_equal): Check it.
+       * cp-tree.h: Declare it.
+
        * decl.c (decls_match): Check versions later.
 
        PR c++/56238
index 303f5f6..d9270e2 100644 (file)
@@ -4247,6 +4247,10 @@ extern GTY(()) tree integer_two_node;
    function, two inside the body of a function in a local class, etc.)  */
 extern int function_depth;
 
+/* Nonzero if we are inside eq_specializations, which affects comparison of
+   PARM_DECLs in cp_tree_equal.  */
+extern int comparing_specializations;
+
 /* In parser.c.  */
 
 /* Nonzero if we are parsing an unevaluated operand: an operand to
index 29664ea..a3359ad 100644 (file)
@@ -1461,14 +1461,21 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
 /* Returns true iff two spec_entry nodes are equivalent.  Only compares the
    TMPL and ARGS members, ignores SPEC.  */
 
+int comparing_specializations;
+
 static int
 eq_specializations (const void *p1, const void *p2)
 {
   const spec_entry *e1 = (const spec_entry *)p1;
   const spec_entry *e2 = (const spec_entry *)p2;
+  int equal;
+
+  ++comparing_specializations;
+  equal = (e1->tmpl == e2->tmpl
+          && comp_template_args (e1->args, e2->args));
+  --comparing_specializations;
 
-  return (e1->tmpl == e2->tmpl
-         && comp_template_args (e1->args, e2->args));
+  return equal;
 }
 
 /* Returns a hash for a template TMPL and template arguments ARGS.  */
index 18d9a98..0b033c2 100644 (file)
@@ -2580,6 +2580,13 @@ cp_tree_equal (tree t1, tree t2)
         with an out-of-class definition of the function, but can also come
         up for expressions that involve 'this' in a member function
         template.  */
+
+      if (comparing_specializations)
+       /* When comparing hash table entries, only an exact match is
+          good enough; we don't want to replace 'this' with the
+          version from another function.  */
+       return false;
+
       if (same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)))
        {
          if (DECL_ARTIFICIAL (t1) ^ DECL_ARTIFICIAL (t2))
diff --git a/gcc/testsuite/g++.dg/template/ptrmem23.C b/gcc/testsuite/g++.dg/template/ptrmem23.C
new file mode 100644 (file)
index 0000000..28c0a63
--- /dev/null
@@ -0,0 +1,22 @@
+// PR c++/56247
+
+struct Base {
+    void method() {}
+};
+
+typedef void (Base::*MemPtr)();
+
+// Template with a member function pointer "non-type parameter".
+template<MemPtr func>
+struct Wrapper {};
+
+template<class C>
+struct Child : public Base {
+    // Templated derived class instantiates the Wrapper with the same parameter
+    // in two different virtual methods.
+    void foo() { typedef Wrapper<&Base::method> W; }
+    void bar() { typedef Wrapper<&Base::method> W; }
+};
+
+// Instantiate Child with some type.
+template class Child<int>;