Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -4165,6 +4165,8 @@ "cannot jump from this goto statement to label %0 inside an inline assembly block">; def note_goto_ms_asm_label : Note< "inline assembly label %0 declared here">; +def err_cross_block_asm_label_use : Error< + "cannot use inline assembly label %0 defined outside of an inline assembly block">; def warn_unused_label : Warning<"unused label %0">, InGroup, DefaultIgnore; Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -3166,6 +3166,7 @@ LabelDecl *GetOrCreateMSAsmLabel(StringRef ExternalLabelName, SourceLocation Location, bool AlwaysCreate); + void DiagnoseCrossBlockLabelUse(const LabelDecl *Label); VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType, SourceLocation StartLoc, Index: lib/Parse/ParseStmtAsm.cpp =================================================================== --- lib/Parse/ParseStmtAsm.cpp +++ lib/Parse/ParseStmtAsm.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include #include "clang/Parse/Parser.h" #include "RAIIObjectsForParser.h" #include "clang/AST/ASTContext.h" @@ -45,6 +46,9 @@ /// The offset of each token in AsmToks within AsmString. ArrayRef AsmTokOffsets; + /// The LabelDecls encountered when parsing the asm block. + std::set LabelDecls; + public: ClangAsmParserCallback(Parser &P, SourceLocation Loc, StringRef AsmString, ArrayRef Toks, ArrayRef Offsets) @@ -99,6 +103,7 @@ SourceLocation Loc = translateLocation(LSM, Location); LabelDecl *Label = TheParser.getActions().GetOrCreateMSAsmLabel(Identifier, Loc, Create); + LabelDecls.insert(Label); return Label->getMSAsmLabel(); } @@ -108,6 +113,14 @@ AsmLoc); } + void CheckExternalLabels() { + for (const auto *Label : LabelDecls) { + if (!Label->isResolvedMSAsmLabel()) { + TheParser.getActions().DiagnoseCrossBlockLabelUse(Label); + } + } + } + static void DiagHandlerCallback(const llvm::SMDiagnostic &D, void *Context) { ((ClangAsmParserCallback *)Context)->handleDiagnostic(D); } @@ -581,6 +594,8 @@ Exprs[i] = OpExpr; } + Callback.CheckExternalLabels(); + // FIXME: We should be passing source locations for better diagnostics. return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLocs[0], AsmToks, AsmStringIR, NumOutputs, NumInputs, ConstraintRefs, Index: lib/Sema/SemaStmtAsm.cpp =================================================================== --- lib/Sema/SemaStmtAsm.cpp +++ lib/Sema/SemaStmtAsm.cpp @@ -585,3 +585,8 @@ return Label; } + +void Sema::DiagnoseCrossBlockLabelUse(const LabelDecl *Label) { + Diag(Label->getLocStart(), diag::err_cross_block_asm_label_use) + << Label->getIdentifier(); +} Index: test/Parser/ms-inline-asm.c =================================================================== --- test/Parser/ms-inline-asm.c +++ test/Parser/ms-inline-asm.c @@ -49,7 +49,38 @@ do { __asm mov eax, 0 __asm { __asm mov edx, 1 } } while(0); } void t12() { - __asm jmp label // expected-error {{use of undeclared label 'label'}} + __asm jmp label // expected-error {{use of undeclared label 'label'}} expected-error {{cannot use inline assembly label 'label' defined outside of an inline assembly block}} +} +void t13() { + __asm { + jmp lbl1 // expected-error {{cannot use inline assembly label 'lbl1' defined outside of an inline assembly block}} + } + __asm { + lbl1: + nop + } +} +void t14() { + __asm { + jmp lbl2 // expected-error {{cannot use inline assembly label 'lbl2' defined outside of an inline assembly block}} + } + for (;;) { + __asm { + lbl2: + nop + } + } +} +void t15() { + for (;;) { + __asm { + jmp lbl2 // expected-error {{cannot use inline assembly label 'lbl2' defined outside of an inline assembly block}} + } + } + __asm { + lbl2: + nop + } } int t_fail() { // expected-note {{to match this}} __asm Index: test/Sema/ms-inline-asm.c =================================================================== --- test/Sema/ms-inline-asm.c +++ test/Sema/ms-inline-asm.c @@ -106,7 +106,7 @@ } __declspec(naked) int t5(int x) { // expected-note {{attribute is here}} - asm { movl eax, x } // expected-error {{parameter references not allowed in naked functions}} expected-error {{use of undeclared label 'x'}} + asm { movl eax, x } // expected-error {{parameter references not allowed in naked functions}} expected-error {{use of undeclared label 'x'}} expected-error {{cannot use inline assembly label 'x' defined outside of an inline assembly block}} asm { retl } } @@ -146,7 +146,7 @@ void t11() { foo: - __asm mov eax, foo // expected-error {{use of undeclared label 'foo'}} expected-warning {{unused label 'foo'}} + __asm mov eax, foo // expected-error {{use of undeclared label 'foo'}} expected-error {{cannot use inline assembly label 'foo' defined outside of an inline assembly block}} } void t12() {