From 809070a886684cb5b92eb0e00a6581ab1fa6b17a Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 18 Feb 2009 17:45:20 +0000 Subject: [PATCH] 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 --- include/clang/Parse/Parser.h | 4 ++-- lib/Parse/ParseDecl.cpp | 31 +++++++++++++++++-------- lib/Parse/ParseExpr.cpp | 44 ++++++++++++++++++++++++------------ lib/Parse/ParseExprCXX.cpp | 20 +++++++++------- lib/Parse/ParseObjc.cpp | 16 +++++++++---- lib/Parse/ParseTemplate.cpp | 10 +++++--- lib/Sema/SemaType.cpp | 15 ++++++------ 7 files changed, 92 insertions(+), 48 deletions(-) diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 4c51e0508a..2432f445d9 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -105,6 +105,7 @@ public: typedef Action::StmtResult StmtResult; typedef Action::BaseResult BaseResult; typedef Action::MemInitResult MemInitResult; + typedef Action::TypeResult TypeResult; typedef Action::OwningExprResult OwningExprResult; typedef Action::OwningStmtResult OwningStmtResult; @@ -912,8 +913,7 @@ private: TPResult TryParseFunctionDeclarator(); TPResult TryParseBracketDeclarator(); - - TypeTy *ParseTypeName(); + TypeResult ParseTypeName(); void ParseBlockId(); // EndLoc, if non-NULL, is filled with the location of the last token of // the attribute list. diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 9974aea005..6e68b20fa5 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -28,7 +28,7 @@ using namespace clang; /// specifier-qualifier-list abstract-declarator[opt] /// /// Called type-id in C++. -Parser::TypeTy *Parser::ParseTypeName() { +Action::TypeResult Parser::ParseTypeName() { // Parse the common declaration-specifiers piece. DeclSpec DS; ParseSpecifierQualifierList(DS); @@ -37,7 +37,10 @@ Parser::TypeTy *Parser::ParseTypeName() { Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); 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. @@ -2383,8 +2386,10 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) { } OwningExprResult Result(ParseCastExpression(true/*isUnaryExpression*/)); - if (Result.isInvalid()) + if (Result.isInvalid()) { + DS.SetTypeSpecError(); return; + } const char *PrevSpec = 0; // Check for duplicate type specifiers. @@ -2400,24 +2405,32 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) { SourceLocation LParenLoc = ConsumeParen(), RParenLoc; 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)) { MatchRHSPunctuation(tok::r_paren, LParenLoc); return; } RParenLoc = ConsumeParen(); - const char *PrevSpec = 0; - // Check for duplicate type specifiers (e.g. "int typeof(int)"). - if (DS.SetTypeSpecType(DeclSpec::TST_typeofType, StartLoc, PrevSpec, Ty)) - Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec; + + if (Ty.isInvalid()) + DS.SetTypeSpecError(); + 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. OwningExprResult Result(ParseExpression()); if (Result.isInvalid() || Tok.isNot(tok::r_paren)) { MatchRHSPunctuation(tok::r_paren, LParenLoc); + DS.SetTypeSpecError(); return; } RParenLoc = ConsumeParen(); diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index d2e59ece35..5133af8f7f 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -939,18 +939,22 @@ Parser::OwningExprResult Parser::ParseBuiltinPrimaryExpression() { if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren)) return ExprError(); - TypeTy *Ty = ParseTypeName(); + TypeResult Ty = ParseTypeName(); if (Tok.isNot(tok::r_paren)) { Diag(Tok, diag::err_expected_rparen); 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; } case tok::kw___builtin_offsetof: { SourceLocation TypeLoc = Tok.getLocation(); - TypeTy *Ty = ParseTypeName(); + TypeResult Ty = ParseTypeName(); if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren)) return ExprError(); @@ -1001,9 +1005,12 @@ Parser::OwningExprResult Parser::ParseBuiltinPrimaryExpression() { Comps.back().LocEnd = MatchRHSPunctuation(tok::r_square, Comps.back().LocStart); } else if (Tok.is(tok::r_paren)) { - Res = Actions.ActOnBuiltinOffsetOf(CurScope, StartLoc, TypeLoc, Ty, - &Comps[0], Comps.size(), - ConsumeParen()); + if (Ty.isInvalid()) + Res = ExprError(); + else + Res = Actions.ActOnBuiltinOffsetOf(CurScope, StartLoc, TypeLoc, + Ty.get(), &Comps[0], + Comps.size(), ConsumeParen()); break; } else { // Error occurred. @@ -1075,18 +1082,23 @@ Parser::OwningExprResult Parser::ParseBuiltinPrimaryExpression() { break; } case tok::kw___builtin_types_compatible_p: - TypeTy *Ty1 = ParseTypeName(); + TypeResult Ty1 = ParseTypeName(); if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren)) return ExprError(); - TypeTy *Ty2 = ParseTypeName(); + TypeResult Ty2 = ParseTypeName(); if (Tok.isNot(tok::r_paren)) { Diag(Tok, diag::err_expected_rparen); 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; } @@ -1129,7 +1141,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, } else if (ExprType >= CompoundLiteral && isTypeIdInParens()) { // Otherwise, this is a compound literal expression or cast expression. - TypeTy *Ty = ParseTypeName(); + TypeResult Ty = ParseTypeName(); // Match the ')'. if (Tok.is(tok::r_paren)) @@ -1142,17 +1154,21 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, Diag(OpenLoc, diag::ext_c99_compound_literal); Result = ParseInitializer(); ExprType = CompoundLiteral; - if (!Result.isInvalid()) - return Actions.ActOnCompoundLiteral(OpenLoc, Ty, RParenLoc, + if (!Result.isInvalid() && !Ty.isInvalid()) + return Actions.ActOnCompoundLiteral(OpenLoc, Ty.get(), RParenLoc, move(Result)); return move(Result); } 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. ExprType = CastExpr; - CastTy = Ty; + + if (Ty.isInvalid()) + return ExprError(); + + CastTy = Ty.get(); return OwningExprResult(Actions); } diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index e8ef8ea61e..fb60bde4f1 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -211,7 +211,7 @@ Parser::OwningExprResult Parser::ParseCXXCasts() { if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName)) return ExprError(); - TypeTy *CastTy = ParseTypeName(); + TypeResult CastTy = ParseTypeName(); SourceLocation RAngleBracketLoc = Tok.getLocation(); if (ExpectAndConsume(tok::greater, diag::err_expected_greater)) @@ -224,9 +224,10 @@ Parser::OwningExprResult Parser::ParseCXXCasts() { OwningExprResult Result(ParseSimpleParenExpression(RParenLoc)); - if (!Result.isInvalid()) + if (!Result.isInvalid() && !CastTy.isInvalid()) Result = Actions.ActOnCXXNamedCast(OpLoc, Kind, - LAngleBracketLoc, CastTy, RAngleBracketLoc, + LAngleBracketLoc, CastTy.get(), + RAngleBracketLoc, LParenLoc, Result.release(), RParenLoc); return move(Result); @@ -253,16 +254,16 @@ Parser::OwningExprResult Parser::ParseCXXTypeid() { OwningExprResult Result(Actions); if (isTypeIdInParens()) { - TypeTy *Ty = ParseTypeName(); + TypeResult Ty = ParseTypeName(); // Match the ')'. MatchRHSPunctuation(tok::r_paren, LParenLoc); - if (!Ty) + if (Ty.isInvalid()) return ExprError(); Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true, - Ty, RParenLoc); + Ty.get(), RParenLoc); } else { Result = ParseExpression(); @@ -919,9 +920,12 @@ Parser::OwningExprResult Parser::ParseUnaryTypeTrait() // FIXME: Error reporting absolutely sucks! If the this fails to parse a type // there will be cryptic errors about mismatched parentheses and missing // specifiers. - TypeTy *Ty = ParseTypeName(); + TypeResult Ty = ParseTypeName(); 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); } diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index a147ee47e8..4ddddb3749 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -629,8 +629,11 @@ Parser::TypeTy *Parser::ParseObjCTypeName(ObjCDeclSpec &DS) { ParseObjCTypeQualifierList(DS); TypeTy *Ty = 0; - if (isTypeSpecifierQualifier()) - Ty = ParseTypeName(); + if (isTypeSpecifierQualifier()) { + TypeResult TypeSpec = ParseTypeName(); + if (!TypeSpec.isInvalid()) + Ty = TypeSpec.get(); + } if (Tok.is(tok::r_paren)) ConsumeParen(); @@ -1627,12 +1630,15 @@ Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) { SourceLocation LParenLoc = ConsumeParen(); - TypeTy *Ty = ParseTypeName(); + TypeResult Ty = ParseTypeName(); SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); - return Owned(Actions.ParseObjCEncodeExpression(AtLoc, EncLoc, LParenLoc, Ty, - RParenLoc)); + if (Ty.isInvalid()) + return ExprError(); + + return Owned(Actions.ParseObjCEncodeExpression(AtLoc, EncLoc, LParenLoc, + Ty.get(), RParenLoc)); } /// objc-protocol-expression diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index 52824f51c1..747a4de152 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -240,9 +240,10 @@ Parser::DeclTy *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) { if(Tok.is(tok::equal)) { SourceLocation EqualLoc = ConsumeToken(); SourceLocation DefaultLoc = Tok.getLocation(); - if (TypeTy *DefaultType = ParseTypeName()) + TypeResult DefaultType = ParseTypeName(); + if (!DefaultType.isInvalid()) Actions.ActOnTypeParameterDefault(TypeParam, EqualLoc, DefaultLoc, - DefaultType); + DefaultType.get()); } return TypeParam; @@ -529,7 +530,10 @@ void *Parser::ParseTemplateArgument(bool &ArgIsType) { // Therefore, we initially try to parse a type-id. if (isCXXTypeId(TypeIdAsTemplateArgument)) { ArgIsType = true; - return ParseTypeName(); + TypeResult TypeArg = ParseTypeName(); + if (TypeArg.isInvalid()) + return 0; + return TypeArg.get(); } OwningExprResult ExprArg = ParseAssignmentExpression(); diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index a385a13f4c..677f994cac 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -29,7 +29,6 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS) { QualType Result; switch (DS.getTypeSpecType()) { - default: assert(0 && "Unknown TypeSpecType!"); case DeclSpec::TST_void: Result = Context.VoidTy; break; @@ -169,6 +168,8 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS) { Result = Context.getTypeOfExpr(E); break; } + case DeclSpec::TST_error: + return QualType(); } // 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 // the first return statement. T = Context.DependentTy; - else + else { T = ConvertDeclSpecToType(DS); + if (T.isNull()) + return T; + } break; } @@ -725,16 +729,13 @@ Sema::TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) { assert(D.getIdentifier() == 0 && "Type name should have no identifier!"); QualType T = GetTypeForDeclarator(D, S); + if (T.isNull()) + return true; - assert(!T.isNull() && "GetTypeForDeclarator() returned null type"); - // Check that there are no default arguments (C++ only). if (getLangOptions().CPlusPlus) 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(); }