Fix crash if base specifier parsing hits an invalid type annotation.

Also change type annotation representation from ParsedType to TypeResult
to make it clearer to consumers that they can represent invalid types.
This commit is contained in:
Richard Smith 2020-03-30 17:19:30 -07:00
parent 5074776de4
commit 3308732300
10 changed files with 53 additions and 44 deletions

View File

@ -763,13 +763,17 @@ public:
}
/// getTypeAnnotation - Read a parsed type out of an annotation token.
static ParsedType getTypeAnnotation(const Token &Tok) {
static TypeResult getTypeAnnotation(const Token &Tok) {
if (!Tok.getAnnotationValue())
return TypeError();
return ParsedType::getFromOpaquePtr(Tok.getAnnotationValue());
}
private:
static void setTypeAnnotation(Token &Tok, ParsedType T) {
Tok.setAnnotationValue(T.getAsOpaquePtr());
static void setTypeAnnotation(Token &Tok, TypeResult T) {
assert((T.isInvalid() || T.get()) &&
"produced a valid-but-null type annotation?");
Tok.setAnnotationValue(T.isInvalid() ? nullptr : T.get().getAsOpaquePtr());
}
static NamedDecl *getNonTypeAnnotation(const Token &Tok) {

View File

@ -667,6 +667,13 @@ public:
bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
unsigned &DiagID, ParsedType Rep,
const PrintingPolicy &Policy);
bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
unsigned &DiagID, TypeResult Rep,
const PrintingPolicy &Policy) {
if (Rep.isInvalid())
return SetTypeSpecError();
return SetTypeSpecType(T, Loc, PrevSpec, DiagID, Rep.get(), Policy);
}
bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
unsigned &DiagID, Decl *Rep, bool Owned,
const PrintingPolicy &Policy);

View File

@ -3217,16 +3217,12 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
if (Next.is(tok::annot_typename)) {
DS.getTypeSpecScope() = SS;
ConsumeAnnotationToken(); // The C++ scope.
if (Tok.getAnnotationValue()) {
ParsedType T = getTypeAnnotation(Tok);
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename,
Tok.getAnnotationEndLoc(),
PrevSpec, DiagID, T, Policy);
if (isInvalid)
break;
}
else
DS.SetTypeSpecError();
TypeResult T = getTypeAnnotation(Tok);
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename,
Tok.getAnnotationEndLoc(),
PrevSpec, DiagID, T, Policy);
if (isInvalid)
break;
DS.SetRangeEnd(Tok.getAnnotationEndLoc());
ConsumeAnnotationToken(); // The typename
}
@ -3294,13 +3290,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
if (DS.hasTypeSpecifier() && DS.hasTagDefinition())
goto DoneWithDeclSpec;
if (Tok.getAnnotationValue()) {
ParsedType T = getTypeAnnotation(Tok);
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
DiagID, T, Policy);
} else
DS.SetTypeSpecError();
TypeResult T = getTypeAnnotation(Tok);
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
DiagID, T, Policy);
if (isInvalid)
break;

View File

@ -1151,13 +1151,10 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
AnnotateTemplateIdTokenAsType(SS, /*IsClassName*/true);
assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
ParsedType Type = getTypeAnnotation(Tok);
TypeResult Type = getTypeAnnotation(Tok);
EndLocation = Tok.getAnnotationEndLoc();
ConsumeAnnotationToken();
if (Type)
return Type;
return true;
return Type;
}
// Fall through to produce an error below.
@ -1204,7 +1201,7 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
// Retrieve the type from the annotation token, consume that token, and
// return.
EndLocation = Tok.getAnnotationEndLoc();
ParsedType Type = getTypeAnnotation(Tok);
TypeResult Type = getTypeAnnotation(Tok);
ConsumeAnnotationToken();
return Type;
}
@ -3510,7 +3507,7 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
// : declype(...)
DeclSpec DS(AttrFactory);
// : template_name<...>
ParsedType TemplateTypeTy;
TypeResult TemplateTypeTy;
if (Tok.is(tok::identifier)) {
// Get the identifier. This may be a member name or a class name,
@ -3532,8 +3529,6 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
TemplateTypeTy = getTypeAnnotation(Tok);
ConsumeAnnotationToken();
if (!TemplateTypeTy)
return true;
} else {
Diag(Tok, diag::err_expected_member_or_base_name);
return true;
@ -3552,8 +3547,10 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
SourceLocation EllipsisLoc;
TryConsumeToken(tok::ellipsis, EllipsisLoc);
if (TemplateTypeTy.isInvalid())
return true;
return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II,
TemplateTypeTy, DS, IdLoc,
TemplateTypeTy.get(), DS, IdLoc,
InitList.get(), EllipsisLoc);
} else if(Tok.is(tok::l_paren)) {
BalancedDelimiterTracker T(*this, tok::l_paren);
@ -3563,8 +3560,10 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
ExprVector ArgExprs;
CommaLocsTy CommaLocs;
auto RunSignatureHelp = [&] {
if (TemplateTypeTy.isInvalid())
return QualType();
QualType PreferredType = Actions.ProduceCtorInitMemberSignatureHelp(
getCurScope(), ConstructorDecl, SS, TemplateTypeTy, ArgExprs, II,
getCurScope(), ConstructorDecl, SS, TemplateTypeTy.get(), ArgExprs, II,
T.getOpenLocation());
CalledSignatureHelp = true;
return PreferredType;
@ -3585,12 +3584,17 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
SourceLocation EllipsisLoc;
TryConsumeToken(tok::ellipsis, EllipsisLoc);
if (TemplateTypeTy.isInvalid())
return true;
return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II,
TemplateTypeTy, DS, IdLoc,
TemplateTypeTy.get(), DS, IdLoc,
T.getOpenLocation(), ArgExprs,
T.getCloseLocation(), EllipsisLoc);
}
if (TemplateTypeTy.isInvalid())
return true;
if (getLangOpts().CPlusPlus11)
return Diag(Tok, diag::err_expected_either) << tok::l_paren << tok::l_brace;
else

