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" }
+ };
+};