* typeck.c (merge_types): Preserve memfn quals.
authorJason Merrill <jason@redhat.com>
Wed, 19 May 2010 21:02:16 +0000 (17:02 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 19 May 2010 21:02:16 +0000 (17:02 -0400)
From-SVN: r159598

gcc/cp/ChangeLog
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/parse/fn-typedef2.C [new file with mode: 0644]

index 26eaafc386d80635529073e14ff429a2a931c414..6dd97bb23eb5940f9faf82d8d01b43d18d4d766f 100644 (file)
@@ -1,5 +1,7 @@
 2010-05-19  Jason Merrill  <jason@redhat.com>
 
+       * typeck.c (merge_types): Preserve memfn quals.
+
        * decl.c (grokdeclarator): Don't check quals on fn type.
        * typeck.c (cp_apply_type_quals_to_decl): Likewise.
        * tree.c (cp_build_qualified_type_real): Simplify qualifier checking.
index 44d7ab10b2141ebc81aab4b73e227b9023405e00..a46b218700da04730f173f0c4bc84775e23b5590 100644 (file)
@@ -810,6 +810,7 @@ merge_types (tree t1, tree t2)
        tree valtype = merge_types (TREE_TYPE (t1), TREE_TYPE (t2));
        tree p1 = TYPE_ARG_TYPES (t1);
        tree p2 = TYPE_ARG_TYPES (t2);
+       tree parms;
        tree rval, raises;
 
        /* Save space: see if the result is identical to one of the args.  */
@@ -821,21 +822,25 @@ merge_types (tree t1, tree t2)
        /* Simple way if one arg fails to specify argument types.  */
        if (p1 == NULL_TREE || TREE_VALUE (p1) == void_type_node)
          {
-           rval = build_function_type (valtype, p2);
-           if ((raises = TYPE_RAISES_EXCEPTIONS (t2)))
-             rval = build_exception_variant (rval, raises);
-           return cp_build_type_attribute_variant (rval, attributes);
+           parms = p2;
+           raises = TYPE_RAISES_EXCEPTIONS (t2);
          }
-       raises = TYPE_RAISES_EXCEPTIONS (t1);
-       if (p2 == NULL_TREE || TREE_VALUE (p2) == void_type_node)
+       else if (p2 == NULL_TREE || TREE_VALUE (p2) == void_type_node)
          {
-           rval = build_function_type (valtype, p1);
-           if (raises)
-             rval = build_exception_variant (rval, raises);
-           return cp_build_type_attribute_variant (rval, attributes);
+           parms = p1;
+           raises = TYPE_RAISES_EXCEPTIONS (t1);
+         }
+       else
+         {
+           parms = commonparms (p1, p2);
+           /* In cases where we're merging a real declaration with a
+              built-in declaration, t1 is the real one.  */
+           raises = TYPE_RAISES_EXCEPTIONS (t1);
          }
 
-       rval = build_function_type (valtype, commonparms (p1, p2));
+       rval = build_function_type (valtype, parms);
+       gcc_assert (type_memfn_quals (t1) == type_memfn_quals (t2));
+       rval = apply_memfn_quals (rval, type_memfn_quals (t1));
        t1 = build_exception_variant (rval, raises);
        break;
       }
index b6146f68cef31843783243610f9c97aa438bef87..3d12129edd878a7a03d657bed6267a9c270e82b5 100644 (file)
@@ -1,5 +1,7 @@
 2010-05-19  Jason Merrill  <jason@redhat.com>
 
+       * g++.dg/parse/fn-typedef2.C: New.
+
        * g++.dg/other/cv_func.C: Don't expect errors about cv-qualified
        function type.
 
diff --git a/gcc/testsuite/g++.dg/parse/fn-typedef2.C b/gcc/testsuite/g++.dg/parse/fn-typedef2.C
new file mode 100644 (file)
index 0000000..c9c7f06
--- /dev/null
@@ -0,0 +1,7 @@
+// Test that merge_types preserves fn cv-quals.
+
+typedef void ft() const;
+typedef void V;
+typedef V ft() const;
+
+ft f;                          // { dg-error "qualified" }