diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp | 610 |
1 files changed, 452 insertions, 158 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp index 60166e8..2af7482 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp @@ -14,6 +14,8 @@ #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" #include "RAIIObjectsForParser.h" +#include "clang/Basic/PrettyStackTrace.h" +#include "clang/Lex/LiteralSupport.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ParsedTemplate.h" @@ -136,7 +138,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, bool EnteringContext, bool *MayBePseudoDestructor, bool IsTypename) { - assert(getLang().CPlusPlus && + assert(getLangOpts().CPlusPlus && "Call sites of this function should be guarded by checking for C++"); if (Tok.is(tok::annot_cxxscope)) { @@ -168,6 +170,22 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, *MayBePseudoDestructor = false; } + if (Tok.is(tok::kw_decltype) || Tok.is(tok::annot_decltype)) { + DeclSpec DS(AttrFactory); + SourceLocation DeclLoc = Tok.getLocation(); + SourceLocation EndLoc = ParseDecltypeSpecifier(DS); + if (Tok.isNot(tok::coloncolon)) { + AnnotateExistingDecltypeSpecifier(DS, DeclLoc, EndLoc); + return false; + } + + SourceLocation CCLoc = ConsumeToken(); + if (Actions.ActOnCXXNestedNameSpecifierDecltype(SS, DS, CCLoc)) + SS.SetInvalid(SourceRange(DeclLoc, CCLoc)); + + HasScopeSpecifier = true; + } + while (true) { if (HasScopeSpecifier) { // C++ [basic.lookup.classref]p5: @@ -247,15 +265,13 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, // Commit to parsing the template-id. TPA.Commit(); TemplateTy Template; - if (TemplateNameKind TNK = Actions.ActOnDependentTemplateName(getCurScope(), - TemplateKWLoc, - SS, - TemplateName, - ObjectType, - EnteringContext, - Template)) { - if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateName, - TemplateKWLoc, false)) + if (TemplateNameKind TNK + = Actions.ActOnDependentTemplateName(getCurScope(), + SS, TemplateKWLoc, TemplateName, + ObjectType, EnteringContext, + Template)) { + if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateKWLoc, + TemplateName, false)) return true; } else return true; @@ -283,16 +299,15 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!"); SourceLocation CCLoc = ConsumeToken(); - if (!HasScopeSpecifier) - HasScopeSpecifier = true; + HasScopeSpecifier = true; ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateId->getTemplateArgs(), TemplateId->NumArgs); if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), - /*FIXME:*/SourceLocation(), - SS, + SS, + TemplateId->TemplateKWLoc, TemplateId->Template, TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, @@ -381,15 +396,15 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, EnteringContext, Template, MemberOfUnknownSpecialization)) { - // We have found a template name, so annotate this this token + // We have found a template name, so annotate this token // with a template-id annotation. We do not permit the // template-id to be translated into a type annotation, // because some clients (e.g., the parsing of class template // specializations) still want to see the original template-id // token. ConsumeToken(); - if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateName, - SourceLocation(), false)) + if (AnnotateTemplateIdToken(Template, TNK, SS, SourceLocation(), + TemplateName, false)) return true; continue; } @@ -401,7 +416,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, // parse correctly as a template, so suggest the keyword 'template' // before 'getAs' and treat this as a dependent template name. unsigned DiagID = diag::err_missing_dependent_template_keyword; - if (getLang().MicrosoftExt) + if (getLangOpts().MicrosoftExt) DiagID = diag::warn_missing_dependent_template_keyword; Diag(Tok.getLocation(), DiagID) @@ -410,14 +425,14 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, if (TemplateNameKind TNK = Actions.ActOnDependentTemplateName(getCurScope(), - Tok.getLocation(), SS, + SS, SourceLocation(), TemplateName, ObjectType, EnteringContext, Template)) { // Consume the identifier. ConsumeToken(); - if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateName, - SourceLocation(), false)) - return true; + if (AnnotateTemplateIdToken(Template, TNK, SS, SourceLocation(), + TemplateName, false)) + return true; } else return true; @@ -488,14 +503,16 @@ ExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) { // '::' unqualified-id // CXXScopeSpec SS; - ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false); - + ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false); + + SourceLocation TemplateKWLoc; UnqualifiedId Name; - if (ParseUnqualifiedId(SS, - /*EnteringContext=*/false, - /*AllowDestructorName=*/false, - /*AllowConstructorName=*/false, + if (ParseUnqualifiedId(SS, + /*EnteringContext=*/false, + /*AllowDestructorName=*/false, + /*AllowConstructorName=*/false, /*ObjectType=*/ ParsedType(), + TemplateKWLoc, Name)) return ExprError(); @@ -503,10 +520,9 @@ ExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) { // followed by a postfix-expression suffix. if (isAddressOfOperand && isPostfixExpressionSuffixStart()) isAddressOfOperand = false; - - return Actions.ActOnIdExpression(getCurScope(), SS, Name, Tok.is(tok::l_paren), - isAddressOfOperand); - + + return Actions.ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Name, + Tok.is(tok::l_paren), isAddressOfOperand); } /// ParseLambdaExpression - Parse a C++0x lambda expression. @@ -548,6 +564,9 @@ ExprResult Parser::ParseLambdaExpression() { if (DiagID) { Diag(Tok, DiagID.getValue()); SkipUntil(tok::r_square); + SkipUntil(tok::l_brace); + SkipUntil(tok::r_brace); + return ExprError(); } return ParseLambdaExpressionAfterIntroducer(Intro); @@ -559,7 +578,7 @@ ExprResult Parser::ParseLambdaExpression() { /// /// If we are not looking at a lambda expression, returns ExprError(). ExprResult Parser::TryParseLambdaExpression() { - assert(getLang().CPlusPlus0x + assert(getLangOpts().CPlusPlus0x && Tok.is(tok::l_square) && "Not at the start of a possible lambda expression."); @@ -576,21 +595,28 @@ ExprResult Parser::TryParseLambdaExpression() { return ParseLambdaExpression(); } - // If lookahead indicates this is an Objective-C message... + // If lookahead indicates an ObjC message send... + // [identifier identifier if (Next.is(tok::identifier) && After.is(tok::identifier)) { - return ExprError(); + return ExprEmpty(); } + // Here, we're stuck: lambda introducers and Objective-C message sends are + // unambiguous, but it requires arbitrary lookhead. [a,b,c,d,e,f,g] is a + // lambda, and [a,b,c,d,e,f,g h] is a Objective-C message send. Instead of + // writing two routines to parse a lambda introducer, just try to parse + // a lambda introducer first, and fall back if that fails. + // (TryParseLambdaIntroducer never produces any diagnostic output.) LambdaIntroducer Intro; if (TryParseLambdaIntroducer(Intro)) - return ExprError(); + return ExprEmpty(); return ParseLambdaExpressionAfterIntroducer(Intro); } /// ParseLambdaExpression - Parse a lambda introducer. /// /// Returns a DiagnosticID if it hit something unexpected. -llvm::Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro) { +llvm::Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro){ typedef llvm::Optional<unsigned> DiagResult; assert(Tok.is(tok::l_square) && "Lambda expressions begin with '['."); @@ -605,28 +631,49 @@ llvm::Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro) if (Tok.is(tok::amp) && (NextToken().is(tok::comma) || NextToken().is(tok::r_square))) { Intro.Default = LCD_ByRef; - ConsumeToken(); + Intro.DefaultLoc = ConsumeToken(); first = false; } else if (Tok.is(tok::equal)) { Intro.Default = LCD_ByCopy; - ConsumeToken(); + Intro.DefaultLoc = ConsumeToken(); first = false; } while (Tok.isNot(tok::r_square)) { if (!first) { - if (Tok.isNot(tok::comma)) + if (Tok.isNot(tok::comma)) { + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro, + /*AfterAmpersand=*/false); + ConsumeCodeCompletionToken(); + break; + } + return DiagResult(diag::err_expected_comma_or_rsquare); + } ConsumeToken(); } - first = false; + if (Tok.is(tok::code_completion)) { + // If we're in Objective-C++ and we have a bare '[', then this is more + // likely to be a message receiver. + if (getLangOpts().ObjC1 && first) + Actions.CodeCompleteObjCMessageReceiver(getCurScope()); + else + Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro, + /*AfterAmpersand=*/false); + ConsumeCodeCompletionToken(); + break; + } + first = false; + // Parse capture. LambdaCaptureKind Kind = LCK_ByCopy; SourceLocation Loc; IdentifierInfo* Id = 0; - + SourceLocation EllipsisLoc; + if (Tok.is(tok::kw_this)) { Kind = LCK_This; Loc = ConsumeToken(); @@ -634,11 +681,21 @@ llvm::Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro) if (Tok.is(tok::amp)) { Kind = LCK_ByRef; ConsumeToken(); + + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro, + /*AfterAmpersand=*/true); + ConsumeCodeCompletionToken(); + break; + } } if (Tok.is(tok::identifier)) { Id = Tok.getIdentifierInfo(); Loc = ConsumeToken(); + + if (Tok.is(tok::ellipsis)) + EllipsisLoc = ConsumeToken(); } else if (Tok.is(tok::kw_this)) { // FIXME: If we want to suggest a fixit here, will need to return more // than just DiagnosticID. Perhaps full DiagnosticBuilder that can be @@ -649,7 +706,7 @@ llvm::Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro) } } - Intro.addCapture(Kind, Loc, Id); + Intro.addCapture(Kind, Loc, Id, EllipsisLoc); } T.consumeClose(); @@ -658,7 +715,7 @@ llvm::Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro) return DiagResult(); } -/// TryParseLambdaExpression - Tentatively parse a lambda introducer. +/// TryParseLambdaIntroducer - Tentatively parse a lambda introducer. /// /// Returns true if it hit something unexpected. bool Parser::TryParseLambdaIntroducer(LambdaIntroducer &Intro) { @@ -679,9 +736,15 @@ bool Parser::TryParseLambdaIntroducer(LambdaIntroducer &Intro) { /// expression. ExprResult Parser::ParseLambdaExpressionAfterIntroducer( LambdaIntroducer &Intro) { + SourceLocation LambdaBeginLoc = Intro.Range.getBegin(); + Diag(LambdaBeginLoc, diag::warn_cxx98_compat_lambda); + + PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), LambdaBeginLoc, + "lambda expression parsing"); + // Parse lambda-declarator[opt]. DeclSpec DS(AttrFactory); - Declarator D(DS, Declarator::PrototypeContext); + Declarator D(DS, Declarator::LambdaExprContext); if (Tok.is(tok::l_paren)) { ParseScope PrototypeScope(this, @@ -746,6 +809,8 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( DS.getTypeQualifiers(), /*RefQualifierIsLValueRef=*/true, /*RefQualifierLoc=*/SourceLocation(), + /*ConstQualifierLoc=*/SourceLocation(), + /*VolatileQualifierLoc=*/SourceLocation(), MutableLoc, ESpecType, ESpecRange.getBegin(), DynamicExceptions.data(), @@ -756,24 +821,78 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( DeclLoc, DeclEndLoc, 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. + Diag(Tok, diag::err_lambda_missing_parens) + << Tok.is(tok::arrow) + << FixItHint::CreateInsertion(Tok.getLocation(), "() "); + SourceLocation DeclLoc = Tok.getLocation(); + SourceLocation DeclEndLoc = DeclLoc; + + // Parse 'mutable', if it's there. + SourceLocation MutableLoc; + if (Tok.is(tok::kw_mutable)) { + MutableLoc = ConsumeToken(); + DeclEndLoc = MutableLoc; + } + + // Parse the return type, if there is one. + ParsedType TrailingReturnType; + if (Tok.is(tok::arrow)) { + SourceRange Range; + TrailingReturnType = ParseTrailingReturnType(Range).get(); + if (Range.getEnd().isValid()) + DeclEndLoc = Range.getEnd(); + } + + ParsedAttributes Attr(AttrFactory); + D.AddTypeInfo(DeclaratorChunk::getFunction(/*hasProto=*/true, + /*isVariadic=*/false, + /*EllipsisLoc=*/SourceLocation(), + /*Params=*/0, /*NumParams=*/0, + /*TypeQuals=*/0, + /*RefQualifierIsLValueRef=*/true, + /*RefQualifierLoc=*/SourceLocation(), + /*ConstQualifierLoc=*/SourceLocation(), + /*VolatileQualifierLoc=*/SourceLocation(), + MutableLoc, + EST_None, + /*ESpecLoc=*/SourceLocation(), + /*Exceptions=*/0, + /*ExceptionRanges=*/0, + /*NumExceptions=*/0, + /*NoexceptExpr=*/0, + DeclLoc, DeclEndLoc, D, + TrailingReturnType), + Attr, DeclEndLoc); } + - // Parse compound-statement. - if (Tok.is(tok::l_brace)) { - // FIXME: Rename BlockScope -> ClosureScope if we decide to continue using - // it. - ParseScope BodyScope(this, Scope::BlockScope | Scope::FnScope | - Scope::BreakScope | Scope::ContinueScope | - Scope::DeclScope); + // FIXME: Rename BlockScope -> ClosureScope if we decide to continue using + // it. + unsigned ScopeFlags = Scope::BlockScope | Scope::FnScope | Scope::DeclScope; + if (getCurScope()->getFlags() & Scope::ThisScope) + ScopeFlags |= Scope::ThisScope; + ParseScope BodyScope(this, ScopeFlags); - StmtResult Stmt(ParseCompoundStatementBody()); + Actions.ActOnStartOfLambdaDefinition(Intro, D, getCurScope()); - BodyScope.Exit(); - } else { + // Parse compound-statement. + if (!Tok.is(tok::l_brace)) { Diag(Tok, diag::err_expected_lambda_body); + Actions.ActOnLambdaError(LambdaBeginLoc, getCurScope()); + return ExprError(); } - return ExprEmpty(); + StmtResult Stmt(ParseCompoundStatementBody()); + BodyScope.Exit(); + + if (!Stmt.isInvalid()) + return Actions.ActOnLambdaExpr(LambdaBeginLoc, Stmt.take(), getCurScope()); + + Actions.ActOnLambdaError(LambdaBeginLoc, getCurScope()); + return ExprError(); } /// ParseCXXCasts - This handles the various ways to cast expressions to another @@ -882,10 +1001,10 @@ ExprResult Parser::ParseCXXTypeid() { // operand (Clause 5). // // Note that we can't tell whether the expression is an lvalue of a - // polymorphic class type until after we've parsed the expression, so - // we the expression is potentially potentially evaluated. - EnterExpressionEvaluationContext Unevaluated(Actions, - Sema::PotentiallyPotentiallyEvaluated); + // polymorphic class type until after we've parsed the expression; we + // speculatively assume the subexpression is unevaluated, and fix it up + // later. + EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated); Result = ParseExpression(); // Match the ')'. @@ -988,6 +1107,8 @@ Parser::ParseCXXPseudoDestructor(ExprArg Base, SourceLocation OpLoc, assert(Tok.is(tok::coloncolon) &&"ParseOptionalCXXScopeSpecifier fail"); CCLoc = ConsumeToken(); } else if (Tok.is(tok::annot_template_id)) { + // FIXME: retrieve TemplateKWLoc from template-id annotation and + // store it in the pseudo-dtor node (to be used when instantiating it). FirstTypeName.setTemplateId( (TemplateIdAnnotation *)Tok.getAnnotationValue()); ConsumeToken(); @@ -1000,6 +1121,17 @@ Parser::ParseCXXPseudoDestructor(ExprArg Base, SourceLocation OpLoc, // Parse the tilde. assert(Tok.is(tok::tilde) && "ParseOptionalCXXScopeSpecifier fail"); SourceLocation TildeLoc = ConsumeToken(); + + if (Tok.is(tok::kw_decltype) && !FirstTypeName.isValid() && SS.isEmpty()) { + DeclSpec DS(AttrFactory); + ParseDecltypeSpecifier(DS); + if (DS.getTypeSpecType() == TST_error) + return ExprError(); + return Actions.ActOnPseudoDestructorExpr(getCurScope(), Base, OpLoc, + OpKind, TildeLoc, DS, + Tok.is(tok::l_paren)); + } + if (!Tok.is(tok::identifier)) { Diag(Tok, diag::err_destructor_tilde_identifier); return ExprError(); @@ -1014,9 +1146,10 @@ Parser::ParseCXXPseudoDestructor(ExprArg Base, SourceLocation OpLoc, // If there is a '<', the second type name is a template-id. Parse // it as such. if (Tok.is(tok::less) && - ParseUnqualifiedIdTemplateId(SS, Name, NameLoc, false, ObjectType, - SecondTypeName, /*AssumeTemplateName=*/true, - /*TemplateKWLoc*/SourceLocation())) + ParseUnqualifiedIdTemplateId(SS, SourceLocation(), + Name, NameLoc, + false, ObjectType, SecondTypeName, + /*AssumeTemplateName=*/true)) return ExprError(); return Actions.ActOnPseudoDestructorExpr(getCurScope(), Base, @@ -1092,14 +1225,17 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get(); assert((Tok.is(tok::l_paren) || - (getLang().CPlusPlus0x && Tok.is(tok::l_brace))) + (getLangOpts().CPlusPlus0x && Tok.is(tok::l_brace))) && "Expected '(' or '{'!"); if (Tok.is(tok::l_brace)) { - - // FIXME: Convert to a proper type construct expression. - return ParseBraceInitializer(); - + ExprResult Init = ParseBraceInitializer(); + if (Init.isInvalid()) + return Init; + Expr *InitList = Init.take(); + return Actions.ActOnCXXTypeConstructExpr(TypeRep, SourceLocation(), + MultiExprArg(&InitList, 1), + SourceLocation()); } else { GreaterThanIsOperatorScope G(GreaterThanIsOperator, true); @@ -1136,6 +1272,8 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { /// condition: /// expression /// type-specifier-seq declarator '=' assignment-expression +/// [C++11] type-specifier-seq declarator '=' initializer-clause +/// [C++11] type-specifier-seq declarator braced-init-list /// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt] /// '=' assignment-expression /// @@ -1206,18 +1344,35 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut, ExprOut = ExprError(); // '=' assignment-expression - if (isTokenEqualOrMistypedEqualEqual( - diag::err_invalid_equalequal_after_declarator)) { + // If a '==' or '+=' is found, suggest a fixit to '='. + bool CopyInitialization = isTokenEqualOrEqualTypo(); + if (CopyInitialization) ConsumeToken(); - ExprResult AssignExpr(ParseAssignmentExpression()); - if (!AssignExpr.isInvalid()) - Actions.AddInitializerToDecl(DeclOut, AssignExpr.take(), false, - DS.getTypeSpecType() == DeclSpec::TST_auto); + + ExprResult InitExpr = ExprError(); + if (getLangOpts().CPlusPlus0x && Tok.is(tok::l_brace)) { + Diag(Tok.getLocation(), + diag::warn_cxx98_compat_generalized_initializer_lists); + InitExpr = ParseBraceInitializer(); + } else if (CopyInitialization) { + InitExpr = ParseAssignmentExpression(); + } else if (Tok.is(tok::l_paren)) { + // This was probably an attempt to initialize the variable. + SourceLocation LParen = ConsumeParen(), RParen = LParen; + if (SkipUntil(tok::r_paren, true, /*DontConsume=*/true)) + RParen = ConsumeParen(); + Diag(DeclOut ? DeclOut->getLocation() : LParen, + diag::err_expected_init_in_condition_lparen) + << SourceRange(LParen, RParen); } else { - // FIXME: C++0x allows a braced-init-list - Diag(Tok, diag::err_expected_equal_after_declarator); + Diag(DeclOut ? DeclOut->getLocation() : Tok.getLocation(), + diag::err_expected_init_in_condition); } - + + if (!InitExpr.isInvalid()) + Actions.AddInitializerToDecl(DeclOut, InitExpr.take(), !CopyInitialization, + DS.getTypeSpecType() == DeclSpec::TST_auto); + // FIXME: Build a reference to this declaration? Convert it to bool? // (This is currently handled by Sema). @@ -1234,6 +1389,7 @@ bool Parser::isCXXSimpleTypeSpecifier() const { case tok::kw_short: case tok::kw_long: case tok::kw___int64: + case tok::kw___int128: case tok::kw_signed: case tok::kw_unsigned: case tok::kw_void: @@ -1312,7 +1468,7 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { // is a specific typedef and 'itf<proto1,proto2>' where 'itf' is an // Objective-C interface. If we don't have Objective-C or a '<', this is // just a normal reference to a typedef name. - if (Tok.is(tok::less) && getLang().ObjC1) + if (Tok.is(tok::less) && getLangOpts().ObjC1) ParseObjCProtocolQualifiers(DS); DS.Finish(Diags, PP); @@ -1344,6 +1500,9 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { case tok::kw_int: DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID); break; + case tok::kw___int128: + DS.SetTypeSpecType(DeclSpec::TST_int128, Loc, PrevSpec, DiagID); + break; case tok::kw_half: DS.SetTypeSpecType(DeclSpec::TST_half, Loc, PrevSpec, DiagID); break; @@ -1365,8 +1524,11 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { case tok::kw_bool: DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, DiagID); break; + case tok::annot_decltype: + case tok::kw_decltype: + DS.SetRangeEnd(ParseDecltypeSpecifier(DS)); + return DS.Finish(Diags, PP); - // FIXME: C++0x decltype support. // GNU typeof support. case tok::kw_typeof: ParseTypeofSpecifier(DS); @@ -1393,22 +1555,7 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { /// type-specifier type-specifier-seq[opt] /// bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) { - DS.SetRangeStart(Tok.getLocation()); - const char *PrevSpec = 0; - unsigned DiagID; - bool isInvalid = 0; - - // Parse one or more of the type specifiers. - if (!ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID, - ParsedTemplateInfo(), /*SuppressDeclarations*/true)) { - Diag(Tok, diag::err_expected_type); - return true; - } - - while (ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID, - ParsedTemplateInfo(), /*SuppressDeclarations*/true)) - {} - + ParseSpecifierQualifierList(DS, AS_none, DSC_type_specifier); DS.Finish(Diags, PP); return false; } @@ -1446,13 +1593,13 @@ bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) { /// /// \returns true if a parse error occurred, false otherwise. bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, IdentifierInfo *Name, SourceLocation NameLoc, bool EnteringContext, ParsedType ObjectType, UnqualifiedId &Id, - bool AssumeTemplateId, - SourceLocation TemplateKWLoc) { + bool AssumeTemplateId) { assert((AssumeTemplateId || Tok.is(tok::less)) && "Expected '<' to finish parsing a template-id"); @@ -1463,7 +1610,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, case UnqualifiedId::IK_OperatorFunctionId: case UnqualifiedId::IK_LiteralOperatorId: if (AssumeTemplateId) { - TNK = Actions.ActOnDependentTemplateName(getCurScope(), TemplateKWLoc, SS, + TNK = Actions.ActOnDependentTemplateName(getCurScope(), SS, TemplateKWLoc, Id, ObjectType, EnteringContext, Template); if (TNK == TNK_Non_template) @@ -1494,9 +1641,10 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, Diag(Id.StartLocation, diag::err_missing_dependent_template_keyword) << Name << FixItHint::CreateInsertion(Id.StartLocation, "template "); - TNK = Actions.ActOnDependentTemplateName(getCurScope(), TemplateKWLoc, - SS, Id, ObjectType, - EnteringContext, Template); + TNK = Actions.ActOnDependentTemplateName(getCurScope(), + SS, TemplateKWLoc, Id, + ObjectType, EnteringContext, + Template); if (TNK == TNK_Non_template) return true; } @@ -1519,9 +1667,10 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, bool MemberOfUnknownSpecialization; TemplateName.setIdentifier(Name, NameLoc); if (ObjectType) { - TNK = Actions.ActOnDependentTemplateName(getCurScope(), TemplateKWLoc, SS, - TemplateName, ObjectType, - EnteringContext, Template); + TNK = Actions.ActOnDependentTemplateName(getCurScope(), + SS, TemplateKWLoc, TemplateName, + ObjectType, EnteringContext, + Template); if (TNK == TNK_Non_template) return true; } else { @@ -1575,6 +1724,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, } TemplateId->SS = SS; + TemplateId->TemplateKWLoc = TemplateKWLoc; TemplateId->Template = Template; TemplateId->Kind = TNK; TemplateId->LAngleLoc = LAngleLoc; @@ -1591,12 +1741,13 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, // Bundle the template arguments together. ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateArgs.data(), TemplateArgs.size()); - + // Constructor and destructor names. TypeResult Type - = Actions.ActOnTemplateIdType(SS, Template, NameLoc, - LAngleLoc, TemplateArgsPtr, - RAngleLoc); + = Actions.ActOnTemplateIdType(SS, TemplateKWLoc, + Template, NameLoc, + LAngleLoc, TemplateArgsPtr, RAngleLoc, + /*IsCtorOrDtorName=*/true); if (Type.isInvalid()) return true; @@ -1666,7 +1817,9 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, bool isNew = Tok.getKind() == tok::kw_new; // Consume the 'new' or 'delete'. SymbolLocations[SymbolIdx++] = ConsumeToken(); - if (Tok.is(tok::l_square)) { + // Check for array new/delete. + if (Tok.is(tok::l_square) && + (!getLangOpts().CPlusPlus0x || NextToken().isNot(tok::l_square))) { // Consume the '[' and ']'. BalancedDelimiterTracker T(*this, tok::l_square); T.consumeOpen(); @@ -1742,18 +1895,68 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, // literal-operator-id: [C++0x 13.5.8] // operator "" identifier - if (getLang().CPlusPlus0x && Tok.is(tok::string_literal)) { - if (Tok.getLength() != 2) - Diag(Tok.getLocation(), diag::err_operator_string_not_empty); - ConsumeStringToken(); + if (getLangOpts().CPlusPlus0x && isTokenStringLiteral()) { + Diag(Tok.getLocation(), diag::warn_cxx98_compat_literal_operator); - if (Tok.isNot(tok::identifier)) { + SourceLocation DiagLoc; + unsigned DiagId = 0; + + // We're past translation phase 6, so perform string literal concatenation + // before checking for "". + llvm::SmallVector<Token, 4> Toks; + llvm::SmallVector<SourceLocation, 4> TokLocs; + while (isTokenStringLiteral()) { + if (!Tok.is(tok::string_literal) && !DiagId) { + DiagLoc = Tok.getLocation(); + DiagId = diag::err_literal_operator_string_prefix; + } + Toks.push_back(Tok); + TokLocs.push_back(ConsumeStringToken()); + } + + StringLiteralParser Literal(Toks.data(), Toks.size(), 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; + SourceLocation SuffixLoc; + if (!Literal.getUDSuffix().empty()) { + II = &PP.getIdentifierTable().get(Literal.getUDSuffix()); + SuffixLoc = + Lexer::AdvanceToTokenCharacter(TokLocs[Literal.getUDSuffixToken()], + Literal.getUDSuffixOffset(), + PP.getSourceManager(), getLangOpts()); + // This form is not permitted by the standard (yet). + DiagLoc = SuffixLoc; + DiagId = diag::err_literal_operator_missing_space; + } else if (Tok.is(tok::identifier)) { + II = Tok.getIdentifierInfo(); + SuffixLoc = ConsumeToken(); + TokLocs.push_back(SuffixLoc); + } else { Diag(Tok.getLocation(), diag::err_expected_ident); return true; } - IdentifierInfo *II = Tok.getIdentifierInfo(); - Result.setLiteralOperatorId(II, KeywordLoc, ConsumeToken()); + // The string literal must be empty. + if (!Literal.GetString().empty() || Literal.Pascal) { + DiagLoc = TokLocs.front(); + DiagId = diag::err_literal_operator_string_not_empty; + } + + if (DiagId) { + // This isn't a valid literal-operator-id, but we think we know + // what the user meant. Tell them what they should have written. + llvm::SmallString<32> Str; + Str += "\"\" "; + Str += II->getName(); + Diag(DiagLoc, DiagId) << FixItHint::CreateReplacement( + SourceRange(TokLocs.front(), TokLocs.back()), Str); + } + + Result.setLiteralOperatorId(II, KeywordLoc, SuffixLoc); return false; } @@ -1823,13 +2026,13 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, bool AllowDestructorName, bool AllowConstructorName, ParsedType ObjectType, + SourceLocation& TemplateKWLoc, UnqualifiedId &Result) { // Handle 'A::template B'. This is for template-ids which have not // already been annotated by ParseOptionalCXXScopeSpecifier(). bool TemplateSpecified = false; - SourceLocation TemplateKWLoc; - if (getLang().CPlusPlus && Tok.is(tok::kw_template) && + if (getLangOpts().CPlusPlus && Tok.is(tok::kw_template) && (ObjectType || SS.isSet())) { TemplateSpecified = true; TemplateKWLoc = ConsumeToken(); @@ -1843,7 +2046,7 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, IdentifierInfo *Id = Tok.getIdentifierInfo(); SourceLocation IdLoc = ConsumeToken(); - if (!getLang().CPlusPlus) { + if (!getLangOpts().CPlusPlus) { // If we're not in C++, only identifiers matter. Record the // identifier and return. Result.setIdentifier(Id, IdLoc); @@ -1853,11 +2056,12 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, if (AllowConstructorName && Actions.isCurrentClassName(*Id, getCurScope(), &SS)) { // We have parsed a constructor name. - Result.setConstructorName(Actions.getTypeName(*Id, IdLoc, getCurScope(), - &SS, false, false, - ParsedType(), - /*NonTrivialTypeSourceInfo=*/true), - IdLoc, IdLoc); + ParsedType Ty = Actions.getTypeName(*Id, IdLoc, getCurScope(), + &SS, false, false, + ParsedType(), + /*IsCtorOrDtorName=*/true, + /*NonTrivialTypeSourceInfo=*/true); + Result.setConstructorName(Ty, IdLoc, IdLoc); } else { // We have parsed an identifier. Result.setIdentifier(Id, IdLoc); @@ -1865,9 +2069,9 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, // If the next token is a '<', we may have a template. if (TemplateSpecified || Tok.is(tok::less)) - return ParseUnqualifiedIdTemplateId(SS, Id, IdLoc, EnteringContext, - ObjectType, Result, - TemplateSpecified, TemplateKWLoc); + return ParseUnqualifiedIdTemplateId(SS, TemplateKWLoc, Id, IdLoc, + EnteringContext, ObjectType, + Result, TemplateSpecified); return false; } @@ -1890,13 +2094,14 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, << TemplateId->Name << FixItHint::CreateRemoval( SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)); - Result.setConstructorName(Actions.getTypeName(*TemplateId->Name, - TemplateId->TemplateNameLoc, - getCurScope(), - &SS, false, false, - ParsedType(), - /*NontrivialTypeSourceInfo=*/true), - TemplateId->TemplateNameLoc, + ParsedType Ty = Actions.getTypeName(*TemplateId->Name, + TemplateId->TemplateNameLoc, + getCurScope(), + &SS, false, false, + ParsedType(), + /*IsCtorOrDtorName=*/true, + /*NontrivialTypeSourceInfo=*/true); + Result.setConstructorName(Ty, TemplateId->TemplateNameLoc, TemplateId->RAngleLoc); ConsumeToken(); return false; @@ -1910,6 +2115,7 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, // We have already parsed a template-id; consume the annotation token as // our unqualified-id. Result.setTemplateId(TemplateId); + TemplateKWLoc = TemplateId->TemplateKWLoc; ConsumeToken(); return false; } @@ -1929,15 +2135,15 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, if ((Result.getKind() == UnqualifiedId::IK_OperatorFunctionId || Result.getKind() == UnqualifiedId::IK_LiteralOperatorId) && (TemplateSpecified || Tok.is(tok::less))) - return ParseUnqualifiedIdTemplateId(SS, 0, SourceLocation(), - EnteringContext, ObjectType, - Result, - TemplateSpecified, TemplateKWLoc); + return ParseUnqualifiedIdTemplateId(SS, TemplateKWLoc, + 0, SourceLocation(), + EnteringContext, ObjectType, + Result, TemplateSpecified); return false; } - if (getLang().CPlusPlus && + if (getLangOpts().CPlusPlus && (AllowDestructorName || SS.isSet()) && Tok.is(tok::tilde)) { // C++ [expr.unary.op]p10: // There is an ambiguity in the unary-expression ~X(), where X is a @@ -1946,6 +2152,16 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, // Parse the '~'. SourceLocation TildeLoc = ConsumeToken(); + + if (SS.isEmpty() && Tok.is(tok::kw_decltype)) { + DeclSpec DS(AttrFactory); + SourceLocation EndLoc = ParseDecltypeSpecifier(DS); + if (ParsedType Type = Actions.getDestructorType(DS, ObjectType)) { + Result.setDestructorName(TildeLoc, Type, EndLoc); + return false; + } + return true; + } // Parse the class-name. if (Tok.isNot(tok::identifier)) { @@ -1959,9 +2175,10 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, if (TemplateSpecified || Tok.is(tok::less)) { Result.setDestructorName(TildeLoc, ParsedType(), ClassNameLoc); - return ParseUnqualifiedIdTemplateId(SS, ClassName, ClassNameLoc, - EnteringContext, ObjectType, Result, - TemplateSpecified, TemplateKWLoc); + return ParseUnqualifiedIdTemplateId(SS, TemplateKWLoc, + ClassName, ClassNameLoc, + EnteringContext, ObjectType, + Result, TemplateSpecified); } // Note that this is a destructor name. @@ -1977,7 +2194,7 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, } Diag(Tok, diag::err_expected_unqualified_id) - << getLang().CPlusPlus; + << getLangOpts().CPlusPlus; return true; } @@ -2083,10 +2300,11 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { return ExprError(); } - ExprVector ConstructorArgs(Actions); - SourceLocation ConstructorLParen, ConstructorRParen; + ExprResult Initializer; if (Tok.is(tok::l_paren)) { + SourceLocation ConstructorLParen, ConstructorRParen; + ExprVector ConstructorArgs(Actions); BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); ConstructorLParen = T.getOpenLocation(); @@ -2103,15 +2321,20 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true); return ExprError(); } - } else if (Tok.is(tok::l_brace)) { - // FIXME: Have to communicate the init-list to ActOnCXXNew. - ParseBraceInitializer(); + Initializer = Actions.ActOnParenListExpr(ConstructorLParen, + ConstructorRParen, + move_arg(ConstructorArgs)); + } else if (Tok.is(tok::l_brace) && getLangOpts().CPlusPlus0x) { + Diag(Tok.getLocation(), + diag::warn_cxx98_compat_generalized_initializer_lists); + Initializer = ParseBraceInitializer(); } + if (Initializer.isInvalid()) + return Initializer; return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen, move_arg(PlacementArgs), PlacementRParen, - TypeIdParens, DeclaratorInfo, ConstructorLParen, - move_arg(ConstructorArgs), ConstructorRParen); + TypeIdParens, DeclaratorInfo, Initializer.take()); } /// ParseDirectNewDeclarator - Parses a direct-new-declarator. Intended to be @@ -2125,6 +2348,10 @@ void Parser::ParseDirectNewDeclarator(Declarator &D) { // Parse the array dimensions. bool first = true; while (Tok.is(tok::l_square)) { + // An array-size expression can't start with a lambda. + if (CheckProhibitedCXX11Attribute()) + continue; + BalancedDelimiterTracker T(*this, tok::l_square); T.consumeOpen(); @@ -2139,13 +2366,16 @@ void Parser::ParseDirectNewDeclarator(Declarator &D) { T.consumeClose(); - ParsedAttributes attrs(AttrFactory); + // Attributes here appertain to the array type. C++11 [expr.new]p5. + ParsedAttributes Attrs(AttrFactory); + MaybeParseCXX0XAttributes(Attrs); + D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false, Size.release(), T.getOpenLocation(), T.getCloseLocation()), - attrs, T.getCloseLocation()); + Attrs, T.getCloseLocation()); if (T.getCloseLocation().isInvalid()) return; @@ -2197,7 +2427,11 @@ Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) { // Array delete? bool ArrayDelete = false; - if (Tok.is(tok::l_square)) { + if (Tok.is(tok::l_square) && NextToken().is(tok::r_square)) { + // FIXME: This could be the start of a lambda-expression. We should + // disambiguate this, but that will require arbitrary lookahead if + // the next token is '(': + // delete [](int*){ /* ... */ ArrayDelete = true; BalancedDelimiterTracker T(*this, tok::l_square); @@ -2235,6 +2469,7 @@ static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) { 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; @@ -2271,6 +2506,15 @@ static BinaryTypeTrait BinaryTypeTraitFromTokKind(tok::TokenKind kind) { 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; + } +} + +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; } } @@ -2356,6 +2600,58 @@ ExprResult Parser::ParseBinaryTypeTrait() { T.getCloseLocation()); } +/// \brief Parse the built-in type-trait pseudo-functions that allow +/// implementation of the TR1/C++11 type traits templates. +/// +/// primary-expression: +/// type-trait '(' type-id-seq ')' +/// +/// type-id-seq: +/// type-id ...[opt] type-id-seq[opt] +/// +ExprResult Parser::ParseTypeTrait() { + TypeTrait Kind = TypeTraitFromTokKind(Tok.getKind()); + SourceLocation Loc = ConsumeToken(); + + BalancedDelimiterTracker Parens(*this, tok::l_paren); + if (Parens.expectAndConsume(diag::err_expected_lparen)) + return ExprError(); + + llvm::SmallVector<ParsedType, 2> Args; + do { + // Parse the next type. + TypeResult Ty = ParseTypeName(); + if (Ty.isInvalid()) { + Parens.skipToEnd(); + return ExprError(); + } + + // Parse the ellipsis, if present. + if (Tok.is(tok::ellipsis)) { + Ty = Actions.ActOnPackExpansion(Ty.get(), ConsumeToken()); + if (Ty.isInvalid()) { + Parens.skipToEnd(); + return ExprError(); + } + } + + // Add this type to the list of arguments. + Args.push_back(Ty.get()); + + if (Tok.is(tok::comma)) { + ConsumeToken(); + continue; + } + + break; + } while (true); + + if (Parens.consumeClose()) + return ExprError(); + + return Actions.ActOnTypeTrait(Kind, Loc, Args, Parens.getCloseLocation()); +} + /// ParseArrayTypeTrait - Parse the built-in array type-trait /// pseudo-functions. /// @@ -2396,10 +2692,8 @@ ExprResult Parser::ParseArrayTypeTrait() { return Actions.ActOnArrayTypeTrait(ATT, Loc, Ty.get(), DimExpr.get(), T.getCloseLocation()); } - default: - break; } - return ExprError(); + llvm_unreachable("Invalid ArrayTypeTrait!"); } /// ParseExpressionTrait - Parse built-in expression-trait @@ -2432,7 +2726,7 @@ ExprResult Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, ParsedType &CastTy, BalancedDelimiterTracker &Tracker) { - assert(getLang().CPlusPlus && "Should only be called for C++!"); + assert(getLangOpts().CPlusPlus && "Should only be called for C++!"); assert(ExprType == CastExpr && "Compound literals are not ambiguous!"); assert(isTypeIdInParens() && "Not a type-id!"); @@ -2484,7 +2778,7 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, false/*isAddressofOperand*/, NotCastExpr, // type-id has priority. - true/*isTypeCast*/); + IsTypeCast); } // If we parsed a cast-expression, it's really a type-id, otherwise it's |