Convert "#pragma unused(...)" into tokens for the parser.
This allows us to cache a "#pragma unused" that occurs inside an inline C++ member function.
Fixes rdar://8829590&8770988.

llvm-svn: 123666
diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp
index 42c1c5f..90c7d76 100644
--- a/clang/lib/Parse/ParsePragma.cpp
+++ b/clang/lib/Parse/ParsePragma.cpp
@@ -17,6 +17,17 @@
 #include "clang/Lex/Preprocessor.h"
 using namespace clang;
 
+/// \brief Handle the annotation token produced for #pragma unused(...)
+///
+/// Each annot_pragma_unused is followed by the argument token so e.g.
+/// "#pragma unused(x,y)" becomes:
+/// annot_pragma_unused 'x' annot_pragma_unused 'y'
+void Parser::HandlePragmaUnused() {
+  assert(Tok.is(tok::annot_pragma_unused));
+  SourceLocation UnusedLoc = ConsumeToken();
+  Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
+  ConsumeToken(); // The argument token.
+}
 
 // #pragma GCC visibility comes in two variants:
 //   'push' '(' [visibility] ')'
@@ -301,9 +312,20 @@
   assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
   assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
 
-  // Perform the action to handle the pragma.
-  Actions.ActOnPragmaUnused(Identifiers.data(), Identifiers.size(),
-                            parser.getCurScope(), UnusedLoc, LParenLoc, RParenLoc);
+  // For each identifier token, insert into the token stream a
+  // annot_pragma_unused token followed by the identifier token.
+  // This allows us to cache a "#pragma unused" that occurs inside an inline
+  // C++ member function.
+
+  Token *Toks = new Token[2*Identifiers.size()];
+  for (unsigned i=0; i != Identifiers.size(); i++) {
+    Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
+    pragmaUnusedTok.startToken();
+    pragmaUnusedTok.setKind(tok::annot_pragma_unused);
+    pragmaUnusedTok.setLocation(UnusedLoc);
+    idTok = Identifiers[i];
+  }
+  PP.EnterTokenStream(Toks, 2*Identifiers.size(), /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
 }
 
 // #pragma weak identifier
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index b1d40d2..113b266 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -465,6 +465,12 @@
 
   StmtVector Stmts(Actions);
   while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+
+    if (Tok.is(tok::annot_pragma_unused)) {
+      HandlePragmaUnused();
+      continue;
+    }
+
     StmtResult R;
     if (Tok.isNot(tok::kw___extension__)) {
       R = ParseStatementOrDeclaration(Stmts, false);
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index 473c6ad..47c6237 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -404,6 +404,10 @@
 /// ParseTopLevelDecl - Parse one top-level declaration, return whatever the
 /// action tells us to.  This returns true if the EOF was encountered.
 bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
+
+  while (Tok.is(tok::annot_pragma_unused))
+    HandlePragmaUnused();
+
   Result = DeclGroupPtrTy();
   if (Tok.is(tok::eof)) {
     Actions.ActOnEndOfTranslationUnit();