View File

@ -1455,7 +1455,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
break;
case tok::annot_typename:
if (isStartOfObjCClassMessageMissingOpenBracket()) {
ParsedType Type = getTypeAnnotation(Tok);
TypeResult Type = getTypeAnnotation(Tok);
// Fake up a Declarator to use with ActOnTypeName.
DeclSpec DS(AttrFactory);

View File

@ -2147,12 +2147,8 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
// type-name
case tok::annot_typename: {
if (getTypeAnnotation(Tok))
DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID,
getTypeAnnotation(Tok), Policy);
else
DS.SetTypeSpecError();
DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID,
getTypeAnnotation(Tok), Policy);
DS.SetRangeEnd(Tok.getAnnotationEndLoc());
ConsumeAnnotationToken();

View File

@ -2978,7 +2978,7 @@ bool Parser::isStartOfObjCClassMessageMissingOpenBracket() {
InMessageExpression)
return false;
ParsedType Type;
TypeResult Type;
if (Tok.is(tok::annot_typename))
Type = getTypeAnnotation(Tok);
@ -2988,7 +2988,8 @@ bool Parser::isStartOfObjCClassMessageMissingOpenBracket() {
else
return false;
if (!Type.get().isNull() && Type.get()->isObjCObjectOrInterfaceType()) {
// FIXME: Should not be querying properties of types from the parser.
if (Type.isUsable() && Type.get().get()->isObjCObjectOrInterfaceType()) {
const Token &AfterNext = GetLookAheadToken(2);
if (AfterNext.isOneOf(tok::colon, tok::r_square)) {
if (Tok.is(tok::identifier))

View File

@ -1321,7 +1321,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
LAngleLoc, TemplateArgsPtr, RAngleLoc);
Tok.setKind(tok::annot_typename);
setTypeAnnotation(Tok, Type.isInvalid() ? nullptr : Type.get());
setTypeAnnotation(Tok, Type);
if (SS.isNotEmpty())
Tok.setLocation(SS.getBeginLoc());
else if (TemplateKWLoc.isValid())
@ -1398,7 +1398,7 @@ void Parser::AnnotateTemplateIdTokenAsType(CXXScopeSpec &SS,
/*IsCtorOrDtorName*/ false, IsClassName);
// Create the new "type" annotation token.
Tok.setKind(tok::annot_typename);
setTypeAnnotation(Tok, Type.isInvalid() ? nullptr : Type.get());
setTypeAnnotation(Tok, Type);
if (SS.isNotEmpty()) // it was a C++ qualified type name.
Tok.setLocation(SS.getBeginLoc());
// End location stays the same

View File

@ -1902,7 +1902,7 @@ bool Parser::TryAnnotateTypeOrScopeToken() {
SourceLocation EndLoc = Tok.getLastLoc();
Tok.setKind(tok::annot_typename);
setTypeAnnotation(Tok, Ty.isInvalid() ? nullptr : Ty.get());
setTypeAnnotation(Tok, Ty);
Tok.setAnnotationEndLoc(EndLoc);
Tok.setLocation(TypenameLoc);
PP.AnnotateCachedTokens(Tok);

View File

@ -298,6 +298,11 @@ namespace ArrayMemberAccess {
}
}
namespace UndeclaredBaseTemplate {
template<class> struct imp;
template<class T> struct is_member_function_pointer : undeclared<imp<T>::member> {}; // expected-error {{unknown template name 'undeclared'}}
}
// PR11109 must appear at the end of the source file
class pr11109r3 { // expected-note{{to match this '{'}}
public // expected-error{{expected ':'}} expected-error{{expected '}'}} expected-error{{expected ';' after class}}