summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/AST/Decl.h13
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td4
-rw-r--r--clang/include/clang/Sema/Sema.h8
-rw-r--r--clang/lib/AST/Decl.cpp7
-rw-r--r--clang/lib/Parse/ParseStmtAsm.cpp22
-rw-r--r--clang/lib/Sema/JumpDiagnostics.cpp22
-rw-r--r--clang/lib/Sema/Sema.cpp1
-rw-r--r--clang/lib/Sema/SemaDecl.cpp10
-rw-r--r--clang/lib/Sema/SemaStmt.cpp6
-rw-r--r--clang/lib/Sema/SemaStmtAsm.cpp30
-rw-r--r--clang/test/CodeGen/mozilla-ms-inline-asm.c17
-rw-r--r--clang/test/CodeGen/ms-inline-asm.c29
-rw-r--r--clang/test/CodeGen/ms-inline-asm.cpp17
-rw-r--r--clang/test/Parser/ms-inline-asm.c3
-rw-r--r--clang/test/Sema/ms-inline-asm.c40
15 files changed, 205 insertions, 24 deletions
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index 3aff0f5424b..8846d0ca8fb 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -308,6 +308,8 @@ inline raw_ostream &operator<<(raw_ostream &OS, const NamedDecl &ND) {
class LabelDecl : public NamedDecl {
void anchor() override;
LabelStmt *TheStmt;
+ StringRef MSAsmName;
+ bool MSAsmNameResolved;
/// LocStart - For normal labels, this is the same as the main declaration
/// label, i.e., the location of the identifier; for GNU local labels,
/// this is the location of the __label__ keyword.
@@ -315,7 +317,10 @@ class LabelDecl : public NamedDecl {
LabelDecl(DeclContext *DC, SourceLocation IdentL, IdentifierInfo *II,
LabelStmt *S, SourceLocation StartL)
- : NamedDecl(Label, DC, IdentL, II), TheStmt(S), LocStart(StartL) {}
+ : NamedDecl(Label, DC, IdentL, II),
+ TheStmt(S),
+ MSAsmNameResolved(false),
+ LocStart(StartL) {}
public:
static LabelDecl *Create(ASTContext &C, DeclContext *DC,
@@ -335,6 +340,12 @@ public:
return SourceRange(LocStart, getLocation());
}
+ bool isMSAsmLabel() const { return MSAsmName.size() != 0; }
+ bool isResolvedMSAsmLabel() const { return isMSAsmLabel() && MSAsmNameResolved; }
+ void setMSAsmLabel(StringRef Name);
+ StringRef getMSAsmLabel() const { return MSAsmName; }
+ void setMSAsmLabelResolved() { MSAsmNameResolved = true; }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Label; }
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 559bf62fd8c..27661c17b73 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4133,6 +4133,10 @@ def warn_missing_braces : Warning<
def err_redefinition_of_label : Error<"redefinition of label %0">;
def err_undeclared_label_use : Error<"use of undeclared label %0">;
+def err_goto_ms_asm_label : Error<
+ "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 warn_unused_label : Warning<"unused label %0">,
InGroup<UnusedLabel>, DefaultIgnore;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 0e5ed350a77..d3c539b9a2d 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -699,7 +699,10 @@ public:
/// \brief will hold 'respondsToSelector:'
Selector RespondsToSelectorSel;
-
+
+ /// \brief counter for internal MS Asm label names.
+ unsigned MSAsmLabelNameCounter;
+
/// A flag to remember whether the implicit forms of operator new and delete
/// have been declared.
bool GlobalNewDeleteDeclared;
@@ -3156,6 +3159,9 @@ public:
ArrayRef<StringRef> Clobbers,
ArrayRef<Expr*> Exprs,
SourceLocation EndLoc);
+ LabelDecl *GetOrCreateMSAsmLabel(StringRef ExternalLabelName,
+ SourceLocation Location,
+ bool AlwaysCreate);
VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType,
SourceLocation StartLoc,
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index cc7c11ca6ef..aec7059490c 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -3709,6 +3709,13 @@ LabelDecl *LabelDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
SourceLocation());
}
+void LabelDecl::setMSAsmLabel(StringRef Name) {
+ char *Buffer = new (getASTContext(), 1) char[Name.size() + 1];
+ memcpy(Buffer, Name.data(), Name.size());
+ Buffer[Name.size()] = '\0';
+ MSAsmName = Buffer;
+}
+
void ValueDecl::anchor() { }
bool ValueDecl::isWeak() const {
diff --git a/clang/lib/Parse/ParseStmtAsm.cpp b/clang/lib/Parse/ParseStmtAsm.cpp
index be3d79e2231..35e2e6294f8 100644
--- a/clang/lib/Parse/ParseStmtAsm.cpp
+++ b/clang/lib/Parse/ParseStmtAsm.cpp
@@ -93,6 +93,15 @@ public:
return Info.OpDecl;
}
+ StringRef LookupInlineAsmLabel(StringRef Identifier, llvm::SourceMgr &LSM,
+ llvm::SMLoc Location,
+ bool Create) override {
+ SourceLocation Loc = translateLocation(LSM, Location);
+ LabelDecl *Label =
+ TheParser.getActions().GetOrCreateMSAsmLabel(Identifier, Loc, Create);
+ return Label->getMSAsmLabel();
+ }
+
bool LookupInlineAsmField(StringRef Base, StringRef Member,
unsigned &Offset) override {
return TheParser.getActions().LookupInlineAsmField(Base, Member, Offset,
@@ -133,14 +142,13 @@ private:
}
}
- void handleDiagnostic(const llvm::SMDiagnostic &D) {
+ SourceLocation translateLocation(const llvm::SourceMgr &LSM, llvm::SMLoc SMLoc) {
// Compute an offset into the inline asm buffer.
// FIXME: This isn't right if .macro is involved (but hopefully, no
// real-world code does that).
- const llvm::SourceMgr &LSM = *D.getSourceMgr();
const llvm::MemoryBuffer *LBuf =
- LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
- unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart();
+ LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(SMLoc));
+ unsigned Offset = SMLoc.getPointer() - LBuf->getBufferStart();
// Figure out which token that offset points into.
const unsigned *TokOffsetPtr =
@@ -157,6 +165,12 @@ private:
Loc = Tok.getLocation();
Loc = Loc.getLocWithOffset(Offset - TokOffset);
}
+ return Loc;
+ }
+
+ void handleDiagnostic(const llvm::SMDiagnostic &D) {
+ const llvm::SourceMgr &LSM = *D.getSourceMgr();
+ SourceLocation Loc = translateLocation(LSM, D.getLoc());
TheParser.Diag(Loc, diag::err_inline_ms_asm_parsing) << D.getMessage();
}
};
diff --git a/clang/lib/Sema/JumpDiagnostics.cpp b/clang/lib/Sema/JumpDiagnostics.cpp
index 255845282df..fd75c02bb1e 100644
--- a/clang/lib/Sema/JumpDiagnostics.cpp
+++ b/clang/lib/Sema/JumpDiagnostics.cpp
@@ -84,6 +84,7 @@ private:
void CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc,
unsigned JumpDiag, unsigned JumpDiagWarning,
unsigned JumpDiagCXX98Compat);
+ void CheckGotoStmt(GotoStmt *GS);
unsigned GetDeepestCommonScope(unsigned A, unsigned B);
};
@@ -489,10 +490,14 @@ void JumpScopeChecker::VerifyJumps() {
// With a goto,
if (GotoStmt *GS = dyn_cast<GotoStmt>(Jump)) {
- CheckJump(GS, GS->getLabel()->getStmt(), GS->getGotoLoc(),
- diag::err_goto_into_protected_scope,
- diag::ext_goto_into_protected_scope,
- diag::warn_cxx98_compat_goto_into_protected_scope);
+ // The label may not have a statement if it's coming from inline MS ASM.
+ if (GS->getLabel()->getStmt()) {
+ CheckJump(GS, GS->getLabel()->getStmt(), GS->getGotoLoc(),
+ diag::err_goto_into_protected_scope,
+ diag::ext_goto_into_protected_scope,
+ diag::warn_cxx98_compat_goto_into_protected_scope);
+ }
+ CheckGotoStmt(GS);
continue;
}
@@ -789,6 +794,15 @@ void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc,
}
}
+void JumpScopeChecker::CheckGotoStmt(GotoStmt *GS) {
+ if (GS->getLabel()->isMSAsmLabel()) {
+ S.Diag(GS->getGotoLoc(), diag::err_goto_ms_asm_label)
+ << GS->getLabel()->getIdentifier();
+ S.Diag(GS->getLabel()->getLocation(), diag::note_goto_ms_asm_label)
+ << GS->getLabel()->getIdentifier();
+ }
+}
+
void Sema::DiagnoseInvalidJumps(Stmt *Body) {
(void)JumpScopeChecker(Body, *this);
}
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 69a4356b450..7ecd41697d6 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -98,6 +98,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
InitDictionaryWithObjectsMethod(nullptr),
ArrayAllocObjectsMethod(nullptr),
DictAllocObjectsMethod(nullptr),
+ MSAsmLabelNameCounter(0),
GlobalNewDeleteDeclared(false),
TUKind(TUKind),
NumSFINAEErrors(0),
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 535e33a2b6e..ae79720e383 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -1517,8 +1517,14 @@ void Sema::DiagnoseUnusedDecl(const NamedDecl *D) {
static void CheckPoppedLabel(LabelDecl *L, Sema &S) {
// Verify that we have no forward references left. If so, there was a goto
// or address of a label taken, but no definition of it. Label fwd
- // definitions are indicated with a null substmt.
- if (L->getStmt() == nullptr)
+ // definitions are indicated with a null substmt which is also not a resolved
+ // MS inline assembly label name.
+ bool Diagnose = false;
+ if (L->isMSAsmLabel())
+ Diagnose = !L->isResolvedMSAsmLabel();
+ else
+ Diagnose = L->getStmt() == nullptr;
+ if (Diagnose)
S.Diag(L->getLocation(), diag::err_undeclared_label_use) <<L->getDeclName();
}
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 8d2a3258b10..464206eafe3 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -432,7 +432,11 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
TheDecl->setStmt(LS);
if (!TheDecl->isGnuLocal()) {
TheDecl->setLocStart(IdentLoc);
- TheDecl->setLocation(IdentLoc);
+ if (!TheDecl->isMSAsmLabel()) {
+ // Don't update the location of MS ASM labels. These will result in
+ // a diagnostic, and changing the location here will mess that up.
+ TheDecl->setLocation(IdentLoc);
+ }
}
return LS;
}
diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp
index 5aa1a2c86a9..dc50e87b589 100644
--- a/clang/lib/Sema/SemaStmtAsm.cpp
+++ b/clang/lib/Sema/SemaStmtAsm.cpp
@@ -15,6 +15,7 @@
#include "clang/AST/RecordLayout.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
@@ -520,6 +521,7 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
ArrayRef<Expr*> Exprs,
SourceLocation EndLoc) {
bool IsSimple = (NumOutputs != 0 || NumInputs != 0);
+ getCurFunction()->setHasBranchProtectedScope();
MSAsmStmt *NS =
new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple,
/*IsVolatile*/ true, AsmToks, NumOutputs, NumInputs,
@@ -527,3 +529,31 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
Clobbers, EndLoc);
return NS;
}
+
+LabelDecl *Sema::GetOrCreateMSAsmLabel(StringRef ExternalLabelName,
+ SourceLocation Location,
+ bool AlwaysCreate) {
+ LabelDecl* Label = LookupOrCreateLabel(PP.getIdentifierInfo(ExternalLabelName),
+ Location);
+
+ if (!Label->isMSAsmLabel()) {
+ // Otherwise, insert it, but only resolve it if we have seen the label itself.
+ std::string InternalName;
+ llvm::raw_string_ostream OS(InternalName);
+ // Create an internal name for the label. The name should not be a valid mangled
+ // name, and should be unique. We use a dot to make the name an invalid mangled
+ // name.
+ OS << "__MSASMLABEL_." << MSAsmLabelNameCounter++ << "__" << ExternalLabelName;
+ Label->setMSAsmLabel(OS.str());
+ }
+ if (AlwaysCreate) {
+ // The label might have been created implicitly from a previously encountered
+ // goto statement. So, for both newly created and looked up labels, we mark
+ // them as resolved.
+ Label->setMSAsmLabelResolved();
+ }
+ // Adjust their location for being able to generate accurate diagnostics.
+ Label->setLocation(Location);
+
+ return Label;
+}
diff --git a/clang/test/CodeGen/mozilla-ms-inline-asm.c b/clang/test/CodeGen/mozilla-ms-inline-asm.c
index 0f541d70fcd..b8b7a2d677d 100644
--- a/clang/test/CodeGen/mozilla-ms-inline-asm.c
+++ b/clang/test/CodeGen/mozilla-ms-inline-asm.c
@@ -3,6 +3,8 @@
// Some test cases for MS inline asm support from Mozilla code base.
+void invoke_copy_to_stack() {}
+
void invoke(void* that, unsigned methodIndex,
unsigned paramCount, void* params)
{
@@ -18,24 +20,25 @@ void invoke(void* that, unsigned methodIndex,
// CHECK: call void asm sideeffect inteldialect
// CHECK: mov edx,dword ptr $1
// CHECK: test edx,edx
-// CHECK: jz noparams
+// CHECK: jz {{[^_]*}}__MSASMLABEL_.0__noparams
+// ^ Can't use {{.*}} here because the matching is greedy.
// CHECK: mov eax,edx
// CHECK: shl eax,$$3
// CHECK: sub esp,eax
// CHECK: mov ecx,esp
// CHECK: push dword ptr $0
-// CHECK: call invoke_copy_to_stack
-// CHECK: noparams:
-// CHECK: mov ecx,dword ptr $2
+// CHECK: call dword ptr $2
+// CHECK: {{.*}}__MSASMLABEL_.0__noparams:
+// CHECK: mov ecx,dword ptr $3
// CHECK: push ecx
// CHECK: mov edx,[ecx]
-// CHECK: mov eax,dword ptr $3
+// CHECK: mov eax,dword ptr $4
// CHECK: call dword ptr[edx+eax*$$4]
// CHECK: mov esp,ebp
// CHECK: pop ebp
// CHECK: ret
-// CHECK: "=*m,*m,*m,*m,~{eax},~{ebp},~{ecx},~{edx},~{flags},~{esp},~{dirflag},~{fpsr},~{flags}"
-// CHECK: (i8** %8, i32* %7, i8** %5, i32* %6)
+// CHECK: "=*m,*m,*m,*m,*m,~{eax},~{ebp},~{ecx},~{edx},~{flags},~{esp},~{dirflag},~{fpsr},~{flags}"
+// CHECK: (i8** %8, i32* %7, void (...)* bitcast (void ()* @invoke_copy_to_stack to void (...)*), i8** %5, i32* %6)
// CHECK: ret void
__asm {
mov edx,paramCount
diff --git a/clang/test/CodeGen/ms-inline-asm.c b/clang/test/CodeGen/ms-inline-asm.c
index 0a7ac110430..3e6ebc8f077 100644
--- a/clang/test/CodeGen/ms-inline-asm.c
+++ b/clang/test/CodeGen/ms-inline-asm.c
@@ -240,7 +240,7 @@ void t23() {
the_label:
}
// CHECK: t23
-// CHECK: call void asm sideeffect inteldialect "the_label:", "~{dirflag},~{fpsr},~{flags}"()
+// CHECK: call void asm sideeffect inteldialect "{{.*}}__MSASMLABEL_.0__the_label:", "~{dirflag},~{fpsr},~{flags}"()
}
void t24_helper(void) {}
@@ -517,3 +517,30 @@ void xgetbv() {
}
// CHECK-LABEL: define void @xgetbv()
// CHECK: call void asm sideeffect inteldialect "xgetbv", "~{eax},~{edx},~{dirflag},~{fpsr},~{flags}"()
+
+void label1() {
+ __asm {
+ label:
+ jmp label
+ }
+ // CHECK-LABEL: define void @label1
+ // CHECK: call void asm sideeffect inteldialect "{{.*}}__MSASMLABEL_.1__label:\0A\09jmp {{.*}}__MSASMLABEL_.1__label", "~{dirflag},~{fpsr},~{flags}"()
+}
+
+void label2() {
+ __asm {
+ jmp label
+ label:
+ }
+ // CHECK-LABEL: define void @label2
+ // CHECK: call void asm sideeffect inteldialect "jmp {{.*}}__MSASMLABEL_.2__label\0A\09{{.*}}__MSASMLABEL_.2__label:", "~{dirflag},~{fpsr},~{flags}"()
+}
+
+void label3() {
+ __asm {
+ label:
+ mov eax, label
+ }
+ // CHECK-LABEL: define void @label3
+ // CHECK: call void asm sideeffect inteldialect "{{.*}}__MSASMLABEL_.3__label:\0A\09mov eax, {{.*}}__MSASMLABEL_.3__label", "~{eax},~{dirflag},~{fpsr},~{flags}"()
+}
diff --git a/clang/test/CodeGen/ms-inline-asm.cpp b/clang/test/CodeGen/ms-inline-asm.cpp
index 65e59d6b947..03d971e698b 100644
--- a/clang/test/CodeGen/ms-inline-asm.cpp
+++ b/clang/test/CodeGen/ms-inline-asm.cpp
@@ -122,3 +122,20 @@ void t7_using() {
// CHECK-LABEL: define void @_Z8t7_usingv
// CHECK: call void asm sideeffect inteldialect "mov eax, [eax].4", "~{eax},~{dirflag},~{fpsr},~{flags}"()
}
+
+void t8() {
+ __asm some_label:
+ // CHECK-LABEL: define void @_Z2t8v()
+ // CHECK: call void asm sideeffect inteldialect "L__MSASMLABEL_.1__some_label:", "~{dirflag},~{fpsr},~{flags}"()
+ struct A {
+ static void g() {
+ __asm jmp some_label ; This should jump forwards
+ __asm some_label:
+ __asm nop
+ // CHECK-LABEL: define internal void @_ZZ2t8vEN1A1gEv()
+ // CHECK: call void asm sideeffect inteldialect "jmp L__MSASMLABEL_.2__some_label\0A\09L__MSASMLABEL_.2__some_label:\0A\09nop", "~{dirflag},~{fpsr},~{flags}"()
+ }
+ };
+ A::g();
+}
+
diff --git a/clang/test/Parser/ms-inline-asm.c b/clang/test/Parser/ms-inline-asm.c
index 646f547e328..72c96c3715d 100644
--- a/clang/test/Parser/ms-inline-asm.c
+++ b/clang/test/Parser/ms-inline-asm.c
@@ -48,6 +48,9 @@ void t10() {
void t11() {
do { __asm mov eax, 0 __asm { __asm mov edx, 1 } } while(0);
}
+void t12() {
+ __asm jmp label // expected-error {{use of undeclared label 'label'}}
+}
int t_fail() { // expected-note {{to match this}}
__asm
__asm { // expected-error 2 {{expected}} expected-note {{to match this}}
diff --git a/clang/test/Sema/ms-inline-asm.c b/clang/test/Sema/ms-inline-asm.c
index 358b0bd4543..6eac7695054 100644
--- a/clang/test/Sema/ms-inline-asm.c
+++ b/clang/test/Sema/ms-inline-asm.c
@@ -29,7 +29,7 @@ void f() {
}
f();
__asm {
- mov eax, TYPE bar // expected-error {{unable to lookup expression}}
+ mov eax, TYPE bar // expected-error {{unable to lookup expression}} expected-error {{use of undeclared label 'bar'}}
}
}
@@ -80,9 +80,10 @@ typedef struct {
} A;
void t3() {
- __asm { mov eax, [eax] UndeclaredId } // expected-error {{unknown token in expression}}
+ __asm { mov eax, [eax] UndeclaredId } // expected-error {{unknown token in expression}} expected-error {{use of undeclared label 'UndeclaredId'}}
// FIXME: Only emit one diagnostic here.
+ // expected-error@+3 {{use of undeclared label 'A'}}
// expected-error@+2 {{unexpected type name 'A': expected expression}}
// expected-error@+1 {{unknown token in expression}}
__asm { mov eax, [eax] A }
@@ -105,7 +106,7 @@ void test_operand_size() {
}
__declspec(naked) int t5(int x) { // expected-note {{attribute is here}}
- asm { movl eax, x } // expected-error {{parameter references not allowed in naked functions}}
+ asm { movl eax, x } // expected-error {{parameter references not allowed in naked functions}} expected-error {{use of undeclared label 'x'}}
asm { retl }
}
@@ -114,3 +115,36 @@ __declspec(naked) int t6(int x) {
asm { mov eax, y } // No error.
asm { ret }
}
+
+void t7() {
+ __asm {
+ foo: // expected-note {{inline assembly label 'foo' declared here}}
+ mov eax, 0
+ }
+ goto foo; // expected-error {{cannot jump from this goto statement to label 'foo' inside an inline assembly block}}
+}
+
+void t8() {
+ __asm foo: // expected-note {{inline assembly label 'foo' declared here}}
+ __asm mov eax, 0
+ goto foo; // expected-error {{cannot jump from this goto statement to label 'foo' inside an inline assembly block}}
+}
+
+void t9() {
+ goto foo; // expected-error {{cannot jump from this goto statement to label 'foo' inside an inline assembly block}}
+ __asm {
+ foo: // expected-note {{inline assembly label 'foo' declared here}}
+ mov eax, 0
+ }
+}
+
+void t10() {
+ goto foo; // expected-error {{cannot jump from this goto statement to label 'foo' inside an inline assembly block}}
+ __asm foo: // expected-note {{inline assembly label 'foo' declared here}}
+ __asm mov eax, 0
+}
+
+void t11() {
+foo:
+ __asm mov eax, foo // expected-error {{use of undeclared label 'foo'}}
+}
OpenPOWER on IntegriCloud