Make parsing a semantic analysis a little more robust following Sema
failures that involve malformed types, e.g., "typename X::foo" where
"foo" isn't a type, or "std::vector<void>" that doens't instantiate
properly.

Similarly, be a bit smarter in our handling of ambiguities that occur
in Sema::getTypeName, to eliminate duplicate error messages about
ambiguous name lookup.

This eliminates two XFAILs in test/SemaCXX, one of which was crying
out to us, trying to tell us that we were producing repeated error
messages.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68251 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 11658d4..e233a22 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -558,8 +558,11 @@
     }
         
     case tok::annot_typename: {
-      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
-                                     Tok.getAnnotationValue());
+      if (Tok.getAnnotationValue())
+        isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
+                                       Tok.getAnnotationValue());
+      else
+        DS.SetTypeSpecError();
       DS.SetRangeEnd(Tok.getAnnotationEndLoc());
       ConsumeToken(); // The typename
       
@@ -648,9 +651,7 @@
 
       // Turn the template-id annotation token into a type annotation
       // token, then try again to parse it as a type-specifier.
-      if (AnnotateTemplateIdTokenAsType())
-        DS.SetTypeSpecError();
-
+      AnnotateTemplateIdTokenAsType();
       continue;
     }
 
@@ -915,8 +916,11 @@
       
   // simple-type-specifier:
   case tok::annot_typename: {
-    isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
-                                   Tok.getAnnotationValue());
+    if (Tok.getAnnotationValue())
+      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
+                                     Tok.getAnnotationValue());
+    else
+      DS.SetTypeSpecError();
     DS.SetRangeEnd(Tok.getAnnotationEndLoc());
     ConsumeToken(); // The typename
     
@@ -1893,11 +1897,11 @@
           // FIXME: Inaccurate.
           SourceLocation NameLoc = Tok.getLocation();
           SourceLocation EndLoc;
-          if (TypeTy *Type = ParseClassName(EndLoc)) {
-            D.setDestructor(Type, TildeLoc, NameLoc);
-          } else {
+          TypeResult Type = ParseClassName(EndLoc);
+          if (Type.isInvalid())
             D.SetIdentifier(0, TildeLoc);
-          }
+          else
+            D.setDestructor(Type.get(), TildeLoc, NameLoc);
         } else {
           Diag(Tok, diag::err_expected_class_name);
           D.SetIdentifier(0, TildeLoc);
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 663fea5..1cf4a8f 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -301,21 +301,23 @@
 ///         identifier
 ///         simple-template-id
 /// 
-Parser::TypeTy *Parser::ParseClassName(SourceLocation &EndLocation,
-                                       const CXXScopeSpec *SS) {
+Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation,
+                                          const CXXScopeSpec *SS) {
   // Check whether we have a template-id that names a type.
   if (Tok.is(tok::annot_template_id)) {
     TemplateIdAnnotation *TemplateId 
       = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
     if (TemplateId->Kind == TNK_Type_template) {
-      if (AnnotateTemplateIdTokenAsType(SS))
-        return 0;
+      AnnotateTemplateIdTokenAsType(SS);
 
       assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
       TypeTy *Type = Tok.getAnnotationValue();
       EndLocation = Tok.getAnnotationEndLoc();
       ConsumeToken();
-      return Type;
+
+      if (Type)
+        return Type;
+      return true;
     }
 
     // Fall through to produce an error below.
@@ -323,7 +325,7 @@
 
   if (Tok.isNot(tok::identifier)) {
     Diag(Tok, diag::err_expected_class_name);
-    return 0;
+    return true;
   }
 
   // We have an identifier; check whether it is actually a type.
@@ -331,7 +333,7 @@
                                      Tok.getLocation(), CurScope, SS);
   if (!Type) {
     Diag(Tok, diag::err_expected_class_name);
-    return 0;
+    return true;
   }
 
   // Consume the identifier.
@@ -592,7 +594,7 @@
     if (IsVirtual) {
       // Complain about duplicate 'virtual'
       Diag(VirtualLoc, diag::err_dup_virtual)
-        << SourceRange(VirtualLoc, VirtualLoc);
+        << CodeModificationHint::CreateRemoval(SourceRange(VirtualLoc));
     }
 
     IsVirtual = true;
@@ -607,8 +609,8 @@
 
   // Parse the class-name.
   SourceLocation EndLocation;
-  TypeTy *BaseType = ParseClassName(EndLocation, &SS);
-  if (!BaseType)
+  TypeResult BaseType = ParseClassName(EndLocation, &SS);
+  if (BaseType.isInvalid())
     return true;
   
   // Find the complete source range for the base-specifier.  
@@ -617,7 +619,7 @@
   // Notify semantic analysis that we have parsed a complete
   // base-specifier.
   return Actions.ActOnBaseSpecifier(ClassDecl, Range, IsVirtual, Access,
-                                    BaseType, BaseLoc);
+                                    BaseType.get(), BaseLoc);
 }
 
 /// getAccessSpecifierIfPresent - Determine whether the next token is
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 2c6963a..5865771 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -148,12 +148,11 @@
 
       if (TemplateId->Kind == TNK_Type_template || 
           TemplateId->Kind == TNK_Dependent_template_name) {
-        if (AnnotateTemplateIdTokenAsType(&SS))
-          SS.clear();
+        AnnotateTemplateIdTokenAsType(&SS);
+        SS.clear();
 
         assert(Tok.is(tok::annot_typename) && 
                "AnnotateTemplateIdTokenAsType isn't working");
-
         Token TypeToken = Tok;
         ConsumeToken();
         assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
@@ -163,12 +162,15 @@
           SS.setBeginLoc(TypeToken.getLocation());
           HasScopeSpecifier = true;
         }
