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