Message ID | 548F5C8E.6000008@oracle.com |
---|---|
State | New |
Headers | show |
Why does error recovery fail? I would expect to be able to just drop the 'friend' and treat it as a normal non-static data member. Jason
Hi, On 12/15/2014 11:25 PM, Jason Merrill wrote: > Why does error recovery fail? I would expect to be able to just drop > the 'friend' and treat it as a normal non-static data member. I agree, that was my first thought too. Unfortunately we do non-trivial preparatory work *before* calling grokdeclarator based on ds_friend which aren't reverted by locally resetting friendp in grokdeclarator, and, eg, build_this_parm gets a null type even if declspecs->locations[ds_friend] itself is reset right at the beginning of grokdeclarator. I'll try the further investigate the above... Thanks, Paolo.
Hi again, On 12/16/2014 11:17 AM, Paolo Carlini wrote: > Hi, > > On 12/15/2014 11:25 PM, Jason Merrill wrote: >> Why does error recovery fail? I would expect to be able to just drop >> the 'friend' and treat it as a normal non-static data member. > I agree, that was my first thought too. Unfortunately we do > non-trivial preparatory work *before* calling grokdeclarator based on > ds_friend which aren't reverted by locally resetting friendp in > grokdeclarator, and, eg, build_this_parm gets a null type even if > declspecs->locations[ds_friend] itself is reset right at the beginning > of grokdeclarator. I'll try the further investigate the above... 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. Then at the end of the function: if (decl) { /* Add DECL to the list of members. */ if (!friend_p) finish_member_declaration (decl); makes all the difference for the crash. Now, I could try resetting in grokdeclarator the primary ds_friend information as stored in the decl_specifiers and read it back, thus update friend_p in cp_parser_member_declaration. It would probably work, but frankly this fiddling only for error recovery makes me a little nervous. What do you think? Thanks, Paolo.
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? Jason
Index: cp/decl.c =================================================================== --- cp/decl.c (revision 218764) +++ cp/decl.c (working copy) @@ -10803,6 +10803,7 @@ grokdeclarator (const cp_declarator *declarator, error ("%qE is neither function nor member function; " "cannot be declared friend", unqualified_id); friendp = 0; + type = error_mark_node; } decl = NULL_TREE; } 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 } +};