diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp | 464 |
1 files changed, 210 insertions, 254 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp index 5fe47fc..83121a8 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp @@ -10,12 +10,13 @@ // This file implements the Expression parsing implementation for C++. // //===----------------------------------------------------------------------===// -#include "clang/AST/DeclTemplate.h" -#include "clang/Parse/Parser.h" +#include "clang/AST/ASTContext.h" #include "RAIIObjectsForParser.h" +#include "clang/AST/DeclTemplate.h" #include "clang/Basic/PrettyStackTrace.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Parse/ParseDiagnostic.h" +#include "clang/Parse/Parser.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" @@ -26,7 +27,9 @@ using namespace clang; static int SelectDigraphErrorMessage(tok::TokenKind Kind) { switch (Kind) { - case tok::kw_template: return 0; + // template name + case tok::unknown: return 0; + // casts case tok::kw_const_cast: return 1; case tok::kw_dynamic_cast: return 2; case tok::kw_reinterpret_cast: return 3; @@ -93,7 +96,7 @@ void Parser::CheckForTemplateAndDigraph(Token &Next, ParsedType ObjectType, Template, MemberOfUnknownSpecialization)) return; - FixDigraph(*this, PP, Next, SecondToken, tok::kw_template, + FixDigraph(*this, PP, Next, SecondToken, tok::unknown, /*AtDigraph*/false); } @@ -204,7 +207,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, } if (LastII) - *LastII = 0; + *LastII = nullptr; bool HasScopeSpecifier = false; @@ -233,12 +236,13 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, DeclSpec DS(AttrFactory); SourceLocation DeclLoc = Tok.getLocation(); SourceLocation EndLoc = ParseDecltypeSpecifier(DS); - if (Tok.isNot(tok::coloncolon)) { + + SourceLocation CCLoc; + if (!TryConsumeToken(tok::coloncolon, CCLoc)) { AnnotateExistingDecltypeSpecifier(DS, DeclLoc, EndLoc); return false; } - - SourceLocation CCLoc = ConsumeToken(); + if (Actions.ActOnCXXNestedNameSpecifierDecltype(SS, DS, CCLoc)) SS.SetInvalid(SourceRange(DeclLoc, CCLoc)); @@ -287,19 +291,23 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, TentativeParsingAction TPA(*this); SourceLocation TemplateKWLoc = ConsumeToken(); - + UnqualifiedId TemplateName; if (Tok.is(tok::identifier)) { // Consume the identifier. TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); ConsumeToken(); } else if (Tok.is(tok::kw_operator)) { - if (ParseUnqualifiedIdOperator(SS, EnteringContext, ObjectType, + // We don't need to actually parse the unqualified-id in this case, + // because a simple-template-id cannot start with 'operator', but + // go ahead and parse it anyway for consistency with the case where + // we already annotated the template-id. + if (ParseUnqualifiedIdOperator(SS, EnteringContext, ObjectType, TemplateName)) { TPA.Commit(); break; } - + if (TemplateName.getKind() != UnqualifiedId::IK_OperatorFunctionId && TemplateName.getKind() != UnqualifiedId::IK_LiteralOperatorId) { Diag(TemplateName.getSourceRange().getBegin(), @@ -341,10 +349,10 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, if (Tok.is(tok::annot_template_id) && NextToken().is(tok::coloncolon)) { // We have // - // simple-template-id '::' + // template-id '::' // - // So we need to check whether the simple-template-id is of the - // right kind (it should name a type or be dependent), and then + // So we need to check whether the template-id is a simple-template-id of + // the right kind (it should name a type or be dependent), and then // convert it into a type within the nested-name-specifier. TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); if (CheckForDestructor && GetLookAheadToken(2).is(tok::tilde)) { @@ -357,15 +365,15 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, // Consume the template-id token. ConsumeToken(); - + assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!"); SourceLocation CCLoc = ConsumeToken(); HasScopeSpecifier = true; - + ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), TemplateId->NumArgs); - + if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), SS, TemplateId->TemplateKWLoc, @@ -385,7 +393,6 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, continue; } - // The rest of the nested-name-specifier possibilities start with // tok::identifier. if (Tok.isNot(tok::identifier)) @@ -410,9 +417,8 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, // error, but they probably meant something else strange so don't // recover like this. PP.LookAhead(1).is(tok::identifier)) { - Diag(Next, diag::err_unexected_colon_in_nested_name_spec) + Diag(Next, diag::err_unexpected_colon_in_nested_name_spec) << FixItHint::CreateReplacement(Next.getLocation(), "::"); - // Recover as if the user wrote '::'. Next.setKind(tok::coloncolon); } @@ -426,23 +432,52 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, return false; } + if (ColonIsSacred) { + const Token &Next2 = GetLookAheadToken(2); + if (Next2.is(tok::kw_private) || Next2.is(tok::kw_protected) || + Next2.is(tok::kw_public) || Next2.is(tok::kw_virtual)) { + Diag(Next2, diag::err_unexpected_token_in_nested_name_spec) + << Next2.getName() + << FixItHint::CreateReplacement(Next.getLocation(), ":"); + Token ColonColon; + PP.Lex(ColonColon); + ColonColon.setKind(tok::colon); + PP.EnterToken(ColonColon); + break; + } + } + if (LastII) *LastII = &II; // We have an identifier followed by a '::'. Lookup this name // as the name in a nested-name-specifier. + Token Identifier = Tok; SourceLocation IdLoc = ConsumeToken(); assert((Tok.is(tok::coloncolon) || Tok.is(tok::colon)) && "NextToken() not working properly!"); + Token ColonColon = Tok; SourceLocation CCLoc = ConsumeToken(); CheckForLParenAfterColonColon(); - HasScopeSpecifier = true; + bool IsCorrectedToColon = false; + bool *CorrectionFlagPtr = ColonIsSacred ? &IsCorrectedToColon : nullptr; if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), II, IdLoc, CCLoc, - ObjectType, EnteringContext, SS)) + ObjectType, EnteringContext, SS, + false, CorrectionFlagPtr)) { + // Identifier is not recognized as a nested name, but we can have + // mistyped '::' instead of ':'. + if (CorrectionFlagPtr && IsCorrectedToColon) { + ColonColon.setKind(tok::colon); + PP.EnterToken(Tok); + PP.EnterToken(ColonColon); + Tok = Identifier; + break; + } SS.SetInvalid(SourceRange(IdLoc, CCLoc)); - + } + HasScopeSpecifier = true; continue; } @@ -732,7 +767,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, !Intro.Captures.empty())) { Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro, /*AfterAmpersand=*/false); - ConsumeCodeCompletionToken(); + cutOffParsing(); break; } @@ -749,7 +784,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, else Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro, /*AfterAmpersand=*/false); - ConsumeCodeCompletionToken(); + cutOffParsing(); break; } @@ -758,7 +793,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, // Parse capture. LambdaCaptureKind Kind = LCK_ByCopy; SourceLocation Loc; - IdentifierInfo* Id = 0; + IdentifierInfo *Id = nullptr; SourceLocation EllipsisLoc; ExprResult Init; @@ -773,7 +808,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, if (Tok.is(tok::code_completion)) { Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro, /*AfterAmpersand=*/true); - ConsumeCodeCompletionToken(); + cutOffParsing(); break; } } @@ -814,8 +849,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, // to save the necessary state, and restore it later. EnterExpressionEvaluationContext EC(Actions, Sema::PotentiallyEvaluated); - if (Tok.is(tok::equal)) - ConsumeToken(); + TryConsumeToken(tok::equal); if (!SkippedInits) Init = ParseInitializer(); @@ -830,8 +864,8 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, // [..., x = expr // // We need to find the end of the following expression in order to - // determine whether this is an Obj-C message send's receiver, or a - // lambda init-capture. + // determine whether this is an Obj-C message send's receiver, a + // C99 designator, or a lambda init-capture. // // Parse the expression to find where it ends, and annotate it back // onto the tokens. We would have parsed this expression the same way @@ -864,8 +898,8 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, ConsumeToken(); } } - } else if (Tok.is(tok::ellipsis)) - EllipsisLoc = ConsumeToken(); + } else + TryConsumeToken(tok::ellipsis, EllipsisLoc); } // If this is an init capture, process the initialization expression // right away. For lambda init-captures such as the following: @@ -988,7 +1022,6 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( ParsedAttributes Attr(AttrFactory); SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo; SourceLocation EllipsisLoc; - if (Tok.isNot(tok::r_paren)) { Actions.RecordParsingTemplateParameterDepth(TemplateParameterDepth); @@ -1002,12 +1035,14 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( SourceLocation RParenLoc = T.getCloseLocation(); DeclEndLoc = RParenLoc; + // GNU-style attributes must be parsed before the mutable specifier to be + // compatible with GCC. + MaybeParseGNUAttributes(Attr, &DeclEndLoc); + // Parse 'mutable'[opt]. SourceLocation MutableLoc; - if (Tok.is(tok::kw_mutable)) { - MutableLoc = ConsumeToken(); + if (TryConsumeToken(tok::kw_mutable, MutableLoc)) DeclEndLoc = MutableLoc; - } // Parse exception-specification[opt]. ExceptionSpecificationType ESpecType = EST_None; @@ -1057,26 +1092,45 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( DynamicExceptionRanges.data(), DynamicExceptions.size(), NoexceptExpr.isUsable() ? - NoexceptExpr.get() : 0, + NoexceptExpr.get() : nullptr, LParenLoc, FunLocalRangeEnd, D, TrailingReturnType), Attr, DeclEndLoc); - } else if (Tok.is(tok::kw_mutable) || Tok.is(tok::arrow)) { - // It's common to forget that one needs '()' before 'mutable' or the - // result type. Deal with this. + } else if (Tok.is(tok::kw_mutable) || Tok.is(tok::arrow) || + Tok.is(tok::kw___attribute) || + (Tok.is(tok::l_square) && NextToken().is(tok::l_square))) { + // It's common to forget that one needs '()' before 'mutable', an attribute + // specifier, or the result type. Deal with this. + unsigned TokKind = 0; + switch (Tok.getKind()) { + case tok::kw_mutable: TokKind = 0; break; + case tok::arrow: TokKind = 1; break; + case tok::kw___attribute: + case tok::l_square: TokKind = 2; break; + default: llvm_unreachable("Unknown token kind"); + } + Diag(Tok, diag::err_lambda_missing_parens) - << Tok.is(tok::arrow) + << TokKind << FixItHint::CreateInsertion(Tok.getLocation(), "() "); SourceLocation DeclLoc = Tok.getLocation(); SourceLocation DeclEndLoc = DeclLoc; - + + // GNU-style attributes must be parsed before the mutable specifier to be + // compatible with GCC. + ParsedAttributes Attr(AttrFactory); + MaybeParseGNUAttributes(Attr, &DeclEndLoc); + // Parse 'mutable', if it's there. SourceLocation MutableLoc; if (Tok.is(tok::kw_mutable)) { MutableLoc = ConsumeToken(); DeclEndLoc = MutableLoc; } - + + // Parse attribute-specifier[opt]. + MaybeParseCXX11Attributes(Attr, &DeclEndLoc); + // Parse the return type, if there is one. TypeResult TrailingReturnType; if (Tok.is(tok::arrow)) { @@ -1086,12 +1140,11 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( DeclEndLoc = Range.getEnd(); } - ParsedAttributes Attr(AttrFactory); SourceLocation NoLoc; D.AddTypeInfo(DeclaratorChunk::getFunction(/*hasProto=*/true, /*isAmbiguous=*/false, /*LParenLoc=*/NoLoc, - /*Params=*/0, + /*Params=*/nullptr, /*NumParams=*/0, /*EllipsisLoc=*/NoLoc, /*RParenLoc=*/NoLoc, @@ -1103,10 +1156,10 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( MutableLoc, EST_None, /*ESpecLoc=*/NoLoc, - /*Exceptions=*/0, - /*ExceptionRanges=*/0, + /*Exceptions=*/nullptr, + /*ExceptionRanges=*/nullptr, /*NumExceptions=*/0, - /*NoexceptExpr=*/0, + /*NoexceptExpr=*/nullptr, DeclLoc, DeclEndLoc, D, TrailingReturnType), Attr, DeclEndLoc); @@ -1131,7 +1184,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( BodyScope.Exit(); if (!Stmt.isInvalid()) - return Actions.ActOnLambdaExpr(LambdaBeginLoc, Stmt.take(), getCurScope()); + return Actions.ActOnLambdaExpr(LambdaBeginLoc, Stmt.get(), getCurScope()); Actions.ActOnLambdaError(LambdaBeginLoc, getCurScope()); return ExprError(); @@ -1148,7 +1201,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( /// ExprResult Parser::ParseCXXCasts() { tok::TokenKind Kind = Tok.getKind(); - const char *CastName = 0; // For error messages + const char *CastName = nullptr; // For error messages switch (Kind) { default: llvm_unreachable("Unknown C++ cast!"); @@ -1182,8 +1235,8 @@ ExprResult Parser::ParseCXXCasts() { SourceLocation RAngleBracketLoc = Tok.getLocation(); - if (ExpectAndConsume(tok::greater, diag::err_expected_greater)) - return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << "<"); + if (ExpectAndConsume(tok::greater)) + return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << tok::less); SourceLocation LParenLoc, RParenLoc; BalancedDelimiterTracker T(*this, tok::l_paren); @@ -1200,7 +1253,7 @@ ExprResult Parser::ParseCXXCasts() { Result = Actions.ActOnCXXNamedCast(OpLoc, Kind, LAngleBracketLoc, DeclaratorInfo, RAngleBracketLoc, - T.getOpenLocation(), Result.take(), + T.getOpenLocation(), Result.get(), T.getCloseLocation()); return Result; @@ -1266,7 +1319,7 @@ ExprResult Parser::ParseCXXTypeid() { return ExprError(); Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false, - Result.release(), RParenLoc); + Result.get(), RParenLoc); } } @@ -1314,7 +1367,7 @@ ExprResult Parser::ParseCXXUuidof() { Result = Actions.ActOnCXXUuidof(OpLoc, T.getOpenLocation(), /*isType=*/false, - Result.release(), T.getCloseLocation()); + Result.get(), T.getCloseLocation()); } } @@ -1364,7 +1417,7 @@ Parser::ParseCXXPseudoDestructor(ExprArg Base, SourceLocation OpLoc, assert(Tok.is(tok::coloncolon) &&"ParseOptionalCXXScopeSpecifier fail"); CCLoc = ConsumeToken(); } else { - FirstTypeName.setIdentifier(0, SourceLocation()); + FirstTypeName.setIdentifier(nullptr, SourceLocation()); } // Parse the tilde. @@ -1436,12 +1489,12 @@ ExprResult Parser::ParseThrowExpression() { case tok::r_brace: case tok::colon: case tok::comma: - return Actions.ActOnCXXThrow(getCurScope(), ThrowLoc, 0); + return Actions.ActOnCXXThrow(getCurScope(), ThrowLoc, nullptr); default: ExprResult Expr(ParseAssignmentExpression()); if (Expr.isInvalid()) return Expr; - return Actions.ActOnCXXThrow(getCurScope(), ThrowLoc, Expr.take()); + return Actions.ActOnCXXThrow(getCurScope(), ThrowLoc, Expr.get()); } } @@ -1481,7 +1534,7 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { ExprResult Init = ParseBraceInitializer(); if (Init.isInvalid()) return Init; - Expr *InitList = Init.take(); + Expr *InitList = Init.get(); return Actions.ActOnCXXTypeConstructExpr(TypeRep, SourceLocation(), MultiExprArg(&InitList, 1), SourceLocation()); @@ -1555,7 +1608,7 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut, // Parse the expression. ExprOut = ParseExpression(); // expression - DeclOut = 0; + DeclOut = nullptr; if (ExprOut.isInvalid()) return true; @@ -1583,7 +1636,7 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut, SkipUntil(tok::semi, StopAtSemi); return true; } - DeclaratorInfo.setAsmLabel(AsmLabel.release()); + DeclaratorInfo.setAsmLabel(AsmLabel.get()); DeclaratorInfo.SetRangeEnd(Loc); } @@ -1623,7 +1676,7 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut, } if (!InitExpr.isInvalid()) - Actions.AddInitializerToDecl(DeclOut, InitExpr.take(), !CopyInitialization, + Actions.AddInitializerToDecl(DeclOut, InitExpr.get(), !CopyInitialization, DS.containsPlaceholderType()); else Actions.ActOnInitializerError(DeclOut); @@ -1667,6 +1720,8 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { const char *PrevSpec; unsigned DiagID; SourceLocation Loc = Tok.getLocation(); + const clang::PrintingPolicy &Policy = + Actions.getASTContext().getPrintingPolicy(); switch (Tok.getKind()) { case tok::identifier: // foo::bar @@ -1679,7 +1734,7 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { case tok::annot_typename: { if (getTypeAnnotation(Tok)) DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, - getTypeAnnotation(Tok)); + getTypeAnnotation(Tok), Policy); else DS.SetTypeSpecError(); @@ -1693,19 +1748,19 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { if (Tok.is(tok::less) && getLangOpts().ObjC1) ParseObjCProtocolQualifiers(DS); - DS.Finish(Diags, PP); + DS.Finish(Diags, PP, Policy); return; } // builtin types case tok::kw_short: - DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, DiagID); + DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, DiagID, Policy); break; case tok::kw_long: - DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec, DiagID); + DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec, DiagID, Policy); break; case tok::kw___int64: - DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec, DiagID); + DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec, DiagID, Policy); break; case tok::kw_signed: DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec, DiagID); @@ -1714,47 +1769,47 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec, DiagID); break; case tok::kw_void: - DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, DiagID); + DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, DiagID, Policy); break; case tok::kw_char: - DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, DiagID); + DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, DiagID, Policy); break; case tok::kw_int: - DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID); + DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID, Policy); break; case tok::kw___int128: - DS.SetTypeSpecType(DeclSpec::TST_int128, Loc, PrevSpec, DiagID); + DS.SetTypeSpecType(DeclSpec::TST_int128, Loc, PrevSpec, DiagID, Policy); break; case tok::kw_half: - DS.SetTypeSpecType(DeclSpec::TST_half, Loc, PrevSpec, DiagID); + DS.SetTypeSpecType(DeclSpec::TST_half, Loc, PrevSpec, DiagID, Policy); break; case tok::kw_float: - DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, DiagID); + DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, DiagID, Policy); break; case tok::kw_double: - DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID); + DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID, Policy); break; case tok::kw_wchar_t: - DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID); + DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID, Policy); break; case tok::kw_char16_t: - DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, DiagID); + DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, DiagID, Policy); break; case tok::kw_char32_t: - DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec, DiagID); + DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec, DiagID, Policy); break; case tok::kw_bool: - DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, DiagID); + DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, DiagID, Policy); break; case tok::annot_decltype: case tok::kw_decltype: DS.SetRangeEnd(ParseDecltypeSpecifier(DS)); - return DS.Finish(Diags, PP); + return DS.Finish(Diags, PP, Policy); // GNU typeof support. case tok::kw_typeof: ParseTypeofSpecifier(DS); - DS.Finish(Diags, PP); + DS.Finish(Diags, PP, Policy); return; } if (Tok.is(tok::annot_typename)) @@ -1762,7 +1817,7 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { else DS.SetRangeEnd(Tok.getLocation()); ConsumeToken(); - DS.Finish(Diags, PP); + DS.Finish(Diags, PP, Policy); } /// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++ @@ -1778,7 +1833,7 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { /// bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) { ParseSpecifierQualifierList(DS, AS_none, DSC_type_specifier); - DS.Finish(Diags, PP); + DS.Finish(Diags, PP, Actions.getASTContext().getPrintingPolicy()); return false; } @@ -1935,12 +1990,13 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, TemplateIdAnnotation *TemplateId = TemplateIdAnnotation::Allocate(TemplateArgs.size(), TemplateIds); + // FIXME: Store name for literal operator too. if (Id.getKind() == UnqualifiedId::IK_Identifier) { TemplateId->Name = Id.Identifier; TemplateId->Operator = OO_None; TemplateId->TemplateNameLoc = Id.StartLocation; } else { - TemplateId->Name = 0; + TemplateId->Name = nullptr; TemplateId->Operator = Id.OperatorFunctionId.Operator; TemplateId->TemplateNameLoc = Id.StartLocation; } @@ -2139,13 +2195,13 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, TokLocs.push_back(ConsumeStringToken()); } - StringLiteralParser Literal(Toks.data(), Toks.size(), PP); + StringLiteralParser Literal(Toks, PP); if (Literal.hadError) return true; // Grab the literal operator's suffix, which will be either the next token // or a ud-suffix from the string literal. - IdentifierInfo *II = 0; + IdentifierInfo *II = nullptr; SourceLocation SuffixLoc; if (!Literal.getUDSuffix().empty()) { II = &PP.getIdentifierTable().get(Literal.getUDSuffix()); @@ -2158,7 +2214,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, SuffixLoc = ConsumeToken(); TokLocs.push_back(SuffixLoc); } else { - Diag(Tok.getLocation(), diag::err_expected_ident); + Diag(Tok.getLocation(), diag::err_expected) << tok::identifier; return true; } @@ -2183,9 +2239,10 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, } Result.setLiteralOperatorId(II, KeywordLoc, SuffixLoc); - return false; + + return Actions.checkLiteralOperatorId(SS, Result); } - + // Parse a conversion-function-id. // // conversion-function-id: [C++ 12.3.2] @@ -2205,8 +2262,8 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, // Parse the conversion-declarator, which is merely a sequence of // ptr-operators. Declarator D(DS, Declarator::ConversionIdContext); - ParseDeclaratorInternal(D, /*DirectDeclParser=*/0); - + ParseDeclaratorInternal(D, /*DirectDeclParser=*/nullptr); + // Finish up the type. TypeResult Ty = Actions.ActOnTypeName(getCurScope(), D); if (Ty.isInvalid()) @@ -2362,10 +2419,10 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, Result.getKind() == UnqualifiedId::IK_LiteralOperatorId) && (TemplateSpecified || Tok.is(tok::less))) return ParseUnqualifiedIdTemplateId(SS, TemplateKWLoc, - 0, SourceLocation(), + nullptr, SourceLocation(), EnteringContext, ObjectType, Result, TemplateSpecified); - + return false; } @@ -2560,7 +2617,7 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen, PlacementArgs, PlacementRParen, - TypeIdParens, DeclaratorInfo, Initializer.take()); + TypeIdParens, DeclaratorInfo, Initializer.get()); } /// ParseDirectNewDeclarator - Parses a direct-new-declarator. Intended to be @@ -2598,7 +2655,7 @@ void Parser::ParseDirectNewDeclarator(Declarator &D) { D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false, - Size.release(), + Size.get(), T.getOpenLocation(), T.getCloseLocation()), Attrs, T.getCloseLocation()); @@ -2675,82 +2732,20 @@ Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) { if (Operand.isInvalid()) return Operand; - return Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete, Operand.take()); -} - -static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) { - switch(kind) { - default: llvm_unreachable("Not a known unary type trait."); - case tok::kw___has_nothrow_assign: return UTT_HasNothrowAssign; - case tok::kw___has_nothrow_move_assign: return UTT_HasNothrowMoveAssign; - case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor; - case tok::kw___has_nothrow_copy: return UTT_HasNothrowCopy; - case tok::kw___has_trivial_assign: return UTT_HasTrivialAssign; - case tok::kw___has_trivial_move_assign: return UTT_HasTrivialMoveAssign; - case tok::kw___has_trivial_constructor: - return UTT_HasTrivialDefaultConstructor; - case tok::kw___has_trivial_move_constructor: - return UTT_HasTrivialMoveConstructor; - case tok::kw___has_trivial_copy: return UTT_HasTrivialCopy; - case tok::kw___has_trivial_destructor: return UTT_HasTrivialDestructor; - case tok::kw___has_virtual_destructor: return UTT_HasVirtualDestructor; - case tok::kw___is_abstract: return UTT_IsAbstract; - case tok::kw___is_arithmetic: return UTT_IsArithmetic; - case tok::kw___is_array: return UTT_IsArray; - case tok::kw___is_class: return UTT_IsClass; - case tok::kw___is_complete_type: return UTT_IsCompleteType; - case tok::kw___is_compound: return UTT_IsCompound; - case tok::kw___is_const: return UTT_IsConst; - case tok::kw___is_empty: return UTT_IsEmpty; - case tok::kw___is_enum: return UTT_IsEnum; - case tok::kw___is_final: return UTT_IsFinal; - case tok::kw___is_floating_point: return UTT_IsFloatingPoint; - case tok::kw___is_function: return UTT_IsFunction; - case tok::kw___is_fundamental: return UTT_IsFundamental; - case tok::kw___is_integral: return UTT_IsIntegral; - case tok::kw___is_interface_class: return UTT_IsInterfaceClass; - case tok::kw___is_lvalue_reference: return UTT_IsLvalueReference; - case tok::kw___is_member_function_pointer: return UTT_IsMemberFunctionPointer; - case tok::kw___is_member_object_pointer: return UTT_IsMemberObjectPointer; - case tok::kw___is_member_pointer: return UTT_IsMemberPointer; - case tok::kw___is_object: return UTT_IsObject; - case tok::kw___is_literal: return UTT_IsLiteral; - case tok::kw___is_literal_type: return UTT_IsLiteral; - case tok::kw___is_pod: return UTT_IsPOD; - case tok::kw___is_pointer: return UTT_IsPointer; - case tok::kw___is_polymorphic: return UTT_IsPolymorphic; - case tok::kw___is_reference: return UTT_IsReference; - case tok::kw___is_rvalue_reference: return UTT_IsRvalueReference; - case tok::kw___is_scalar: return UTT_IsScalar; - case tok::kw___is_sealed: return UTT_IsSealed; - case tok::kw___is_signed: return UTT_IsSigned; - case tok::kw___is_standard_layout: return UTT_IsStandardLayout; - case tok::kw___is_trivial: return UTT_IsTrivial; - case tok::kw___is_trivially_copyable: return UTT_IsTriviallyCopyable; - case tok::kw___is_union: return UTT_IsUnion; - case tok::kw___is_unsigned: return UTT_IsUnsigned; - case tok::kw___is_void: return UTT_IsVoid; - case tok::kw___is_volatile: return UTT_IsVolatile; - } -} - -static BinaryTypeTrait BinaryTypeTraitFromTokKind(tok::TokenKind kind) { - switch(kind) { - default: llvm_unreachable("Not a known binary type trait"); - case tok::kw___is_base_of: return BTT_IsBaseOf; - case tok::kw___is_convertible: return BTT_IsConvertible; - case tok::kw___is_same: return BTT_IsSame; - case tok::kw___builtin_types_compatible_p: return BTT_TypeCompatible; - case tok::kw___is_convertible_to: return BTT_IsConvertibleTo; - case tok::kw___is_trivially_assignable: return BTT_IsTriviallyAssignable; - } + return Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete, Operand.get()); } static TypeTrait TypeTraitFromTokKind(tok::TokenKind kind) { switch (kind) { default: llvm_unreachable("Not a known type trait"); - case tok::kw___is_trivially_constructible: - return TT_IsTriviallyConstructible; +#define TYPE_TRAIT_1(Spelling, Name, Key) \ +case tok::kw_ ## Spelling: return UTT_ ## Name; +#define TYPE_TRAIT_2(Spelling, Name, Key) \ +case tok::kw_ ## Spelling: return BTT_ ## Name; +#include "clang/Basic/TokenKinds.def" +#define TYPE_TRAIT_N(Spelling, Name, Key) \ + case tok::kw_ ## Spelling: return TT_ ## Name; +#include "clang/Basic/TokenKinds.def" } } @@ -2770,87 +2765,33 @@ static ExpressionTrait ExpressionTraitFromTokKind(tok::TokenKind kind) { } } -/// ParseUnaryTypeTrait - Parse the built-in unary type-trait -/// pseudo-functions that allow implementation of the TR1/C++0x type traits -/// templates. -/// -/// primary-expression: -/// [GNU] unary-type-trait '(' type-id ')' -/// -ExprResult Parser::ParseUnaryTypeTrait() { - UnaryTypeTrait UTT = UnaryTypeTraitFromTokKind(Tok.getKind()); - SourceLocation Loc = ConsumeToken(); - - BalancedDelimiterTracker T(*this, tok::l_paren); - if (T.expectAndConsume(diag::err_expected_lparen)) - return ExprError(); - - // FIXME: Error reporting absolutely sucks! If the this fails to parse a type - // there will be cryptic errors about mismatched parentheses and missing - // specifiers. - TypeResult Ty = ParseTypeName(); - - T.consumeClose(); - - if (Ty.isInvalid()) - return ExprError(); - - return Actions.ActOnUnaryTypeTrait(UTT, Loc, Ty.get(), T.getCloseLocation()); -} - -/// ParseBinaryTypeTrait - Parse the built-in binary type-trait -/// pseudo-functions that allow implementation of the TR1/C++0x type traits -/// templates. -/// -/// primary-expression: -/// [GNU] binary-type-trait '(' type-id ',' type-id ')' -/// -ExprResult Parser::ParseBinaryTypeTrait() { - BinaryTypeTrait BTT = BinaryTypeTraitFromTokKind(Tok.getKind()); - SourceLocation Loc = ConsumeToken(); - - BalancedDelimiterTracker T(*this, tok::l_paren); - if (T.expectAndConsume(diag::err_expected_lparen)) - return ExprError(); - - TypeResult LhsTy = ParseTypeName(); - if (LhsTy.isInvalid()) { - SkipUntil(tok::r_paren, StopAtSemi); - return ExprError(); - } - - if (ExpectAndConsume(tok::comma, diag::err_expected_comma)) { - SkipUntil(tok::r_paren, StopAtSemi); - return ExprError(); - } - - TypeResult RhsTy = ParseTypeName(); - if (RhsTy.isInvalid()) { - SkipUntil(tok::r_paren, StopAtSemi); - return ExprError(); +static unsigned TypeTraitArity(tok::TokenKind kind) { + switch (kind) { + default: llvm_unreachable("Not a known type trait"); +#define TYPE_TRAIT(N,Spelling,K) case tok::kw_##Spelling: return N; +#include "clang/Basic/TokenKinds.def" } - - T.consumeClose(); - - return Actions.ActOnBinaryTypeTrait(BTT, Loc, LhsTy.get(), RhsTy.get(), - T.getCloseLocation()); } /// \brief Parse the built-in type-trait pseudo-functions that allow /// implementation of the TR1/C++11 type traits templates. /// /// primary-expression: +/// unary-type-trait '(' type-id ')' +/// binary-type-trait '(' type-id ',' type-id ')' /// type-trait '(' type-id-seq ')' /// /// type-id-seq: /// type-id ...[opt] type-id-seq[opt] /// ExprResult Parser::ParseTypeTrait() { - TypeTrait Kind = TypeTraitFromTokKind(Tok.getKind()); + tok::TokenKind Kind = Tok.getKind(); + unsigned Arity = TypeTraitArity(Kind); + SourceLocation Loc = ConsumeToken(); BalancedDelimiterTracker Parens(*this, tok::l_paren); - if (Parens.expectAndConsume(diag::err_expected_lparen)) + if (Parens.expectAndConsume()) return ExprError(); SmallVector<ParsedType, 2> Args; @@ -2873,19 +2814,26 @@ ExprResult Parser::ParseTypeTrait() { // Add this type to the list of arguments. Args.push_back(Ty.get()); - - if (Tok.is(tok::comma)) { - ConsumeToken(); - continue; - } - - break; - } while (true); - + } while (TryConsumeToken(tok::comma)); + if (Parens.consumeClose()) return ExprError(); - - return Actions.ActOnTypeTrait(Kind, Loc, Args, Parens.getCloseLocation()); + + SourceLocation EndLoc = Parens.getCloseLocation(); + + if (Arity && Args.size() != Arity) { + Diag(EndLoc, diag::err_type_trait_arity) + << Arity << 0 << (Arity > 1) << (int)Args.size() << SourceRange(Loc); + return ExprError(); + } + + if (!Arity && Args.empty()) { + Diag(EndLoc, diag::err_type_trait_arity) + << 1 << 1 << 1 << (int)Args.size() << SourceRange(Loc); + return ExprError(); + } + + return Actions.ActOnTypeTrait(TypeTraitFromTokKind(Kind), Loc, Args, EndLoc); } /// ParseArrayTypeTrait - Parse the built-in array type-trait @@ -2900,7 +2848,7 @@ ExprResult Parser::ParseArrayTypeTrait() { SourceLocation Loc = ConsumeToken(); BalancedDelimiterTracker T(*this, tok::l_paren); - if (T.expectAndConsume(diag::err_expected_lparen)) + if (T.expectAndConsume()) return ExprError(); TypeResult Ty = ParseTypeName(); @@ -2913,11 +2861,11 @@ ExprResult Parser::ParseArrayTypeTrait() { switch (ATT) { case ATT_ArrayRank: { T.consumeClose(); - return Actions.ActOnArrayTypeTrait(ATT, Loc, Ty.get(), NULL, + return Actions.ActOnArrayTypeTrait(ATT, Loc, Ty.get(), nullptr, T.getCloseLocation()); } case ATT_ArrayExtent: { - if (ExpectAndConsume(tok::comma, diag::err_expected_comma)) { + if (ExpectAndConsume(tok::comma)) { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } @@ -2943,7 +2891,7 @@ ExprResult Parser::ParseExpressionTrait() { SourceLocation Loc = ConsumeToken(); BalancedDelimiterTracker T(*this, tok::l_paren); - if (T.expectAndConsume(diag::err_expected_lparen)) + if (T.expectAndConsume()) return ExprError(); ExprResult Expr = ParseExpression(); @@ -2961,7 +2909,8 @@ ExprResult Parser::ParseExpressionTrait() { ExprResult Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, ParsedType &CastTy, - BalancedDelimiterTracker &Tracker) { + BalancedDelimiterTracker &Tracker, + ColonProtectionRAIIObject &ColonProt) { assert(getLangOpts().CPlusPlus && "Should only be called for C++!"); assert(ExprType == CastExpr && "Compound literals are not ambiguous!"); assert(isTypeIdInParens() && "Not a type-id!"); @@ -3003,13 +2952,13 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, ParseAs = CompoundLiteral; } else { bool NotCastExpr; - // FIXME: Special-case ++ and --: "(S())++;" is not a cast-expression if (Tok.is(tok::l_paren) && NextToken().is(tok::r_paren)) { NotCastExpr = true; } else { // Try parsing the cast-expression that may follow. // If it is not a cast-expression, NotCastExpr will be true and no token // will be consumed. + ColonProt.restore(); Result = ParseCastExpression(false/*isUnaryExpression*/, false/*isAddressofOperand*/, NotCastExpr, @@ -3035,17 +2984,24 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, if (ParseAs >= CompoundLiteral) { // Parse the type declarator. DeclSpec DS(AttrFactory); - ParseSpecifierQualifierList(DS); Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); - ParseDeclarator(DeclaratorInfo); + { + ColonProtectionRAIIObject InnerColonProtection(*this); + ParseSpecifierQualifierList(DS); + ParseDeclarator(DeclaratorInfo); + } // Match the ')'. Tracker.consumeClose(); + ColonProt.restore(); if (ParseAs == CompoundLiteral) { ExprType = CompoundLiteral; - TypeResult Ty = ParseTypeName(); - return ParseCompoundLiteralExpression(Ty.get(), + if (DeclaratorInfo.isInvalidType()) + return ExprError(); + + TypeResult Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); + return ParseCompoundLiteralExpression(Ty.get(), Tracker.getOpenLocation(), Tracker.getCloseLocation()); } @@ -3060,7 +3016,7 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, if (!Result.isInvalid()) Result = Actions.ActOnCastExpr(getCurScope(), Tracker.getOpenLocation(), DeclaratorInfo, CastTy, - Tracker.getCloseLocation(), Result.take()); + Tracker.getCloseLocation(), Result.get()); return Result; } @@ -3071,7 +3027,7 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, Result = ParseExpression(); if (!Result.isInvalid() && Tok.is(tok::r_paren)) Result = Actions.ActOnParenExpr(Tracker.getOpenLocation(), - Tok.getLocation(), Result.take()); + Tok.getLocation(), Result.get()); // Match the ')'. if (Result.isInvalid()) { |