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" }