re PR c++/65880 (Member function issue with argument "pointer to const array of membe...
authorJason Merrill <jason@redhat.com>
Fri, 19 Jun 2015 18:15:36 +0000 (14:15 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 19 Jun 2015 18:15:36 +0000 (14:15 -0400)
PR c++/65880
* decl.c (build_ptrmemfunc_type): Check TYPE_GET_PTRMEMFUNC_TYPE after
cv-qualifiers.
* typeck.c (merge_types): build_ptrmemfunc_type before applying
quals and attributes.

From-SVN: r224678

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/typeck.c
gcc/testsuite/g++.dg/overload/pmf3.C [new file with mode: 0644]

index 2f5e0fa8c125d50b195aa749b2f6a511b6aba3f7..7d42381a47408de82290044644ce48226e864c03 100644 (file)
@@ -1,5 +1,11 @@
 2015-06-19  Jason Merrill  <jason@redhat.com>
 
+       PR c++/65880
+       * decl.c (build_ptrmemfunc_type): Check TYPE_GET_PTRMEMFUNC_TYPE after
+       cv-qualifiers.
+       * typeck.c (merge_types): build_ptrmemfunc_type before applying
+       quals and attributes.
+
        PR c++/65973
        * constexpr.c (build_constexpr_constructor_member_initializers):
        Handle an empty STATEMENT_LIST.
index c102a4ee7171a74f292ae84ba899ec331c660393..515c2d33e10d3afe6bb712347e8d128b4bfe2eaa 100644 (file)
@@ -8224,13 +8224,6 @@ build_ptrmemfunc_type (tree type)
   if (type == error_mark_node)
     return type;
 
-  /* If a canonical type already exists for this type, use it.  We use
-     this method instead of type_hash_canon, because it only does a
-     simple equality check on the list of field members.  */
-
-  if ((t = TYPE_GET_PTRMEMFUNC_TYPE (type)))
-    return t;
-
   /* Make sure that we always have the unqualified pointer-to-member
      type first.  */
   if (cp_cv_quals quals = cp_type_quals (type))
@@ -8239,6 +8232,13 @@ build_ptrmemfunc_type (tree type)
       return cp_build_qualified_type (unqual, quals);
     }
 
+  /* If a canonical type already exists for this type, use it.  We use
+     this method instead of type_hash_canon, because it only does a
+     simple equality check on the list of field members.  */
+
+  if ((t = TYPE_GET_PTRMEMFUNC_TYPE (type)))
+    return t;
+
   t = make_node (RECORD_TYPE);
 
   /* Let the front end know this is a pointer to member function.  */
index c33ffd57a0bf4fce28efaf4a159c872e4187ee1b..22fbb6e23892295cf89f41bd1f4af96d299b3fe1 100644 (file)
@@ -786,15 +786,16 @@ merge_types (tree t1, tree t2)
        int quals = cp_type_quals (t1);
 
        if (code1 == POINTER_TYPE)
-         t1 = build_pointer_type (target);
+         {
+           t1 = build_pointer_type (target);
+           if (TREE_CODE (target) == METHOD_TYPE)
+             t1 = build_ptrmemfunc_type (t1);
+         }
        else
          t1 = cp_build_reference_type (target, TYPE_REF_IS_RVALUE (t1));
        t1 = build_type_attribute_variant (t1, attributes);
        t1 = cp_build_qualified_type (t1, quals);
 
-       if (TREE_CODE (target) == METHOD_TYPE)
-         t1 = build_ptrmemfunc_type (t1);
-
        return t1;
       }
 
diff --git a/gcc/testsuite/g++.dg/overload/pmf3.C b/gcc/testsuite/g++.dg/overload/pmf3.C
new file mode 100644 (file)
index 0000000..a71f554
--- /dev/null
@@ -0,0 +1,70 @@
+// PR c++/65880
+
+class Test
+{
+  public:
+    Test();
+    ~Test();
+
+    bool barl(void);
+
+  private:
+    bool fool(bool (Test::* const *fms)(void));
+    bool foo(void);
+    bool bar(void);
+};
+
+Test::Test()
+{
+}
+
+Test::~Test()
+{
+}
+
+bool Test::fool(bool (Test::* const *fms)(void))
+{
+    bool retval = false;
+
+    int i = 0;
+    bool (Test::*f)(void) = fms[i++];
+
+    while (f) {
+        retval = (this->*f)();
+        if (retval) break;
+        f = fms[i++];
+    }
+
+    return retval;
+}
+
+
+bool Test::barl(void)
+{
+    static bool (Test::* const fms[])(void) = {
+        &Test::foo,
+        &Test::bar,
+        0
+    };
+
+
+
+    return fool(fms);
+}
+
+
+bool Test::foo(void)
+{
+    return false;
+}
+
+bool Test::bar(void)
+{
+    return true;
+}
+
+int main(int argc, const char *argv[])
+{
+    Test t;
+    return t.barl();
+}