[C++,Patch/RFC] PR 84348 ("[7/8 Regression] ICE with invalid friend declaration")

Message ID c7f63114-d717-d9f7-73d7-cde9cfe2e9e5@oracle.com
State New
Headers show
Series
  • [C++,Patch/RFC] PR 84348 ("[7/8 Regression] ICE with invalid friend declaration")
Related show

Commit Message

Paolo Carlini Feb. 16, 2018, 10:30 p.m.
Hi,

here we ICE during error recovery when, after emitting a correct error 
from grokdeclarator, we go on, we only clear friendp, and grokfield 
proceeds to call cp_finish_decl where 'gcc_assert 
(CLASS_PLACEHOLDER_TEMPLATE (auto_node));' triggers. We could imagine 
solving the problem in various ways... If we want to do something as 
early as possible, in grokdeclarator, over the years in turn we handled 
different cases in different ways related to the error recovery effects, 
mostly. A straightforward solution, which I'm finishing testing, would 
be just bailing-out after the error, alternately we could also imagine 
something relatively sophisticated like going on, but also setting type 
= error_mark_node conditional to type_uses_auto (auto) thus mimicking 
the error recovery strategy we use above for a non-friend ill-formed 
variant. Just unconditionally setting type = error_mark_node doesn't 
seem morally correct to me - even if probably it would also pass the 
testsuite - because what we are actually diagnosing to the user, in fact 
the first problem in such snippet in parsing order, doesn't have to do 
with the type per se, but with friend - the diagnostic for 'friend int 
foo' is the same. As usual I'm on x86_64-linux.

Thanks, Paolo.

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

Comments

Jason Merrill Feb. 19, 2018, 4:40 a.m. | #1
OK.

On Fri, Feb 16, 2018 at 5:30 PM, Paolo Carlini <paolo.carlini@oracle.com> wrote:
> Hi,

>

> here we ICE during error recovery when, after emitting a correct error from

> grokdeclarator, we go on, we only clear friendp, and grokfield proceeds to

> call cp_finish_decl where 'gcc_assert (CLASS_PLACEHOLDER_TEMPLATE

> (auto_node));' triggers. We could imagine solving the problem in various

> ways... If we want to do something as early as possible, in grokdeclarator,

> over the years in turn we handled different cases in different ways related

> to the error recovery effects, mostly. A straightforward solution, which I'm

> finishing testing, would be just bailing-out after the error, alternately we

> could also imagine something relatively sophisticated like going on, but

> also setting type = error_mark_node conditional to type_uses_auto (auto)

> thus mimicking the error recovery strategy we use above for a non-friend

> ill-formed variant. Just unconditionally setting type = error_mark_node

> doesn't seem morally correct to me - even if probably it would also pass the

> testsuite - because what we are actually diagnosing to the user, in fact the

> first problem in such snippet in parsing order, doesn't have to do with the

> type per se, but with friend - the diagnostic for 'friend int foo' is the

> same. As usual I'm on x86_64-linux.

>

> Thanks, Paolo.

>

> ////////////////////

>

Patch

Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 257767)
+++ cp/decl.c	(working copy)
@@ -12141,7 +12141,7 @@  grokdeclarator (const cp_declarator *declarator,
 	      {
 		error ("%qE is neither function nor member function; "
 		       "cannot be declared friend", unqualified_id);
-		friendp = 0;
+		return error_mark_node;
 	      }
 	    decl = NULL_TREE;
 	  }
Index: testsuite/g++.dg/cpp0x/auto50.C
===================================================================
--- testsuite/g++.dg/cpp0x/auto50.C	(nonexistent)
+++ testsuite/g++.dg/cpp0x/auto50.C	(working copy)
@@ -0,0 +1,7 @@ 
+// PR c++/84348
+// { dg-do compile { target c++11 } }
+
+template<typename> struct A
+{
+  friend auto foo;  // { dg-error "cannot be declared friend" }
+};
Index: testsuite/g++.dg/parse/friend12.C
===================================================================
--- testsuite/g++.dg/parse/friend12.C	(revision 257767)
+++ testsuite/g++.dg/parse/friend12.C	(working copy)
@@ -3,5 +3,4 @@ 
 struct A
 {
   friend int i = 0;  // { dg-error "cannot be declared friend" }
-// { dg-error "non-static data member" "" { target { ! c++11 } } .-1 }
 };