diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2010-05-27 15:17:06 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2010-05-27 15:17:06 +0000 |
commit | 53992adde3eda3ccf9da63bc7e45673f043de18f (patch) | |
tree | 3558f327a6f9ab59c5d7a06528d84e1560445247 /lib/Parse | |
parent | 7e411337c0ed226dace6e07f1420486768161308 (diff) | |
download | FreeBSD-src-53992adde3eda3ccf9da63bc7e45673f043de18f.zip FreeBSD-src-53992adde3eda3ccf9da63bc7e45673f043de18f.tar.gz |
Update clang to r104832.
Diffstat (limited to 'lib/Parse')
-rw-r--r-- | lib/Parse/AttributeList.cpp | 6 | ||||
-rw-r--r-- | lib/Parse/MinimalAction.cpp | 4 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 70 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 21 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 33 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 140 | ||||
-rw-r--r-- | lib/Parse/ParseObjc.cpp | 58 | ||||
-rw-r--r-- | lib/Parse/ParsePragma.cpp | 53 | ||||
-rw-r--r-- | lib/Parse/ParsePragma.h | 9 | ||||
-rw-r--r-- | lib/Parse/ParseStmt.cpp | 94 | ||||
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 37 | ||||
-rw-r--r-- | lib/Parse/ParseTentative.cpp | 1 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 38 |
13 files changed, 438 insertions, 126 deletions
diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp index bae2a09..1ebff22 100644 --- a/lib/Parse/AttributeList.cpp +++ b/lib/Parse/AttributeList.cpp @@ -84,6 +84,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { .Case("fastcall", AT_fastcall) .Case("ibaction", AT_IBAction) .Case("iboutlet", AT_IBOutlet) + .Case("iboutletcollection", AT_IBOutletCollection) .Case("noreturn", AT_noreturn) .Case("noinline", AT_noinline) .Case("override", AT_override) @@ -119,5 +120,10 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { .Case("cf_returns_retained", AT_cf_returns_retained) .Case("reqd_work_group_size", AT_reqd_wg_size) .Case("no_instrument_function", AT_no_instrument_function) + .Case("thiscall", AT_thiscall) + .Case("__cdecl", AT_cdecl) + .Case("__stdcall", AT_stdcall) + .Case("__fastcall", AT_fastcall) + .Case("__thiscall", AT_thiscall) .Default(UnknownAttribute); } diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp index 5a03767..b720516 100644 --- a/lib/Parse/MinimalAction.cpp +++ b/lib/Parse/MinimalAction.cpp @@ -194,7 +194,9 @@ MinimalAction::isTemplateName(Scope *S, UnqualifiedId &Name, TypeTy *ObjectType, bool EnteringScope, - TemplateTy &TemplateDecl) { + TemplateTy &TemplateDecl, + bool &MemberOfUnknownSpecialization) { + MemberOfUnknownSpecialization = false; return TNK_Non_template; } diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 91050e0..3e7d4a1 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -277,8 +277,8 @@ AttributeList* Parser::ParseMicrosoftTypeAttributes(AttributeList *CurrAttr) { // Treat these like attributes // FIXME: Allow Sema to distinguish between these and real attributes! while (Tok.is(tok::kw___fastcall) || Tok.is(tok::kw___stdcall) || - Tok.is(tok::kw___cdecl) || Tok.is(tok::kw___ptr64) || - Tok.is(tok::kw___w64)) { + Tok.is(tok::kw___thiscall) || Tok.is(tok::kw___cdecl) || + Tok.is(tok::kw___ptr64) || Tok.is(tok::kw___w64)) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); if (Tok.is(tok::kw___ptr64) || Tok.is(tok::kw___w64)) @@ -364,7 +364,8 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context, // declaration-specifiers init-declarator-list[opt] ';' if (Tok.is(tok::semi)) { if (RequireSemi) ConsumeToken(); - DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS); + DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, AS_none, + DS); DS.complete(TheDecl); return Actions.ConvertDeclToDeclGroup(TheDecl); } @@ -838,7 +839,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, CCC = Action::CCC_ObjCImplementation; Actions.CodeCompleteOrdinaryName(CurScope, CCC); - ConsumeToken(); + ConsumeCodeCompletionToken(); } DS.SetRangeStart(Tok.getLocation()); @@ -1143,6 +1144,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, case tok::kw___cdecl: case tok::kw___stdcall: case tok::kw___fastcall: + case tok::kw___thiscall: DS.AddAttributes(ParseMicrosoftTypeAttributes()); continue; @@ -1622,6 +1624,7 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid, case tok::kw___cdecl: case tok::kw___stdcall: case tok::kw___fastcall: + case tok::kw___thiscall: DS.AddAttributes(ParseMicrosoftTypeAttributes()); return true; @@ -1674,7 +1677,7 @@ ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) { // If there are no declarators, this is a free-standing declaration // specifier. Let the actions module cope with it. if (Tok.is(tok::semi)) { - Actions.ParsedFreeStandingDeclSpec(CurScope, DS); + Actions.ParsedFreeStandingDeclSpec(CurScope, AS_none, DS); return; } @@ -1867,7 +1870,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, if (Tok.is(tok::code_completion)) { // Code completion for an enum name. Actions.CodeCompleteTag(CurScope, DeclSpec::TST_enum); - ConsumeToken(); + ConsumeCodeCompletionToken(); } llvm::OwningPtr<AttributeList> Attr; @@ -1875,7 +1878,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, if (Tok.is(tok::kw___attribute)) Attr.reset(ParseGNUAttributes()); - CXXScopeSpec SS; + CXXScopeSpec &SS = DS.getTypeSpecScope(); if (getLang().CPlusPlus) { if (ParseOptionalCXXScopeSpecifier(SS, 0, false)) return; @@ -2198,6 +2201,7 @@ bool Parser::isTypeSpecifierQualifier() { case tok::kw___cdecl: case tok::kw___stdcall: case tok::kw___fastcall: + case tok::kw___thiscall: case tok::kw___w64: case tok::kw___ptr64: return true; @@ -2304,6 +2308,7 @@ bool Parser::isDeclarationSpecifier() { case tok::kw___cdecl: case tok::kw___stdcall: case tok::kw___fastcall: + case tok::kw___thiscall: case tok::kw___w64: case tok::kw___ptr64: case tok::kw___forceinline: @@ -2401,6 +2406,7 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, bool GNUAttributesAllowed, case tok::kw___cdecl: case tok::kw___stdcall: case tok::kw___fastcall: + case tok::kw___thiscall: if (GNUAttributesAllowed) { DS.AddAttributes(ParseMicrosoftTypeAttributes()); continue; @@ -2785,8 +2791,8 @@ void Parser::ParseParenDeclarator(Declarator &D) { } // Eat any Microsoft extensions. if (Tok.is(tok::kw___cdecl) || Tok.is(tok::kw___stdcall) || - Tok.is(tok::kw___fastcall) || Tok.is(tok::kw___w64) || - Tok.is(tok::kw___ptr64)) { + Tok.is(tok::kw___thiscall) || Tok.is(tok::kw___fastcall) || + Tok.is(tok::kw___w64) || Tok.is(tok::kw___ptr64)) { AttrList.reset(ParseMicrosoftTypeAttributes(AttrList.take())); } @@ -2937,9 +2943,33 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, Diag(Tok, diag::err_argument_required_after_attribute); delete AttrList; } + // Identifier list. Note that '(' identifier-list ')' is only allowed for - // normal declarators, not for abstract-declarators. - return ParseFunctionDeclaratorIdentifierList(LParenLoc, D); + // normal declarators, not for abstract-declarators. Get the first + // identifier. + Token FirstTok = Tok; + ConsumeToken(); // eat the first identifier. + + // Identifier lists follow a really simple grammar: the identifiers can + // be followed *only* by a ", moreidentifiers" or ")". However, K&R + // identifier lists are really rare in the brave new modern world, and it + // is very common for someone to typo a type in a non-k&r style list. If + // we are presented with something like: "void foo(intptr x, float y)", + // we don't want to start parsing the function declarator as though it is + // a K&R style declarator just because intptr is an invalid type. + // + // To handle this, we check to see if the token after the first identifier + // is a "," or ")". Only if so, do we parse it as an identifier list. + if (Tok.is(tok::comma) || Tok.is(tok::r_paren)) + return ParseFunctionDeclaratorIdentifierList(LParenLoc, + FirstTok.getIdentifierInfo(), + FirstTok.getLocation(), D); + + // If we get here, the code is invalid. Push the first identifier back + // into the token stream and parse the first argument as an (invalid) + // normal argument declarator. + PP.EnterToken(Tok); + Tok = FirstTok; } } @@ -3122,13 +3152,16 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, /// ParseFunctionDeclaratorIdentifierList - While parsing a function declarator /// we found a K&R-style identifier list instead of a type argument list. The -/// current token is known to be the first identifier in the list. +/// first identifier has already been consumed, and the current token is the +/// token right after it. /// /// identifier-list: [C99 6.7.5] /// identifier /// identifier-list ',' identifier /// void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc, + IdentifierInfo *FirstIdent, + SourceLocation FirstIdentLoc, Declarator &D) { // Build up an array of information about the parsed arguments. llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo; @@ -3139,17 +3172,14 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc, // to be abstract. In abstract-declarators, identifier lists are not valid: // diagnose this. if (!D.getIdentifier()) - Diag(Tok, diag::ext_ident_list_in_param); + Diag(FirstIdentLoc, diag::ext_ident_list_in_param); - // Tok is known to be the first identifier in the list. Remember this - // identifier in ParamInfo. - ParamsSoFar.insert(Tok.getIdentifierInfo()); - ParamInfo.push_back(DeclaratorChunk::ParamInfo(Tok.getIdentifierInfo(), - Tok.getLocation(), + // The first identifier was already read, and is known to be the first + // identifier in the list. Remember this identifier in ParamInfo. + ParamsSoFar.insert(FirstIdent); + ParamInfo.push_back(DeclaratorChunk::ParamInfo(FirstIdent, FirstIdentLoc, DeclPtrTy())); - ConsumeToken(); // eat the first identifier. - while (Tok.is(tok::comma)) { // Eat the comma. ConsumeToken(); diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 015ac5b..479c04c 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -50,7 +50,7 @@ Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context, if (Tok.is(tok::code_completion)) { Actions.CodeCompleteNamespaceDecl(CurScope); - ConsumeToken(); + ConsumeCodeCompletionToken(); } SourceLocation IdentLoc; @@ -87,6 +87,14 @@ Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context, SourceLocation LBrace = ConsumeBrace(); + if (CurScope->isClassScope() || CurScope->isTemplateParamScope() || + CurScope->isInObjcMethodScope() || CurScope->getBlockParent() || + CurScope->getFnParent()) { + Diag(LBrace, diag::err_namespace_nonnamespace_scope); + SkipUntil(tok::r_brace, false); + return DeclPtrTy(); + } + // Enter a scope for the namespace. ParseScope NamespaceScope(this, Scope::DeclScope); @@ -128,7 +136,7 @@ Parser::DeclPtrTy Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc, if (Tok.is(tok::code_completion)) { Actions.CodeCompleteNamespaceAliasDecl(CurScope); - ConsumeToken(); + ConsumeCodeCompletionToken(); } CXXScopeSpec SS; @@ -223,7 +231,7 @@ Parser::DeclPtrTy Parser::ParseUsingDirectiveOrDeclaration(unsigned Context, if (Tok.is(tok::code_completion)) { Actions.CodeCompleteUsing(CurScope); - ConsumeToken(); + ConsumeCodeCompletionToken(); } if (Tok.is(tok::kw_namespace)) @@ -260,7 +268,7 @@ Parser::DeclPtrTy Parser::ParseUsingDirective(unsigned Context, if (Tok.is(tok::code_completion)) { Actions.CodeCompleteUsingDirective(CurScope); - ConsumeToken(); + ConsumeCodeCompletionToken(); } CXXScopeSpec SS; @@ -602,7 +610,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, if (Tok.is(tok::code_completion)) { // Code completion for a struct, class, or union name. Actions.CodeCompleteTag(CurScope, TagType); - ConsumeToken(); + ConsumeCodeCompletionToken(); } AttributeList *AttrList = 0; @@ -973,6 +981,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, case tok::kw_typedef: // struct foo {...} typedef x; case tok::kw_register: // struct foo {...} register x; case tok::kw_auto: // struct foo {...} auto x; + case tok::kw_mutable: // struct foo {...} mutable x; // As shown above, type qualifiers and storage class specifiers absolutely // can occur after class specifiers according to the grammar. However, // almost noone actually writes code like this. If we see one of these, @@ -1298,7 +1307,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (Tok.is(tok::semi)) { ConsumeToken(); - Actions.ParsedFreeStandingDeclSpec(CurScope, DS); + Actions.ParsedFreeStandingDeclSpec(CurScope, AS, DS); return; } diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index b9e632a..b036e56 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -222,7 +222,7 @@ Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) { Parser::OwningExprResult Parser::ParseAssignmentExpression() { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Expression); - ConsumeToken(); + ConsumeCodeCompletionToken(); } if (Tok.is(tok::kw_throw)) @@ -315,8 +315,29 @@ Parser::ParseRHSOfBinaryExpression(OwningExprResult LHS, prec::Level MinPrec) { // Eat the colon. ColonLoc = ConsumeToken(); } else { + // Otherwise, we're missing a ':'. Assume that this was a typo that the + // user forgot. If we're not in a macro instantion, we can suggest a + // fixit hint. If there were two spaces before the current token, + // suggest inserting the colon in between them, otherwise insert ": ". + SourceLocation FILoc = Tok.getLocation(); + const char *FIText = ": "; + if (FILoc.isFileID()) { + const SourceManager &SM = PP.getSourceManager(); + bool IsInvalid = false; + const char *SourcePtr = + SM.getCharacterData(FILoc.getFileLocWithOffset(-1), &IsInvalid); + if (!IsInvalid && *SourcePtr == ' ') { + SourcePtr = + SM.getCharacterData(FILoc.getFileLocWithOffset(-2), &IsInvalid); + if (!IsInvalid && *SourcePtr == ' ') { + FILoc = FILoc.getFileLocWithOffset(-1); + FIText = ":"; + } + } + } + Diag(Tok, diag::err_expected_colon) - << FixItHint::CreateInsertion(Tok.getLocation(), ": "); + << FixItHint::CreateInsertion(FILoc, FIText); Diag(OpToken, diag::note_matching) << "?"; ColonLoc = Tok.getLocation(); } @@ -885,7 +906,7 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression, return ParsePostfixExpressionSuffix(ParseBlockLiteralExpression()); case tok::code_completion: Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Expression); - ConsumeToken(); + ConsumeCodeCompletionToken(); return ParseCastExpression(isUnaryExpression, isAddressOfOperand, NotCastExpr, TypeOfCast); case tok::l_square: @@ -954,7 +975,7 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteCall(CurScope, LHS.get(), 0, 0); - ConsumeToken(); + ConsumeCodeCompletionToken(); } if (Tok.isNot(tok::r_paren)) { @@ -1008,7 +1029,7 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) { Actions.CodeCompleteMemberReferenceExpr(CurScope, LHS.get(), OpLoc, OpKind == tok::arrow); - ConsumeToken(); + ConsumeCodeCompletionToken(); } if (MayBePseudoDestructor) { @@ -1541,7 +1562,7 @@ bool Parser::ParseExpressionList(ExprListTy &Exprs, CommaLocsTy &CommaLocs, if (Tok.is(tok::code_completion)) { if (Completer) (Actions.*Completer)(CurScope, Data, Exprs.data(), Exprs.size()); - ConsumeToken(); + ConsumeCodeCompletionToken(); } OwningExprResult Expr(ParseAssignmentExpression()); diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 146762b..46f1d94 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -110,7 +110,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, // Code completion for a nested-name-specifier, where the code // code completion token follows the '::'. Actions.CodeCompleteQualifiedId(CurScope, SS, EnteringContext); - ConsumeToken(); + ConsumeCodeCompletionToken(); } } @@ -289,11 +289,13 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, TemplateTy Template; UnqualifiedId TemplateName; TemplateName.setIdentifier(&II, Tok.getLocation()); + bool MemberOfUnknownSpecialization; if (TemplateNameKind TNK = Actions.isTemplateName(CurScope, SS, TemplateName, ObjectType, EnteringContext, - Template)) { + Template, + MemberOfUnknownSpecialization)) { // We have found a template name, so annotate this this token // with a template-id annotation. We do not permit the // template-id to be translated into a type annotation, @@ -305,6 +307,31 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, SourceLocation(), false)) return true; continue; + } + + if (MemberOfUnknownSpecialization && (ObjectType || SS.isSet()) && + IsTemplateArgumentList(1)) { + // We have something like t::getAs<T>, where getAs is a + // member of an unknown specialization. However, this will only + // parse correctly as a template, so suggest the keyword 'template' + // before 'getAs' and treat this as a dependent template name. + Diag(Tok.getLocation(), diag::err_missing_dependent_template_keyword) + << II.getName() + << FixItHint::CreateInsertion(Tok.getLocation(), "template "); + + Template = Actions.ActOnDependentTemplateName(Tok.getLocation(), SS, + TemplateName, ObjectType, + EnteringContext); + if (!Template.get()) + return true; + + // Consume the identifier. + ConsumeToken(); + if (AnnotateTemplateIdToken(Template, TNK_Dependent_template_name, &SS, + TemplateName, SourceLocation(), false)) + return true; + + continue; } } @@ -576,7 +603,8 @@ Parser::ParseCXXPseudoDestructor(ExprArg Base, SourceLocation OpLoc, // it as such. if (Tok.is(tok::less) && ParseUnqualifiedIdTemplateId(SS, Name, NameLoc, false, ObjectType, - SecondTypeName, /*AssumeTemplateName=*/true)) + SecondTypeName, /*AssumeTemplateName=*/true, + /*TemplateKWLoc*/SourceLocation())) return ExprError(); return Actions.ActOnPseudoDestructorExpr(CurScope, move(Base), OpLoc, OpKind, @@ -688,17 +716,33 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { /// \param DeclResult if the condition was parsed as a declaration, the /// parsed declaration. /// +/// \param Loc The location of the start of the statement that requires this +/// condition, e.g., the "for" in a for loop. +/// +/// \param ConvertToBoolean Whether the condition expression should be +/// converted to a boolean value. +/// /// \returns true if there was a parsing, false otherwise. bool Parser::ParseCXXCondition(OwningExprResult &ExprResult, - DeclPtrTy &DeclResult) { + DeclPtrTy &DeclResult, + SourceLocation Loc, + bool ConvertToBoolean) { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Condition); - ConsumeToken(); + ConsumeCodeCompletionToken(); } if (!isCXXConditionDeclaration()) { + // Parse the expression. ExprResult = ParseExpression(); // expression DeclResult = DeclPtrTy(); + if (ExprResult.isInvalid()) + return true; + + // If required, convert to a boolean value. + if (ConvertToBoolean) + ExprResult + = Actions.ActOnBooleanCondition(CurScope, Loc, move(ExprResult)); return ExprResult.isInvalid(); } @@ -746,6 +790,9 @@ bool Parser::ParseCXXCondition(OwningExprResult &ExprResult, Diag(Tok, diag::err_expected_equal_after_declarator); } + // FIXME: Build a reference to this declaration? Convert it to bool? + // (This is currently handled by Sema). + return false; } @@ -952,8 +999,10 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, bool EnteringContext, TypeTy *ObjectType, UnqualifiedId &Id, - bool AssumeTemplateId) { - assert(Tok.is(tok::less) && "Expected '<' to finish parsing a template-id"); + bool AssumeTemplateId, + SourceLocation TemplateKWLoc) { + assert((AssumeTemplateId || Tok.is(tok::less)) && + "Expected '<' to finish parsing a template-id"); TemplateTy Template; TemplateNameKind TNK = TNK_Non_template; @@ -962,30 +1011,63 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, case UnqualifiedId::IK_OperatorFunctionId: case UnqualifiedId::IK_LiteralOperatorId: if (AssumeTemplateId) { - Template = Actions.ActOnDependentTemplateName(SourceLocation(), SS, + Template = Actions.ActOnDependentTemplateName(TemplateKWLoc, SS, Id, ObjectType, EnteringContext); TNK = TNK_Dependent_template_name; if (!Template.get()) return true; - } else + } else { + bool MemberOfUnknownSpecialization; TNK = Actions.isTemplateName(CurScope, SS, Id, ObjectType, - EnteringContext, Template); + EnteringContext, Template, + MemberOfUnknownSpecialization); + + if (TNK == TNK_Non_template && MemberOfUnknownSpecialization && + ObjectType && IsTemplateArgumentList()) { + // We have something like t->getAs<T>(), where getAs is a + // member of an unknown specialization. However, this will only + // parse correctly as a template, so suggest the keyword 'template' + // before 'getAs' and treat this as a dependent template name. + std::string Name; + if (Id.getKind() == UnqualifiedId::IK_Identifier) + Name = Id.Identifier->getName(); + else { + Name = "operator "; + if (Id.getKind() == UnqualifiedId::IK_OperatorFunctionId) + Name += getOperatorSpelling(Id.OperatorFunctionId.Operator); + else + Name += Id.Identifier->getName(); + } + Diag(Id.StartLocation, diag::err_missing_dependent_template_keyword) + << Name + << FixItHint::CreateInsertion(Id.StartLocation, "template "); + Template = Actions.ActOnDependentTemplateName(TemplateKWLoc, SS, + Id, ObjectType, + EnteringContext); + TNK = TNK_Dependent_template_name; + if (!Template.get()) + return true; + } + } break; case UnqualifiedId::IK_ConstructorName: { UnqualifiedId TemplateName; + bool MemberOfUnknownSpecialization; TemplateName.setIdentifier(Name, NameLoc); TNK = Actions.isTemplateName(CurScope, SS, TemplateName, ObjectType, - EnteringContext, Template); + EnteringContext, Template, + MemberOfUnknownSpecialization); break; } case UnqualifiedId::IK_DestructorName: { UnqualifiedId TemplateName; + bool MemberOfUnknownSpecialization; TemplateName.setIdentifier(Name, NameLoc); if (ObjectType) { - Template = Actions.ActOnDependentTemplateName(SourceLocation(), SS, + Template = Actions.ActOnDependentTemplateName(TemplateKWLoc, SS, TemplateName, ObjectType, EnteringContext); TNK = TNK_Dependent_template_name; @@ -993,7 +1075,8 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, return true; } else { TNK = Actions.isTemplateName(CurScope, SS, TemplateName, ObjectType, - EnteringContext, Template); + EnteringContext, Template, + MemberOfUnknownSpecialization); if (TNK == TNK_Non_template && Id.DestructorName == 0) { Diag(NameLoc, diag::err_destructor_template_id) @@ -1014,7 +1097,8 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, // Parse the enclosed template argument list. SourceLocation LAngleLoc, RAngleLoc; TemplateArgList TemplateArgs; - if (ParseTemplateIdAfterTemplateName(Template, Id.StartLocation, + if (Tok.is(tok::less) && + ParseTemplateIdAfterTemplateName(Template, Id.StartLocation, &SS, true, LAngleLoc, TemplateArgs, RAngleLoc)) @@ -1190,7 +1274,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, Actions.CodeCompleteOperatorName(CurScope); // Consume the operator token. - ConsumeToken(); + ConsumeCodeCompletionToken(); // Don't try to parse any further. return true; @@ -1293,6 +1377,17 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, bool AllowConstructorName, TypeTy *ObjectType, 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) && + (ObjectType || SS.isSet())) { + TemplateSpecified = true; + TemplateKWLoc = ConsumeToken(); + } + // unqualified-id: // identifier // template-id (when it hasn't already been annotated) @@ -1320,9 +1415,10 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, } // If the next token is a '<', we may have a template. - if (Tok.is(tok::less)) + if (TemplateSpecified || Tok.is(tok::less)) return ParseUnqualifiedIdTemplateId(SS, Id, IdLoc, EnteringContext, - ObjectType, Result); + ObjectType, Result, + TemplateSpecified, TemplateKWLoc); return false; } @@ -1383,10 +1479,11 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, // operator-function-id < template-argument-list[opt] > if ((Result.getKind() == UnqualifiedId::IK_OperatorFunctionId || Result.getKind() == UnqualifiedId::IK_LiteralOperatorId) && - Tok.is(tok::less)) + (TemplateSpecified || Tok.is(tok::less))) return ParseUnqualifiedIdTemplateId(SS, 0, SourceLocation(), EnteringContext, ObjectType, - Result); + Result, + TemplateSpecified, TemplateKWLoc); return false; } @@ -1411,10 +1508,11 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, IdentifierInfo *ClassName = Tok.getIdentifierInfo(); SourceLocation ClassNameLoc = ConsumeToken(); - if (Tok.is(tok::less)) { + if (TemplateSpecified || Tok.is(tok::less)) { Result.setDestructorName(TildeLoc, 0, ClassNameLoc); return ParseUnqualifiedIdTemplateId(SS, ClassName, ClassNameLoc, - EnteringContext, ObjectType, Result); + EnteringContext, ObjectType, Result, + TemplateSpecified, TemplateKWLoc); } // Note that this is a destructor name. diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 7b1ecf6..9cfe734 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -32,7 +32,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtDirectives() { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCAtDirective(CurScope, ObjCImpDecl, false); - ConsumeToken(); + ConsumeCodeCompletionToken(); } switch (Tok.getObjCKeywordID()) { @@ -131,7 +131,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration( // Code completion after '@interface'. if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCInterfaceDecl(CurScope); - ConsumeToken(); + ConsumeCodeCompletionToken(); } if (Tok.isNot(tok::identifier)) { @@ -149,7 +149,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration( IdentifierInfo *categoryId = 0; if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCInterfaceCategory(CurScope, nameId, nameLoc); - ConsumeToken(); + ConsumeCodeCompletionToken(); } // For ObjC2, the category name is optional (not an error). @@ -204,7 +204,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration( // Code completion of superclass names. if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCSuperclass(CurScope, nameId, nameLoc); - ConsumeToken(); + ConsumeCodeCompletionToken(); } if (Tok.isNot(tok::identifier)) { @@ -350,7 +350,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl, Actions.CodeCompleteOrdinaryName(CurScope, ObjCImpDecl? Action::CCC_ObjCImplementation : Action::CCC_ObjCInterface); - ConsumeToken(); + ConsumeCodeCompletionToken(); } // If we don't have an @ directive, parse it as a function definition. @@ -371,7 +371,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl, SourceLocation AtLoc = ConsumeToken(); // the "@" if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCAtDirective(CurScope, ObjCImpDecl, true); - ConsumeToken(); + ConsumeCodeCompletionToken(); break; } @@ -438,7 +438,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl, // EOF. In the former case, eat the @end. In the later case, emit an error. if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCAtDirective(CurScope, ObjCImpDecl, true); - ConsumeToken(); + ConsumeCodeCompletionToken(); } else if (Tok.isObjCAtKeyword(tok::objc_end)) ConsumeToken(); // the "end" identifier else @@ -446,7 +446,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl, // Insert collected methods declarations into the @interface object. // This passes in an invalid SourceLocation for AtEndLoc when EOF is hit. - Actions.ActOnAtEnd(AtEnd, interfaceDecl, + Actions.ActOnAtEnd(CurScope, AtEnd, interfaceDecl, allMethods.data(), allMethods.size(), allProperties.data(), allProperties.size(), allTUVariables.data(), allTUVariables.size()); @@ -477,7 +477,7 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, DeclPtrTy ClassDecl, while (1) { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCPropertyFlags(CurScope, DS); - ConsumeToken(); + ConsumeCodeCompletionToken(); } const IdentifierInfo *II = Tok.getIdentifierInfo(); @@ -514,7 +514,7 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, DeclPtrTy ClassDecl, else Actions.CodeCompleteObjCPropertyGetter(CurScope, ClassDecl, Methods, NumMethods); - ConsumeToken(); + ConsumeCodeCompletionToken(); } if (Tok.isNot(tok::identifier)) { @@ -782,7 +782,7 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc, if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCMethodDecl(CurScope, mType == tok::minus, /*ReturnType=*/0, IDecl); - ConsumeToken(); + ConsumeCodeCompletionToken(); } // Parse the return type if present. @@ -799,7 +799,7 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc, if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCMethodDecl(CurScope, mType == tok::minus, ReturnType, IDecl); - ConsumeToken(); + ConsumeCodeCompletionToken(); } // Now parse the selector. @@ -945,7 +945,7 @@ ParseObjCProtocolReferences(llvm::SmallVectorImpl<Action::DeclPtrTy> &Protocols, if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCProtocolReferences(ProtocolIdents.data(), ProtocolIdents.size()); - ConsumeToken(); + ConsumeCodeCompletionToken(); } if (Tok.isNot(tok::identifier)) { @@ -1026,7 +1026,7 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl, if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCAtVisibility(CurScope); - ConsumeToken(); + ConsumeCodeCompletionToken(); } switch (Tok.getObjCKeywordID()) { @@ -1046,7 +1046,7 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl, if (Tok.is(tok::code_completion)) { Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_ObjCInstanceVariableList); - ConsumeToken(); + ConsumeCodeCompletionToken(); } struct ObjCIvarCallback : FieldCallback { @@ -1117,7 +1117,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCProtocolDecl(CurScope); - ConsumeToken(); + ConsumeCodeCompletionToken(); } if (Tok.isNot(tok::identifier)) { @@ -1203,7 +1203,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration( // Code completion after '@implementation'. if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCImplementationDecl(CurScope); - ConsumeToken(); + ConsumeCodeCompletionToken(); } if (Tok.isNot(tok::identifier)) { @@ -1222,7 +1222,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration( if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCImplementationCategory(CurScope, nameId, nameLoc); - ConsumeToken(); + ConsumeCodeCompletionToken(); } if (Tok.is(tok::identifier)) { @@ -1277,7 +1277,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) { DeclPtrTy Result = ObjCImpDecl; ConsumeToken(); // the "end" identifier if (ObjCImpDecl) { - Actions.ActOnAtEnd(atEnd, ObjCImpDecl); + Actions.ActOnAtEnd(CurScope, atEnd, ObjCImpDecl); ObjCImpDecl = DeclPtrTy(); PendingObjCImpDecl.pop_back(); } @@ -1292,7 +1292,7 @@ Parser::DeclGroupPtrTy Parser::RetrievePendingObjCImpDecl() { if (PendingObjCImpDecl.empty()) return Actions.ConvertDeclToDeclGroup(DeclPtrTy()); DeclPtrTy ImpDecl = PendingObjCImpDecl.pop_back_val(); - Actions.ActOnAtEnd(SourceRange(), ImpDecl); + Actions.ActOnAtEnd(CurScope, SourceRange(), ImpDecl); return Actions.ConvertDeclToDeclGroup(ImpDecl); } @@ -1342,7 +1342,7 @@ Parser::DeclPtrTy Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { while (true) { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCPropertyDefinition(CurScope, ObjCImpDecl); - ConsumeToken(); + ConsumeCodeCompletionToken(); } if (Tok.isNot(tok::identifier)) { @@ -1361,7 +1361,7 @@ Parser::DeclPtrTy Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCPropertySynthesizeIvar(CurScope, propertyId, ObjCImpDecl); - ConsumeToken(); + ConsumeCodeCompletionToken(); } if (Tok.isNot(tok::identifier)) { @@ -1371,7 +1371,7 @@ Parser::DeclPtrTy Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { propertyIvar = Tok.getIdentifierInfo(); ConsumeToken(); // consume ivar-name } - Actions.ActOnPropertyImplDecl(atLoc, propertyLoc, true, ObjCImpDecl, + Actions.ActOnPropertyImplDecl(CurScope, atLoc, propertyLoc, true, ObjCImpDecl, propertyId, propertyIvar); if (Tok.isNot(tok::comma)) break; @@ -1400,7 +1400,7 @@ Parser::DeclPtrTy Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) { while (true) { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCPropertyDefinition(CurScope, ObjCImpDecl); - ConsumeToken(); + ConsumeCodeCompletionToken(); } if (Tok.isNot(tok::identifier)) { @@ -1411,7 +1411,7 @@ Parser::DeclPtrTy Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) { IdentifierInfo *propertyId = Tok.getIdentifierInfo(); SourceLocation propertyLoc = ConsumeToken(); // consume property name - Actions.ActOnPropertyImplDecl(atLoc, propertyLoc, false, ObjCImpDecl, + Actions.ActOnPropertyImplDecl(CurScope, atLoc, propertyLoc, false, ObjCImpDecl, propertyId, 0); if (Tok.isNot(tok::comma)) @@ -1654,7 +1654,7 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDefinition() { Parser::OwningStmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCAtStatement(CurScope); - ConsumeToken(); + ConsumeCodeCompletionToken(); return StmtError(); } @@ -1685,7 +1685,7 @@ Parser::OwningExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { switch (Tok.getKind()) { case tok::code_completion: Actions.CodeCompleteObjCAtExpression(CurScope); - ConsumeToken(); + ConsumeCodeCompletionToken(); return ExprError(); case tok::string_literal: // primary-expression: string-literal @@ -1925,7 +1925,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, else Actions.CodeCompleteObjCInstanceMessage(CurScope, ReceiverExpr.get(), 0, 0); - ConsumeToken(); + ConsumeCodeCompletionToken(); } // Parse objc-selector @@ -1979,7 +1979,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, Actions.CodeCompleteObjCInstanceMessage(CurScope, ReceiverExpr.get(), KeyIdents.data(), KeyIdents.size()); - ConsumeToken(); + ConsumeCodeCompletionToken(); } // Check for another keyword selector. diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp index 812d8e2..c4e4a52 100644 --- a/lib/Parse/ParsePragma.cpp +++ b/lib/Parse/ParsePragma.cpp @@ -23,7 +23,6 @@ using namespace clang; // pack '(' 'show' ')' // pack '(' ('push' | 'pop') [',' identifier] [, integer] ')' void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) { - // FIXME: Should we be expanding macros here? My guess is no. SourceLocation PackLoc = PackTok.getLocation(); Token Tok; @@ -100,17 +99,67 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) { return; } + SourceLocation RParenLoc = Tok.getLocation(); PP.Lex(Tok); if (Tok.isNot(tok::eom)) { PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack"; return; } - SourceLocation RParenLoc = Tok.getLocation(); Actions.ActOnPragmaPack(Kind, Name, Alignment.release(), PackLoc, LParenLoc, RParenLoc); } +// #pragma 'options' 'align' '=' {'natural', 'mac68k', 'power', 'reset'} +void PragmaOptionsHandler::HandlePragma(Preprocessor &PP, Token &OptionsTok) { + SourceLocation OptionsLoc = OptionsTok.getLocation(); + + Token Tok; + PP.Lex(Tok); + if (Tok.isNot(tok::identifier) || !Tok.getIdentifierInfo()->isStr("align")) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align); + return; + } + + PP.Lex(Tok); + if (Tok.isNot(tok::equal)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_equal); + return; + } + + PP.Lex(Tok); + if (Tok.isNot(tok::identifier)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) + << "options"; + return; + } + + Action::PragmaOptionsAlignKind Kind = Action::POAK_Natural; + const IdentifierInfo *II = Tok.getIdentifierInfo(); + if (II->isStr("natural")) + Kind = Action::POAK_Natural; + else if (II->isStr("power")) + Kind = Action::POAK_Power; + else if (II->isStr("mac68k")) + Kind = Action::POAK_Mac68k; + else if (II->isStr("reset")) + Kind = Action::POAK_Reset; + else { + PP.Diag(Tok.getLocation(), diag::warn_pragma_options_invalid_option); + return; + } + + SourceLocation KindLoc = Tok.getLocation(); + PP.Lex(Tok); + if (Tok.isNot(tok::eom)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) + << "options"; + return; + } + + Actions.ActOnPragmaOptionsAlign(Kind, OptionsLoc, KindLoc); +} + // #pragma unused(identifier) void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, Token &UnusedTok) { // FIXME: Should we be expanding macros here? My guess is no. diff --git a/lib/Parse/ParsePragma.h b/lib/Parse/ParsePragma.h index db385c6..d9d06a1 100644 --- a/lib/Parse/ParsePragma.h +++ b/lib/Parse/ParsePragma.h @@ -20,6 +20,15 @@ namespace clang { class Action; class Parser; +class PragmaOptionsHandler : public PragmaHandler { + Action &Actions; +public: + PragmaOptionsHandler(const IdentifierInfo *N, Action &A) : PragmaHandler(N), + Actions(A) {} + + virtual void HandlePragma(Preprocessor &PP, Token &FirstToken); +}; + class PragmaPackHandler : public PragmaHandler { Action &Actions; public: diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 9b22270..98c0058 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -283,7 +283,7 @@ Parser::OwningStmtResult Parser::ParseCaseStatement(AttributeList *Attr) { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteCase(CurScope); - ConsumeToken(); + ConsumeCodeCompletionToken(); } /// We don't want to treat 'case x : y' as a potential typo for 'case x::y'. @@ -536,15 +536,23 @@ Parser::OwningStmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { /// successfully parsed. Note that a successful parse can still have semantic /// errors in the condition. bool Parser::ParseParenExprOrCondition(OwningExprResult &ExprResult, - DeclPtrTy &DeclResult) { + DeclPtrTy &DeclResult, + SourceLocation Loc, + bool ConvertToBoolean) { bool ParseError = false; SourceLocation LParenLoc = ConsumeParen(); if (getLang().CPlusPlus) - ParseError = ParseCXXCondition(ExprResult, DeclResult); + ParseError = ParseCXXCondition(ExprResult, DeclResult, Loc, + ConvertToBoolean); else { ExprResult = ParseExpression(); DeclResult = DeclPtrTy(); + + // If required, convert to a boolean value. + if (!ExprResult.isInvalid() && ConvertToBoolean) + ExprResult + = Actions.ActOnBooleanCondition(CurScope, Loc, move(ExprResult)); } // If the parser was confused by the condition and we don't have a ')', try to @@ -603,7 +611,7 @@ Parser::OwningStmtResult Parser::ParseIfStatement(AttributeList *Attr) { // Parse the condition. OwningExprResult CondExp(Actions); DeclPtrTy CondVar; - if (ParseParenExprOrCondition(CondExp, CondVar)) + if (ParseParenExprOrCondition(CondExp, CondVar, IfLoc, true)) return StmtError(); FullExprArg FullCondExp(Actions.MakeFullExpr(CondExp)); @@ -735,13 +743,25 @@ Parser::OwningStmtResult Parser::ParseSwitchStatement(AttributeList *Attr) { // Parse the condition. OwningExprResult Cond(Actions); DeclPtrTy CondVar; - if (ParseParenExprOrCondition(Cond, CondVar)) + if (ParseParenExprOrCondition(Cond, CondVar, SwitchLoc, false)) return StmtError(); - FullExprArg FullCond(Actions.MakeFullExpr(Cond)); + OwningStmtResult Switch + = Actions.ActOnStartOfSwitchStmt(SwitchLoc, move(Cond), CondVar); + + if (Switch.isInvalid()) { + // Skip the switch body. + // FIXME: This is not optimal recovery, but parsing the body is more + // dangerous due to the presence of case and default statements, which + // will have no place to connect back with the switch. + if (Tok.is(tok::l_brace)) { + ConsumeBrace(); + SkipUntil(tok::r_brace, false, false); + } else + SkipUntil(tok::semi); + return move(Switch); + } - OwningStmtResult Switch = Actions.ActOnStartOfSwitchStmt(FullCond, CondVar); - // C99 6.8.4p3 - In C99, the body of the switch statement is a scope, even if // there is no compound stmt. C90 does not have this clause. We only do this // if the body isn't a compound statement to avoid push/pop in common cases. @@ -763,11 +783,6 @@ Parser::OwningStmtResult Parser::ParseSwitchStatement(AttributeList *Attr) { InnerScope.Exit(); SwitchScope.Exit(); - if (Cond.isInvalid() && !CondVar.get()) { - Actions.ActOnSwitchBodyError(SwitchLoc, move(Switch), move(Body)); - return StmtError(); - } - if (Body.isInvalid()) // FIXME: Remove the case statement list from the Switch statement. Body = Actions.ActOnNullStmt(Tok.getLocation()); @@ -818,7 +833,7 @@ Parser::OwningStmtResult Parser::ParseWhileStatement(AttributeList *Attr) { // Parse the condition. OwningExprResult Cond(Actions); DeclPtrTy CondVar; - if (ParseParenExprOrCondition(Cond, CondVar)) + if (ParseParenExprOrCondition(Cond, CondVar, WhileLoc, true)) return StmtError(); FullExprArg FullCond(Actions.MakeFullExpr(Cond)); @@ -975,14 +990,17 @@ Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) { bool ForEach = false; OwningStmtResult FirstPart(Actions); - OwningExprResult SecondPart(Actions), ThirdPart(Actions); + bool SecondPartIsInvalid = false; + FullExprArg SecondPart(Actions); + OwningExprResult Collection(Actions); + FullExprArg ThirdPart(Actions); DeclPtrTy SecondVar; if (Tok.is(tok::code_completion)) { Actions.CodeCompleteOrdinaryName(CurScope, C99orCXXorObjC? Action::CCC_ForInit : Action::CCC_Expression); - ConsumeToken(); + ConsumeCodeCompletionToken(); } // Parse the first part of the for specifier. @@ -1009,7 +1027,7 @@ Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) { Actions.ActOnForEachDeclStmt(DG); // ObjC: for (id x in expr) ConsumeToken(); // consume 'in' - SecondPart = ParseExpression(); + Collection = ParseExpression(); } else { Diag(Tok, diag::err_expected_semi_for); SkipUntil(tok::semi); @@ -1025,35 +1043,44 @@ Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) { ConsumeToken(); } else if ((ForEach = isTokIdentifier_in())) { ConsumeToken(); // consume 'in' - SecondPart = ParseExpression(); + Collection = ParseExpression(); } else { if (!Value.isInvalid()) Diag(Tok, diag::err_expected_semi_for); SkipUntil(tok::semi); } } if (!ForEach) { - assert(!SecondPart.get() && "Shouldn't have a second expression yet."); + assert(!SecondPart->get() && "Shouldn't have a second expression yet."); // Parse the second part of the for specifier. if (Tok.is(tok::semi)) { // for (...;; // no second part. } else { + OwningExprResult Second(Actions); if (getLang().CPlusPlus) - ParseCXXCondition(SecondPart, SecondVar); - else - SecondPart = ParseExpression(); + ParseCXXCondition(Second, SecondVar, ForLoc, true); + else { + Second = ParseExpression(); + if (!Second.isInvalid()) + Second = Actions.ActOnBooleanCondition(CurScope, ForLoc, + move(Second)); + } + SecondPartIsInvalid = Second.isInvalid(); + SecondPart = Actions.MakeFullExpr(Second); } if (Tok.is(tok::semi)) { ConsumeToken(); } else { - if (!SecondPart.isInvalid() || SecondVar.get()) + if (!SecondPartIsInvalid || SecondVar.get()) Diag(Tok, diag::err_expected_semi_for); SkipUntil(tok::semi); } // Parse the third part of the for specifier. - if (Tok.isNot(tok::r_paren)) // for (...;...;) - ThirdPart = ParseExpression(); + if (Tok.isNot(tok::r_paren)) { // for (...;...;) + OwningExprResult Third = ParseExpression(); + ThirdPart = Actions.MakeFullExpr(Third); + } } // Match the ')'. SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); @@ -1085,15 +1112,14 @@ Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) { return StmtError(); if (!ForEach) - return Actions.ActOnForStmt(ForLoc, LParenLoc, move(FirstPart), - Actions.MakeFullExpr(SecondPart), SecondVar, - Actions.MakeFullExpr(ThirdPart), RParenLoc, - move(Body)); - - return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc, - move(FirstPart), - move(SecondPart), - RParenLoc, move(Body)); + return Actions.ActOnForStmt(ForLoc, LParenLoc, move(FirstPart), SecondPart, + SecondVar, ThirdPart, RParenLoc, move(Body)); + + // FIXME: It isn't clear how to communicate the late destruction of + // C++ temporaries used to create the collection. + return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc, move(FirstPart), + move(Collection), RParenLoc, + move(Body)); } /// ParseGotoStatement diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index ff69953..c87ddad 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -201,7 +201,7 @@ Parser::ParseSingleDeclarationAfterTemplate( if (Tok.is(tok::semi)) { DeclEnd = ConsumeToken(); - DeclPtrTy Decl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS); + DeclPtrTy Decl = Actions.ParsedFreeStandingDeclSpec(CurScope, AS, DS); DS.complete(Decl); return Decl; } @@ -902,10 +902,12 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() { ConsumeToken(); // the identifier if (isEndOfTemplateArgument(Tok)) { + bool MemberOfUnknownSpecialization; TemplateNameKind TNK = Actions.isTemplateName(CurScope, SS, Name, /*ObjectType=*/0, /*EnteringContext=*/false, - Template); + Template, + MemberOfUnknownSpecialization); if (TNK == TNK_Dependent_template_name || TNK == TNK_Type_template) { // We have an id-expression that refers to a class template or // (C++0x) template alias. @@ -966,6 +968,37 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() { ExprArg.release(), Loc); } +/// \brief Determine whether the current tokens can only be parsed as a +/// template argument list (starting with the '<') and never as a '<' +/// expression. +bool Parser::IsTemplateArgumentList(unsigned Skip) { + struct AlwaysRevertAction : TentativeParsingAction { + AlwaysRevertAction(Parser &P) : TentativeParsingAction(P) { } + ~AlwaysRevertAction() { Revert(); } + } Tentative(*this); + + while (Skip) { + ConsumeToken(); + --Skip; + } + + // '<' + if (!Tok.is(tok::less)) + return false; + ConsumeToken(); + + // An empty template argument list. + if (Tok.is(tok::greater)) + return true; + + // See whether we have declaration specifiers, which indicate a type. + while (isCXXDeclarationSpecifier() == TPResult::True()) + ConsumeToken(); + + // If we have a '>' or a ',' then this is a template argument list. + return Tok.is(tok::greater) || Tok.is(tok::comma); +} + /// ParseTemplateArgumentList - Parse a C++ template-argument-list /// (C++ [temp.names]). Returns true if there was an error. /// diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp index a6c6d3f..5e64e61 100644 --- a/lib/Parse/ParseTentative.cpp +++ b/lib/Parse/ParseTentative.cpp @@ -753,6 +753,7 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() { case tok::kw___cdecl: case tok::kw___stdcall: case tok::kw___fastcall: + case tok::kw___thiscall: case tok::kw___w64: case tok::kw___ptr64: case tok::kw___forceinline: diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 6dbb99e..2968970 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -33,6 +33,11 @@ Parser::Parser(Preprocessor &pp, Action &actions) // Add #pragma handlers. These are removed and destroyed in the // destructor. + OptionsHandler.reset(new + PragmaOptionsHandler(&PP.getIdentifierTable().get("options"), + actions)); + PP.AddPragmaHandler(0, OptionsHandler.get()); + PackHandler.reset(new PragmaPackHandler(&PP.getIdentifierTable().get("pack"), actions)); PP.AddPragmaHandler(0, PackHandler.get()); @@ -134,7 +139,7 @@ SourceLocation Parser::MatchRHSPunctuation(tok::TokenKind RHSTok, /// returned. bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID, const char *Msg, tok::TokenKind SkipToTok) { - if (Tok.is(ExpectedTok)) { + if (Tok.is(ExpectedTok) || Tok.is(tok::code_completion)) { ConsumeAnyToken(); return false; } @@ -189,7 +194,11 @@ bool Parser::SkipUntil(const tok::TokenKind *Toks, unsigned NumToks, case tok::eof: // Ran out of tokens. return false; - + + case tok::code_completion: + ConsumeToken(); + return false; + case tok::l_paren: // Recursively skip properly-nested parens. ConsumeParen(); @@ -294,6 +303,8 @@ Parser::~Parser() { delete ScopeCache[i]; // Remove the pragma handlers we installed. + PP.RemovePragmaHandler(0, OptionsHandler.get()); + OptionsHandler.reset(); PP.RemovePragmaHandler(0, PackHandler.get()); PackHandler.reset(); PP.RemovePragmaHandler(0, UnusedHandler.get()); @@ -447,7 +458,7 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr) Actions.CodeCompleteOrdinaryName(CurScope, ObjCImpDecl? Action::CCC_ObjCImplementation : Action::CCC_Namespace); - ConsumeToken(); + ConsumeCodeCompletionToken(); return ParseExternalDeclaration(Attr); case tok::kw_using: case tok::kw_namespace: @@ -538,7 +549,7 @@ Parser::ParseDeclarationOrFunctionDefinition(ParsingDeclSpec &DS, // declaration-specifiers init-declarator-list[opt] ';' if (Tok.is(tok::semi)) { ConsumeToken(); - DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS); + DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, AS, DS); DS.complete(TheDecl); return Actions.ConvertDeclToDeclGroup(TheDecl); } @@ -980,10 +991,11 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) { TemplateTy Template; UnqualifiedId TemplateName; TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); + bool MemberOfUnknownSpecialization; if (TemplateNameKind TNK = Actions.isTemplateName(CurScope, SS, TemplateName, /*ObjectType=*/0, EnteringContext, - Template)) { + Template, MemberOfUnknownSpecialization)) { // Consume the identifier. ConsumeToken(); if (AnnotateTemplateIdToken(Template, TNK, &SS, TemplateName)) { @@ -1071,6 +1083,22 @@ bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) { return false; } +void Parser::CodeCompletionRecovery() { + for (Scope *S = CurScope; S; S = S->getParent()) { + if (S->getFlags() & Scope::FnScope) { + Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_RecoveryInFunction); + return; + } + + if (S->getFlags() & Scope::ClassScope) { + Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Class); + return; + } + } + + Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Namespace); +} + // Anchor the Parser::FieldCallback vtable to this translation unit. // We use a spurious method instead of the destructor because // destroying FieldCallbacks can actually be slightly |