Hi,

this is just an ICE on invalid, but I think it hints to a small clean-up. Essentially the issue is that we diagnose qualified free functions in two different places: in the grokdeclarator itself and in grokfndecl. The former handles non-friend declarations and does type = TYPE_MAIN_VARIANT (type), the latter handles friends and then doesn't even try to do what grokdeclarator does to type. Then in situations like 58810, when we have *both* at the same time:

typedef int F() const;

F f;

struct A
{
  friend F f;
};

the two types become inconsistent, one has the const and the other doesn't, and an assert in typeck.c:merge_types triggers. Thus the idea of resolving the inconsistency by removing completely one of the two checks: that in grokfndecl is more precise (separate messages for cv-qualifiers and ref-qualifiers) and seems the best candidate. The patch below passes testing modulo trivial adjustments to a couple of existing testcases.

Admittedly, the change is a bit risky, but it's still Stage 1, maybe we can take the chance and try to shave some lines off the mammuth grokdeclarator ;) What do you think?

Thanks,
Paolo.

///////////////////
/cp
2013-10-21  Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/58810
        * decl.c (grokdeclarator): Don't handle qualified free functions here,
        leave the diagnostic to grokfndecl.

/testsuite
2013-10-21  Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/58810
        * g++.dg/other/cv_func3.C: New.
        * g++.dg/other/cv_func.C: Adjust.
        * g++.dg/parse/fn-typedef2.C: Likewise.
Index: cp/decl.c
===================================================================
--- cp/decl.c   (revision 203893)
+++ cp/decl.c   (working copy)
@@ -10242,21 +10242,6 @@ grokdeclarator (const cp_declarator *declarator,
 
       if (decl_context != TYPENAME)
        {
-         /* A cv-qualifier-seq shall only be part of the function type
-            for a non-static member function. A ref-qualifier shall only
-            .... /same as above/ [dcl.fct] */
-         if ((type_memfn_quals (type) != TYPE_UNQUALIFIED
-              || type_memfn_rqual (type) != REF_QUAL_NONE)
-             && (current_class_type == NULL_TREE || staticp) )
-           {
-             error (staticp
-                     ? G_("qualified function types cannot be used to "
-                          "declare static member functions")
-                     : G_("qualified function types cannot be used to "
-                          "declare free functions"));
-             type = TYPE_MAIN_VARIANT (type);
-           }
-
          /* The qualifiers on the function type become the qualifiers on
             the non-static member function. */
          memfn_quals |= type_memfn_quals (type);
Index: testsuite/g++.dg/other/cv_func.C
===================================================================
--- testsuite/g++.dg/other/cv_func.C    (revision 203893)
+++ testsuite/g++.dg/other/cv_func.C    (working copy)
@@ -3,7 +3,7 @@
 typedef int FIC(int) const;
 typedef int FI(int);
 
-FIC f; // { dg-error "qualified" }
+FIC f; // { dg-error "cv-qualifier" }
 struct S {
   FIC f; // OK
 
Index: testsuite/g++.dg/other/cv_func3.C
===================================================================
--- testsuite/g++.dg/other/cv_func3.C   (revision 0)
+++ testsuite/g++.dg/other/cv_func3.C   (working copy)
@@ -0,0 +1,10 @@
+// PR c++/58810
+
+typedef int F() const;
+
+F f;           // { dg-error "cv-qualifier" }
+
+struct A
+{
+  friend F f;  // { dg-error "cv-qualifier" }
+};
Index: testsuite/g++.dg/parse/fn-typedef2.C
===================================================================
--- testsuite/g++.dg/parse/fn-typedef2.C        (revision 203893)
+++ testsuite/g++.dg/parse/fn-typedef2.C        (working copy)
@@ -4,4 +4,4 @@ typedef void ft() const;
 typedef void V;
 typedef V ft() const;
 
-ft f;                          // { dg-error "qualified" }
+ft f;                          // { dg-error "cv-qualifier" }

Reply via email to