Update Parser::ParseTypeName to return a TypeResult, which also tells

us whether there was an error in trying to parse a type-name (type-id
in C++). This allows propagation of errors further in the compiler,
suppressing more bogus error messages.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64922 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Douglas Gregor 2009-02-18 17:45:20 +00:00
Родитель e53f8206eb
Коммит 809070a886
7 изменённых файлов: 92 добавлений и 48 удалений

Просмотреть файл

@ -105,6 +105,7 @@ public:
typedef Action::StmtResult StmtResult; typedef Action::StmtResult StmtResult;
typedef Action::BaseResult BaseResult; typedef Action::BaseResult BaseResult;
typedef Action::MemInitResult MemInitResult; typedef Action::MemInitResult MemInitResult;
typedef Action::TypeResult TypeResult;
typedef Action::OwningExprResult OwningExprResult; typedef Action::OwningExprResult OwningExprResult;
typedef Action::OwningStmtResult OwningStmtResult; typedef Action::OwningStmtResult OwningStmtResult;
@ -912,8 +913,7 @@ private:
TPResult TryParseFunctionDeclarator(); TPResult TryParseFunctionDeclarator();
TPResult TryParseBracketDeclarator(); TPResult TryParseBracketDeclarator();
TypeResult ParseTypeName();
TypeTy *ParseTypeName();
void ParseBlockId(); void ParseBlockId();
// EndLoc, if non-NULL, is filled with the location of the last token of // EndLoc, if non-NULL, is filled with the location of the last token of
// the attribute list. // the attribute list.

Просмотреть файл

