@@ -7117,6 +7117,33 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
71177117 diagID))
71187118 return ExprError();
71197119 }
7120+ } else if (LangOpts.C23 &&
7121+ (literalType->isRecordType() || literalType->isEnumeralType())) {
7122+ // C23 6.2.1p7: Structure, union, and enumeration tags have scope that
7123+ // begins just after the appearance of the tag in a type specifier that
7124+ // declares the tag.
7125+ // [...]
7126+ // An ordinary identifier that has an underspecified definition has scope
7127+ // that starts when the definition is completed; if the same ordinary
7128+ // identifier declares another entity with a scope that encloses the current
7129+ // block, that declaration is hidden as soon as the inner declarator is
7130+ // completed*.)
7131+ // [...]
7132+ // *) That means, that the outer declaration is not visible for the
7133+ // initializer.
7134+ auto Range = SourceRange(LParenLoc, RParenLoc);
7135+ const auto *Tag = literalType->castAs<TagType>();
7136+ const auto &TagRange = Tag->getDecl()->getSourceRange();
7137+
7138+ // We should diagnose underspecified declaration, unless the identifier has
7139+ // been diagnosed as being a redefinition, since the tag is made anonymous.
7140+ if (Range.fullyContains(TagRange) && Tag->getDecl()->getIdentifier()) {
7141+ Diag(TagRange.getBegin(),
7142+ diag::err_c23_underspecified_object_declaration)
7143+ << (unsigned)Tag->getDecl()->getTagKind()
7144+ << Tag->getDecl()->getName() << TagRange;
7145+ return ExprError();
7146+ }
71207147 } else if (!literalType->isDependentType() &&
71217148 RequireCompleteType(LParenLoc, literalType,
71227149 diag::err_typecheck_decl_incomplete_type,
0 commit comments