diff options
-rw-r--r-- | include/clang/AST/Stmt.h | 7 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 2 | ||||
-rw-r--r-- | lib/AST/Stmt.cpp | 9 | ||||
-rw-r--r-- | lib/Parse/ParseStmt.cpp | 61 | ||||
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 36 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 11 |
6 files changed, 53 insertions, 73 deletions
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 1b5d45317d..5a082b7ecf 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -1627,13 +1627,16 @@ class MSAsmStmt : public Stmt { bool IsVolatile; unsigned NumAsmToks; + unsigned NumLineEnds; Token *AsmToks; + unsigned *LineEnds; Stmt **Exprs; public: MSAsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple, - bool isvolatile, ArrayRef<Token> asmtoks, std::string &asmstr, + bool isvolatile, ArrayRef<Token> asmtoks, + ArrayRef<unsigned> lineends, std::string &asmstr, SourceLocation endloc); SourceLocation getAsmLoc() const { return AsmLoc; } @@ -1643,6 +1646,8 @@ public: unsigned getNumAsmToks() { return NumAsmToks; } Token *getAsmToks() { return AsmToks; } + unsigned getNumLineEnds() { return NumLineEnds; } + unsigned *getLineEnds() { return LineEnds; } bool isVolatile() const { return IsVolatile; } void setVolatile(bool V) { IsVolatile = V; } diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 2dacdd74f6..fe8d297db0 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -2544,7 +2544,7 @@ public: StmtResult ActOnMSAsmStmt(SourceLocation AsmLoc, ArrayRef<Token> AsmToks, - std::string &AsmString, + ArrayRef<unsigned> LineEnds, SourceLocation EndLoc); VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType, diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index 2894720b76..e5ff75eac6 100644 --- a/lib/AST/Stmt.cpp +++ b/lib/AST/Stmt.cpp @@ -585,14 +585,19 @@ AsmStmt::AsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple, MSAsmStmt::MSAsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple, bool isvolatile, ArrayRef<Token> asmtoks, - std::string &asmstr, SourceLocation endloc) + ArrayRef<unsigned> lineends, std::string &asmstr, + SourceLocation endloc) : Stmt(MSAsmStmtClass), AsmLoc(asmloc), EndLoc(endloc), AsmStr(asmstr), IsSimple(issimple), IsVolatile(isvolatile), - NumAsmToks(asmtoks.size()) { + NumAsmToks(asmtoks.size()), NumLineEnds(lineends.size()) { AsmToks = new (C) Token[NumAsmToks]; for (unsigned i = 0, e = NumAsmToks; i != e; ++i) AsmToks[i] = asmtoks[i]; + + LineEnds = new (C) unsigned[NumLineEnds]; + for (unsigned i = 0, e = NumLineEnds; i != e; ++i) + LineEnds[i] = lineends[i]; } ObjCForCollectionStmt::ObjCForCollectionStmt(Stmt *Elem, Expr *Collect, diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 56e87e4904..d2e4309c3f 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -1638,41 +1638,6 @@ 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. /// @@ -1795,31 +1760,9 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { EndLoc = ConsumeToken(); } while (1); - // Collect the tokens into a string - SmallString<512> Asm; - SmallString<512> TokenBuf; - TokenBuf.resize(512); - unsigned AsmLineNum = 0; - 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]) && - needSpaceAsmToken(AsmToks[i])) - Asm += ' '; - Asm += StringRef(ThisTokBuf, ThisTokLen); - if (i + 1 == LineEnds[AsmLineNum] && i + 1 != AsmToks.size()) { - Asm += '\n'; - ++AsmLineNum; - } - } - // FIXME: We should be passing source locations for better diagnostics. - std::string AsmString = Asm.c_str(); - return Actions.ActOnMSAsmStmt(AsmLoc, llvm::makeArrayRef(AsmToks), AsmString, - EndLoc); + return Actions.ActOnMSAsmStmt(AsmLoc, llvm::makeArrayRef(AsmToks), + llvm::makeArrayRef(LineEnds), EndLoc); } /// ParseAsmStatement - Parse a GNU extended asm statement. diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 80f58b90c3..a8a06a93fc 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -2749,9 +2749,6 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, // needSpaceAsmToken - This function handles whitespace around asm punctuation. // Returns true if a space should be emitted. -// -// FIXME: This is replicated in ParseStmt.cpp. Maybe we should defer building -// the AsmString (i.e., non-patched AsmString) until Sema. static inline bool needSpaceAsmToken(Token currTok) { static Token prevTok; @@ -2840,13 +2837,42 @@ static std::string PatchMSAsmString(Sema &SemaRef, bool &IsSimple, return Res; } +// Build the unmodified MSAsmString. +static std::string buildMSAsmString(Sema &SemaRef, + ArrayRef<Token> AsmToks, + ArrayRef<unsigned> LineEnds) { + // Collect the tokens into a string + SmallString<512> Asm; + SmallString<512> TokenBuf; + TokenBuf.resize(512); + unsigned AsmLineNum = 0; + 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, SemaRef.getSourceManager(), + SemaRef.getLangOpts(), &StringInvalid); + 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'; + ++AsmLineNum; + } + } + return Asm.c_str(); +} + StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, ArrayRef<Token> AsmToks, - std::string &AsmString, + ArrayRef<unsigned> LineEnds, SourceLocation EndLoc) { // MS-style inline assembly is not fully supported, so emit a warning. Diag(AsmLoc, diag::warn_unsupported_msasm); + std::string AsmString = buildMSAsmString(*this, AsmToks, LineEnds); + bool IsSimple; // Rewrite operands to appease the AsmParser. std::string PatchedAsmString = @@ -2858,7 +2884,7 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, MSAsmStmt *NS = new (Context) MSAsmStmt(Context, AsmLoc, IsSimple, /* IsVolatile */ true, - AsmToks, AsmString, EndLoc); + AsmToks, LineEnds, AsmString, EndLoc); return Owned(NS); } diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 6b211b09a1..90d5840378 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -1186,9 +1186,9 @@ public: /// Subclasses may override this routine to provide different behavior. StmtResult RebuildMSAsmStmt(SourceLocation AsmLoc, ArrayRef<Token> AsmToks, - std::string &AsmString, + ArrayRef<unsigned> LineEnds, SourceLocation EndLoc) { - return getSema().ActOnMSAsmStmt(AsmLoc, AsmToks, AsmString, EndLoc); + return getSema().ActOnMSAsmStmt(AsmLoc, AsmToks, LineEnds, EndLoc); } /// \brief Build a new Objective-C \@try statement. @@ -5612,10 +5612,11 @@ StmtResult TreeTransform<Derived>::TransformMSAsmStmt(MSAsmStmt *S) { ArrayRef<Token> AsmToks = llvm::makeArrayRef(S->getAsmToks(), S->getNumAsmToks()); + ArrayRef<unsigned> LineEnds = + llvm::makeArrayRef(S->getLineEnds(), S->getNumLineEnds()); + // No need to transform the asm string literal. - return getDerived().RebuildMSAsmStmt(S->getAsmLoc(), - AsmToks, - *S->getAsmString(), + return getDerived().RebuildMSAsmStmt(S->getAsmLoc(), AsmToks, LineEnds, S->getEndLoc()); } |