@ -28,7 +28,7 @@ using namespace clang;
/// specifier-qualifier-list abstract-declarator[opt] /// specifier-qualifier-list abstract-declarator[opt]
/// ///
/// Called type-id in C++. /// Called type-id in C++.
Parser::TypeTy *Parser::ParseTypeName() { Action::TypeResult Parser::ParseTypeName() {
// Parse the common declaration-specifiers piece. // Parse the common declaration-specifiers piece.
DeclSpec DS; DeclSpec DS;
ParseSpecifierQualifierList(DS); ParseSpecifierQualifierList(DS);
@ -37,7 +37,10 @@ Parser::TypeTy *Parser::ParseTypeName() {
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
ParseDeclarator(DeclaratorInfo); ParseDeclarator(DeclaratorInfo);
return Actions.ActOnTypeName(CurScope, DeclaratorInfo).get(); if (DeclaratorInfo.getInvalidType())
return true;
return Actions.ActOnTypeName(CurScope, DeclaratorInfo);
} }
/// ParseAttributes - Parse a non-empty attributes list. /// ParseAttributes - Parse a non-empty attributes list.
@ -2383,8 +2386,10 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
} }
OwningExprResult Result(ParseCastExpression(true/*isUnaryExpression*/)); OwningExprResult Result(ParseCastExpression(true/*isUnaryExpression*/));
if (Result.isInvalid()) if (Result.isInvalid()) {
DS.SetTypeSpecError();
return; return;
}
const char *PrevSpec = 0; const char *PrevSpec = 0;
// Check for duplicate type specifiers. // Check for duplicate type specifiers.
@ -2400,24 +2405,32 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
SourceLocation LParenLoc = ConsumeParen(), RParenLoc; SourceLocation LParenLoc = ConsumeParen(), RParenLoc;
if (isTypeIdInParens()) { if (isTypeIdInParens()) {
TypeTy *Ty = ParseTypeName(); Action::TypeResult Ty = ParseTypeName();
assert(Ty && "Parser::ParseTypeofSpecifier(): missing type"); assert((Ty.isInvalid() || Ty.get()) &&
"Parser::ParseTypeofSpecifier(): missing type");
if (Tok.isNot(tok::r_paren)) { if (Tok.isNot(tok::r_paren)) {
MatchRHSPunctuation(tok::r_paren, LParenLoc); MatchRHSPunctuation(tok::r_paren, LParenLoc);
return; return;
} }
RParenLoc = ConsumeParen(); RParenLoc = ConsumeParen();
const char *PrevSpec = 0;
// Check for duplicate type specifiers (e.g. "int typeof(int)"). if (Ty.isInvalid())
if (DS.SetTypeSpecType(DeclSpec::TST_typeofType, StartLoc, PrevSpec, Ty)) DS.SetTypeSpecError();
Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec; else {
const char *PrevSpec = 0;
// Check for duplicate type specifiers (e.g. "int typeof(int)").
if (DS.SetTypeSpecType(DeclSpec::TST_typeofType, StartLoc, PrevSpec,
Ty.get()))
Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec;
}
} else { // we have an expression. } else { // we have an expression.
OwningExprResult Result(ParseExpression()); OwningExprResult Result(ParseExpression());
if (Result.isInvalid() || Tok.isNot(tok::r_paren)) { if (Result.isInvalid() || Tok.isNot(tok::r_paren)) {
MatchRHSPunctuation(tok::r_paren, LParenLoc); MatchRHSPunctuation(tok::r_paren, LParenLoc);
DS.SetTypeSpecError();
return; return;
} }
RParenLoc = ConsumeParen(); RParenLoc = ConsumeParen();

Просмотреть файл

@ -939,18 +939,22 @@ Parser::OwningExprResult Parser::ParseBuiltinPrimaryExpression() {
if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren)) if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
return ExprError(); return ExprError();
TypeTy *Ty = ParseTypeName(); TypeResult Ty = ParseTypeName();
if (Tok.isNot(tok::r_paren)) { if (Tok.isNot(tok::r_paren)) {
Diag(Tok, diag::err_expected_rparen); Diag(Tok, diag::err_expected_rparen);
return ExprError(); return ExprError();
} }
Res = Actions.ActOnVAArg(StartLoc, Expr.release(), Ty, ConsumeParen()); if (Ty.isInvalid())
Res = ExprError();
else
Res = Actions.ActOnVAArg(StartLoc, Expr.release(), Ty.get(),
ConsumeParen());
break; break;
} }
case tok::kw___builtin_offsetof: { case tok::kw___builtin_offsetof: {
SourceLocation TypeLoc = Tok.getLocation(); SourceLocation TypeLoc = Tok.getLocation();
TypeTy *Ty = ParseTypeName(); TypeResult Ty = ParseTypeName();
if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren)) if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
return ExprError(); return ExprError();
@ -1001,9 +1005,12 @@ Parser::OwningExprResult Parser::ParseBuiltinPrimaryExpression() {
Comps.back().LocEnd = Comps.back().LocEnd =
MatchRHSPunctuation(tok::r_square, Comps.back().LocStart); MatchRHSPunctuation(tok::r_square, Comps.back().LocStart);
} else if (Tok.is(tok::r_paren)) { } else if (Tok.is(tok::r_paren)) {
Res = Actions.ActOnBuiltinOffsetOf(CurScope, StartLoc, TypeLoc, Ty, if (Ty.isInvalid())
&Comps[0], Comps.size(), Res = ExprError();
ConsumeParen()); else
Res = Actions.ActOnBuiltinOffsetOf(CurScope, StartLoc, TypeLoc,
Ty.get(), &Comps[0],
Comps.size(), ConsumeParen());
break; break;
} else { } else {
// Error occurred. // Error occurred.
@ -1075,18 +1082,23 @@ Parser::OwningExprResult Parser::ParseBuiltinPrimaryExpression() {
break; break;
} }
case tok::kw___builtin_types_compatible_p: case tok::kw___builtin_types_compatible_p:
TypeTy *Ty1 = ParseTypeName(); TypeResult Ty1 = ParseTypeName();
if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren)) if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
return ExprError(); return ExprError();
TypeTy *Ty2 = ParseTypeName(); TypeResult Ty2 = ParseTypeName();
if (Tok.isNot(tok::r_paren)) { if (Tok.isNot(tok::r_paren)) {
Diag(Tok, diag::err_expected_rparen); Diag(Tok, diag::err_expected_rparen);
return ExprError(); return ExprError();
} }
Res = Actions.ActOnTypesCompatibleExpr(StartLoc, Ty1, Ty2, ConsumeParen());
if (Ty1.isInvalid() || Ty2.isInvalid())
Res = ExprError();
else
Res = Actions.ActOnTypesCompatibleExpr(StartLoc, Ty1.get(), Ty2.get(),
ConsumeParen());
break; break;
} }
@ -1129,7 +1141,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType,
} else if (ExprType >= CompoundLiteral && isTypeIdInParens()) { } else if (ExprType >= CompoundLiteral && isTypeIdInParens()) {
// Otherwise, this is a compound literal expression or cast expression. // Otherwise, this is a compound literal expression or cast expression.
TypeTy *Ty = ParseTypeName(); TypeResult Ty = ParseTypeName();
// Match the ')'. // Match the ')'.
if (Tok.is(tok::r_paren)) if (Tok.is(tok::r_paren))
@ -1142,17 +1154,21 @@ Parser::ParseParenExpression(ParenParseOption &ExprType,
Diag(OpenLoc, diag::ext_c99_compound_literal); Diag(OpenLoc, diag::ext_c99_compound_literal);
Result = ParseInitializer(); Result = ParseInitializer();
ExprType = CompoundLiteral; ExprType = CompoundLiteral;
if (!Result.isInvalid()) if (!Result.isInvalid() && !Ty.isInvalid())
return Actions.ActOnCompoundLiteral(OpenLoc, Ty, RParenLoc, return Actions.ActOnCompoundLiteral(OpenLoc, Ty.get(), RParenLoc,
move(Result)); move(Result));
return move(Result); return move(Result);
} }
if (ExprType == CastExpr) { if (ExprType == CastExpr) {
// Note that this doesn't parse the subsequence cast-expression, it just // Note that this doesn't parse the subsequent cast-expression, it just
// returns the parsed type to the callee. // returns the parsed type to the callee.
ExprType = CastExpr; ExprType = CastExpr;
CastTy = Ty;
if (Ty.isInvalid())
return ExprError();
CastTy = Ty.get();
return OwningExprResult(Actions); return OwningExprResult(Actions);
} }

