diff --git a/clang/lib/Sema/JumpDiagnostics.cpp b/clang/lib/Sema/JumpDiagnostics.cpp --- a/clang/lib/Sema/JumpDiagnostics.cpp +++ b/clang/lib/Sema/JumpDiagnostics.cpp @@ -370,7 +370,7 @@ // have it. This makes the second scan not have to walk the AST again. LabelAndGotoScopes[S] = ParentScope; AsmJumps.push_back(GS); - for (auto *E : GS->labels()) + for (AddrLabelExpr *E : GS->labels()) AsmJumpTargets.push_back(E->getLabel()); } break; @@ -788,6 +788,17 @@ // Walk through all the jump sites, checking that they can trivially // reach this label scope. for (auto [JumpScope, JumpStmt] : JumpScopes) { + // This unnecessary copy is because: + // warning: captured structured bindings are a C++20 extension + // [-Wc++20-extensions] + LabelDecl *TL = TargetLabel; + // Is TargetLabel one of the targets of the JumpStmt? If not, then skip + // it. + if (IsAsmGoto && + llvm::none_of(cast(JumpStmt)->labels(), + [=](AddrLabelExpr *E) { return E->getLabel() == TL; })) + continue; + unsigned Scope = JumpScope; // Walk out the "scope chain" for this scope, looking for a scope // we've marked reachable. For well-formed code this amortizes diff --git a/clang/test/Sema/asm-goto.cpp b/clang/test/Sema/asm-goto.cpp --- a/clang/test/Sema/asm-goto.cpp +++ b/clang/test/Sema/asm-goto.cpp @@ -59,3 +59,13 @@ loop: return 0; } + +void test4cleanup(int*); +// No errors expected. +void test4(void) { + asm goto(""::::l0); +l0:; + int x __attribute__((cleanup(test4cleanup))); + asm goto(""::::l1); +l1:; +}