@@ -4466,7 +4466,8 @@ LabelDecl *Sema::LookupExistingLabel(IdentifierInfo *II, SourceLocation Loc) {
44664466}
44674467
44684468LabelDecl *Sema::LookupOrCreateLabel (IdentifierInfo *II, SourceLocation Loc,
4469- SourceLocation GnuLabelLoc) {
4469+ SourceLocation GnuLabelLoc,
4470+ bool ForLabelStmt) {
44704471 if (GnuLabelLoc.isValid ()) {
44714472 // Local label definitions always shadow existing labels.
44724473 auto *Res = LabelDecl::Create (Context, CurContext, Loc, II, GnuLabelLoc);
@@ -4475,15 +4476,43 @@ LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
44754476 return cast<LabelDecl>(Res);
44764477 }
44774478
4478- // Not a GNU local label.
4479- LabelDecl *Res = LookupExistingLabel (II, Loc);
4480- if (!Res) {
4481- // If not forward referenced or defined already, create the backing decl.
4482- Res = LabelDecl::Create (Context, CurContext, Loc, II);
4483- Scope *S = CurScope->getFnParent ();
4484- assert (S && " Not in a function?" );
4485- PushOnScopeChains (Res, S, true );
4479+ LabelDecl *Existing = LookupExistingLabel (II, Loc);
4480+
4481+ // C++26 [stmt.label]p4 An identifier label shall not be enclosed by an
4482+ // expansion-statement.
4483+ //
4484+ // As an extension, we allow GNU local labels since they are logically
4485+ // scoped to the containing block, which prevents us from ending up with
4486+ // multiple copies of the same label in a function after instantiation.
4487+ //
4488+ // While allowing this is slightly more complicated, it also has the nice
4489+ // side-effect of avoiding otherwise rather horrible diagnostics you'd get
4490+ // when trying to use '__label__' if we didn't support this.
4491+ if (ForLabelStmt && CurContext->isExpansionStmt ()) {
4492+ if (Existing && Existing->isGnuLocal ())
4493+ return Existing;
4494+
4495+ // Drop the label from the AST as creating it anyway would cause us to
4496+ // either issue various unhelpful diagnostics (if we were to declare
4497+ // it in the function decl context) or shadow a valid label with the
4498+ // same name outside the expansion statement.
4499+ Diag (Loc, diag::err_expansion_stmt_label);
4500+ return nullptr ;
44864501 }
4502+
4503+ if (Existing)
4504+ return Existing;
4505+
4506+ // Declare non-local labels outside any expansion statements; this is required
4507+ // to support jumping out of an expansion statement.
4508+ ContextRAII Ctx{*this , CurContext->getEnclosingNonExpansionStatementContext (),
4509+ /* NewThisContext=*/ false };
4510+
4511+ // Not a GNU local label. Create the backing decl.
4512+ auto *Res = LabelDecl::Create (Context, CurContext, Loc, II);
4513+ Scope *S = CurScope->getFnParent ();
4514+ assert (S && " Not in a function?" );
4515+ PushOnScopeChains (Res, S, true );
44874516 return Res;
44884517}
44894518
0 commit comments