Просмотреть файл

@ -211,7 +211,7 @@ Parser::OwningExprResult Parser::ParseCXXCasts() {
if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName)) if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName))
return ExprError(); return ExprError();
TypeTy *CastTy = ParseTypeName(); TypeResult CastTy = ParseTypeName();
SourceLocation RAngleBracketLoc = Tok.getLocation(); SourceLocation RAngleBracketLoc = Tok.getLocation();
if (ExpectAndConsume(tok::greater, diag::err_expected_greater)) if (ExpectAndConsume(tok::greater, diag::err_expected_greater))
@ -224,9 +224,10 @@ Parser::OwningExprResult Parser::ParseCXXCasts() {
OwningExprResult Result(ParseSimpleParenExpression(RParenLoc)); OwningExprResult Result(ParseSimpleParenExpression(RParenLoc));
if (!Result.isInvalid()) if (!Result.isInvalid() && !CastTy.isInvalid())
Result = Actions.ActOnCXXNamedCast(OpLoc, Kind, Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
LAngleBracketLoc, CastTy, RAngleBracketLoc, LAngleBracketLoc, CastTy.get(),
RAngleBracketLoc,
LParenLoc, Result.release(), RParenLoc); LParenLoc, Result.release(), RParenLoc);
return move(Result); return move(Result);
@ -253,16 +254,16 @@ Parser::OwningExprResult Parser::ParseCXXTypeid() {
OwningExprResult Result(Actions); OwningExprResult Result(Actions);
if (isTypeIdInParens()) { if (isTypeIdInParens()) {
TypeTy *Ty = ParseTypeName(); TypeResult Ty = ParseTypeName();
// Match the ')'. // Match the ')'.
MatchRHSPunctuation(tok::r_paren, LParenLoc); MatchRHSPunctuation(tok::r_paren, LParenLoc);
if (!Ty) if (Ty.isInvalid())
return ExprError(); return ExprError();
Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true, Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true,
Ty, RParenLoc); Ty.get(), RParenLoc);
} else { } else {
Result = ParseExpression(); Result = ParseExpression();
@ -919,9 +920,12 @@ Parser::OwningExprResult Parser::ParseUnaryTypeTrait()
// FIXME: Error reporting absolutely sucks! If the this fails to parse a type // FIXME: Error reporting absolutely sucks! If the this fails to parse a type
// there will be cryptic errors about mismatched parentheses and missing // there will be cryptic errors about mismatched parentheses and missing
// specifiers. // specifiers.
TypeTy *Ty = ParseTypeName(); TypeResult Ty = ParseTypeName();
SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen); SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen);
return Actions.ActOnUnaryTypeTrait(UTT, Loc, LParen, Ty, RParen); if (Ty.isInvalid())
return ExprError();
return Actions.ActOnUnaryTypeTrait(UTT, Loc, LParen, Ty.get(), RParen);
} }

Просмотреть файл

