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.carl...@oracle.com>

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

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

        PR c++/84605
        * g++.dg/parse/crash69.C: New.
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" }
+  };
+};

Reply via email to