From a5ef584fd3d18da0c98342b4b6453948b7eb30d3 Mon Sep 17 00:00:00 2001
From: Peter Collingbourne <peter@pcc.me.uk>
Date: Tue, 22 Feb 2011 13:49:06 +0000
Subject: [PATCH] Reimplement __pragma support using a TokenLexer

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126221 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/Lex/Preprocessor.h |  3 --
 lib/Lex/PPDirectives.cpp         |  1 +
 lib/Lex/Pragma.cpp               | 65 ++++++++++++++------------------
 3 files changed, 30 insertions(+), 39 deletions(-)

diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index 018f7e9c8c..9005adc6ad 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/include/clang/Lex/Preprocessor.h
@@ -942,9 +942,6 @@ private:
   /// is not enclosed within a string literal.
   void HandleMicrosoft__pragma(Token &Tok);
 
-  void Handle_Pragma(unsigned Introducer, const std::string &StrVal, 
-                     SourceLocation PragmaLoc, SourceLocation RParenLoc);
-
   /// EnterSourceFileWithLexer - Add a lexer to the top of the include stack and
   /// start lexing tokens from it instead of the current buffer.
   void EnterSourceFileWithLexer(Lexer *TheLexer, const DirectoryLookup *Dir);
diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp
index f92fa038a3..3e871ae7ab 100644
--- a/lib/Lex/PPDirectives.cpp
+++ b/lib/Lex/PPDirectives.cpp
@@ -86,6 +86,7 @@ void Preprocessor::DiscardUntilEndOfDirective() {
   Token Tmp;
   do {
     LexUnexpandedToken(Tmp);
+    assert(Tmp.isNot(tok::eof) && "EOF seen while discarding directive tokens");
   } while (Tmp.isNot(tok::eom));
 }
 
diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp
index 31e777604e..80d3bb1d27 100644
--- a/lib/Lex/Pragma.cpp
+++ b/lib/Lex/Pragma.cpp
@@ -175,7 +175,22 @@ void Preprocessor::Handle_Pragma(Token &Tok) {
     }
   }
   
-  Handle_Pragma(PIK__Pragma, StrVal, PragmaLoc, RParenLoc);
+  // Plop the string (including the newline and trailing null) into a buffer
+  // where we can lex it.
+  Token TmpTok;
+  TmpTok.startToken();
+  CreateString(&StrVal[0], StrVal.size(), TmpTok);
+  SourceLocation TokLoc = TmpTok.getLocation();
+
+  // Make and enter a lexer object so that we lex and expand the tokens just
+  // like any others.
+  Lexer *TL = Lexer::Create_PragmaLexer(TokLoc, PragmaLoc, RParenLoc,
+                                        StrVal.size(), *this);
+
+  EnterSourceFileWithLexer(TL, 0);
+
+  // With everything set up, lex this as a #pragma directive.
+  HandlePragmaDirective(PIK__Pragma);
 
   // Finally, return whatever came after the pragma directive.
   return Lex(Tok);
@@ -194,16 +209,16 @@ void Preprocessor::HandleMicrosoft__pragma(Token &Tok) {
     return;
   }
 
-  // Get the tokens enclosed within the __pragma().
+  // Get the tokens enclosed within the __pragma(), as well as the final ')'.
   llvm::SmallVector<Token, 32> PragmaToks;
   int NumParens = 0;
   Lex(Tok);
   while (Tok.isNot(tok::eof)) {
+    PragmaToks.push_back(Tok);
     if (Tok.is(tok::l_paren))
       NumParens++;
     else if (Tok.is(tok::r_paren) && NumParens-- == 0)
       break;
-    PragmaToks.push_back(Tok);
     Lex(Tok);
   }
 
@@ -212,45 +227,23 @@ void Preprocessor::HandleMicrosoft__pragma(Token &Tok) {
     return;
   }
 
-  // Build the pragma string.
-  std::string StrVal = " ";
-  for (llvm::SmallVector<Token, 32>::iterator I =
-       PragmaToks.begin(), E = PragmaToks.end(); I != E; ++I) {
-    StrVal += getSpelling(*I);
-  }
-  
-  SourceLocation RParenLoc = Tok.getLocation();
-
-  Handle_Pragma(PIK___pragma, StrVal, PragmaLoc, RParenLoc);
+  PragmaToks.front().setFlag(Token::LeadingSpace);
 
-  // Finally, return whatever came after the pragma directive.
-  return Lex(Tok);
-}
+  // Replace the ')' with an EOM to mark the end of the pragma.
+  PragmaToks.back().setKind(tok::eom);
 
-void Preprocessor::Handle_Pragma(unsigned Introducer,
-                                 const std::string &StrVal,
-                                 SourceLocation PragmaLoc,
-                                 SourceLocation RParenLoc) {
+  Token *TokArray = new Token[PragmaToks.size()];
+  std::copy(PragmaToks.begin(), PragmaToks.end(), TokArray);
 
-  // Plop the string (including the newline and trailing null) into a buffer
-  // where we can lex it.
-  Token TmpTok;
-  TmpTok.startToken();
-  CreateString(&StrVal[0], StrVal.size(), TmpTok);
-  SourceLocation TokLoc = TmpTok.getLocation();
-
-  // Make and enter a lexer object so that we lex and expand the tokens just
-  // like any others.
-  Lexer *TL = Lexer::Create_PragmaLexer(TokLoc, PragmaLoc, RParenLoc,
-                                        StrVal.size(), *this);
-
-  EnterSourceFileWithLexer(TL, 0);
+  // Push the tokens onto the stack.
+  EnterTokenStream(TokArray, PragmaToks.size(), true, true);
 
   // With everything set up, lex this as a #pragma directive.
-  HandlePragmaDirective(Introducer);
-}
-
+  HandlePragmaDirective(PIK___pragma);
 
+  // Finally, return whatever came after the pragma directive.
+  return Lex(Tok);
+}
 
 /// HandlePragmaOnce - Handle #pragma once.  OnceTok is the 'once'.
 ///
-- 
2.40.0