@@ -6978,6 +6978,33 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
69786978 diagID))
69796979 return ExprError();
69806980 }
6981+ } else if (LangOpts.C23 &&
6982+ (literalType->isRecordType() || literalType->isEnumeralType())) {
6983+ // C23 6.2.1p7: Structure, union, and enumeration tags have scope that
6984+ // begins just after the appearance of the tag in a type specifier that
6985+ // declares the tag.
6986+ // [...]
6987+ // An ordinary identifier that has an underspecified definition has scope
6988+ // that starts when the definition is completed; if the same ordinary
6989+ // identifier declares another entity with a scope that encloses the current
6990+ // block, that declaration is hidden as soon as the inner declarator is
6991+ // completed*.)
6992+ // [...]
6993+ // *) That means, that the outer declaration is not visible for the
6994+ // initializer.
6995+ auto Range = SourceRange(LParenLoc, RParenLoc);
6996+ const auto *Tag = literalType->castAs<TagType>();
6997+ const auto &TagRange = Tag->getDecl()->getSourceRange();
6998+
6999+ // We should diagnose underspecified declaration, unless the identifier has
7000+ // been diagnosed as being a redefinition, since the tag is made anonymous.
7001+ if (Range.fullyContains(TagRange) && Tag->getDecl()->getIdentifier()) {
7002+ Diag(TagRange.getBegin(),
7003+ diag::err_c23_underspecified_object_declaration)
7004+ << (unsigned)Tag->getDecl()->getTagKind()
7005+ << Tag->getDecl()->getName() << TagRange;
7006+ return ExprError();
7007+ }
69817008 } else if (!literalType->isDependentType() &&
69827009 RequireCompleteType(LParenLoc, literalType,
69837010 diag::err_typecheck_decl_incomplete_type,
0 commit comments