@ -629,8 +629,11 @@ Parser::TypeTy *Parser::ParseObjCTypeName(ObjCDeclSpec &DS) {
ParseObjCTypeQualifierList(DS); ParseObjCTypeQualifierList(DS);
TypeTy *Ty = 0; TypeTy *Ty = 0;
if (isTypeSpecifierQualifier()) if (isTypeSpecifierQualifier()) {
Ty = ParseTypeName(); TypeResult TypeSpec = ParseTypeName();
if (!TypeSpec.isInvalid())
Ty = TypeSpec.get();
}
if (Tok.is(tok::r_paren)) if (Tok.is(tok::r_paren))
ConsumeParen(); ConsumeParen();
@ -1627,12 +1630,15 @@ Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) {
SourceLocation LParenLoc = ConsumeParen(); SourceLocation LParenLoc = ConsumeParen();
TypeTy *Ty = ParseTypeName(); TypeResult Ty = ParseTypeName();
SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
return Owned(Actions.ParseObjCEncodeExpression(AtLoc, EncLoc, LParenLoc, Ty, if (Ty.isInvalid())
RParenLoc)); return ExprError();
return Owned(Actions.ParseObjCEncodeExpression(AtLoc, EncLoc, LParenLoc,
Ty.get(), RParenLoc));
} }
/// objc-protocol-expression /// objc-protocol-expression

Просмотреть файл

@ -240,9 +240,10 @@ Parser::DeclTy *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
if(Tok.is(tok::equal)) { if(Tok.is(tok::equal)) {
SourceLocation EqualLoc = ConsumeToken(); SourceLocation EqualLoc = ConsumeToken();
SourceLocation DefaultLoc = Tok.getLocation(); SourceLocation DefaultLoc = Tok.getLocation();
if (TypeTy *DefaultType = ParseTypeName()) TypeResult DefaultType = ParseTypeName();
if (!DefaultType.isInvalid())
Actions.ActOnTypeParameterDefault(TypeParam, EqualLoc, DefaultLoc, Actions.ActOnTypeParameterDefault(TypeParam, EqualLoc, DefaultLoc,
DefaultType); DefaultType.get());
} }
return TypeParam; return TypeParam;
@ -529,7 +530,10 @@ void *Parser::ParseTemplateArgument(bool &ArgIsType) {
// Therefore, we initially try to parse a type-id. // Therefore, we initially try to parse a type-id.
if (isCXXTypeId(TypeIdAsTemplateArgument)) { if (isCXXTypeId(TypeIdAsTemplateArgument)) {
ArgIsType = true; ArgIsType = true;
return ParseTypeName(); TypeResult TypeArg = ParseTypeName();
if (TypeArg.isInvalid())
return 0;
return TypeArg.get();
} }
OwningExprResult ExprArg = ParseAssignmentExpression(); OwningExprResult ExprArg = ParseAssignmentExpression();

Просмотреть файл

@ -29,7 +29,6 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS) {
QualType Result; QualType Result;
switch (DS.getTypeSpecType()) { switch (DS.getTypeSpecType()) {
default: assert(0 && "Unknown TypeSpecType!");
case DeclSpec::TST_void: case DeclSpec::TST_void:
Result = Context.VoidTy; Result = Context.VoidTy;
break; break;
@ -169,6 +168,8 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS) {
Result = Context.getTypeOfExpr(E); Result = Context.getTypeOfExpr(E);
break; break;
} }
case DeclSpec::TST_error:
return QualType();
} }
// Handle complex types. // Handle complex types.
@ -277,8 +278,11 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip) {
// We default to a dependent type initially. Can be modified by // We default to a dependent type initially. Can be modified by
// the first return statement. // the first return statement.
T = Context.DependentTy; T = Context.DependentTy;
else else {
T = ConvertDeclSpecToType(DS); T = ConvertDeclSpecToType(DS);
if (T.isNull())
return T;
}
break; break;
} }
@ -725,16 +729,13 @@ Sema::TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
assert(D.getIdentifier() == 0 && "Type name should have no identifier!"); assert(D.getIdentifier() == 0 && "Type name should have no identifier!");
QualType T = GetTypeForDeclarator(D, S); QualType T = GetTypeForDeclarator(D, S);
if (T.isNull())
assert(!T.isNull() && "GetTypeForDeclarator() returned null type"); return true;
// Check that there are no default arguments (C++ only). // Check that there are no default arguments (C++ only).
if (getLangOptions().CPlusPlus) if (getLangOptions().CPlusPlus)
CheckExtraCXXDefaultArguments(D); CheckExtraCXXDefaultArguments(D);
// In this context, we *do not* check D.getInvalidType(). If the declarator
// type was invalid, GetTypeForDeclarator() still returns a "valid" type,
// though it will not reflect the user specified type.
return T.getAsOpaquePtr(); return T.getAsOpaquePtr();
} }