Hi,

On 12/16/2014 04:10 PM, Jason Merrill wrote:
On 12/16/2014 05:40 AM, Paolo Carlini wrote:
In better detail: grokdeclarator is called, via grokfield, by
cp_parser_member_declaration. The latter stores the friendship
information in a friend_p local flag, which remains true when
grokdeclarator returns.

Maybe check function_declarator_p in cp_parser_member_declaration?
I see what you mean: try to somehow realize that grokdeclarator issued an error and we are in error recovery. What about directly addressing NSDMIs, the specific case at issue, thus the below? A bit ad-hoc-ish but on the other hand should be lighter than calling function_declarator_p, etc, to figure out...

Well, I'd like to add a consideration in favor of the simplistic solution involving error_mark_node which I proposed earlier today: it has the advantage that we end up with consistent diagnostic for

struct A
{
    friend int i;

    A() { i = 1; }
};

and

struct B
{
    friend int i = 0;

    B() { i = 1; }
};

as far as the constructor is concerned: that is, 'i' is diagnosed as undeclared in both cases. This is, apparently, what both current clang and edg do. All the other solutions I figured out so far, so to speak "recover too much" in case of NSDMIs, that is beyond what we do for normal data members: no diagnostic is produced for the constructor in B.

Thanks,
Paolo.

//////////////////////////


Index: cp/parser.c
===================================================================
--- cp/parser.c (revision 218777)
+++ cp/parser.c (working copy)
@@ -21077,8 +21077,16 @@ cp_parser_member_declaration (cp_parser* parser)
              else if (TREE_CODE (decl) == FIELD_DECL
                       && !DECL_C_BIT_FIELD (decl)
                       && DECL_INITIAL (decl))
-               /* Add DECL to the queue of NSDMI to be parsed later.  */
-               vec_safe_push (unparsed_nsdmis, decl);
+               {
+
+                 if (friend_p)
+                   /* Explicitly include NSDMIs for error recovery purposes:
+                      avoid crashing later if one is wrongly declared friend
+                      (c++/58650).  */
+                   finish_member_declaration (decl);
+                 /* Add DECL to the queue of NSDMI to be parsed later.  */
+                 vec_safe_push (unparsed_nsdmis, decl);
+               }
            }
 
          if (assume_semicolon)
Index: testsuite/g++.dg/parse/friend12.C
===================================================================
--- testsuite/g++.dg/parse/friend12.C   (revision 0)
+++ testsuite/g++.dg/parse/friend12.C   (working copy)
@@ -0,0 +1,7 @@
+// PR c++/58650
+
+struct A
+{
+  friend int i = 0;  // { dg-error "cannot be declared friend" }
+// { dg-error "non-static data member" "" { target { ! c++11 } } 5 }
+};

Reply via email to