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

llvm-svn: 161518
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 80f58b9..a8a06a9 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/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/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 6b211b0..90d5840 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/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());
 }