[C++] PR 84605 ("[7/8/9 Regression] internal compiler error: in xref_basetypes, at cp/decl.c:13818")

Message ID 9fae7281-9921-1a49-01f3-2bb8690b3577@oracle.com
State New
Headers show
Series
  • [C++] PR 84605 ("[7/8/9 Regression] internal compiler error: in xref_basetypes, at cp/decl.c:13818")
Related show

Commit Message

Paolo Carlini March 4, 2019, 11:03 a.m.
Hi,

this error recovery regression too is rather easy to explain: since 
Jason's fix for c++/79580 (r245587) when defining a type from within an 
expression we pass ts_within_enclosing_non_class to xref_tag when we 
call it from cp_parser_class_head. Thus, in the ill-formed testcases at 
issue, cp_parser_class_head is called twice for the same 'type' returned 
by xref_tag, and the second time TYPE_BINFO is already set while 
TYPE_SIZE is still zero, thus the gcc_assert in xref_basetypes triggers. 
A rather straightforward way to give again an error message instead of 
crashing is rejecting TYPE_BEING_DEFINED too, additionally to 
COMPLETE_TYPE_P. in the check placed between the xref_tag and the 
xref_basetypes calls. The wording of the error message is probably a tad 
suboptimal in the TYPE_BEING_DEFINED case, but I'm not sure it's worth 
spending time and code on that, the issue appears anyway to be rather 
rare and all the testcases I have are error-recovery ones. Tested 
x86_64-linux.

Thanks, Paolo.

//////////////////////
/cp
2019-03-04  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/84605
	* parser.c (cp_parser_class_head): Reject TYPE_BEING_DEFINED too.

/testsuite
2019-03-04  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/84605
	* g++.dg/parse/crash69.C: New.

Comments

Jason Merrill March 4, 2019, 4:58 p.m. | #1
On 3/4/19 6:03 AM, Paolo Carlini wrote:
> Hi,

> 

> this error recovery regression too is rather easy to explain: since 

> Jason's fix for c++/79580 (r245587) when defining a type from within an 

> expression we pass ts_within_enclosing_non_class to xref_tag when we 

> call it from cp_parser_class_head. Thus, in the ill-formed testcases at 

> issue, cp_parser_class_head is called twice for the same 'type' returned 

> by xref_tag, and the second time TYPE_BINFO is already set while 

> TYPE_SIZE is still zero, thus the gcc_assert in xref_basetypes triggers. 

> A rather straightforward way to give again an error message instead of 

> crashing is rejecting TYPE_BEING_DEFINED too, additionally to 

> COMPLETE_TYPE_P. in the check placed between the xref_tag and the 

> xref_basetypes calls. The wording of the error message is probably a tad 

> suboptimal in the TYPE_BEING_DEFINED case, but I'm not sure it's worth 

> spending time and code on that, the issue appears anyway to be rather 

> rare and all the testcases I have are error-recovery ones. Tested 

> x86_64-linux.


OK.

Jason

Patch

Index: cp/parser.c
===================================================================
--- cp/parser.c	(revision 269342)
+++ cp/parser.c	(working copy)
@@ -24021,8 +24021,11 @@  cp_parser_class_head (cp_parser* parser,
   cp_parser_check_class_key (class_key, type);
 
   /* If this type was already complete, and we see another definition,
-     that's an error.  */
-  if (type != error_mark_node && COMPLETE_TYPE_P (type))
+     that's an error.  Likewise if the type is already being defined:
+     this can happen, eg, when it's defined from within an expression 
+     (c++/84605).  */
+  if (type != error_mark_node
+      && (COMPLETE_TYPE_P (type) || TYPE_BEING_DEFINED (type)))
     {
       error_at (type_start_token->location, "redefinition of %q#T",
 		type);
Index: testsuite/g++.dg/parse/crash69.C
===================================================================
--- testsuite/g++.dg/parse/crash69.C	(nonexistent)
+++ testsuite/g++.dg/parse/crash69.C	(working copy)
@@ -0,0 +1,11 @@ 
+// PR c++/84605
+
+struct b {
+  int x(((struct b {})));  // { dg-error "expected|redefinition" }
+};
+
+struct c {
+  struct d {
+    int x(((struct c {})));  // { dg-error "expected|redefinition" }
+  };
+};