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;
}
}