diff options
-rw-r--r-- | lib/Parse/ParseStmt.cpp | 55 | ||||
-rw-r--r-- | test/Parser/ms-inline-asm.c | 9 |
2 files changed, 54 insertions, 10 deletions
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 9f49ab59ce..dd5ccc2f5d 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -1626,6 +1626,41 @@ StmtResult Parser::ParseReturnStatement() { return Actions.ActOnReturnStmt(ReturnLoc, R.take()); } +// needSpaceAsmToken - This function handles whitespace around asm punctuation. +// Returns true if a space should be emitted. +static inline bool needSpaceAsmToken(Token currTok) { + static Token prevTok; + + // No need for space after prevToken. + switch(prevTok.getKind()) { + default: + break; + case tok::l_square: + case tok::r_square: + case tok::l_brace: + case tok::r_brace: + case tok::colon: + prevTok = currTok; + return false; + } + + // No need for a space before currToken. + switch(currTok.getKind()) { + default: + break; + case tok::l_square: + case tok::r_square: + case tok::l_brace: + case tok::r_brace: + case tok::comma: + case tok::colon: + prevTok = currTok; + return false; + } + prevTok = currTok; + return true; +} + /// ParseMicrosoftAsmStatement. When -fms-extensions/-fasm-blocks is enabled, /// this routine is called to collect the tokens for an MS asm statement. /// @@ -1703,22 +1738,23 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { // does MSVC do here? break; } - } else if (InBraces && Tok.is(tok::r_brace) && - BraceCount == savedBraceCount + 1) { + } + if (!InAsmComment && InBraces && Tok.is(tok::r_brace) && + BraceCount == (savedBraceCount + 1)) { // Consume the closing brace, and finish EndLoc = ConsumeBrace(); break; } - AsmToks.push_back(Tok); - // Consume the next token; make sure we don't modify the brace count etc. // if we are in a comment. EndLoc = TokLoc; if (InAsmComment) PP.Lex(Tok); - else + else { + AsmToks.push_back(Tok); ConsumeAnyToken(); + } TokLoc = Tok.getLocation(); ++NumTokensRead; } while (1); @@ -1747,14 +1783,15 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { SmallString<512> TokenBuf; TokenBuf.resize(512); unsigned AsmLineNum = 0; - for (unsigned i = 0, e = AsmToks.size(); i < e; i++) { + for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) { const char *ThisTokBuf = &TokenBuf[0]; bool StringInvalid = false; unsigned ThisTokLen = Lexer::getSpelling(AsmToks[i], ThisTokBuf, PP.getSourceManager(), PP.getLangOpts(), &StringInvalid); - if (i && (!AsmLineNum || i != LineEnds[AsmLineNum-1])) - Asm += ' '; // FIXME: Too much whitespace around punctuation + if (i && (!AsmLineNum || i != LineEnds[AsmLineNum-1]) && + needSpaceAsmToken(AsmToks[i])) + Asm += ' '; Asm += StringRef(ThisTokBuf, ThisTokLen); if (i + 1 == LineEnds[AsmLineNum] && i + 1 != AsmToks.size()) { Asm += '\n'; @@ -1766,7 +1803,7 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { // (or possibly in addition to the) AsmString. Sema is going to interact with // MC to determine Constraints, Clobbers, etc., which would be simplest to // do with the tokens. - std::string AsmString = Asm.data(); + std::string AsmString = Asm.c_str(); return Actions.ActOnMSAsmStmt(AsmLoc, AsmString, EndLoc); } diff --git a/test/Parser/ms-inline-asm.c b/test/Parser/ms-inline-asm.c index b1af23e472..3a1efb0984 100644 --- a/test/Parser/ms-inline-asm.c +++ b/test/Parser/ms-inline-asm.c @@ -20,6 +20,13 @@ int t6() { __asm int 4 return 10; } -int t7() { // expected-note {{to match this}} +int t7() { + __asm { + push ebx + mov ebx, 0x07 + pop ebx + } +} +int t_fail() { // expected-note {{to match this}} __asm __asm { // expected-error 3 {{expected}} expected-note {{to match this}} |