Teach TryAnnotateTypeOrScopeToken to deal with already-annotated
scope specifiers.  Fix a tentative parsing bug that came up in LLVM.
Incidentally fixes some random FIXMEs in an existing testcase.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91734 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
index dabd065..f521bc3 100644
--- a/lib/Parse/ParseTentative.cpp
+++ b/lib/Parse/ParseTentative.cpp
@@ -680,10 +680,10 @@
     // Otherwise, not a typename.
     return TPResult::False();
 
-  case tok::coloncolon:   // ::foo::bar
-      if (NextToken().is(tok::kw_new) ||    // ::new
-          NextToken().is(tok::kw_delete))   // ::delete
-        return TPResult::False();
+  case tok::coloncolon:     // ::foo::bar
+    if (NextToken().is(tok::kw_new) ||    // ::new
+        NextToken().is(tok::kw_delete))   // ::delete
+      return TPResult::False();
 
     // Annotate typenames and C++ scope specifiers.  If we get one, just
     // recurse to handle whatever we get.
@@ -750,6 +750,12 @@
   case tok::kw___forceinline:
     return TPResult::True();
 
+  case tok::annot_cxxscope: // foo::bar or ::foo::bar, but already parsed
+    // We've already annotated a scope; try to annotate a type.
+    if (!(TryAnnotateTypeOrScopeToken() && Tok.is(tok::annot_typename)))
+      return TPResult::False();
+    // If that succeeded, fallthrough into the generic simple-type-id case.
+
     // The ambiguity resides in a simple-type-specifier/typename-specifier
     // followed by a '('. The '(' could either be the start of:
     //
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index a864e7c..52c0153 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -880,7 +880,7 @@
 /// as the current tokens, so only call it in contexts where these are invalid.
 bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
   assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon)
-          || Tok.is(tok::kw_typename)) &&
+          || Tok.is(tok::kw_typename) || Tok.is(tok::annot_cxxscope)) &&
          "Cannot be a type or scope token!");
 
   if (Tok.is(tok::kw_typename)) {
@@ -935,6 +935,9 @@
     return true;
   }
 
+  // Remembers whether the token was originally a scope annotation.
+  bool wasScopeAnnotation = Tok.is(tok::annot_cxxscope);
+
   CXXScopeSpec SS;
   if (getLang().CPlusPlus)
     ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, EnteringContext);
@@ -1017,9 +1020,11 @@
   Tok.setAnnotationValue(SS.getScopeRep());
   Tok.setAnnotationRange(SS.getRange());
 
-  // In case the tokens were cached, have Preprocessor replace them with the
-  // annotation token.
-  PP.AnnotateCachedTokens(Tok);
+  // In case the tokens were cached, have Preprocessor replace them
+  // with the annotation token.  We don't need to do this if we've
+  // just reverted back to the state we were in before being called.
+  if (!wasScopeAnnotation)
+    PP.AnnotateCachedTokens(Tok);
   return true;
 }