@@ -7813,6 +7813,33 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
78137813 diag::err_variable_object_no_init))
78147814 return ExprError();
78157815 }
7816+ } else if (LangOpts.C23 &&
7817+ (literalType->isRecordType() || literalType->isEnumeralType())) {
7818+ // C23 6.2.1p7: Structure, union, and enumeration tags have scope that
7819+ // begins just after the appearance of the tag in a type specifier that
7820+ // declares the tag.
7821+ // [...]
7822+ // An ordinary identifier that has an underspecified definition has scope
7823+ // that starts when the definition is completed; if the same ordinary
7824+ // identifier declares another entity with a scope that encloses the current
7825+ // block, that declaration is hidden as soon as the inner declarator is
7826+ // completed*.)
7827+ // [...]
7828+ // *) That means, that the outer declaration is not visible for the
7829+ // initializer.
7830+ auto Range = SourceRange(LParenLoc, RParenLoc);
7831+ const auto *Tag = literalType->castAs<TagType>();
7832+ const auto &TagRange = Tag->getDecl()->getSourceRange();
7833+
7834+ // We should diagnose underspecified declaration, unless the identifier has
7835+ // been diagnosed as being a redefinition, since the tag is made anonymous.
7836+ if (Range.fullyContains(TagRange) && Tag->getDecl()->getIdentifier()) {
7837+ Diag(TagRange.getBegin(),
7838+ diag::err_c23_underspecified_object_declaration)
7839+ << (unsigned)Tag->getDecl()->getTagKind()
7840+ << Tag->getDecl()->getName() << TagRange;
7841+ return ExprError();
7842+ }
78167843 } else if (!literalType->isDependentType() &&
78177844 RequireCompleteType(LParenLoc, literalType,
78187845 diag::err_typecheck_decl_incomplete_type,
0 commit comments