Index: lib/Parse/ParseStmtAsm.cpp =================================================================== --- lib/Parse/ParseStmtAsm.cpp +++ lib/Parse/ParseStmtAsm.cpp @@ -322,19 +322,21 @@ SourceLocation EndLoc = AsmLoc; SmallVector AsmToks; - bool InBraces = false; + unsigned BraceNesting = 0; unsigned short savedBraceCount = 0; bool InAsmComment = false; FileID FID; unsigned LineNo = 0; unsigned NumTokensRead = 0; - SourceLocation LBraceLoc; + SmallVector LBraceLocs; + bool SkippedStartOfLine = false; if (Tok.is(tok::l_brace)) { // Braced inline asm: consume the opening brace. - InBraces = true; + BraceNesting = 1; savedBraceCount = BraceCount; - EndLoc = LBraceLoc = ConsumeBrace(); + EndLoc = ConsumeBrace(); + LBraceLocs.push_back(EndLoc); ++NumTokensRead; } else { // Single-line inline asm; compute which line it is on. @@ -342,6 +344,7 @@ SrcMgr.getDecomposedExpansionLoc(EndLoc); FID = ExpAsmLoc.first; LineNo = SrcMgr.getLineNumber(FID, ExpAsmLoc.second); + LBraceLocs.push_back(SourceLocation()); } SourceLocation TokLoc = Tok.getLocation(); @@ -350,17 +353,26 @@ if (isEofOrEom()) break; - if (!InAsmComment && Tok.is(tok::semi)) { + if (!InAsmComment && Tok.is(tok::l_brace)) { + // Consume the opening brace. + SkippedStartOfLine = Tok.isAtStartOfLine(); + EndLoc = ConsumeBrace(); + BraceNesting++; + LBraceLocs.push_back(EndLoc); + TokLoc = Tok.getLocation(); + ++NumTokensRead; + continue; + } else if (!InAsmComment && Tok.is(tok::semi)) { // A semicolon in an asm is the start of a comment. InAsmComment = true; - if (InBraces) { + if (BraceNesting) { // Compute which line the comment is on. std::pair ExpSemiLoc = SrcMgr.getDecomposedExpansionLoc(TokLoc); FID = ExpSemiLoc.first; LineNo = SrcMgr.getLineNumber(FID, ExpSemiLoc.second); } - } else if (!InBraces || InAsmComment) { + } else if (!BraceNesting || InAsmComment) { // If end-of-line is significant, check whether this token is on a // new line. std::pair ExpLoc = @@ -368,7 +380,7 @@ if (ExpLoc.first != FID || SrcMgr.getLineNumber(ExpLoc.first, ExpLoc.second) != LineNo) { // If this is a single-line __asm, we're done. - if (!InBraces) + if (!BraceNesting) break; // We're no longer in a comment. InAsmComment = false; @@ -379,11 +391,21 @@ break; } } - if (!InAsmComment && InBraces && Tok.is(tok::r_brace) && - BraceCount == (savedBraceCount + 1)) { - // Consume the closing brace, and finish + if (!InAsmComment && BraceNesting && Tok.is(tok::r_brace) && + BraceCount == (savedBraceCount + BraceNesting)) { + // Consume the closing brace. + SkippedStartOfLine = Tok.isAtStartOfLine(); EndLoc = ConsumeBrace(); - break; + BraceNesting--; + // Finish if all of the opened braces in the inline asm section were consumed. + if (BraceNesting == 0) + break; + else { + LBraceLocs.pop_back(); + TokLoc = Tok.getLocation(); + ++NumTokensRead; + continue; + } } // Consume the next token; make sure we don't modify the brace count etc. @@ -392,17 +414,25 @@ if (InAsmComment) PP.Lex(Tok); else { + // Set the token as the start of line if we skipped the original start + // of line token in case it was a nested brace. + if (SkippedStartOfLine) + Tok.setFlag(Token::StartOfLine); AsmToks.push_back(Tok); ConsumeAnyToken(); } TokLoc = Tok.getLocation(); ++NumTokensRead; + SkippedStartOfLine = false; } while (1); - if (InBraces && BraceCount != savedBraceCount) { + if (BraceNesting && BraceCount != savedBraceCount) { // __asm without closing brace (this can happen at EOF). - Diag(Tok, diag::err_expected) << tok::r_brace; - Diag(LBraceLoc, diag::note_matching) << tok::l_brace; + for (unsigned i = 0; i < BraceNesting; ++i) { + Diag(Tok, diag::err_expected) << tok::r_brace; + Diag(LBraceLocs.back(), diag::note_matching) << tok::l_brace; + LBraceLocs.pop_back(); + } return StmtError(); } else if (NumTokensRead == 0) { // Empty __asm. @@ -434,7 +464,7 @@ // If we don't support assembly, or the assembly is empty, we don't // need to instantiate the AsmParser, etc. if (!TheTarget || AsmToks.empty()) { - return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLoc, AsmToks, StringRef(), + return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLocs[0], AsmToks, StringRef(), /*NumOutputs*/ 0, /*NumInputs*/ 0, ConstraintRefs, ClobberRefs, Exprs, EndLoc); } @@ -523,7 +553,7 @@ } // FIXME: We should be passing source locations for better diagnostics. - return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLoc, AsmToks, AsmStringIR, + return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLocs[0], AsmToks, AsmStringIR, NumOutputs, NumInputs, ConstraintRefs, ClobberRefs, Exprs, EndLoc); } Index: test/CodeGen/ms-inline-asm-64.c =================================================================== --- test/CodeGen/ms-inline-asm-64.c +++ test/CodeGen/ms-inline-asm-64.c @@ -37,7 +37,9 @@ foo.b = 2; __asm { lea ebx, foo - mov eax, [ebx].foo.a + { + mov eax, [ebx].foo.a + } mov [ebx].foo.b, ecx } return foo.b; Index: test/CodeGen/ms-inline-asm.c =================================================================== --- test/CodeGen/ms-inline-asm.c +++ test/CodeGen/ms-inline-asm.c @@ -52,6 +52,11 @@ __asm { int 0x2c ; } asm comments are fun! }{ } + __asm { + { + int 0x2c ; } asm comments are fun! }{ + } + } __asm {} // CHECK: t7 // CHECK: call void asm sideeffect inteldialect "int $$0x2c", "~{dirflag},~{fpsr},~{flags}"() @@ -73,8 +78,8 @@ void t9() { __asm { push ebx - mov ebx, 0x07 - pop ebx + { mov ebx, 0x07 } + __asm { pop ebx } } // CHECK: t9 // CHECK: call void asm sideeffect inteldialect "push ebx\0A\09mov ebx, $$0x07\0A\09pop ebx", "~{ebx},~{esp},~{dirflag},~{fpsr},~{flags}"() @@ -129,7 +134,7 @@ unsigned i = 1, j = 2; __asm { .if 1 - mov eax, i + { mov eax, i } .else mov ebx, j .endif Index: test/Parser/ms-inline-asm-nested-braces.c =================================================================== --- /dev/null +++ test/Parser/ms-inline-asm-nested-braces.c @@ -0,0 +1,9 @@ +// REQUIRES: x86-registered-target +// RUN: %clang_cc1 %s -triple i386-apple-darwin10 -verify -fasm-blocks + +int t_fail() { // expected-note {{to match this}} + __asm + { // expected-note {{to match this}} + { // expected-note {{to match this}} + { + } // expected-error 3 {{expected}} Index: test/Parser/ms-inline-asm.c =================================================================== --- test/Parser/ms-inline-asm.c +++ test/Parser/ms-inline-asm.c @@ -34,6 +34,17 @@ void t9() { __asm nop __asm nop ; __asm nop } +void t10() { + __asm { + mov eax, 0 + __asm { + mov eax, 1 + { + mov eax, 2 + } + } + } +} int t_fail() { // expected-note {{to match this}} __asm __asm { // expected-error 3 {{expected}} expected-note {{to match this}}