commit 504f38b8ed59af62c0226372837f8cb56765905c
Author: Jason Merrill <jason@redhat.com>
Date: Fri Feb 8 22:00:02 2013 -0500
PR c++/56247
* pt.c (eq_specializations): Set comparing_specializations.
* tree.c (cp_tree_equal): Check it.
* cp-tree.h: Declare it.
@@ -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
@@ -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;
- return (e1->tmpl == e2->tmpl
- && comp_template_args (e1->args, e2->args));
+ ++comparing_specializations;
+ equal = (e1->tmpl == e2->tmpl
+ && comp_template_args (e1->args, e2->args));
+ --comparing_specializations;
+
+ return equal;
}
/* Returns a hash for a template TMPL and template arguments ARGS. */
@@ -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))
new file mode 100644
@@ -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>;