[ms-inline asm] Refactor the logic to generate the AsmString into Sema.  No
functional change intended.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161518 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index 1b5d453..5a082b7 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -1627,13 +1627,16 @@
   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 @@
 
   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 2dacdd7..fe8d297 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -2544,7 +2544,7 @@
 
   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 2894720..e5ff75e 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -585,14 +585,19 @@
 
 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 56e87e4..d2e4309 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -1638,41 +1638,6 @@
   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 @@
     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 80f58b9..a8a06a9 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -2749,9 +2749,6 @@
 
 // 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 @@
   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 @@
 
   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 6b211b0..90d5840 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -1186,9 +1186,9 @@
   /// 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 @@
 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());
 }