-
-        SS.setScopeRep(
-          Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, 
-                                              TypeToken.getAnnotationValue(),
-                                              TypeToken.getAnnotationRange(),
-                                              CCLoc));
+        
+        if (TypeToken.getAnnotationValue())
+          SS.setScopeRep(
+            Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, 
+                                                TypeToken.getAnnotationValue(),
+                                                TypeToken.getAnnotationRange(),
+                                                CCLoc));
+        else
+          SS.setScopeRep(0);
         SS.setEndLoc(CCLoc);
         continue;
       } else
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 45d148e..0f9bcd2 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -588,8 +588,10 @@
 /// \brief Replaces a template-id annotation token with a type
 /// annotation token.
 ///
-/// \returns true if there was an error, false otherwise.
-bool Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) {
+/// If there was a failure when forming the type from the template-id,
+/// a type annotation token will still be created, but will have a
+/// NULL type pointer to signify an error.
+void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) {
   assert(Tok.is(tok::annot_template_id) && "Requires template-id tokens");
 
   TemplateIdAnnotation *TemplateId 
@@ -610,16 +612,9 @@
                                   TemplateArgsPtr,
                                   TemplateId->getTemplateArgLocations(),
                                   TemplateId->RAngleLoc);
-  if (Type.isInvalid()) {
-    // FIXME: better recovery?
-    ConsumeToken();
-    TemplateId->Destroy();
-    return true;
-  }
-
   // Create the new "type" annotation token.
   Tok.setKind(tok::annot_typename);
-  Tok.setAnnotationValue(Type.get());
+  Tok.setAnnotationValue(Type.isInvalid()? 0 : Type.get());
   if (SS && SS->isNotEmpty()) // it was a C++ qualified type name.
     Tok.setLocation(SS->getBeginLoc());
 
@@ -629,8 +624,6 @@
   // class template specialization again.
   PP.ReplaceLastTokenWithAnnotation(Tok);
   TemplateId->Destroy();
-
-  return false;
 }
 
 /// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]).
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 17eca37..8903da2 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -851,22 +851,22 @@
         return false;
       }
 
-      if (AnnotateTemplateIdTokenAsType(0))
-        return false;
-
+      AnnotateTemplateIdTokenAsType(0);
       assert(Tok.is(tok::annot_typename) && 
              "AnnotateTemplateIdTokenAsType isn't working properly");
-      Ty = Actions.ActOnTypenameType(TypenameLoc, SS, SourceLocation(),
-                                     Tok.getAnnotationValue());
+      if (Tok.getAnnotationValue())
+        Ty = Actions.ActOnTypenameType(TypenameLoc, SS, SourceLocation(),
+                                       Tok.getAnnotationValue());
+      else
+        Ty = true;
     } else {
       Diag(Tok, diag::err_expected_type_name_after_typename)
         << SS.getRange();
       return false;
     }
 
-    // FIXME: better error recovery!
     Tok.setKind(tok::annot_typename);
-    Tok.setAnnotationValue(Ty.get());
+    Tok.setAnnotationValue(Ty.isInvalid()? 0 : Ty.get());
     Tok.setAnnotationEndLoc(Tok.getLocation());
     Tok.setLocation(TypenameLoc);
     PP.AnnotateCachedTokens(Tok);
@@ -925,7 +925,8 @@
       // template-id annotation in a context where we weren't allowed
       // to produce a type annotation token. Update the template-id
       // annotation token to a type annotation token now.
-      return !AnnotateTemplateIdTokenAsType(&SS);
+      AnnotateTemplateIdTokenAsType(&SS);
+      return true;
     }
   }