diff options
author | dim <dim@FreeBSD.org> | 2012-12-02 13:20:44 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2012-12-02 13:20:44 +0000 |
commit | 056abd2059c65a3e908193aeae16fad98017437c (patch) | |
tree | 2732d02d7d51218d6eed98ac7fcfc5b8794896b5 /lib/Parse | |
parent | cc73504950eb7b5dff2dded9bedd67bc36d64641 (diff) | |
download | FreeBSD-src-056abd2059c65a3e908193aeae16fad98017437c.zip FreeBSD-src-056abd2059c65a3e908193aeae16fad98017437c.tar.gz |
Vendor import of clang release_32 branch r168974 (effectively, 3.2 RC2):
http://llvm.org/svn/llvm-project/cfe/branches/release_32@168974
Diffstat (limited to 'lib/Parse')
-rw-r--r-- | lib/Parse/ParseAST.cpp | 1 | ||||
-rw-r--r-- | lib/Parse/ParseCXXInlineMethods.cpp | 6 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 224 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 190 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 179 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 203 | ||||
-rw-r--r-- | lib/Parse/ParseInit.cpp | 11 | ||||
-rw-r--r-- | lib/Parse/ParseObjc.cpp | 67 | ||||
-rw-r--r-- | lib/Parse/ParsePragma.cpp | 248 | ||||
-rw-r--r-- | lib/Parse/ParsePragma.h | 37 | ||||
-rw-r--r-- | lib/Parse/ParseStmt.cpp | 297 | ||||
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 10 | ||||
-rw-r--r-- | lib/Parse/ParseTentative.cpp | 131 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 272 | ||||
-rw-r--r-- | lib/Parse/RAIIObjectsForParser.h | 10 |
15 files changed, 1289 insertions, 597 deletions
diff --git a/lib/Parse/ParseAST.cpp b/lib/Parse/ParseAST.cpp index bd4f859..7d68e1f 100644 --- a/lib/Parse/ParseAST.cpp +++ b/lib/Parse/ParseAST.cpp @@ -78,7 +78,6 @@ void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) { S.getPreprocessor().EnterMainSourceFile(); P.Initialize(); - S.Initialize(); // C11 6.9p1 says translation units must have at least one top-level // declaration. C++ doesn't have this restriction. We also don't want to diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp index abce27c..9c5c0597 100644 --- a/lib/Parse/ParseCXXInlineMethods.cpp +++ b/lib/Parse/ParseCXXInlineMethods.cpp @@ -34,7 +34,7 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Tok.is(tok::equal)) && "Current token not a '{', ':', '=', or 'try'!"); - MultiTemplateParamsArg TemplateParams(Actions, + MultiTemplateParamsArg TemplateParams( TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data() : 0, TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0); @@ -42,10 +42,10 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, D.setFunctionDefinitionKind(DefinitionKind); if (D.getDeclSpec().isFriendSpecified()) FnD = Actions.ActOnFriendFunctionDecl(getCurScope(), D, - move(TemplateParams)); + TemplateParams); else { FnD = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS, D, - move(TemplateParams), 0, + TemplateParams, 0, VS, ICIS_NoInit); if (FnD) { Actions.ProcessDeclAttributeList(getCurScope(), FnD, AccessAttrs, diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index cb865cc..f73907a 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -143,7 +143,7 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, // Attributes in a class are parsed at the end of the class, along // with other late-parsed declarations. - if (!ClassStack.empty()) + if (!ClassStack.empty() && !LateAttrs->parseSoon()) getCurrentClass().LateParsedDeclarations.push_back(LA); // consume everything up to and including the matching right parens @@ -154,7 +154,8 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, Eof.setLocation(Tok.getLocation()); LA->Toks.push_back(Eof); } else { - ParseGNUAttributeArgs(AttrName, AttrNameLoc, attrs, endLoc); + ParseGNUAttributeArgs(AttrName, AttrNameLoc, attrs, endLoc, + 0, SourceLocation(), AttributeList::AS_GNU); } } else { attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, @@ -173,11 +174,15 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, } -/// Parse the arguments to a parameterized GNU attribute +/// Parse the arguments to a parameterized GNU attribute or +/// a C++11 attribute in "gnu" namespace. void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, SourceLocation AttrNameLoc, ParsedAttributes &Attrs, - SourceLocation *EndLoc) { + SourceLocation *EndLoc, + IdentifierInfo *ScopeName, + SourceLocation ScopeLoc, + AttributeList::Syntax Syntax) { assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('"); @@ -236,7 +241,7 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, break; } - ExprVector ArgExprs(Actions); + ExprVector ArgExprs; if (!BuiltinType && (ParmLoc.isValid() ? Tok.is(tok::comma) : Tok.isNot(tok::r_paren))) { @@ -277,10 +282,11 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, SourceLocation RParen = Tok.getLocation(); if (!ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) { + SourceLocation AttrLoc = ScopeLoc.isValid() ? ScopeLoc : AttrNameLoc; AttributeList *attr = - Attrs.addNew(AttrName, SourceRange(AttrNameLoc, RParen), 0, AttrNameLoc, - ParmName, ParmLoc, ArgExprs.take(), ArgExprs.size(), - AttributeList::AS_GNU); + Attrs.addNew(AttrName, SourceRange(AttrLoc, RParen), + ScopeName, ScopeLoc, ParmName, ParmLoc, + ArgExprs.data(), ArgExprs.size(), Syntax); if (BuiltinType && attr->getKind() == AttributeList::AT_IBOutletCollection) Diag(Tok, diag::err_iboutletcollection_builtintype); } @@ -851,10 +857,6 @@ void Parser::ParseLexedAttributes(ParsingClass &Class) { Actions.ActOnStartDelayedMemberDeclarations(getCurScope(), Class.TagOrTemplate); if (!Class.LateParsedDeclarations.empty()) { - // Allow 'this' within late-parsed attributes. - Sema::CXXThisScopeRAII ThisScope(Actions, Class.TagOrTemplate, - /*TypeQuals=*/0); - for (unsigned i = 0, ni = Class.LateParsedDeclarations.size(); i < ni; ++i){ Class.LateParsedDeclarations[i]->ParseLexedAttributes(); } @@ -869,6 +871,8 @@ void Parser::ParseLexedAttributes(ParsingClass &Class) { /// \brief Parse all attributes in LAs, and attach them to Decl D. void Parser::ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D, bool EnterScope, bool OnDefinition) { + assert(LAs.parseSoon() && + "Attribute list should be marked for immediate parsing."); for (unsigned i = 0, ni = LAs.size(); i < ni; ++i) { if (D) LAs[i]->addDecl(D); @@ -904,34 +908,45 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA, ParsedAttributes Attrs(AttrFactory); SourceLocation endLoc; - if (LA.Decls.size() == 1) { + if (LA.Decls.size() > 0) { Decl *D = LA.Decls[0]; + NamedDecl *ND = dyn_cast<NamedDecl>(D); + RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext()); - // If the Decl is templatized, add template parameters to scope. - bool HasTemplateScope = EnterScope && D->isTemplateDecl(); - ParseScope TempScope(this, Scope::TemplateParamScope, HasTemplateScope); - if (HasTemplateScope) - Actions.ActOnReenterTemplateScope(Actions.CurScope, D); - - // If the Decl is on a function, add function parameters to the scope. - bool HasFunctionScope = EnterScope && D->isFunctionOrFunctionTemplate(); - ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope, HasFunctionScope); - if (HasFunctionScope) - Actions.ActOnReenterFunctionContext(Actions.CurScope, D); - - ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc); - - if (HasFunctionScope) { - Actions.ActOnExitFunctionContext(); - FnScope.Exit(); // Pop scope, and remove Decls from IdResolver - } - if (HasTemplateScope) { - TempScope.Exit(); + // Allow 'this' within late-parsed attributes. + Sema::CXXThisScopeRAII ThisScope(Actions, RD, + /*TypeQuals=*/0, + ND && RD && ND->isCXXInstanceMember()); + + if (LA.Decls.size() == 1) { + // If the Decl is templatized, add template parameters to scope. + bool HasTemplateScope = EnterScope && D->isTemplateDecl(); + ParseScope TempScope(this, Scope::TemplateParamScope, HasTemplateScope); + if (HasTemplateScope) + Actions.ActOnReenterTemplateScope(Actions.CurScope, D); + + // If the Decl is on a function, add function parameters to the scope. + bool HasFunScope = EnterScope && D->isFunctionOrFunctionTemplate(); + ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope, HasFunScope); + if (HasFunScope) + Actions.ActOnReenterFunctionContext(Actions.CurScope, D); + + ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc, + 0, SourceLocation(), AttributeList::AS_GNU); + + if (HasFunScope) { + Actions.ActOnExitFunctionContext(); + FnScope.Exit(); // Pop scope, and remove Decls from IdResolver + } + if (HasTemplateScope) { + TempScope.Exit(); + } + } else { + // If there are multiple decls, then the decl cannot be within the + // function scope. + ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc, + 0, SourceLocation(), AttributeList::AS_GNU); } - } else if (LA.Decls.size() > 0) { - // If there are multiple decls, then the decl cannot be within the - // function scope. - ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc); } else { Diag(Tok, diag::warn_attribute_no_decl) << LA.AttrName.getName(); } @@ -998,7 +1013,7 @@ void Parser::ParseThreadSafetyAttribute(IdentifierInfo &AttrName, BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); - ExprVector ArgExprs(Actions); + ExprVector ArgExprs; bool ArgExprsOk = true; // now parse the list of expressions @@ -1018,7 +1033,7 @@ void Parser::ParseThreadSafetyAttribute(IdentifierInfo &AttrName, // Match the ')'. if (ArgExprsOk && !T.consumeClose()) { Attrs.addNew(&AttrName, AttrNameLoc, 0, AttrNameLoc, 0, SourceLocation(), - ArgExprs.take(), ArgExprs.size(), AttributeList::AS_GNU); + ArgExprs.data(), ArgExprs.size(), AttributeList::AS_GNU); } if (EndLoc) *EndLoc = T.getCloseLocation(); @@ -1127,6 +1142,18 @@ void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs) { << attrs.Range; } +void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &attrs) { + AttributeList *AttrList = attrs.getList(); + while (AttrList) { + if (AttrList->isCXX0XAttribute()) { + Diag(AttrList->getLoc(), diag::warn_attribute_no_decl) + << AttrList->getName(); + AttrList->setInvalid(); + } + AttrList = AttrList->getNext(); + } +} + /// ParseDeclaration - Parse a full 'declaration', which consists of /// declaration-specifiers, some number of declarators, and a semicolon. /// 'Context' should be a Declarator::TheContext value. This returns the @@ -1400,7 +1427,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, // Save late-parsed attributes for now; they need to be parsed in the // appropriate function scope after the function Decl has been constructed. - LateParsedAttrList LateParsedAttrs; + // These will be parsed in ParseFunctionDefinition or ParseLexedAttrList. + LateParsedAttrList LateParsedAttrs(true); if (D.isFunctionDeclarator()) MaybeParseGNUAttributes(D, &LateParsedAttrs); @@ -1587,9 +1615,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, case ParsedTemplateInfo::Template: case ParsedTemplateInfo::ExplicitSpecialization: ThisDecl = Actions.ActOnTemplateDeclarator(getCurScope(), - MultiTemplateParamsArg(Actions, - TemplateInfo.TemplateParams->data(), - TemplateInfo.TemplateParams->size()), + *TemplateInfo.TemplateParams, D); break; @@ -1660,7 +1686,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); - ExprVector Exprs(Actions); + ExprVector Exprs; CommaLocsTy CommaLocs; if (getLangOpts().CPlusPlus && D.getCXXScopeSpec().isSet()) { @@ -1669,6 +1695,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, } if (ParseExpressionList(Exprs, CommaLocs)) { + Actions.ActOnInitializerError(ThisDecl); SkipUntil(tok::r_paren); if (getLangOpts().CPlusPlus && D.getCXXScopeSpec().isSet()) { @@ -1689,7 +1716,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, ExprResult Initializer = Actions.ActOnParenListExpr(T.getOpenLocation(), T.getCloseLocation(), - move_arg(Exprs)); + Exprs); Actions.AddInitializerToDecl(ThisDecl, Initializer.take(), /*DirectInit=*/true, TypeContainsAuto); } @@ -1872,6 +1899,9 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, TagName="union" ; FixitTagName = "union " ;TagKind=tok::kw_union ;break; case DeclSpec::TST_struct: TagName="struct"; FixitTagName = "struct ";TagKind=tok::kw_struct;break; + case DeclSpec::TST_interface: + TagName="__interface"; FixitTagName = "__interface "; + TagKind=tok::kw___interface;break; case DeclSpec::TST_class: TagName="class" ; FixitTagName = "class " ;TagKind=tok::kw_class ;break; } @@ -2069,13 +2099,13 @@ void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs, return; } - ExprVector ArgExprs(Actions); + ExprVector ArgExprs; ArgExprs.push_back(ArgExpr.release()); // FIXME: This should not be GNU, but we since the attribute used is // based on the spelling, and there is no true spelling for // C++11 attributes, this isn't accepted. Attrs.addNew(PP.getIdentifierInfo("aligned"), KWLoc, 0, KWLoc, - 0, T.getOpenLocation(), ArgExprs.take(), 1, + 0, T.getOpenLocation(), ArgExprs.data(), 1, AttributeList::AS_GNU); } @@ -2130,8 +2160,14 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, DoneWithDeclSpec: if (!AttrsLastTime) ProhibitAttributes(attrs); - else + else { + // Reject C++11 attributes that appertain to decl specifiers as + // we don't support any C++11 attributes that appertain to decl + // specifiers. This also conforms to what g++ 4.8 is doing. + ProhibitCXX11Attributes(attrs); + DS.takeAttributesFrom(attrs); + } // If this is not a declaration specifier token, we're done reading decl // specifiers. First verify that DeclSpec's are consistent. @@ -2271,6 +2307,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Tok.getAnnotationEndLoc(), PrevSpec, DiagID, T); + if (isInvalid) + break; } else DS.SetTypeSpecError(); @@ -2476,12 +2514,12 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, case tok::kw___forceinline: { isInvalid = DS.SetFunctionSpecInline(Loc, PrevSpec, DiagID); IdentifierInfo *AttrName = Tok.getIdentifierInfo(); - SourceLocation AttrNameLoc = ConsumeToken(); + SourceLocation AttrNameLoc = Tok.getLocation(); // FIXME: This does not work correctly if it is set to be a declspec // attribute, and a GNU attribute is simply incorrect. DS.getAttributes().addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, SourceLocation(), 0, 0, AttributeList::AS_GNU); - continue; + break; } case tok::kw___ptr64: @@ -2706,6 +2744,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // class-specifier: case tok::kw_class: case tok::kw_struct: + case tok::kw___interface: case tok::kw_union: { tok::TokenKind Kind = Tok.getKind(); ConsumeToken(); @@ -2723,15 +2762,15 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // cv-qualifier: case tok::kw_const: isInvalid = DS.SetTypeQual(DeclSpec::TQ_const, Loc, PrevSpec, DiagID, - getLangOpts(), /*IsTypeSpec*/true); + getLangOpts()); break; case tok::kw_volatile: isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, DiagID, - getLangOpts(), /*IsTypeSpec*/true); + getLangOpts()); break; case tok::kw_restrict: isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID, - getLangOpts(), /*IsTypeSpec*/true); + getLangOpts()); break; // C++ typename-specifier: @@ -3165,6 +3204,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, // anything that's a simple-type-specifier followed by '(' as an // expression. This suffices because function types are not valid // underlying types anyway. + EnterExpressionEvaluationContext Unevaluated(Actions, + Sema::ConstantEvaluated); TPResult TPR = isExpressionOrTypeSpecifierSimple(NextToken().getKind()); // If the next token starts an expression, we know we're parsing a // bit-field. This is the common case. @@ -3213,11 +3254,14 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, SourceRange Range; BaseType = ParseTypeName(&Range); - if (!getLangOpts().CPlusPlus0x && !getLangOpts().ObjC2) - Diag(StartLoc, diag::ext_ms_enum_fixed_underlying_type) - << Range; - if (getLangOpts().CPlusPlus0x) + if (getLangOpts().CPlusPlus0x) { Diag(StartLoc, diag::warn_cxx98_compat_enum_fixed_underlying_type); + } else if (!getLangOpts().ObjC2) { + if (getLangOpts().CPlusPlus) + Diag(StartLoc, diag::ext_cxx11_enum_fixed_underlying_type) << Range; + else + Diag(StartLoc, diag::ext_c_enum_fixed_underlying_type) << Range; + } } } @@ -3526,6 +3570,7 @@ bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const { // struct-or-union-specifier (C99) or class-specifier (C++) case tok::kw_class: case tok::kw_struct: + case tok::kw___interface: case tok::kw_union: // enum-specifier case tok::kw_enum: @@ -3597,6 +3642,7 @@ bool Parser::isTypeSpecifierQualifier() { // struct-or-union-specifier (C99) or class-specifier (C++) case tok::kw_class: case tok::kw_struct: + case tok::kw___interface: case tok::kw_union: // enum-specifier case tok::kw_enum: @@ -3735,6 +3781,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::kw_class: case tok::kw_struct: case tok::kw_union: + case tok::kw___interface: // enum-specifier case tok::kw_enum: @@ -3748,6 +3795,9 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::kw_virtual: case tok::kw_explicit: + // friend keyword. + case tok::kw_friend: + // static_assert-declaration case tok::kw__Static_assert: @@ -3756,11 +3806,10 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { // GNU attributes. case tok::kw___attribute: - return true; - // C++0x decltype. + // C++11 decltype and constexpr. case tok::annot_decltype: - return true; + case tok::kw_constexpr: // C11 _Atomic() case tok::kw__Atomic: @@ -3925,15 +3974,15 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, case tok::kw_const: isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , Loc, PrevSpec, DiagID, - getLangOpts(), /*IsTypeSpec*/false); + getLangOpts()); break; case tok::kw_volatile: isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, DiagID, - getLangOpts(), /*IsTypeSpec*/false); + getLangOpts()); break; case tok::kw_restrict: isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID, - getLangOpts(), /*IsTypeSpec*/false); + getLangOpts()); break; // OpenCL qualifiers: @@ -4344,7 +4393,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) { D.SetIdentifier(0, Tok.getLocation()); } else { if (Tok.getKind() == tok::annot_pragma_parser_crash) - *(volatile int*) 0x11 = 0; + LLVM_BUILTIN_TRAP; if (D.getContext() == Declarator::MemberContext) Diag(Tok, diag::err_expected_member_name_or_semi) << D.getDeclSpec().getSourceRange(); @@ -4374,9 +4423,15 @@ void Parser::ParseDirectDeclarator(Declarator &D) { // In such a case, check if we actually have a function declarator; if it // is not, the declarator has been fully parsed. bool IsAmbiguous = false; - if (getLangOpts().CPlusPlus && D.mayBeFollowedByCXXDirectInit() && - !isCXXFunctionDeclarator(&IsAmbiguous)) - break; + if (getLangOpts().CPlusPlus && D.mayBeFollowedByCXXDirectInit()) { + // The name of the declarator, if any, is tentatively declared within + // a possible direct initializer. + TentativelyDeclaredIdentifiers.push_back(D.getIdentifier()); + bool IsFunctionDecl = isCXXFunctionDeclarator(&IsAmbiguous); + TentativelyDeclaredIdentifiers.pop_back(); + if (!IsFunctionDecl) + break; + } ParsedAttributes attrs(AttrFactory); BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); @@ -4553,7 +4608,14 @@ void Parser::ParseFunctionDeclarator(Declarator &D, Actions.ActOnStartFunctionDeclarator(); - SourceLocation EndLoc; + /* LocalEndLoc is the end location for the local FunctionTypeLoc. + EndLoc is the end location for the function declarator. + They differ for trailing return types. */ + SourceLocation StartLoc, LocalEndLoc, EndLoc; + SourceLocation LParenLoc, RParenLoc; + LParenLoc = Tracker.getOpenLocation(); + StartLoc = LParenLoc; + if (isFunctionDeclaratorIdentifierList()) { if (RequiresArg) Diag(Tok, diag::err_argument_required_after_attribute); @@ -4561,7 +4623,9 @@ void Parser::ParseFunctionDeclarator(Declarator &D, ParseFunctionDeclaratorIdentifierList(D, ParamInfo); Tracker.consumeClose(); - EndLoc = Tracker.getCloseLocation(); + RParenLoc = Tracker.getCloseLocation(); + LocalEndLoc = RParenLoc; + EndLoc = RParenLoc; } else { if (Tok.isNot(tok::r_paren)) ParseParameterDeclarationClause(D, FirstArgAttrs, ParamInfo, EllipsisLoc); @@ -4572,7 +4636,9 @@ void Parser::ParseFunctionDeclarator(Declarator &D, // If we have the closing ')', eat it. Tracker.consumeClose(); - EndLoc = Tracker.getCloseLocation(); + RParenLoc = Tracker.getCloseLocation(); + LocalEndLoc = RParenLoc; + EndLoc = RParenLoc; if (getLangOpts().CPlusPlus) { // FIXME: Accept these components in any order, and produce fixits to @@ -4628,21 +4694,25 @@ void Parser::ParseFunctionDeclarator(Declarator &D, MaybeParseCXX0XAttributes(FnAttrs); // Parse trailing-return-type[opt]. + LocalEndLoc = EndLoc; if (getLangOpts().CPlusPlus0x && Tok.is(tok::arrow)) { Diag(Tok, diag::warn_cxx98_compat_trailing_return_type); + if (D.getDeclSpec().getTypeSpecType() == TST_auto) + StartLoc = D.getDeclSpec().getTypeSpecTypeLoc(); + LocalEndLoc = Tok.getLocation(); SourceRange Range; TrailingReturnType = ParseTrailingReturnType(Range); - if (Range.getEnd().isValid()) - EndLoc = Range.getEnd(); + EndLoc = Range.getEnd(); } } } // Remember that we parsed a function type, and remember the attributes. D.AddTypeInfo(DeclaratorChunk::getFunction(HasProto, - /*isVariadic=*/EllipsisLoc.isValid(), - IsAmbiguous, EllipsisLoc, + IsAmbiguous, + LParenLoc, ParamInfo.data(), ParamInfo.size(), + EllipsisLoc, RParenLoc, DS.getTypeQualifiers(), RefQualifierIsLValueRef, RefQualifierLoc, ConstQualifierLoc, @@ -4654,8 +4724,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D, DynamicExceptions.size(), NoexceptExpr.isUsable() ? NoexceptExpr.get() : 0, - Tracker.getOpenLocation(), - EndLoc, D, + StartLoc, LocalEndLoc, D, TrailingReturnType), FnAttrs, EndLoc); @@ -5058,7 +5127,8 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) { const bool hasParens = Tok.is(tok::l_paren); - EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated); + EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated, + Sema::ReuseLambdaContextDecl); bool isCastExpr; ParsedType CastTy; diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 3dc96cf..4cb14e2 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -18,6 +18,7 @@ #include "clang/Sema/Scope.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/PrettyDeclStackTrace.h" +#include "clang/Sema/SemaDiagnostic.h" #include "llvm/ADT/SmallString.h" #include "RAIIObjectsForParser.h" using namespace clang; @@ -87,6 +88,12 @@ Decl *Parser::ParseNamespace(unsigned Context, } if (Tok.is(tok::equal)) { + if (Ident == 0) { + Diag(Tok, diag::err_expected_ident); + // Skip to end of the definition and eat the ';'. + SkipUntil(tok::semi); + return 0; + } if (!attrs.empty()) Diag(attrTok, diag::err_unexpected_namespace_attributes_alias); if (InlineLoc.isValid()) @@ -581,7 +588,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, if (IsAliasDecl) { TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams; - MultiTemplateParamsArg TemplateParamsArg(Actions, + MultiTemplateParamsArg TemplateParamsArg( TemplateParams ? TemplateParams->data() : 0, TemplateParams ? TemplateParams->size() : 0); // FIXME: Propagate attributes. @@ -616,12 +623,13 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){ BalancedDelimiterTracker T(*this, tok::l_paren); if (T.consumeOpen()) { Diag(Tok, diag::err_expected_lparen); + SkipMalformedDecl(); return 0; } ExprResult AssertExpr(ParseConstantExpression()); if (AssertExpr.isInvalid()) { - SkipUntil(tok::semi); + SkipMalformedDecl(); return 0; } @@ -630,13 +638,13 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){ if (!isTokenStringLiteral()) { Diag(Tok, diag::err_expected_string_literal); - SkipUntil(tok::semi); + SkipMalformedDecl(); return 0; } ExprResult AssertMessage(ParseStringLiteralExpression()); if (AssertMessage.isInvalid()) { - SkipUntil(tok::semi); + SkipMalformedDecl(); return 0; } @@ -694,9 +702,22 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { 0, /*IsDecltype=*/true); Result = ParseExpression(); if (Result.isInvalid()) { - SkipUntil(tok::r_paren); DS.SetTypeSpecError(); - return StartLoc; + if (SkipUntil(tok::r_paren, /*StopAtSemi=*/true, /*DontConsume=*/true)) { + EndLoc = ConsumeParen(); + } else { + assert(Tok.is(tok::semi)); + if (PP.isBacktrackEnabled()) { + // Backtrack to get the location of the last token before the semi. + PP.RevertCachedTokens(2); + ConsumeToken(); // the semi. + EndLoc = ConsumeAnyToken(); + assert(Tok.is(tok::semi)); + } else { + EndLoc = Tok.getLocation(); + } + } + return EndLoc; } // Match the ')' @@ -1034,6 +1055,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, DeclSpec::TST TagType; if (TagTokKind == tok::kw_struct) TagType = DeclSpec::TST_struct; + else if (TagTokKind == tok::kw___interface) + TagType = DeclSpec::TST_interface; else if (TagTokKind == tok::kw_class) TagType = DeclSpec::TST_class; else { @@ -1151,7 +1174,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, << (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) << (TagType == DeclSpec::TST_class? 0 : TagType == DeclSpec::TST_struct? 1 - : 2) + : TagType == DeclSpec::TST_interface? 2 + : 3) << Name << SourceRange(LAngleLoc, RAngleLoc); @@ -1243,8 +1267,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, if (Tok.isNot(tok::semi)) { // A semicolon was missing after this declaration. Diagnose and recover. ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl, - TagType == DeclSpec::TST_class ? "class" : - TagType == DeclSpec::TST_struct ? "struct" : "union"); + DeclSpec::getSpecifierName(TagType)); PP.EnterToken(Tok); Tok.setKind(tok::semi); } @@ -1279,8 +1302,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, if (TemplateId) { // Explicit specialization, class template partial specialization, // or explicit instantiation. - ASTTemplateArgsPtr TemplateArgsPtr(Actions, - TemplateId->getTemplateArgs(), + ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), TemplateId->NumArgs); if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation && TUK == Sema::TUK_Declaration) { @@ -1362,7 +1384,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TemplateArgsPtr, TemplateId->RAngleLoc, attrs.getList(), - MultiTemplateParamsArg(Actions, + MultiTemplateParamsArg( TemplateParams? &(*TemplateParams)[0] : 0, TemplateParams? TemplateParams->size() : 0)); } @@ -1389,7 +1411,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, Actions.ActOnTemplatedFriendTag(getCurScope(), DS.getFriendSpecLoc(), TagType, StartLoc, SS, Name, NameLoc, attrs.getList(), - MultiTemplateParamsArg(Actions, + MultiTemplateParamsArg( TemplateParams? &(*TemplateParams)[0] : 0, TemplateParams? TemplateParams->size() : 0)); } else { @@ -1470,8 +1492,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, if (TUK == Sema::TUK_Definition && (TemplateInfo.Kind || !isValidAfterTypeSpecifier(false))) { ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl, - TagType == DeclSpec::TST_class ? "class" : - TagType == DeclSpec::TST_struct ? "struct" : "union"); + DeclSpec::getSpecifierName(TagType)); // Push this token back into the preprocessor and change our current token // to ';' so that the rest of the code recovers as though there were an // ';' after the definition. @@ -1667,7 +1688,8 @@ VirtSpecifiers::Specifier Parser::isCXX0XVirtSpecifier(const Token &Tok) const { /// virt-specifier-seq: /// virt-specifier /// virt-specifier-seq virt-specifier -void Parser::ParseOptionalCXX0XVirtSpecifierSeq(VirtSpecifiers &VS) { +void Parser::ParseOptionalCXX0XVirtSpecifierSeq(VirtSpecifiers &VS, + bool IsInterface) { while (true) { VirtSpecifiers::Specifier Specifier = isCXX0XVirtSpecifier(); if (Specifier == VirtSpecifiers::VS_None) @@ -1681,10 +1703,15 @@ void Parser::ParseOptionalCXX0XVirtSpecifierSeq(VirtSpecifiers &VS) { << PrevSpec << FixItHint::CreateRemoval(Tok.getLocation()); - Diag(Tok.getLocation(), getLangOpts().CPlusPlus0x ? - diag::warn_cxx98_compat_override_control_keyword : - diag::ext_override_control_keyword) - << VirtSpecifiers::getSpecifierName(Specifier); + if (IsInterface && Specifier == VirtSpecifiers::VS_Final) { + Diag(Tok.getLocation(), diag::err_override_control_interface) + << VirtSpecifiers::getSpecifierName(Specifier); + } else { + Diag(Tok.getLocation(), getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_override_control_keyword : + diag::ext_override_control_keyword) + << VirtSpecifiers::getSpecifierName(Specifier); + } ConsumeToken(); } } @@ -1869,7 +1896,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class, &CommonLateParsedAttrs); - MultiTemplateParamsArg TemplateParams(Actions, + MultiTemplateParamsArg TemplateParams( TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data() : 0, TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->size() : 0); @@ -1905,7 +1932,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, return; } - ParseOptionalCXX0XVirtSpecifierSeq(VS); + ParseOptionalCXX0XVirtSpecifierSeq(VS, getCurrentClass().IsInterface); // If attributes exist after the declarator, but before an '{', parse them. MaybeParseGNUAttributes(DeclaratorInfo, &LateParsedAttrs); @@ -2026,7 +2053,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // FIXME: When g++ adds support for this, we'll need to check whether it // goes before or after the GNU attributes and __asm__. - ParseOptionalCXX0XVirtSpecifierSeq(VS); + ParseOptionalCXX0XVirtSpecifierSeq(VS, getCurrentClass().IsInterface); InClassInitStyle HasInClassInit = ICIS_NoInit; if ((Tok.is(tok::equal) || Tok.is(tok::l_brace)) && !HasInitializer) { @@ -2052,11 +2079,11 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (DS.isFriendSpecified()) { // TODO: handle initializers, bitfields, 'delete' ThisDecl = Actions.ActOnFriendFunctionDecl(getCurScope(), DeclaratorInfo, - move(TemplateParams)); + TemplateParams); } else { ThisDecl = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS, DeclaratorInfo, - move(TemplateParams), + TemplateParams, BitfieldSize.release(), VS, HasInClassInit); if (AccessAttrs) @@ -2240,6 +2267,7 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction, void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, unsigned TagType, Decl *TagDecl) { assert((TagType == DeclSpec::TST_struct || + TagType == DeclSpec::TST_interface || TagType == DeclSpec::TST_union || TagType == DeclSpec::TST_class) && "Invalid TagType!"); @@ -2254,6 +2282,15 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, if (S->isClassScope()) { // We're inside a class scope, so this is a nested class. NonNestedClass = false; + + // The Microsoft extension __interface does not permit nested classes. + if (getCurrentClass().IsInterface) { + Diag(RecordLoc, diag::err_invalid_member_in_interface) + << /*ErrorType=*/6 + << (isa<NamedDecl>(TagDecl) + ? cast<NamedDecl>(TagDecl)->getQualifiedNameAsString() + : "<anonymous>"); + } break; } @@ -2274,7 +2311,8 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope); // Note that we are parsing a new (potentially-nested) class definition. - ParsingClassDefinition ParsingDef(*this, TagDecl, NonNestedClass); + ParsingClassDefinition ParsingDef(*this, TagDecl, NonNestedClass, + TagType == DeclSpec::TST_interface); if (TagDecl) Actions.ActOnTagStartDefinition(getCurScope(), TagDecl); @@ -2286,9 +2324,14 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, assert(isCXX0XFinalKeyword() && "not a class definition"); FinalLoc = ConsumeToken(); - Diag(FinalLoc, getLangOpts().CPlusPlus0x ? - diag::warn_cxx98_compat_override_control_keyword : - diag::ext_override_control_keyword) << "final"; + if (TagType == DeclSpec::TST_interface) { + Diag(FinalLoc, diag::err_override_control_interface) + << "final"; + } else { + Diag(FinalLoc, getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_override_control_keyword : + diag::ext_override_control_keyword) << "final"; + } } if (Tok.is(tok::colon)) { @@ -2348,6 +2391,11 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, continue; } + if (Tok.is(tok::annot_pragma_align)) { + HandlePragmaAlign(); + continue; + } + AccessSpecifier AS = getAccessSpecifierIfPresent(); if (AS != AS_none) { // Current token is a C++ access specifier. @@ -2373,6 +2421,13 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, << FixItHint::CreateInsertion(EndLoc, ":"); } + // The Microsoft extension __interface does not permit non-public + // access specifiers. + if (TagType == DeclSpec::TST_interface && CurAS != AS_public) { + Diag(ASLoc, diag::err_access_specifier_interface) + << (CurAS == AS_protected); + } + if (Actions.ActOnAccessSpecifier(AS, ASLoc, EndLoc, AccessAttrs.getList())) { // found another attribute than only annotations @@ -2571,7 +2626,7 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { T.consumeOpen(); // Parse the optional expression-list. - ExprVector ArgExprs(Actions); + ExprVector ArgExprs; CommaLocsTy CommaLocs; if (Tok.isNot(tok::r_paren) && ParseExpressionList(ArgExprs, CommaLocs)) { SkipUntil(tok::r_paren); @@ -2586,7 +2641,7 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II, TemplateTypeTy, DS, IdLoc, - T.getOpenLocation(), ArgExprs.take(), + T.getOpenLocation(), ArgExprs.data(), ArgExprs.size(), T.getCloseLocation(), EllipsisLoc); } @@ -2752,10 +2807,11 @@ TypeResult Parser::ParseTrailingReturnType(SourceRange &Range) { /// so push that class onto our stack of classes that is currently /// being parsed. Sema::ParsingClassState -Parser::PushParsingClass(Decl *ClassDecl, bool NonNestedClass) { +Parser::PushParsingClass(Decl *ClassDecl, bool NonNestedClass, + bool IsInterface) { assert((NonNestedClass || !ClassStack.empty()) && "Nested class without outer class"); - ClassStack.push(new ParsingClass(ClassDecl, NonNestedClass)); + ClassStack.push(new ParsingClass(ClassDecl, NonNestedClass, IsInterface)); return Actions.PushParsingClass(); } @@ -2773,9 +2829,6 @@ void Parser::DeallocateParsedClasses(Parser::ParsingClass *Class) { /// This routine should be called when we have finished parsing the /// definition of a class, but have not yet popped the Scope /// associated with the class's definition. -/// -/// \returns true if the class we've popped is a top-level class, -/// false otherwise. void Parser::PopParsingClass(Sema::ParsingClassState state) { assert(!ClassStack.empty() && "Mismatched push/pop for class parsing"); @@ -2850,6 +2903,21 @@ IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(SourceLocation &Loc) { } } +static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName, + IdentifierInfo *ScopeName) { + switch (AttributeList::getKind(AttrName, ScopeName, + AttributeList::AS_CXX11)) { + case AttributeList::AT_CarriesDependency: + case AttributeList::AT_FallThrough: + case AttributeList::AT_NoReturn: { + return true; + } + + default: + return false; + } +} + /// ParseCXX11AttributeSpecifier - Parse a C++11 attribute-specifier. Currently /// only parses standard attributes. /// @@ -2934,46 +3002,38 @@ void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs, } } + bool StandardAttr = IsBuiltInOrStandardCXX11Attribute(AttrName,ScopeName); bool AttrParsed = false; - switch (AttributeList::getKind(AttrName, ScopeName, - AttributeList::AS_CXX11)) { - // No arguments - case AttributeList::AT_CarriesDependency: - // FIXME: implement generic support of attributes with C++11 syntax - // see Parse/ParseDecl.cpp: ParseGNUAttributes - case AttributeList::AT_FallThrough: - case AttributeList::AT_NoReturn: { - if (Tok.is(tok::l_paren)) { - Diag(Tok.getLocation(), diag::err_cxx11_attribute_forbids_arguments) - << AttrName->getName(); - break; + + // Parse attribute arguments + if (Tok.is(tok::l_paren)) { + if (ScopeName && ScopeName->getName() == "gnu") { + ParseGNUAttributeArgs(AttrName, AttrLoc, attrs, endLoc, + ScopeName, ScopeLoc, AttributeList::AS_CXX11); + AttrParsed = true; + } else { + if (StandardAttr) + Diag(Tok.getLocation(), diag::err_cxx11_attribute_forbids_arguments) + << AttrName->getName(); + + // FIXME: handle other formats of c++11 attribute arguments + ConsumeParen(); + SkipUntil(tok::r_paren, false); } + } + if (!AttrParsed) attrs.addNew(AttrName, SourceRange(ScopeLoc.isValid() ? ScopeLoc : AttrLoc, AttrLoc), ScopeName, ScopeLoc, 0, SourceLocation(), 0, 0, AttributeList::AS_CXX11); - AttrParsed = true; - break; - } - - // Silence warnings - default: break; - } - - // Skip the entire parameter clause, if any - if (!AttrParsed && Tok.is(tok::l_paren)) { - ConsumeParen(); - // SkipUntil maintains the balancedness of tokens. - SkipUntil(tok::r_paren, false); - } if (Tok.is(tok::ellipsis)) { - if (AttrParsed) - Diag(Tok, diag::err_cxx11_attribute_forbids_ellipsis) - << AttrName->getName(); ConsumeToken(); + + Diag(Tok, diag::err_cxx11_attribute_forbids_ellipsis) + << AttrName->getName(); } } diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 8d4668b..c7be0d3 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -179,7 +179,7 @@ static prec::Level getBinOpPrecedence(tok::TokenKind Kind, /// \endverbatim ExprResult Parser::ParseExpression(TypeCastState isTypeCast) { ExprResult LHS(ParseAssignmentExpression(isTypeCast)); - return ParseRHSOfBinaryExpression(move(LHS), prec::Comma); + return ParseRHSOfBinaryExpression(LHS, prec::Comma); } /// This routine is called when the '@' is seen and consumed. @@ -190,7 +190,7 @@ ExprResult Parser::ParseExpression(TypeCastState isTypeCast) { ExprResult Parser::ParseExpressionWithLeadingAt(SourceLocation AtLoc) { ExprResult LHS(ParseObjCAtExpression(AtLoc)); - return ParseRHSOfBinaryExpression(move(LHS), prec::Comma); + return ParseRHSOfBinaryExpression(LHS, prec::Comma); } /// This routine is called when a leading '__extension__' is seen and @@ -210,7 +210,7 @@ Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) { LHS = Actions.ActOnUnaryOp(getCurScope(), ExtLoc, tok::kw___extension__, LHS.take()); - return ParseRHSOfBinaryExpression(move(LHS), prec::Comma); + return ParseRHSOfBinaryExpression(LHS, prec::Comma); } /// \brief Parse an expr that doesn't include (top-level) commas. @@ -227,7 +227,7 @@ ExprResult Parser::ParseAssignmentExpression(TypeCastState isTypeCast) { ExprResult LHS = ParseCastExpression(/*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, isTypeCast); - return ParseRHSOfBinaryExpression(move(LHS), prec::Assignment); + return ParseRHSOfBinaryExpression(LHS, prec::Assignment); } /// \brief Parse an assignment expression where part of an Objective-C message @@ -265,6 +265,17 @@ ExprResult Parser::ParseConstantExpression(TypeCastState isTypeCast) { return Actions.ActOnConstantExpression(Res); } +bool Parser::isNotExpressionStart() { + tok::TokenKind K = Tok.getKind(); + if (K == tok::l_brace || K == tok::r_brace || + K == tok::kw_for || K == tok::kw_while || + K == tok::kw_if || K == tok::kw_else || + K == tok::kw_goto || K == tok::kw_try) + return true; + // If this is a decl-specifier, we can't be at the start of an expression. + return isKnownToBeDeclarationSpecifier(); +} + /// \brief Parse a binary expression that starts with \p LHS and has a /// precedence of at least \p MinPrec. ExprResult @@ -279,12 +290,23 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { // because we are called recursively, or because the token is not a binop), // then we are done! if (NextTokPrec < MinPrec) - return move(LHS); + return LHS; // Consume the operator, saving the operator token for error reporting. Token OpToken = Tok; ConsumeToken(); + // Bail out when encountering a comma followed by a token which can't + // possibly be the start of an expression. For instance: + // int f() { return 1, } + // We can't do this before consuming the comma, because + // isNotExpressionStart() looks at the token stream. + if (OpToken.is(tok::comma) && isNotExpressionStart()) { + PP.EnterToken(Tok); + Tok = OpToken; + return LHS; + } + // Special case handling for the ternary operator. ExprResult TernaryMiddle(true); if (NextTokPrec == prec::Conditional) { @@ -458,7 +480,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, isTypeCast); if (NotCastExpr) Diag(Tok, diag::err_expected_expression); - return move(Res); + return Res; } namespace { @@ -698,7 +720,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case CastExpr: // We have parsed the cast-expression and no postfix-expr pieces are // following. - return move(Res); + return Res; } break; @@ -741,6 +763,53 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, // Avoid the unnecessary parse-time lookup in the common case // where the syntax forbids a type. const Token &Next = NextToken(); + + // If this identifier was reverted from a token ID, and the next token + // is a parenthesis, this is likely to be a use of a type trait. Check + // those tokens. + if (Next.is(tok::l_paren) && + Tok.is(tok::identifier) && + Tok.getIdentifierInfo()->hasRevertedTokenIDToIdentifier()) { + IdentifierInfo *II = Tok.getIdentifierInfo(); + // Build up the mapping of revertable type traits, for future use. + if (RevertableTypeTraits.empty()) { +#define RTT_JOIN(X,Y) X##Y +#define REVERTABLE_TYPE_TRAIT(Name) \ + RevertableTypeTraits[PP.getIdentifierInfo(#Name)] \ + = RTT_JOIN(tok::kw_,Name) + + REVERTABLE_TYPE_TRAIT(__is_arithmetic); + REVERTABLE_TYPE_TRAIT(__is_convertible); + REVERTABLE_TYPE_TRAIT(__is_empty); + REVERTABLE_TYPE_TRAIT(__is_floating_point); + REVERTABLE_TYPE_TRAIT(__is_function); + REVERTABLE_TYPE_TRAIT(__is_fundamental); + REVERTABLE_TYPE_TRAIT(__is_integral); + REVERTABLE_TYPE_TRAIT(__is_member_function_pointer); + REVERTABLE_TYPE_TRAIT(__is_member_pointer); + REVERTABLE_TYPE_TRAIT(__is_pod); + REVERTABLE_TYPE_TRAIT(__is_pointer); + REVERTABLE_TYPE_TRAIT(__is_same); + REVERTABLE_TYPE_TRAIT(__is_scalar); + REVERTABLE_TYPE_TRAIT(__is_signed); + REVERTABLE_TYPE_TRAIT(__is_unsigned); + REVERTABLE_TYPE_TRAIT(__is_void); +#undef REVERTABLE_TYPE_TRAIT +#undef RTT_JOIN + } + + // If we find that this is in fact the name of a type trait, + // update the token kind in place and parse again to treat it as + // the appropriate kind of type trait. + llvm::SmallDenseMap<IdentifierInfo *, tok::TokenKind>::iterator Known + = RevertableTypeTraits.find(II); + if (Known != RevertableTypeTraits.end()) { + Tok.setKind(Known->second); + return ParseCastExpression(isUnaryExpression, isAddressOfOperand, + NotCastExpr, isTypeCast); + } + } + if (Next.is(tok::coloncolon) || (!ColonIsSacred && Next.is(tok::colon)) || Next.is(tok::less) || @@ -758,7 +827,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, // '.'. IdentifierInfo &II = *Tok.getIdentifierInfo(); SourceLocation ILoc = ConsumeToken(); - + // Support 'Class.property' and 'super.property' notation. if (getLangOpts().ObjC1 && Tok.is(tok::period) && (Actions.getTypeName(II, ILoc, getCurScope()) || @@ -888,7 +957,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, Res = ParseCastExpression(!getLangOpts().CPlusPlus); if (!Res.isInvalid()) Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get()); - return move(Res); + return Res; } case tok::amp: { // unary-expression: '&' cast-expression // Special treatment because of member pointers @@ -896,7 +965,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, Res = ParseCastExpression(false, true); if (!Res.isInvalid()) Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get()); - return move(Res); + return Res; } case tok::star: // unary-expression: '*' cast-expression @@ -910,7 +979,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, Res = ParseCastExpression(false); if (!Res.isInvalid()) Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get()); - return move(Res); + return Res; } case tok::kw___extension__:{//unary-expression:'__extension__' cast-expr [GNU] @@ -920,7 +989,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, Res = ParseCastExpression(false); if (!Res.isInvalid()) Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get()); - return move(Res); + return Res; } case tok::kw__Alignof: // unary-expression: '_Alignof' '(' type-name ')' if (!getLangOpts().C11) @@ -946,7 +1015,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, Tok.getLocation()); Res = Actions.ActOnAddrLabel(AmpAmpLoc, Tok.getLocation(), LD); ConsumeToken(); - return move(Res); + return Res; } case tok::kw_const_cast: case tok::kw_dynamic_cast: @@ -1132,13 +1201,14 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, if (!Result.isInvalid()) Result = Actions.ActOnNoexceptExpr(KeyLoc, T.getOpenLocation(), Result.take(), T.getCloseLocation()); - return move(Result); + return Result; } case tok::kw___is_abstract: // [GNU] unary-type-trait case tok::kw___is_class: case tok::kw___is_empty: case tok::kw___is_enum: + case tok::kw___is_interface_class: case tok::kw___is_literal: case tok::kw___is_arithmetic: case tok::kw___is_integral: @@ -1270,7 +1340,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { switch (Tok.getKind()) { case tok::code_completion: if (InMessageExpression) - return move(LHS); + return LHS; Actions.CodeCompletePostfixExpression(getCurScope(), LHS); cutOffParsing(); @@ -1290,7 +1360,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { // Fall through; this isn't a message send. default: // Not a postfix-expression suffix. - return move(LHS); + return LHS; case tok::l_square: { // postfix-expression: p-e '[' expression ']' // If we have a array postfix expression that starts on a new line and // Objective-C is enabled, it is highly likely that the user forgot a @@ -1300,7 +1370,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { // expression and recover by pretending there is no suffix. if (getLangOpts().ObjC1 && Tok.isAtStartOfLine() && isSimpleObjCMessageExpression()) - return move(LHS); + return LHS; // Reject array indices starting with a lambda-expression. '[[' is // reserved for attributes. @@ -1341,7 +1411,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { BalancedDelimiterTracker PT(*this, tok::l_paren); if (OpKind == tok::lesslessless) { - ExprVector ExecConfigExprs(Actions); + ExprVector ExecConfigExprs; CommaLocsTy ExecConfigCommaLocs; SourceLocation OpenLoc = ConsumeToken(); @@ -1372,7 +1442,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { if (!LHS.isInvalid()) { ExprResult ECResult = Actions.ActOnCUDAExecConfigExpr(getCurScope(), OpenLoc, - move_arg(ExecConfigExprs), + ExecConfigExprs, CloseLoc); if (ECResult.isInvalid()) LHS = ExprError(); @@ -1384,7 +1454,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { Loc = PT.getOpenLocation(); } - ExprVector ArgExprs(Actions); + ExprVector ArgExprs; CommaLocsTy CommaLocs; if (Tok.is(tok::code_completion)) { @@ -1414,7 +1484,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { ArgExprs.size()-1 == CommaLocs.size())&& "Unexpected number of commas!"); LHS = Actions.ActOnCallExpr(getCurScope(), LHS.take(), Loc, - move_arg(ArgExprs), Tok.getLocation(), + ArgExprs, Tok.getLocation(), ExecConfig); PT.consumeClose(); } @@ -1583,7 +1653,7 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, // If we get here, the operand to the typeof/sizeof/alignof was an expresion. isCastExpr = false; - return move(Operand); + return Operand; } @@ -1653,7 +1723,8 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { if (OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw__Alignof)) Diag(OpTok, diag::warn_cxx98_compat_alignof); - EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated); + EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated, + Sema::ReuseLambdaContextDecl); bool isCastExpr; ParsedType CastTy; @@ -1684,7 +1755,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { /*isType=*/false, Operand.release(), CastRange); - return move(Operand); + return Operand; } /// ParseBuiltinPrimaryExpression @@ -1796,7 +1867,7 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { Res = ParseExpression(); if (Res.isInvalid()) { SkipUntil(tok::r_paren); - return move(Res); + return Res; } Comps.back().U.E = Res.release(); @@ -1823,7 +1894,7 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { ExprResult Cond(ParseAssignmentExpression()); if (Cond.isInvalid()) { SkipUntil(tok::r_paren); - return move(Cond); + return Cond; } if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren)) return ExprError(); @@ -1831,7 +1902,7 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { ExprResult Expr1(ParseAssignmentExpression()); if (Expr1.isInvalid()) { SkipUntil(tok::r_paren); - return move(Expr1); + return Expr1; } if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren)) return ExprError(); @@ -1839,7 +1910,7 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { ExprResult Expr2(ParseAssignmentExpression()); if (Expr2.isInvalid()) { SkipUntil(tok::r_paren); - return move(Expr2); + return Expr2; } if (Tok.isNot(tok::r_paren)) { Diag(Tok, diag::err_expected_rparen); @@ -2083,7 +2154,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, DeclaratorInfo, CastTy, RParenLoc, Result.take()); } - return move(Result); + return Result; } Diag(Tok, diag::err_expected_lbrace_in_compound_literal); @@ -2093,13 +2164,13 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, // Parse the expression-list. InMessageExpressionRAIIObject InMessage(*this, false); - ExprVector ArgExprs(Actions); + ExprVector ArgExprs; CommaLocsTy CommaLocs; if (!ParseExpressionList(ArgExprs, CommaLocs)) { ExprType = SimpleExpr; Result = Actions.ActOnParenListExpr(OpenLoc, Tok.getLocation(), - move_arg(ArgExprs)); + ArgExprs); } } else { InMessageExpressionRAIIObject InMessage(*this, false); @@ -2120,7 +2191,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, T.consumeClose(); RParenLoc = T.getCloseLocation(); - return move(Result); + return Result; } /// ParseCompoundLiteralExpression - We have parsed the parenthesized type-name @@ -2141,7 +2212,7 @@ Parser::ParseCompoundLiteralExpression(ParsedType Ty, ExprResult Result = ParseInitializer(); if (!Result.isInvalid() && Ty) return Actions.ActOnCompoundLiteral(LParenLoc, Ty, RParenLoc, Result.take()); - return move(Result); + return Result; } /// ParseStringLiteralExpression - This handles the various token types that @@ -2211,8 +2282,8 @@ ExprResult Parser::ParseGenericSelectionExpression() { } SourceLocation DefaultLoc; - TypeVector Types(Actions); - ExprVector Exprs(Actions); + TypeVector Types; + ExprVector Exprs; while (1) { ParsedType Ty; if (Tok.is(tok::kw_default)) { @@ -2263,7 +2334,7 @@ ExprResult Parser::ParseGenericSelectionExpression() { return Actions.ActOnGenericSelectionExpr(KeyLoc, DefaultLoc, T.getCloseLocation(), ControllingExpr.release(), - move_arg(Types), move_arg(Exprs)); + Types, Exprs); } /// ParseExpressionList - Used for C/C++ (argument-)expression-list. @@ -2415,18 +2486,28 @@ ExprResult Parser::ParseBlockLiteralExpression() { } else { // Otherwise, pretend we saw (void). ParsedAttributes attrs(AttrFactory); - ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(true, false, false, - SourceLocation(), - 0, 0, 0, - true, SourceLocation(), - SourceLocation(), - SourceLocation(), - SourceLocation(), - EST_None, - SourceLocation(), - 0, 0, 0, 0, - CaretLoc, CaretLoc, - ParamInfo), + SourceLocation NoLoc; + ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(/*HasProto=*/true, + /*IsAmbiguous=*/false, + /*RParenLoc=*/NoLoc, + /*ArgInfo=*/0, + /*NumArgs=*/0, + /*EllipsisLoc=*/NoLoc, + /*RParenLoc=*/NoLoc, + /*TypeQuals=*/0, + /*RefQualifierIsLvalueRef=*/true, + /*RefQualifierLoc=*/NoLoc, + /*ConstQualifierLoc=*/NoLoc, + /*VolatileQualifierLoc=*/NoLoc, + /*MutableLoc=*/NoLoc, + EST_None, + /*ESpecLoc=*/NoLoc, + /*Exceptions=*/0, + /*ExceptionRanges=*/0, + /*NumExceptions=*/0, + /*NoexceptExpr=*/0, + CaretLoc, CaretLoc, + ParamInfo), attrs, CaretLoc); MaybeParseGNUAttributes(ParamInfo); @@ -2450,7 +2531,7 @@ ExprResult Parser::ParseBlockLiteralExpression() { Result = Actions.ActOnBlockStmtExpr(CaretLoc, Stmt.take(), getCurScope()); else Actions.ActOnBlockError(CaretLoc, getCurScope()); - return move(Result); + return Result; } /// ParseObjCBoolLiteral - This handles the objective-c Boolean literals. diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index afac257..2f615e1 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -96,6 +96,45 @@ void Parser::CheckForTemplateAndDigraph(Token &Next, ParsedType ObjectType, /*AtDigraph*/false); } +/// \brief Emits an error for a left parentheses after a double colon. +/// +/// When a '(' is found after a '::', emit an error. Attempt to fix the token +/// stream by removing the '(', and the matching ')' if it found. +void Parser::CheckForLParenAfterColonColon() { + if (!Tok.is(tok::l_paren)) + return; + + SourceLocation l_parenLoc = ConsumeParen(), r_parenLoc; + Token Tok1 = getCurToken(); + if (!Tok1.is(tok::identifier) && !Tok1.is(tok::star)) + return; + + if (Tok1.is(tok::identifier)) { + Token Tok2 = GetLookAheadToken(1); + if (Tok2.is(tok::r_paren)) { + ConsumeToken(); + PP.EnterToken(Tok1); + r_parenLoc = ConsumeParen(); + } + } else if (Tok1.is(tok::star)) { + Token Tok2 = GetLookAheadToken(1); + if (Tok2.is(tok::identifier)) { + Token Tok3 = GetLookAheadToken(2); + if (Tok3.is(tok::r_paren)) { + ConsumeToken(); + ConsumeToken(); + PP.EnterToken(Tok2); + PP.EnterToken(Tok1); + r_parenLoc = ConsumeParen(); + } + } + } + + Diag(l_parenLoc, diag::err_paren_after_colon_colon) + << FixItHint::CreateRemoval(l_parenLoc) + << FixItHint::CreateRemoval(r_parenLoc); +} + /// \brief Parse global scope or nested-name-specifier if present. /// /// Parses a C++ global scope specifier ('::') or nested-name-specifier (which @@ -160,7 +199,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, // '::' - Global scope qualifier. if (Actions.ActOnCXXGlobalScopeSpecifier(getCurScope(), ConsumeToken(), SS)) return true; - + + CheckForLParenAfterColonColon(); + HasScopeSpecifier = true; } @@ -301,8 +342,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, HasScopeSpecifier = true; - ASTTemplateArgsPtr TemplateArgsPtr(Actions, - TemplateId->getTemplateArgs(), + ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), TemplateId->NumArgs); if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), @@ -372,6 +412,8 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, "NextToken() not working properly!"); SourceLocation CCLoc = ConsumeToken(); + CheckForLParenAfterColonColon(); + HasScopeSpecifier = true; if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), II, IdLoc, CCLoc, ObjectType, EnteringContext, SS)) @@ -757,10 +799,10 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( Scope::FunctionPrototypeScope | Scope::DeclScope); - SourceLocation DeclLoc, DeclEndLoc; + SourceLocation DeclEndLoc; BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); - DeclLoc = T.getOpenLocation(); + SourceLocation LParenLoc = T.getOpenLocation(); // Parse parameter-declaration-clause. ParsedAttributes Attr(AttrFactory); @@ -771,7 +813,8 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( ParseParameterDeclarationClause(D, Attr, ParamInfo, EllipsisLoc); T.consumeClose(); - DeclEndLoc = T.getCloseLocation(); + SourceLocation RParenLoc = T.getCloseLocation(); + DeclEndLoc = RParenLoc; // Parse 'mutable'[opt]. SourceLocation MutableLoc; @@ -797,9 +840,12 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( // Parse attribute-specifier[opt]. MaybeParseCXX0XAttributes(Attr, &DeclEndLoc); + SourceLocation FunLocalRangeEnd = DeclEndLoc; + // Parse trailing-return-type[opt]. TypeResult TrailingReturnType; if (Tok.is(tok::arrow)) { + FunLocalRangeEnd = Tok.getLocation(); SourceRange Range; TrailingReturnType = ParseTrailingReturnType(Range); if (Range.getEnd().isValid()) @@ -808,15 +854,17 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( PrototypeScope.Exit(); + SourceLocation NoLoc; D.AddTypeInfo(DeclaratorChunk::getFunction(/*hasProto=*/true, - /*isVariadic=*/EllipsisLoc.isValid(), - /*isAmbiguous=*/false, EllipsisLoc, + /*isAmbiguous=*/false, + LParenLoc, ParamInfo.data(), ParamInfo.size(), + EllipsisLoc, RParenLoc, DS.getTypeQualifiers(), /*RefQualifierIsLValueRef=*/true, - /*RefQualifierLoc=*/SourceLocation(), - /*ConstQualifierLoc=*/SourceLocation(), - /*VolatileQualifierLoc=*/SourceLocation(), + /*RefQualifierLoc=*/NoLoc, + /*ConstQualifierLoc=*/NoLoc, + /*VolatileQualifierLoc=*/NoLoc, MutableLoc, ESpecType, ESpecRange.getBegin(), DynamicExceptions.data(), @@ -824,7 +872,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( DynamicExceptions.size(), NoexceptExpr.isUsable() ? NoexceptExpr.get() : 0, - DeclLoc, DeclEndLoc, D, + LParenLoc, FunLocalRangeEnd, D, TrailingReturnType), Attr, DeclEndLoc); } else if (Tok.is(tok::kw_mutable) || Tok.is(tok::arrow)) { @@ -853,25 +901,28 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( } ParsedAttributes Attr(AttrFactory); + SourceLocation NoLoc; D.AddTypeInfo(DeclaratorChunk::getFunction(/*hasProto=*/true, - /*isVariadic=*/false, - /*isAmbiguous=*/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), + /*isAmbiguous=*/false, + /*LParenLoc=*/NoLoc, + /*Params=*/0, + /*NumParams=*/0, + /*EllipsisLoc=*/NoLoc, + /*RParenLoc=*/NoLoc, + /*TypeQuals=*/0, + /*RefQualifierIsLValueRef=*/true, + /*RefQualifierLoc=*/NoLoc, + /*ConstQualifierLoc=*/NoLoc, + /*VolatileQualifierLoc=*/NoLoc, + MutableLoc, + EST_None, + /*ESpecLoc=*/NoLoc, + /*Exceptions=*/0, + /*ExceptionRanges=*/0, + /*NumExceptions=*/0, + /*NoexceptExpr=*/0, + DeclLoc, DeclEndLoc, D, + TrailingReturnType), Attr, DeclEndLoc); } @@ -926,10 +977,11 @@ ExprResult Parser::ParseCXXCasts() { // Check for "<::" which is parsed as "[:". If found, fix token stream, // diagnose error, suggest fix, and recover parsing. - Token Next = NextToken(); - if (Tok.is(tok::l_square) && Tok.getLength() == 2 && Next.is(tok::colon) && - areTokensAdjacent(Tok, Next)) - FixDigraph(*this, PP, Tok, Next, Kind, /*AtDigraph*/true); + if (Tok.is(tok::l_square) && Tok.getLength() == 2) { + Token Next = NextToken(); + if (Next.is(tok::colon) && areTokensAdjacent(Tok, Next)) + FixDigraph(*this, PP, Tok, Next, Kind, /*AtDigraph*/true); + } if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName)) return ExprError(); @@ -965,7 +1017,7 @@ ExprResult Parser::ParseCXXCasts() { T.getOpenLocation(), Result.take(), T.getCloseLocation()); - return move(Result); + return Result; } /// ParseCXXTypeid - This handles the C++ typeid expression. @@ -988,6 +1040,22 @@ ExprResult Parser::ParseCXXTypeid() { ExprResult Result; + // C++0x [expr.typeid]p3: + // When typeid is applied to an expression other than an lvalue of a + // polymorphic class type [...] The expression is an unevaluated + // 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; we + // speculatively assume the subexpression is unevaluated, and fix it up + // later. + // + // We enter the unevaluated context before trying to determine whether we + // have a type-id, because the tentative parse logic will try to resolve + // names, and must treat them as unevaluated. + EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated, + Sema::ReuseLambdaContextDecl); + if (isTypeIdInParens()) { TypeResult Ty = ParseTypeName(); @@ -1000,16 +1068,6 @@ ExprResult Parser::ParseCXXTypeid() { Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true, Ty.get().getAsOpaquePtr(), RParenLoc); } else { - // C++0x [expr.typeid]p3: - // When typeid is applied to an expression other than an lvalue of a - // polymorphic class type [...] The expression is an unevaluated - // 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; we - // speculatively assume the subexpression is unevaluated, and fix it up - // later. - EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated); Result = ParseExpression(); // Match the ')'. @@ -1026,7 +1084,7 @@ ExprResult Parser::ParseCXXTypeid() { } } - return move(Result); + return Result; } /// ParseCXXUuidof - This handles the Microsoft C++ __uuidof expression. @@ -1074,7 +1132,7 @@ ExprResult Parser::ParseCXXUuidof() { } } - return move(Result); + return Result; } /// \brief Parse a C++ pseudo-destructor expression after the base, @@ -1196,7 +1254,7 @@ ExprResult Parser::ParseThrowExpression() { default: ExprResult Expr(ParseAssignmentExpression()); - if (Expr.isInvalid()) return move(Expr); + if (Expr.isInvalid()) return Expr; return Actions.ActOnCXXThrow(getCurScope(), ThrowLoc, Expr.take()); } } @@ -1245,7 +1303,7 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); - ExprVector Exprs(Actions); + ExprVector Exprs; CommaLocsTy CommaLocs; if (Tok.isNot(tok::r_paren)) { @@ -1265,7 +1323,7 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&& "Unexpected number of commas!"); return Actions.ActOnCXXTypeConstructExpr(TypeRep, T.getOpenLocation(), - move_arg(Exprs), + Exprs, T.getCloseLocation()); } } @@ -1280,11 +1338,11 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { /// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt] /// '=' assignment-expression /// -/// \param ExprResult if the condition was parsed as an expression, the -/// parsed expression. +/// \param ExprOut if the condition was parsed as an expression, the parsed +/// expression. /// -/// \param DeclResult if the condition was parsed as a declaration, the -/// parsed declaration. +/// \param DeclOut 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. @@ -1714,8 +1772,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, } // Bundle the template arguments together. - ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateArgs.data(), - TemplateArgs.size()); + ASTTemplateArgsPtr TemplateArgsPtr(TemplateArgs); // Constructor and destructor names. TypeResult Type @@ -1762,7 +1819,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, /// ptr-operator conversion-declarator[opt] /// \endcode /// -/// \param The nested-name-specifier that preceded this unqualified-id. If +/// \param SS The nested-name-specifier that preceded this unqualified-id. If /// non-empty, then we are parsing the unqualified-id of a qualified-id. /// /// \param EnteringContext whether we are entering the scope of the @@ -1867,8 +1924,9 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, // Parse a literal-operator-id. // - // literal-operator-id: [C++0x 13.5.8] - // operator "" identifier + // literal-operator-id: C++11 [over.literal] + // operator string-literal identifier + // operator user-defined-string-literal if (getLangOpts().CPlusPlus0x && isTokenStringLiteral()) { Diag(Tok.getLocation(), diag::warn_cxx98_compat_literal_operator); @@ -1882,6 +1940,9 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, llvm::SmallVector<SourceLocation, 4> TokLocs; while (isTokenStringLiteral()) { if (!Tok.is(tok::string_literal) && !DiagId) { + // C++11 [over.literal]p1: + // The string-literal or user-defined-string-literal in a + // literal-operator-id shall have no encoding-prefix [...]. DiagLoc = Tok.getLocation(); DiagId = diag::err_literal_operator_string_prefix; } @@ -1903,9 +1964,6 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, 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(); @@ -1917,6 +1975,10 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, // The string literal must be empty. if (!Literal.GetString().empty() || Literal.Pascal) { + // C++11 [over.literal]p1: + // The string-literal or user-defined-string-literal in a + // literal-operator-id shall [...] contain no characters + // other than the implicit terminating '\0'. DiagLoc = TokLocs.front(); DiagId = diag::err_literal_operator_string_not_empty; } @@ -1981,7 +2043,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, /// /// \endcode /// -/// \param The nested-name-specifier that preceded this unqualified-id. If +/// \param SS The nested-name-specifier that preceded this unqualified-id. If /// non-empty, then we are parsing the unqualified-id of a qualified-id. /// /// \param EnteringContext whether we are entering the scope of the @@ -2209,7 +2271,7 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { // A '(' now can be a new-placement or the '(' wrapping the type-id in the // second form of new-expression. It can't be a new-type-id. - ExprVector PlacementArgs(Actions); + ExprVector PlacementArgs; SourceLocation PlacementLParen, PlacementRParen; SourceRange TypeIdParens; @@ -2279,7 +2341,7 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { if (Tok.is(tok::l_paren)) { SourceLocation ConstructorLParen, ConstructorRParen; - ExprVector ConstructorArgs(Actions); + ExprVector ConstructorArgs; BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); ConstructorLParen = T.getOpenLocation(); @@ -2298,7 +2360,7 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { } Initializer = Actions.ActOnParenListExpr(ConstructorLParen, ConstructorRParen, - move_arg(ConstructorArgs)); + ConstructorArgs); } else if (Tok.is(tok::l_brace) && getLangOpts().CPlusPlus0x) { Diag(Tok.getLocation(), diag::warn_cxx98_compat_generalized_initializer_lists); @@ -2308,7 +2370,7 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { return Initializer; return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen, - move_arg(PlacementArgs), PlacementRParen, + PlacementArgs, PlacementRParen, TypeIdParens, DeclaratorInfo, Initializer.take()); } @@ -2422,7 +2484,7 @@ Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) { ExprResult Operand(ParseCastExpression(false)); if (Operand.isInvalid()) - return move(Operand); + return Operand; return Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete, Operand.take()); } @@ -2453,6 +2515,7 @@ static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) { 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; @@ -2804,7 +2867,7 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, Result = Actions.ActOnCastExpr(getCurScope(), Tracker.getOpenLocation(), DeclaratorInfo, CastTy, Tracker.getCloseLocation(), Result.take()); - return move(Result); + return Result; } // Not a compound literal, and not followed by a cast-expression. @@ -2823,5 +2886,5 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, } Tracker.consumeClose(); - return move(Result); + return Result; } diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp index 1c349fd..e47fd9b 100644 --- a/lib/Parse/ParseInit.cpp +++ b/lib/Parse/ParseInit.cpp @@ -313,7 +313,7 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() { Idx = ParseAssignmentExpression(); if (Idx.isInvalid()) { SkipUntil(tok::r_square); - return move(Idx); + return Idx; } } @@ -341,7 +341,7 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() { ExprResult RHS(ParseConstantExpression()); if (RHS.isInvalid()) { SkipUntil(tok::r_square); - return move(RHS); + return RHS; } Desig.AddDesignator(Designator::getArrayRange(Idx.release(), RHS.release(), @@ -405,15 +405,14 @@ ExprResult Parser::ParseBraceInitializer() { /// InitExprs - This is the actual list of expressions contained in the /// initializer. - ExprVector InitExprs(Actions); + ExprVector InitExprs; if (Tok.is(tok::r_brace)) { // Empty initializers are a C++ feature and a GNU extension to C. if (!getLangOpts().CPlusPlus) Diag(LBraceLoc, diag::ext_gnu_empty_initializer); // Match the '}'. - return Actions.ActOnInitList(LBraceLoc, MultiExprArg(Actions), - ConsumeBrace()); + return Actions.ActOnInitList(LBraceLoc, MultiExprArg(), ConsumeBrace()); } bool InitExprsOk = true; @@ -476,7 +475,7 @@ ExprResult Parser::ParseBraceInitializer() { bool closed = !T.consumeClose(); if (InitExprsOk && closed) - return Actions.ActOnInitList(LBraceLoc, move_arg(InitExprs), + return Actions.ActOnInitList(LBraceLoc, InitExprs, T.getCloseLocation()); return ExprError(); // an error occurred. diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index db35a38..d321baf 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -18,6 +18,7 @@ #include "clang/Sema/PrettyDeclStackTrace.h" #include "clang/Sema/Scope.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" using namespace clang; @@ -1031,7 +1032,6 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, Scope::FunctionPrototypeScope|Scope::DeclScope); AttributePool allParamAttrs(AttrFactory); - while (1) { ParsedAttributes paramAttrs(AttrFactory); Sema::ObjCArgInfo ArgInfo; @@ -1102,6 +1102,14 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, SelIdent = ParseObjCSelectorPiece(selLoc); if (!SelIdent && Tok.isNot(tok::colon)) break; + if (!SelIdent) { + SourceLocation ColonLoc = Tok.getLocation(); + if (PP.getLocForEndOfToken(ArgInfo.NameLoc) == ColonLoc) { + Diag(ArgInfo.NameLoc, diag::warn_missing_selector_name) << ArgInfo.Name; + Diag(ArgInfo.NameLoc, diag::note_missing_selector_name) << ArgInfo.Name; + Diag(ColonLoc, diag::note_force_empty_selector_name) << ArgInfo.Name; + } + } // We have a selector or a colon, continue parsing. } @@ -1806,7 +1814,7 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { Diag(Tok, diag::err_expected_lbrace); return StmtError(); } - StmtVector CatchStmts(Actions); + StmtVector CatchStmts; StmtResult FinallyStmt; ParseScope TryScope(this, Scope::DeclScope); StmtResult TryBody(ParseCompoundStatementBody()); @@ -1894,7 +1902,7 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { } return Actions.ActOnObjCAtTryStmt(atLoc, TryBody.take(), - move_arg(CatchStmts), + CatchStmts, FinallyStmt.take()); } @@ -2061,13 +2069,13 @@ ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { ExprResult Lit(Actions.ActOnNumericConstant(Tok)); if (Lit.isInvalid()) { - return move(Lit); + return Lit; } ConsumeToken(); // Consume the literal token. Lit = Actions.ActOnUnaryOp(getCurScope(), OpLoc, Kind, Lit.take()); if (Lit.isInvalid()) - return move(Lit); + return Lit; return ParsePostfixExpressionSuffix( Actions.BuildObjCNumericLiteral(AtLoc, Lit.take())); @@ -2134,7 +2142,7 @@ ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { } } -/// \brirg Parse the receiver of an Objective-C++ message send. +/// \brief Parse the receiver of an Objective-C++ message send. /// /// This routine parses the receiver of a message send in /// Objective-C++ either as a type or as an expression. Note that this @@ -2346,7 +2354,7 @@ ExprResult Parser::ParseObjCMessageExpression() { ExprResult Res(ParseExpression()); if (Res.isInvalid()) { SkipUntil(tok::r_square); - return move(Res); + return Res; } return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), @@ -2418,7 +2426,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, SmallVector<IdentifierInfo *, 12> KeyIdents; SmallVector<SourceLocation, 12> KeyLocs; - ExprVector KeyExprs(Actions); + ExprVector KeyExprs; if (Tok.is(tok::colon)) { while (1) { @@ -2465,7 +2473,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, // stop at the ']' when it skips to the ';'. We want it to skip beyond // the enclosing expression. SkipUntil(tok::r_square); - return move(Res); + return Res; } // We have a valid expression. @@ -2512,7 +2520,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, // stop at the ']' when it skips to the ';'. We want it to skip beyond // the enclosing expression. SkipUntil(tok::r_square); - return move(Res); + return Res; } // We have a valid expression. @@ -2551,32 +2559,23 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, if (SuperLoc.isValid()) return Actions.ActOnSuperMessage(getCurScope(), SuperLoc, Sel, - LBracLoc, KeyLocs, RBracLoc, - MultiExprArg(Actions, - KeyExprs.take(), - KeyExprs.size())); + LBracLoc, KeyLocs, RBracLoc, KeyExprs); else if (ReceiverType) return Actions.ActOnClassMessage(getCurScope(), ReceiverType, Sel, - LBracLoc, KeyLocs, RBracLoc, - MultiExprArg(Actions, - KeyExprs.take(), - KeyExprs.size())); + LBracLoc, KeyLocs, RBracLoc, KeyExprs); return Actions.ActOnInstanceMessage(getCurScope(), ReceiverExpr, Sel, - LBracLoc, KeyLocs, RBracLoc, - MultiExprArg(Actions, - KeyExprs.take(), - KeyExprs.size())); + LBracLoc, KeyLocs, RBracLoc, KeyExprs); } ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) { ExprResult Res(ParseStringLiteralExpression()); - if (Res.isInvalid()) return move(Res); + if (Res.isInvalid()) return Res; // @"foo" @"bar" is a valid concatenated string. Eat any subsequent string // expressions. At this point, we know that the only valid thing that starts // with '@' is an @"". SmallVector<SourceLocation, 4> AtLocs; - ExprVector AtStrings(Actions); + ExprVector AtStrings; AtLocs.push_back(AtLoc); AtStrings.push_back(Res.release()); @@ -2589,12 +2588,12 @@ ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) { ExprResult Lit(ParseStringLiteralExpression()); if (Lit.isInvalid()) - return move(Lit); + return Lit; AtStrings.push_back(Lit.release()); } - return Owned(Actions.ParseObjCStringLiteral(&AtLocs[0], AtStrings.take(), + return Owned(Actions.ParseObjCStringLiteral(&AtLocs[0], AtStrings.data(), AtStrings.size())); } @@ -2615,7 +2614,7 @@ ExprResult Parser::ParseObjCBooleanLiteral(SourceLocation AtLoc, ExprResult Parser::ParseObjCCharacterLiteral(SourceLocation AtLoc) { ExprResult Lit(Actions.ActOnCharacterConstant(Tok)); if (Lit.isInvalid()) { - return move(Lit); + return Lit; } ConsumeToken(); // Consume the literal token. return Owned(Actions.BuildObjCNumericLiteral(AtLoc, Lit.take())); @@ -2629,7 +2628,7 @@ ExprResult Parser::ParseObjCCharacterLiteral(SourceLocation AtLoc) { ExprResult Parser::ParseObjCNumericLiteral(SourceLocation AtLoc) { ExprResult Lit(Actions.ActOnNumericConstant(Tok)); if (Lit.isInvalid()) { - return move(Lit); + return Lit; } ConsumeToken(); // Consume the literal token. return Owned(Actions.BuildObjCNumericLiteral(AtLoc, Lit.take())); @@ -2661,7 +2660,7 @@ Parser::ParseObjCBoxedExpr(SourceLocation AtLoc) { } ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) { - ExprVector ElementExprs(Actions); // array elements. + ExprVector ElementExprs; // array elements. ConsumeBracket(); // consume the l_square. while (Tok.isNot(tok::r_square)) { @@ -2672,7 +2671,7 @@ ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) { // stop at the ']' when it skips to the ';'. We want it to skip beyond // the enclosing expression. SkipUntil(tok::r_square); - return move(Res); + return Res; } // Parse the ellipsis that indicates a pack expansion. @@ -2689,7 +2688,7 @@ ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) { return ExprError(Diag(Tok, diag::err_expected_rsquare_or_comma)); } SourceLocation EndLoc = ConsumeBracket(); // location of ']' - MultiExprArg Args(Actions, ElementExprs.take(), ElementExprs.size()); + MultiExprArg Args(ElementExprs); return Owned(Actions.BuildObjCArrayLiteral(SourceRange(AtLoc, EndLoc), Args)); } @@ -2707,7 +2706,7 @@ ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) { // stop at the '}' when it skips to the ';'. We want it to skip beyond // the enclosing expression. SkipUntil(tok::r_brace); - return move(KeyExpr); + return KeyExpr; } } @@ -2723,7 +2722,7 @@ ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) { // stop at the '}' when it skips to the ';'. We want it to skip beyond // the enclosing expression. SkipUntil(tok::r_brace); - return move(ValueExpr); + return ValueExpr; } // Parse the ellipsis that designates this as a pack expansion. @@ -2752,7 +2751,7 @@ ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) { } /// objc-encode-expression: -/// @encode ( type-name ) +/// \@encode ( type-name ) ExprResult Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) { assert(Tok.isObjCAtKeyword(tok::objc_encode) && "Not an @encode expression!"); diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp index eb13e0d..a7605f0 100644 --- a/lib/Parse/ParsePragma.cpp +++ b/lib/Parse/ParsePragma.cpp @@ -40,7 +40,7 @@ void Parser::HandlePragmaVisibility() { struct PragmaPackInfo { Sema::PragmaPackKind Kind; IdentifierInfo *Name; - Expr *Alignment; + Token Alignment; SourceLocation LParenLoc; SourceLocation RParenLoc; }; @@ -50,10 +50,107 @@ void Parser::HandlePragmaPack() { PragmaPackInfo *Info = static_cast<PragmaPackInfo *>(Tok.getAnnotationValue()); SourceLocation PragmaLoc = ConsumeToken(); - Actions.ActOnPragmaPack(Info->Kind, Info->Name, Info->Alignment, PragmaLoc, + ExprResult Alignment; + if (Info->Alignment.is(tok::numeric_constant)) { + Alignment = Actions.ActOnNumericConstant(Info->Alignment); + if (Alignment.isInvalid()) + return; + } + Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc, Info->LParenLoc, Info->RParenLoc); } +void Parser::HandlePragmaMSStruct() { + assert(Tok.is(tok::annot_pragma_msstruct)); + Sema::PragmaMSStructKind Kind = + static_cast<Sema::PragmaMSStructKind>( + reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); + Actions.ActOnPragmaMSStruct(Kind); + ConsumeToken(); // The annotation token. +} + +void Parser::HandlePragmaAlign() { + assert(Tok.is(tok::annot_pragma_align)); + Sema::PragmaOptionsAlignKind Kind = + static_cast<Sema::PragmaOptionsAlignKind>( + reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); + SourceLocation PragmaLoc = ConsumeToken(); + Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc); +} + +void Parser::HandlePragmaWeak() { + assert(Tok.is(tok::annot_pragma_weak)); + SourceLocation PragmaLoc = ConsumeToken(); + Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc, + Tok.getLocation()); + ConsumeToken(); // The weak name. +} + +void Parser::HandlePragmaWeakAlias() { + assert(Tok.is(tok::annot_pragma_weakalias)); + SourceLocation PragmaLoc = ConsumeToken(); + IdentifierInfo *WeakName = Tok.getIdentifierInfo(); + SourceLocation WeakNameLoc = Tok.getLocation(); + ConsumeToken(); + IdentifierInfo *AliasName = Tok.getIdentifierInfo(); + SourceLocation AliasNameLoc = Tok.getLocation(); + ConsumeToken(); + Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc, + WeakNameLoc, AliasNameLoc); + +} + +void Parser::HandlePragmaRedefineExtname() { + assert(Tok.is(tok::annot_pragma_redefine_extname)); + SourceLocation RedefLoc = ConsumeToken(); + IdentifierInfo *RedefName = Tok.getIdentifierInfo(); + SourceLocation RedefNameLoc = Tok.getLocation(); + ConsumeToken(); + IdentifierInfo *AliasName = Tok.getIdentifierInfo(); + SourceLocation AliasNameLoc = Tok.getLocation(); + ConsumeToken(); + Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc, + RedefNameLoc, AliasNameLoc); +} + +void Parser::HandlePragmaFPContract() { + assert(Tok.is(tok::annot_pragma_fp_contract)); + tok::OnOffSwitch OOS = + static_cast<tok::OnOffSwitch>( + reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); + Actions.ActOnPragmaFPContract(OOS); + ConsumeToken(); // The annotation token. +} + +namespace { + typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData; +} + +void Parser::HandlePragmaOpenCLExtension() { + assert(Tok.is(tok::annot_pragma_opencl_extension)); + OpenCLExtData data = + OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue()); + unsigned state = data.getInt(); + IdentifierInfo *ename = data.getPointer(); + SourceLocation NameLoc = Tok.getLocation(); + ConsumeToken(); // The annotation token. + + OpenCLOptions &f = Actions.getOpenCLOptions(); + // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions, + // overriding all previously issued extension directives, but only if the + // behavior is set to disable." + if (state == 0 && ename->isStr("all")) { +#define OPENCLEXT(nm) f.nm = 0; +#include "clang/Basic/OpenCLExtensions.def" + } +#define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; } +#include "clang/Basic/OpenCLExtensions.def" + else { + PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename; + return; + } +} + // #pragma GCC visibility comes in two variants: // 'push' '(' [visibility] ')' // 'pop' @@ -130,13 +227,12 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, Sema::PragmaPackKind Kind = Sema::PPK_Default; IdentifierInfo *Name = 0; - ExprResult Alignment; + Token Alignment; + Alignment.startToken(); SourceLocation LParenLoc = Tok.getLocation(); PP.Lex(Tok); if (Tok.is(tok::numeric_constant)) { - Alignment = Actions.ActOnNumericConstant(Tok); - if (Alignment.isInvalid()) - return; + Alignment = Tok; PP.Lex(Tok); @@ -165,9 +261,7 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, PP.Lex(Tok); if (Tok.is(tok::numeric_constant)) { - Alignment = Actions.ActOnNumericConstant(Tok); - if (Alignment.isInvalid()) - return; + Alignment = Tok; PP.Lex(Tok); } else if (Tok.is(tok::identifier)) { @@ -182,9 +276,7 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, return; } - Alignment = Actions.ActOnNumericConstant(Tok); - if (Alignment.isInvalid()) - return; + Alignment = Tok; PP.Lex(Tok); } @@ -219,7 +311,7 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, new (Info) PragmaPackInfo(); Info->Kind = Kind; Info->Name = Name; - Info->Alignment = Alignment.release(); + Info->Alignment = Alignment; Info->LParenLoc = LParenLoc; Info->RParenLoc = RParenLoc; @@ -265,12 +357,23 @@ void PragmaMSStructHandler::HandlePragma(Preprocessor &PP, << "ms_struct"; return; } - Actions.ActOnPragmaMSStruct(Kind); + + Token *Toks = + (Token*) PP.getPreprocessorAllocator().Allocate( + sizeof(Token) * 1, llvm::alignOf<Token>()); + new (Toks) Token(); + Toks[0].startToken(); + Toks[0].setKind(tok::annot_pragma_msstruct); + Toks[0].setLocation(MSStructTok.getLocation()); + Toks[0].setAnnotationValue(reinterpret_cast<void*>( + static_cast<uintptr_t>(Kind))); + PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, + /*OwnsTokens=*/false); } // #pragma 'align' '=' {'native','natural','mac68k','power','reset'} // #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'} -static void ParseAlignPragma(Sema &Actions, Preprocessor &PP, Token &FirstTok, +static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok, bool IsOptions) { Token Tok; @@ -317,7 +420,6 @@ static void ParseAlignPragma(Sema &Actions, Preprocessor &PP, Token &FirstTok, return; } - SourceLocation KindLoc = Tok.getLocation(); PP.Lex(Tok); if (Tok.isNot(tok::eod)) { PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) @@ -325,19 +427,29 @@ static void ParseAlignPragma(Sema &Actions, Preprocessor &PP, Token &FirstTok, return; } - Actions.ActOnPragmaOptionsAlign(Kind, FirstTok.getLocation(), KindLoc); + Token *Toks = + (Token*) PP.getPreprocessorAllocator().Allocate( + sizeof(Token) * 1, llvm::alignOf<Token>()); + new (Toks) Token(); + Toks[0].startToken(); + Toks[0].setKind(tok::annot_pragma_align); + Toks[0].setLocation(FirstTok.getLocation()); + Toks[0].setAnnotationValue(reinterpret_cast<void*>( + static_cast<uintptr_t>(Kind))); + PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, + /*OwnsTokens=*/false); } void PragmaAlignHandler::HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &AlignTok) { - ParseAlignPragma(Actions, PP, AlignTok, /*IsOptions=*/false); + ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false); } void PragmaOptionsHandler::HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &OptionsTok) { - ParseAlignPragma(Actions, PP, OptionsTok, /*IsOptions=*/true); + ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true); } // #pragma unused(identifier) @@ -426,7 +538,6 @@ void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, void PragmaWeakHandler::HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &WeakTok) { - // FIXME: Should we be expanding macros here? My guess is no. SourceLocation WeakLoc = WeakTok.getLocation(); Token Tok; @@ -436,19 +547,20 @@ void PragmaWeakHandler::HandlePragma(Preprocessor &PP, return; } - IdentifierInfo *WeakName = Tok.getIdentifierInfo(), *AliasName = 0; - SourceLocation WeakNameLoc = Tok.getLocation(), AliasNameLoc; + Token WeakName = Tok; + bool HasAlias = false; + Token AliasName; PP.Lex(Tok); if (Tok.is(tok::equal)) { + HasAlias = true; PP.Lex(Tok); if (Tok.isNot(tok::identifier)) { PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak"; return; } - AliasName = Tok.getIdentifierInfo(); - AliasNameLoc = Tok.getLocation(); + AliasName = Tok; PP.Lex(Tok); } @@ -457,11 +569,29 @@ void PragmaWeakHandler::HandlePragma(Preprocessor &PP, return; } - if (AliasName) { - Actions.ActOnPragmaWeakAlias(WeakName, AliasName, WeakLoc, WeakNameLoc, - AliasNameLoc); + if (HasAlias) { + Token *Toks = + (Token*) PP.getPreprocessorAllocator().Allocate( + sizeof(Token) * 3, llvm::alignOf<Token>()); + Token &pragmaUnusedTok = Toks[0]; + pragmaUnusedTok.startToken(); + pragmaUnusedTok.setKind(tok::annot_pragma_weakalias); + pragmaUnusedTok.setLocation(WeakLoc); + Toks[1] = WeakName; + Toks[2] = AliasName; + PP.EnterTokenStream(Toks, 3, + /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false); } else { - Actions.ActOnPragmaWeakID(WeakName, WeakLoc, WeakNameLoc); + Token *Toks = + (Token*) PP.getPreprocessorAllocator().Allocate( + sizeof(Token) * 2, llvm::alignOf<Token>()); + Token &pragmaUnusedTok = Toks[0]; + pragmaUnusedTok.startToken(); + pragmaUnusedTok.setKind(tok::annot_pragma_weak); + pragmaUnusedTok.setLocation(WeakLoc); + Toks[1] = WeakName; + PP.EnterTokenStream(Toks, 2, + /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false); } } @@ -479,17 +609,16 @@ void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP, return; } - IdentifierInfo *RedefName = Tok.getIdentifierInfo(), *AliasName = 0; - SourceLocation RedefNameLoc = Tok.getLocation(), AliasNameLoc; - + Token RedefName = Tok; PP.Lex(Tok); + if (Tok.isNot(tok::identifier)) { PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "redefine_extname"; return; } - AliasName = Tok.getIdentifierInfo(); - AliasNameLoc = Tok.getLocation(); + + Token AliasName = Tok; PP.Lex(Tok); if (Tok.isNot(tok::eod)) { @@ -498,8 +627,17 @@ void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP, return; } - Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc, - RedefNameLoc, AliasNameLoc); + Token *Toks = + (Token*) PP.getPreprocessorAllocator().Allocate( + sizeof(Token) * 3, llvm::alignOf<Token>()); + Token &pragmaRedefTok = Toks[0]; + pragmaRedefTok.startToken(); + pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname); + pragmaRedefTok.setLocation(RedefLoc); + Toks[1] = RedefName; + Toks[2] = AliasName; + PP.EnterTokenStream(Toks, 3, + /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false); } @@ -511,7 +649,17 @@ PragmaFPContractHandler::HandlePragma(Preprocessor &PP, if (PP.LexOnOffSwitch(OOS)) return; - Actions.ActOnPragmaFPContract(OOS); + Token *Toks = + (Token*) PP.getPreprocessorAllocator().Allocate( + sizeof(Token) * 1, llvm::alignOf<Token>()); + new (Toks) Token(); + Toks[0].startToken(); + Toks[0].setKind(tok::annot_pragma_fp_contract); + Toks[0].setLocation(Tok.getLocation()); + Toks[0].setAnnotationValue(reinterpret_cast<void*>( + static_cast<uintptr_t>(OOS))); + PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, + /*OwnsTokens=*/false); } void @@ -550,19 +698,23 @@ PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP, return; } - OpenCLOptions &f = Actions.getOpenCLOptions(); - // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions, - // overriding all previously issued extension directives, but only if the - // behavior is set to disable." - if (state == 0 && ename->isStr("all")) { -#define OPENCLEXT(nm) f.nm = 0; -#include "clang/Basic/OpenCLExtensions.def" - } -#define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; } -#include "clang/Basic/OpenCLExtensions.def" - else { - PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename; + PP.Lex(Tok); + if (Tok.isNot(tok::eod)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << + "OPENCL EXTENSION"; return; } + + OpenCLExtData data(ename, state); + Token *Toks = + (Token*) PP.getPreprocessorAllocator().Allocate( + sizeof(Token) * 1, llvm::alignOf<Token>()); + new (Toks) Token(); + Toks[0].startToken(); + Toks[0].setKind(tok::annot_pragma_opencl_extension); + Toks[0].setLocation(NameLoc); + Toks[0].setAnnotationValue(data.getOpaqueValue()); + PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, + /*OwnsTokens=*/false); } diff --git a/lib/Parse/ParsePragma.h b/lib/Parse/ParsePragma.h index fef6960..b9a2a25 100644 --- a/lib/Parse/ParsePragma.h +++ b/lib/Parse/ParsePragma.h @@ -21,9 +21,8 @@ namespace clang { class Parser; class PragmaAlignHandler : public PragmaHandler { - Sema &Actions; public: - explicit PragmaAlignHandler(Sema &A) : PragmaHandler("align"), Actions(A) {} + explicit PragmaAlignHandler() : PragmaHandler("align") {} virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &FirstToken); @@ -31,38 +30,31 @@ public: class PragmaGCCVisibilityHandler : public PragmaHandler { public: - explicit PragmaGCCVisibilityHandler(Sema &/*A*/) - : PragmaHandler("visibility") {} + explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {} virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &FirstToken); }; class PragmaOptionsHandler : public PragmaHandler { - Sema &Actions; public: - explicit PragmaOptionsHandler(Sema &A) : PragmaHandler("options"), - Actions(A) {} + explicit PragmaOptionsHandler() : PragmaHandler("options") {} virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &FirstToken); }; class PragmaPackHandler : public PragmaHandler { - Sema &Actions; public: - explicit PragmaPackHandler(Sema &A) : PragmaHandler("pack"), - Actions(A) {} + explicit PragmaPackHandler() : PragmaHandler("pack") {} virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &FirstToken); }; class PragmaMSStructHandler : public PragmaHandler { - Sema &Actions; public: - explicit PragmaMSStructHandler(Sema &A) : PragmaHandler("ms_struct"), - Actions(A) {} + explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {} virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &FirstToken); @@ -70,48 +62,39 @@ public: class PragmaUnusedHandler : public PragmaHandler { public: - PragmaUnusedHandler(Sema &/*A*/) - : PragmaHandler("unused") {} + PragmaUnusedHandler() : PragmaHandler("unused") {} virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &FirstToken); }; class PragmaWeakHandler : public PragmaHandler { - Sema &Actions; public: - explicit PragmaWeakHandler(Sema &A) - : PragmaHandler("weak"), Actions(A) {} + explicit PragmaWeakHandler() : PragmaHandler("weak") {} virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &FirstToken); }; class PragmaRedefineExtnameHandler : public PragmaHandler { - Sema &Actions; public: - explicit PragmaRedefineExtnameHandler(Sema &A) - : PragmaHandler("redefine_extname"), Actions(A) {} + explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {} virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &FirstToken); }; class PragmaOpenCLExtensionHandler : public PragmaHandler { - Sema &Actions; public: - PragmaOpenCLExtensionHandler(Sema &A) : - PragmaHandler("EXTENSION"), Actions(A) {} + PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {} virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &FirstToken); }; class PragmaFPContractHandler : public PragmaHandler { - Sema &Actions; public: - PragmaFPContractHandler(Sema &A) : - PragmaHandler("FP_CONTRACT"), Actions(A) {} + PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {} virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &FirstToken); }; diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index df9b996..f604e03 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -17,6 +17,7 @@ #include "clang/Sema/DeclSpec.h" #include "clang/Sema/PrettyDeclStackTrace.h" #include "clang/Sema/Scope.h" +#include "clang/Sema/TypoCorrection.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/PrettyStackTrace.h" #include "clang/Basic/SourceManager.h" @@ -130,96 +131,38 @@ Retry: return ParseLabeledStatement(Attrs); } + // Look up the identifier, and typo-correct it to a keyword if it's not + // found. if (Next.isNot(tok::coloncolon)) { - CXXScopeSpec SS; - IdentifierInfo *Name = Tok.getIdentifierInfo(); - SourceLocation NameLoc = Tok.getLocation(); - - if (getLangOpts().CPlusPlus) - CheckForTemplateAndDigraph(Next, ParsedType(), - /*EnteringContext=*/false, *Name, SS); - - Sema::NameClassification Classification - = Actions.ClassifyName(getCurScope(), SS, Name, NameLoc, Next); - switch (Classification.getKind()) { - case Sema::NC_Keyword: - // The identifier was corrected to a keyword. Update the token - // to this keyword, and try again. - if (Name->getTokenID() != tok::identifier) { - Tok.setIdentifierInfo(Name); - Tok.setKind(Name->getTokenID()); - goto Retry; - } - - // Fall through via the normal error path. - // FIXME: This seems like it could only happen for context-sensitive - // keywords. - - case Sema::NC_Error: + // Try to limit which sets of keywords should be included in typo + // correction based on what the next token is. + // FIXME: Pass the next token into the CorrectionCandidateCallback and + // do this filtering in a more fine-grained manner. + CorrectionCandidateCallback DefaultValidator; + DefaultValidator.WantTypeSpecifiers = + Next.is(tok::l_paren) || Next.is(tok::less) || + Next.is(tok::identifier) || Next.is(tok::star) || + Next.is(tok::amp) || Next.is(tok::l_square); + DefaultValidator.WantExpressionKeywords = + Next.is(tok::l_paren) || Next.is(tok::identifier) || + Next.is(tok::arrow) || Next.is(tok::period); + DefaultValidator.WantRemainingKeywords = + Next.is(tok::l_paren) || Next.is(tok::semi) || + Next.is(tok::identifier) || Next.is(tok::l_brace); + DefaultValidator.WantCXXNamedCasts = false; + if (TryAnnotateName(/*IsAddressOfOperand*/false, &DefaultValidator) + == ANK_Error) { // Handle errors here by skipping up to the next semicolon or '}', and // eat the semicolon if that's what stopped us. SkipUntil(tok::r_brace, /*StopAtSemi=*/true, /*DontConsume=*/true); if (Tok.is(tok::semi)) ConsumeToken(); return StmtError(); - - case Sema::NC_Unknown: - // Either we don't know anything about this identifier, or we know that - // we're in a syntactic context we haven't handled yet. - break; - - case Sema::NC_Type: - Tok.setKind(tok::annot_typename); - setTypeAnnotation(Tok, Classification.getType()); - Tok.setAnnotationEndLoc(NameLoc); - PP.AnnotateCachedTokens(Tok); - break; - - case Sema::NC_Expression: - Tok.setKind(tok::annot_primary_expr); - setExprAnnotation(Tok, Classification.getExpression()); - Tok.setAnnotationEndLoc(NameLoc); - PP.AnnotateCachedTokens(Tok); - break; - - case Sema::NC_TypeTemplate: - case Sema::NC_FunctionTemplate: { - ConsumeToken(); // the identifier - UnqualifiedId Id; - Id.setIdentifier(Name, NameLoc); - if (AnnotateTemplateIdToken( - TemplateTy::make(Classification.getTemplateName()), - Classification.getTemplateNameKind(), - SS, SourceLocation(), Id, - /*AllowTypeAnnotation=*/false)) { - // Handle errors here by skipping up to the next semicolon or '}', and - // eat the semicolon if that's what stopped us. - SkipUntil(tok::r_brace, /*StopAtSemi=*/true, /*DontConsume=*/true); - if (Tok.is(tok::semi)) - ConsumeToken(); - return StmtError(); - } - - // If the next token is '::', jump right into parsing a - // nested-name-specifier. We don't want to leave the template-id - // hanging. - if (NextToken().is(tok::coloncolon) && TryAnnotateCXXScopeToken(false)){ - // Handle errors here by skipping up to the next semicolon or '}', and - // eat the semicolon if that's what stopped us. - SkipUntil(tok::r_brace, /*StopAtSemi=*/true, /*DontConsume=*/true); - if (Tok.is(tok::semi)) - ConsumeToken(); - return StmtError(); - } - - // We've annotated a template-id, so try again now. - goto Retry; } - case Sema::NC_NestedNameSpecifier: - // FIXME: Implement this! - break; - } + // If the identifier was typo-corrected, try again. + if (Tok.isNot(tok::identifier)) + goto Retry; } // Fall through @@ -289,7 +232,7 @@ Retry: bool msAsm = false; Res = ParseAsmStatement(msAsm); Res = Actions.ActOnFinishFullStmt(Res.get()); - if (msAsm) return move(Res); + if (msAsm) return Res; SemiError = "asm"; break; } @@ -310,6 +253,41 @@ Retry: ProhibitAttributes(Attrs); HandlePragmaPack(); return StmtEmpty(); + + case tok::annot_pragma_msstruct: + ProhibitAttributes(Attrs); + HandlePragmaMSStruct(); + return StmtEmpty(); + + case tok::annot_pragma_align: + ProhibitAttributes(Attrs); + HandlePragmaAlign(); + return StmtEmpty(); + + case tok::annot_pragma_weak: + ProhibitAttributes(Attrs); + HandlePragmaWeak(); + return StmtEmpty(); + + case tok::annot_pragma_weakalias: + ProhibitAttributes(Attrs); + HandlePragmaWeakAlias(); + return StmtEmpty(); + + case tok::annot_pragma_redefine_extname: + ProhibitAttributes(Attrs); + HandlePragmaRedefineExtname(); + return StmtEmpty(); + + case tok::annot_pragma_fp_contract: + Diag(Tok, diag::err_pragma_fp_contract_scope); + ConsumeToken(); + return StmtError(); + + case tok::annot_pragma_opencl_extension: + ProhibitAttributes(Attrs); + HandlePragmaOpenCLExtension(); + return StmtEmpty(); } // If we reached this code, the statement must end in a semicolon. @@ -324,7 +302,7 @@ Retry: SkipUntil(tok::r_brace, true, true); } - return move(Res); + return Res; } /// \brief Parse an expression statement. @@ -381,7 +359,7 @@ StmtResult Parser::ParseSEHTryBlockCommon(SourceLocation TryLoc) { StmtResult TryBlock(ParseCompoundStatement()); if(TryBlock.isInvalid()) - return move(TryBlock); + return TryBlock; StmtResult Handler; if (Tok.is(tok::identifier) && @@ -396,7 +374,7 @@ StmtResult Parser::ParseSEHTryBlockCommon(SourceLocation TryLoc) { } if(Handler.isInvalid()) - return move(Handler); + return Handler; return Actions.ActOnSEHTryBlock(false /* IsCXXTry */, TryLoc, @@ -441,7 +419,7 @@ StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) { StmtResult Block(ParseCompoundStatement()); if(Block.isInvalid()) - return move(Block); + return Block; return Actions.ActOnSEHExceptBlock(ExceptLoc, FilterExpr.take(), Block.take()); } @@ -458,7 +436,7 @@ StmtResult Parser::ParseSEHFinallyBlock(SourceLocation FinallyBlock) { StmtResult Block(ParseCompoundStatement()); if(Block.isInvalid()) - return move(Block); + return Block; return Actions.ActOnSEHFinallyBlock(FinallyBlock,Block.take()); } @@ -603,7 +581,7 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) { // Otherwise we link it into the current chain. Stmt *NextDeepest = Case.get(); if (TopLevelCase.isInvalid()) - TopLevelCase = move(Case); + TopLevelCase = Case; else Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, Case.get()); DeepestParsedCaseStmt = NextDeepest; @@ -636,7 +614,7 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) { Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, SubStmt.get()); // Return the top level parsed statement tree. - return move(TopLevelCase); + return TopLevelCase; } /// ParseDefaultStatement @@ -728,6 +706,48 @@ StmtResult Parser::ParseCompoundStatement(bool isStmtExpr, return ParseCompoundStatementBody(isStmtExpr); } +/// Parse any pragmas at the start of the compound expression. We handle these +/// separately since some pragmas (FP_CONTRACT) must appear before any C +/// statement in the compound, but may be intermingled with other pragmas. +void Parser::ParseCompoundStatementLeadingPragmas() { + bool checkForPragmas = true; + while (checkForPragmas) { + switch (Tok.getKind()) { + case tok::annot_pragma_vis: + HandlePragmaVisibility(); + break; + case tok::annot_pragma_pack: + HandlePragmaPack(); + break; + case tok::annot_pragma_msstruct: + HandlePragmaMSStruct(); + break; + case tok::annot_pragma_align: + HandlePragmaAlign(); + break; + case tok::annot_pragma_weak: + HandlePragmaWeak(); + break; + case tok::annot_pragma_weakalias: + HandlePragmaWeakAlias(); + break; + case tok::annot_pragma_redefine_extname: + HandlePragmaRedefineExtname(); + break; + case tok::annot_pragma_opencl_extension: + HandlePragmaOpenCLExtension(); + break; + case tok::annot_pragma_fp_contract: + HandlePragmaFPContract(); + break; + default: + checkForPragmas = false; + break; + } + } + +} + /// ParseCompoundStatementBody - Parse a sequence of statements and invoke the /// ActOnCompoundStmt action. This expects the '{' to be the current token, and /// consume the '}' at the end of the block. It does not manipulate the scope @@ -736,6 +756,11 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), Tok.getLocation(), "in compound statement ('{}')"); + + // Record the state of the FP_CONTRACT pragma, restore on leaving the + // compound statement. + Sema::FPContractStateRAII SaveFPContractState(Actions); + InMessageExpressionRAIIObject InMessage(*this, false); BalancedDelimiterTracker T(*this, tok::l_brace); if (T.consumeOpen()) @@ -743,7 +768,10 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { Sema::CompoundScopeRAII CompoundScope(Actions); - StmtVector Stmts(Actions); + // Parse any pragmas at the beginning of the compound statement. + ParseCompoundStatementLeadingPragmas(); + + StmtVector Stmts; // "__label__ X, Y, Z;" is the GNU "Local Label" extension. These are // only allowed at the start of a compound stmt regardless of the language. @@ -850,7 +878,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { } return Actions.ActOnCompoundStmt(T.getOpenLocation(), CloseLoc, - move_arg(Stmts), isStmtExpr); + Stmts, isStmtExpr); } /// ParseParenExprOrCondition: @@ -1096,7 +1124,7 @@ StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) { SkipUntil(tok::r_brace, false, false); } else SkipUntil(tok::semi); - return move(Switch); + return Switch; } // C99 6.8.4p3 - In C99, the body of the switch statement is a scope, even if @@ -1375,7 +1403,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { ColonProtectionRAIIObject ColonProtection(*this, MightBeForRangeStmt); SourceLocation DeclStart = Tok.getLocation(), DeclEnd; - StmtVector Stmts(Actions); + StmtVector Stmts; DeclGroupPtrTy DG = ParseSimpleDeclaration(Stmts, Declarator::ForContext, DeclEnd, attrs, false, MightBeForRangeStmt ? @@ -1498,7 +1526,8 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { ForRangeStmt = Actions.ActOnCXXForRangeStmt(ForLoc, FirstPart.take(), ForRangeInit.ColonLoc, ForRangeInit.RangeExpr.get(), - T.getCloseLocation()); + T.getCloseLocation(), + Sema::BFRK_Build); // Similarly, we need to do the semantic analysis for a for-range @@ -1580,7 +1609,7 @@ StmtResult Parser::ParseGotoStatement() { return StmtError(); } - return move(Res); + return Res; } /// ParseContinueStatement @@ -1653,6 +1682,9 @@ StmtResult Parser::ParseReturnStatement() { /// ms-asm-line '\n' ms-asm-instruction-block /// StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { + // MS-style inline assembly is not fully supported, so emit a warning. + Diag(AsmLoc, diag::warn_unsupported_msasm); + SourceManager &SrcMgr = PP.getSourceManager(); SourceLocation EndLoc = AsmLoc; SmallVector<Token, 4> AsmToks; @@ -1745,6 +1777,21 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { return StmtError(); } + // If MS-style inline assembly is disabled, then build an empty asm. + if (!getLangOpts().EmitMicrosoftInlineAsm) { + Token t; + t.setKind(tok::string_literal); + t.setLiteralData("\"/*FIXME: not done*/\""); + t.clearFlag(Token::NeedsCleaning); + t.setLength(21); + ExprResult AsmString(Actions.ActOnStringLiteral(&t, 1)); + ExprVector Constraints; + ExprVector Exprs; + ExprVector Clobbers; + return Actions.ActOnGCCAsmStmt(AsmLoc, true, true, 0, 0, 0, Constraints, + Exprs, AsmString.take(), Clobbers, EndLoc); + } + // FIXME: We should be passing source locations for better diagnostics. return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLoc, llvm::makeArrayRef(AsmToks), EndLoc); @@ -1806,18 +1853,17 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) { } SmallVector<IdentifierInfo *, 4> Names; - ExprVector Constraints(Actions); - ExprVector Exprs(Actions); - ExprVector Clobbers(Actions); + ExprVector Constraints; + ExprVector Exprs; + ExprVector Clobbers; if (Tok.is(tok::r_paren)) { // We have a simple asm expression like 'asm("foo")'. T.consumeClose(); - return Actions.ActOnAsmStmt(AsmLoc, /*isSimple*/ true, isVolatile, - /*NumOutputs*/ 0, /*NumInputs*/ 0, 0, - move_arg(Constraints), move_arg(Exprs), - AsmString.take(), move_arg(Clobbers), - T.getCloseLocation()); + return Actions.ActOnGCCAsmStmt(AsmLoc, /*isSimple*/ true, isVolatile, + /*NumOutputs*/ 0, /*NumInputs*/ 0, 0, + Constraints, Exprs, AsmString.take(), + Clobbers, T.getCloseLocation()); } // Parse Outputs, if present. @@ -1878,11 +1924,10 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) { } T.consumeClose(); - return Actions.ActOnAsmStmt(AsmLoc, false, isVolatile, - NumOutputs, NumInputs, Names.data(), - move_arg(Constraints), move_arg(Exprs), - AsmString.take(), move_arg(Clobbers), - T.getCloseLocation()); + return Actions.ActOnGCCAsmStmt(AsmLoc, false, isVolatile, NumOutputs, + NumInputs, Names.data(), Constraints, Exprs, + AsmString.take(), Clobbers, + T.getCloseLocation()); } /// ParseAsmOperands - Parse the asm-operands production as used by @@ -1975,7 +2020,7 @@ Decl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) { if (FnBody.isInvalid()) { Sema::CompoundScopeRAII CompoundScope(Actions); FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc, - MultiStmtArg(Actions), false); + MultiStmtArg(), false); } BodyScope.Exit(); @@ -2006,13 +2051,13 @@ Decl *Parser::ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope) { } SourceLocation LBraceLoc = Tok.getLocation(); - StmtResult FnBody(ParseCXXTryBlockCommon(TryLoc)); + StmtResult FnBody(ParseCXXTryBlockCommon(TryLoc, /*FnTry*/true)); // If we failed to parse the try-catch, we just give the function an empty // compound statement as the body. if (FnBody.isInvalid()) { Sema::CompoundScopeRAII CompoundScope(Actions); FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc, - MultiStmtArg(Actions), false); + MultiStmtArg(), false); } BodyScope.Exit(); @@ -2024,12 +2069,18 @@ bool Parser::trySkippingFunctionBody() { assert(SkipFunctionBodies && "Should only be called when SkipFunctionBodies is enabled"); + if (!PP.isCodeCompletionEnabled()) { + ConsumeBrace(); + SkipUntil(tok::r_brace, /*StopAtSemi=*/false, /*DontConsume=*/false); + return true; + } + // We're in code-completion mode. Skip parsing for all function bodies unless // the body contains the code-completion point. TentativeParsingAction PA(*this); ConsumeBrace(); if (SkipUntil(tok::r_brace, /*StopAtSemi=*/false, /*DontConsume=*/false, - /*StopAtCodeCompletion=*/PP.isCodeCompletionEnabled())) { + /*StopAtCodeCompletion=*/true)) { PA.Commit(); return true; } @@ -2066,15 +2117,16 @@ StmtResult Parser::ParseCXXTryBlock() { /// 'try' compound-statement seh-except-block /// 'try' compound-statment seh-finally-block /// -StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) { +StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry) { if (Tok.isNot(tok::l_brace)) return StmtError(Diag(Tok, diag::err_expected_lbrace)); // FIXME: Possible draft standard bug: attribute-specifier should be allowed? StmtResult TryBlock(ParseCompoundStatement(/*isStmtExpr=*/false, - Scope::DeclScope|Scope::TryScope)); + Scope::DeclScope | + (FnTry ? Scope::FnTryScope : Scope::TryScope))); if (TryBlock.isInvalid()) - return move(TryBlock); + return TryBlock; // Borland allows SEH-handlers with 'try' @@ -2092,7 +2144,7 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) { Handler = ParseSEHFinallyBlock(Loc); } if(Handler.isInvalid()) - return move(Handler); + return Handler; return Actions.ActOnSEHTryBlock(true /* IsCXXTry */, TryLoc, @@ -2100,7 +2152,7 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) { Handler.take()); } else { - StmtVector Handlers(Actions); + StmtVector Handlers; ParsedAttributesWithRange attrs(AttrFactory); MaybeParseCXX0XAttributes(attrs); ProhibitAttributes(attrs); @@ -2108,7 +2160,7 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) { if (Tok.isNot(tok::kw_catch)) return StmtError(Diag(Tok, diag::err_expected_catch)); while (Tok.is(tok::kw_catch)) { - StmtResult Handler(ParseCXXCatchBlock()); + StmtResult Handler(ParseCXXCatchBlock(FnTry)); if (!Handler.isInvalid()) Handlers.push_back(Handler.release()); } @@ -2117,7 +2169,7 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) { if (Handlers.empty()) return StmtError(); - return Actions.ActOnCXXTryBlock(TryLoc, TryBlock.take(),move_arg(Handlers)); + return Actions.ActOnCXXTryBlock(TryLoc, TryBlock.take(),Handlers); } } @@ -2132,7 +2184,7 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) { /// type-specifier-seq /// '...' /// -StmtResult Parser::ParseCXXCatchBlock() { +StmtResult Parser::ParseCXXCatchBlock(bool FnCatch) { assert(Tok.is(tok::kw_catch) && "Expected 'catch'"); SourceLocation CatchLoc = ConsumeToken(); @@ -2144,7 +2196,8 @@ StmtResult Parser::ParseCXXCatchBlock() { // C++ 3.3.2p3: // The name in a catch exception-declaration is local to the handler and // shall not be redeclared in the outermost block of the handler. - ParseScope CatchScope(this, Scope::DeclScope | Scope::ControlScope); + ParseScope CatchScope(this, Scope::DeclScope | Scope::ControlScope | + (FnCatch ? Scope::FnCatchScope : 0)); // exception-declaration is equivalent to '...' or a parameter-declaration // without default arguments. @@ -2169,7 +2222,7 @@ StmtResult Parser::ParseCXXCatchBlock() { // FIXME: Possible draft standard bug: attribute-specifier should be allowed? StmtResult Block(ParseCompoundStatement()); if (Block.isInvalid()) - return move(Block); + return Block; return Actions.ActOnCXXCatchBlock(CatchLoc, ExceptionDecl, Block.take()); } diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index ade918f..2e0411e 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -246,7 +246,7 @@ Parser::ParseSingleDeclarationAfterTemplate( return 0; } - LateParsedAttrList LateParsedAttrs; + LateParsedAttrList LateParsedAttrs(true); if (DeclaratorInfo.isFunctionDeclarator()) MaybeParseGNUAttributes(DeclaratorInfo, &LateParsedAttrs); @@ -889,8 +889,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, return true; } - ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateArgs.data(), - TemplateArgs.size()); + ASTTemplateArgsPtr TemplateArgsPtr(TemplateArgs); // Build the annotation token. if (TNK == TNK_Type_template && AllowTypeAnnotation) { @@ -942,8 +941,6 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, Tok.setLocation(TemplateKWLoc); else Tok.setLocation(TemplateNameLoc); - - TemplateArgsPtr.release(); } // Common fields for the annotation token @@ -969,8 +966,7 @@ void Parser::AnnotateTemplateIdTokenAsType() { TemplateId->Kind == TNK_Dependent_template_name) && "Only works for type and dependent templates"); - ASTTemplateArgsPtr TemplateArgsPtr(Actions, - TemplateId->getTemplateArgs(), + ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), TemplateId->NumArgs); TypeResult Type diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp index 1a4df47..40c4eee 100644 --- a/lib/Parse/ParseTentative.cpp +++ b/lib/Parse/ParseTentative.cpp @@ -104,16 +104,27 @@ bool Parser::isCXXSimpleDeclaration(bool AllowForRangeDecl) { // isCXXDeclarationSpecifier will return TPResult::Ambiguous() only in such // a case. - TPResult TPR = isCXXDeclarationSpecifier(); + bool InvalidAsDeclaration = false; + TPResult TPR = isCXXDeclarationSpecifier(TPResult::False(), + &InvalidAsDeclaration); if (TPR != TPResult::Ambiguous()) return TPR != TPResult::False(); // Returns true for TPResult::True() or // TPResult::Error(). + // FIXME: TryParseSimpleDeclaration doesn't look past the first initializer, + // and so gets some cases wrong. We can't carry on if we've already seen + // something which makes this statement invalid as a declaration in this case, + // since it can cause us to misparse valid code. Revisit this once + // TryParseInitDeclaratorList is fixed. + if (InvalidAsDeclaration) + return false; + // FIXME: Add statistics about the number of ambiguous statements encountered // and how they were resolved (number of declarations+number of expressions). - // Ok, we have a simple-type-specifier/typename-specifier followed by a '('. - // We need tentative parsing... + // Ok, we have a simple-type-specifier/typename-specifier followed by a '(', + // or an identifier which doesn't resolve as anything. We need tentative + // parsing... TentativeParsingAction PA(*this); TPR = TryParseSimpleDeclaration(AllowForRangeDecl); @@ -140,20 +151,28 @@ bool Parser::isCXXSimpleDeclaration(bool AllowForRangeDecl) { /// attribute-specifier-seqopt type-specifier-seq declarator /// Parser::TPResult Parser::TryParseSimpleDeclaration(bool AllowForRangeDecl) { - // We know that we have a simple-type-specifier/typename-specifier followed - // by a '('. - assert(isCXXDeclarationSpecifier() == TPResult::Ambiguous()); - if (Tok.is(tok::kw_typeof)) TryParseTypeofSpecifier(); else { + if (Tok.is(tok::annot_cxxscope)) + ConsumeToken(); ConsumeToken(); - + if (getLangOpts().ObjC1 && Tok.is(tok::less)) TryParseProtocolQualifiers(); } - - assert(Tok.is(tok::l_paren) && "Expected '('"); + + // Two decl-specifiers in a row conclusively disambiguate this as being a + // simple-declaration. Don't bother calling isCXXDeclarationSpecifier in the + // overwhelmingly common case that the next token is a '('. + if (Tok.isNot(tok::l_paren)) { + TPResult TPR = isCXXDeclarationSpecifier(); + if (TPR == TPResult::Ambiguous()) + return TPResult::True(); + if (TPR == TPResult::True() || TPR == TPResult::Error()) + return TPR; + assert(TPR == TPResult::False()); + } TPResult TPR = TryParseInitDeclaratorList(); if (TPR != TPResult::Ambiguous()) @@ -623,6 +642,8 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract, // declarator-id if (Tok.is(tok::annot_cxxscope)) ConsumeToken(); + else + TentativelyDeclaredIdentifiers.push_back(Tok.getIdentifierInfo()); ConsumeToken(); } else if (Tok.is(tok::l_paren)) { ConsumeParen(); @@ -761,6 +782,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) { case tok::kw___is_convertible_to: case tok::kw___is_empty: case tok::kw___is_enum: + case tok::kw___is_interface_class: case tok::kw___is_final: case tok::kw___is_literal: case tok::kw___is_literal_type: @@ -824,6 +846,12 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) { return TPResult::Ambiguous(); } +bool Parser::isTentativelyDeclared(IdentifierInfo *II) { + return std::find(TentativelyDeclaredIdentifiers.begin(), + TentativelyDeclaredIdentifiers.end(), II) + != TentativelyDeclaredIdentifiers.end(); +} + /// isCXXDeclarationSpecifier - Returns TPResult::True() if it is a declaration /// specifier, TPResult::False() if it is not, TPResult::Ambiguous() if it could /// be either a decl-specifier or a function-style cast, and TPResult::Error() @@ -831,7 +859,10 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) { /// /// If HasMissingTypename is provided, a name with a dependent scope specifier /// will be treated as ambiguous if the 'typename' keyword is missing. If this -/// happens, *HasMissingTypename will be set to 'true'. +/// happens, *HasMissingTypename will be set to 'true'. This will also be used +/// as an indicator that undeclared identifiers (which will trigger a later +/// parse error) should be treated as types. Returns TPResult::Ambiguous() in +/// such cases. /// /// decl-specifier: /// storage-class-specifier @@ -927,22 +958,64 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, bool *HasMissingTypename) { switch (Tok.getKind()) { - case tok::identifier: // foo::bar + case tok::identifier: { // Check for need to substitute AltiVec __vector keyword // for "vector" identifier. if (TryAltiVecVectorToken()) return TPResult::True(); - // Fall through. + + const Token &Next = NextToken(); + // In 'foo bar', 'foo' is always a type name outside of Objective-C. + if (!getLangOpts().ObjC1 && Next.is(tok::identifier)) + return TPResult::True(); + + if (Next.isNot(tok::coloncolon) && Next.isNot(tok::less)) { + // Determine whether this is a valid expression. If not, we will hit + // a parse error one way or another. In that case, tell the caller that + // this is ambiguous. Typo-correct to type and expression keywords and + // to types and identifiers, in order to try to recover from errors. + CorrectionCandidateCallback TypoCorrection; + TypoCorrection.WantRemainingKeywords = false; + switch (TryAnnotateName(false /* no nested name specifier */, + &TypoCorrection)) { + case ANK_Error: + return TPResult::Error(); + case ANK_TentativeDecl: + return TPResult::False(); + case ANK_TemplateName: + // A bare type template-name which can't be a template template + // argument is an error, and was probably intended to be a type. + return GreaterThanIsOperator ? TPResult::True() : TPResult::False(); + case ANK_Unresolved: + return HasMissingTypename ? TPResult::Ambiguous() : TPResult::False(); + case ANK_Success: + break; + } + assert(Tok.isNot(tok::identifier) && + "TryAnnotateName succeeded without producing an annotation"); + } else { + // This might possibly be a type with a dependent scope specifier and + // a missing 'typename' keyword. Don't use TryAnnotateName in this case, + // since it will annotate as a primary expression, and we want to use the + // "missing 'typename'" logic. + if (TryAnnotateTypeOrScopeToken()) + return TPResult::Error(); + // If annotation failed, assume it's a non-type. + // FIXME: If this happens due to an undeclared identifier, treat it as + // ambiguous. + if (Tok.is(tok::identifier)) + return TPResult::False(); + } + + // We annotated this token as something. Recurse to handle whatever we got. + return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename); + } + case tok::kw_typename: // typename T::type // Annotate typenames and C++ scope specifiers. If we get one, just // recurse to handle whatever we get. if (TryAnnotateTypeOrScopeToken()) return TPResult::Error(); - if (Tok.is(tok::identifier)) { - const Token &Next = NextToken(); - return (!getLangOpts().ObjC1 && Next.is(tok::identifier)) ? - TPResult::True() : TPResult::False(); - } return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename); case tok::coloncolon: { // ::foo::bar @@ -1073,6 +1146,28 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, *HasMissingTypename = true; return TPResult::Ambiguous(); } + } else { + // Try to resolve the name. If it doesn't exist, assume it was + // intended to name a type and keep disambiguating. + switch (TryAnnotateName(false /* SS is not dependent */)) { + case ANK_Error: + return TPResult::Error(); + case ANK_TentativeDecl: + return TPResult::False(); + case ANK_TemplateName: + // A bare type template-name which can't be a template template + // argument is an error, and was probably intended to be a type. + return GreaterThanIsOperator ? TPResult::True() : TPResult::False(); + case ANK_Unresolved: + return HasMissingTypename ? TPResult::Ambiguous() + : TPResult::False(); + case ANK_Success: + // Annotated it, check again. + assert(Tok.isNot(tok::annot_cxxscope) || + NextToken().isNot(tok::identifier)); + return isCXXDeclarationSpecifier(BracedCastResult, + HasMissingTypename); + } } } return TPResult::False(); diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 3725e2b..f4cdd61 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -23,6 +23,7 @@ #include "clang/AST/ASTConsumer.h" using namespace clang; + namespace { /// \brief A comment handler that passes comments found by the preprocessor /// to the parser action. @@ -47,11 +48,13 @@ IdentifierInfo *Parser::getSEHExceptKeyword() { return Ident__except; } -Parser::Parser(Preprocessor &pp, Sema &actions, bool SkipFunctionBodies) +Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies) : PP(pp), Actions(actions), Diags(PP.getDiagnostics()), GreaterThanIsOperator(true), ColonIsSacred(false), InMessageExpression(false), TemplateParameterDepth(0), - ParsingInObjCContainer(false), SkipFunctionBodies(SkipFunctionBodies) { + ParsingInObjCContainer(false) { + SkipFunctionBodies = pp.isCodeCompletionEnabled() || skipFunctionBodies; + Tok.startToken(); Tok.setKind(tok::eof); Actions.CurScope = 0; NumCachedScopes = 0; @@ -60,35 +63,35 @@ Parser::Parser(Preprocessor &pp, Sema &actions, bool SkipFunctionBodies) // Add #pragma handlers. These are removed and destroyed in the // destructor. - AlignHandler.reset(new PragmaAlignHandler(actions)); + AlignHandler.reset(new PragmaAlignHandler()); PP.AddPragmaHandler(AlignHandler.get()); - GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler(actions)); + GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler()); PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get()); - OptionsHandler.reset(new PragmaOptionsHandler(actions)); + OptionsHandler.reset(new PragmaOptionsHandler()); PP.AddPragmaHandler(OptionsHandler.get()); - PackHandler.reset(new PragmaPackHandler(actions)); + PackHandler.reset(new PragmaPackHandler()); PP.AddPragmaHandler(PackHandler.get()); - MSStructHandler.reset(new PragmaMSStructHandler(actions)); + MSStructHandler.reset(new PragmaMSStructHandler()); PP.AddPragmaHandler(MSStructHandler.get()); - UnusedHandler.reset(new PragmaUnusedHandler(actions)); + UnusedHandler.reset(new PragmaUnusedHandler()); PP.AddPragmaHandler(UnusedHandler.get()); - WeakHandler.reset(new PragmaWeakHandler(actions)); + WeakHandler.reset(new PragmaWeakHandler()); PP.AddPragmaHandler(WeakHandler.get()); - RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler(actions)); + RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler()); PP.AddPragmaHandler(RedefineExtnameHandler.get()); - FPContractHandler.reset(new PragmaFPContractHandler(actions)); + FPContractHandler.reset(new PragmaFPContractHandler()); PP.AddPragmaHandler("STDC", FPContractHandler.get()); if (getLangOpts().OpenCL) { - OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler(actions)); + OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler()); PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get()); PP.AddPragmaHandler("OPENCL", FPContractHandler.get()); @@ -135,7 +138,7 @@ DiagnosticBuilder Parser::Diag(const Token &Tok, unsigned DiagID) { /// given range. /// /// \param Loc The location where we'll emit the diagnostic. -/// \param Loc The kind of diagnostic to emit. +/// \param DK The kind of diagnostic to emit. /// \param ParenRange Source range enclosing code that should be parenthesized. void Parser::SuggestParentheses(SourceLocation Loc, unsigned DK, SourceRange ParenRange) { @@ -154,7 +157,8 @@ void Parser::SuggestParentheses(SourceLocation Loc, unsigned DK, static bool IsCommonTypo(tok::TokenKind ExpectedTok, const Token &Tok) { switch (ExpectedTok) { - case tok::semi: return Tok.is(tok::colon); // : for ; + case tok::semi: + return Tok.is(tok::colon) || Tok.is(tok::comma); // : or , for ; default: return false; } } @@ -466,9 +470,6 @@ void Parser::Initialize() { EnterScope(Scope::DeclScope); Actions.ActOnTranslationUnitScope(getCurScope()); - // Prime the lexer look-ahead. - ConsumeToken(); - // Initialization for Objective-C context sensitive keywords recognition. // Referenced in Parser::ParseObjCTypeQualifierList. if (getLangOpts().ObjC1) { @@ -523,6 +524,11 @@ void Parser::Initialize() { PP.SetPoisonReason(Ident___abnormal_termination,diag::err_seh___finally_block); PP.SetPoisonReason(Ident_AbnormalTermination,diag::err_seh___finally_block); } + + Actions.Initialize(); + + // Prime the lexer look-ahead. + ConsumeToken(); } namespace { @@ -634,6 +640,27 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, case tok::annot_pragma_pack: HandlePragmaPack(); return DeclGroupPtrTy(); + case tok::annot_pragma_msstruct: + HandlePragmaMSStruct(); + return DeclGroupPtrTy(); + case tok::annot_pragma_align: + HandlePragmaAlign(); + return DeclGroupPtrTy(); + case tok::annot_pragma_weak: + HandlePragmaWeak(); + return DeclGroupPtrTy(); + case tok::annot_pragma_weakalias: + HandlePragmaWeakAlias(); + return DeclGroupPtrTy(); + case tok::annot_pragma_redefine_extname: + HandlePragmaRedefineExtname(); + return DeclGroupPtrTy(); + case tok::annot_pragma_fp_contract: + HandlePragmaFPContract(); + return DeclGroupPtrTy(); + case tok::annot_pragma_opencl_extension: + HandlePragmaOpenCLExtension(); + return DeclGroupPtrTy(); case tok::semi: ConsumeExtraSemi(OutsideFunction); // TODO: Invoke action for top-level semicolon. @@ -693,7 +720,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, // A function definition cannot start with any of these keywords. { SourceLocation DeclEnd; - StmtVector Stmts(Actions); + StmtVector Stmts; return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs); } @@ -704,7 +731,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, Diag(ConsumeToken(), diag::warn_static_inline_explicit_inst_ignored) << 0; SourceLocation DeclEnd; - StmtVector Stmts(Actions); + StmtVector Stmts; return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs); } goto dont_know; @@ -716,7 +743,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, // Inline namespaces. Allowed as an extension even in C++03. if (NextKind == tok::kw_namespace) { SourceLocation DeclEnd; - StmtVector Stmts(Actions); + StmtVector Stmts; return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs); } @@ -726,7 +753,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, Diag(ConsumeToken(), diag::warn_static_inline_explicit_inst_ignored) << 1; SourceLocation DeclEnd; - StmtVector Stmts(Actions); + StmtVector Stmts; return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs); } } @@ -972,16 +999,14 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, if (getLangOpts().DelayedTemplateParsing && Tok.isNot(tok::equal) && TemplateInfo.Kind == ParsedTemplateInfo::Template) { - MultiTemplateParamsArg TemplateParameterLists(Actions, - TemplateInfo.TemplateParams->data(), - TemplateInfo.TemplateParams->size()); + MultiTemplateParamsArg TemplateParameterLists(*TemplateInfo.TemplateParams); ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope); Scope *ParentScope = getCurScope()->getParent(); D.setFunctionDefinitionKind(FDK_Definition); Decl *DP = Actions.HandleDeclarator(ParentScope, D, - move(TemplateParameterLists)); + TemplateParameterLists); D.complete(DP); D.getMutableDeclSpec().abort(); @@ -1009,13 +1034,12 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, (Tok.is(tok::l_brace) || Tok.is(tok::kw_try) || Tok.is(tok::colon)) && Actions.CurContext->isTranslationUnit()) { - MultiTemplateParamsArg TemplateParameterLists(Actions, 0, 0); ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope); Scope *ParentScope = getCurScope()->getParent(); D.setFunctionDefinitionKind(FDK_Definition); Decl *FuncDecl = Actions.HandleDeclarator(ParentScope, D, - move(TemplateParameterLists)); + MultiTemplateParamsArg()); D.complete(FuncDecl); D.getMutableDeclSpec().abort(); if (FuncDecl) { @@ -1033,10 +1057,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, // specified Declarator for the function. Decl *Res = TemplateInfo.TemplateParams? Actions.ActOnStartOfFunctionTemplateDef(getCurScope(), - MultiTemplateParamsArg(Actions, - TemplateInfo.TemplateParams->data(), - TemplateInfo.TemplateParams->size()), - D) + *TemplateInfo.TemplateParams, D) : Actions.ActOnStartOfFunctionDef(getCurScope(), D); // Break out of the ParsingDeclarator context before we parse the body. @@ -1288,7 +1309,7 @@ Parser::ExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) { *EndLoc = T.getCloseLocation(); } - return move(Result); + return Result; } /// \brief Get the TemplateIdAnnotation from the token and put it in the @@ -1301,6 +1322,143 @@ TemplateIdAnnotation *Parser::takeTemplateIdAnnotation(const Token &tok) { return Id; } +void Parser::AnnotateScopeToken(CXXScopeSpec &SS, bool IsNewAnnotation) { + // Push the current token back into the token stream (or revert it if it is + // cached) and use an annotation scope token for current token. + if (PP.isBacktrackEnabled()) + PP.RevertCachedTokens(1); + else + PP.EnterToken(Tok); + Tok.setKind(tok::annot_cxxscope); + Tok.setAnnotationValue(Actions.SaveNestedNameSpecifierAnnotation(SS)); + Tok.setAnnotationRange(SS.getRange()); + + // In case the tokens were cached, have Preprocessor replace them + // with the annotation token. We don't need to do this if we've + // just reverted back to a prior state. + if (IsNewAnnotation) + PP.AnnotateCachedTokens(Tok); +} + +/// \brief Attempt to classify the name at the current token position. This may +/// form a type, scope or primary expression annotation, or replace the token +/// with a typo-corrected keyword. This is only appropriate when the current +/// name must refer to an entity which has already been declared. +/// +/// \param IsAddressOfOperand Must be \c true if the name is preceded by an '&' +/// and might possibly have a dependent nested name specifier. +/// \param CCC Indicates how to perform typo-correction for this name. If NULL, +/// no typo correction will be performed. +Parser::AnnotatedNameKind +Parser::TryAnnotateName(bool IsAddressOfOperand, + CorrectionCandidateCallback *CCC) { + assert(Tok.is(tok::identifier) || Tok.is(tok::annot_cxxscope)); + + const bool EnteringContext = false; + const bool WasScopeAnnotation = Tok.is(tok::annot_cxxscope); + + CXXScopeSpec SS; + if (getLangOpts().CPlusPlus && + ParseOptionalCXXScopeSpecifier(SS, ParsedType(), EnteringContext)) + return ANK_Error; + + if (Tok.isNot(tok::identifier) || SS.isInvalid()) { + if (TryAnnotateTypeOrScopeTokenAfterScopeSpec(EnteringContext, false, SS, + !WasScopeAnnotation)) + return ANK_Error; + return ANK_Unresolved; + } + + IdentifierInfo *Name = Tok.getIdentifierInfo(); + SourceLocation NameLoc = Tok.getLocation(); + + // FIXME: Move the tentative declaration logic into ClassifyName so we can + // typo-correct to tentatively-declared identifiers. + if (isTentativelyDeclared(Name)) { + // Identifier has been tentatively declared, and thus cannot be resolved as + // an expression. Fall back to annotating it as a type. + if (TryAnnotateTypeOrScopeTokenAfterScopeSpec(EnteringContext, false, SS, + !WasScopeAnnotation)) + return ANK_Error; + return Tok.is(tok::annot_typename) ? ANK_Success : ANK_TentativeDecl; + } + + Token Next = NextToken(); + + // Look up and classify the identifier. We don't perform any typo-correction + // after a scope specifier, because in general we can't recover from typos + // there (eg, after correcting 'A::tempalte B<X>::C', we would need to jump + // back into scope specifier parsing). + Sema::NameClassification Classification + = Actions.ClassifyName(getCurScope(), SS, Name, NameLoc, Next, + IsAddressOfOperand, SS.isEmpty() ? CCC : 0); + + switch (Classification.getKind()) { + case Sema::NC_Error: + return ANK_Error; + + case Sema::NC_Keyword: + // The identifier was typo-corrected to a keyword. + Tok.setIdentifierInfo(Name); + Tok.setKind(Name->getTokenID()); + PP.TypoCorrectToken(Tok); + if (SS.isNotEmpty()) + AnnotateScopeToken(SS, !WasScopeAnnotation); + // We've "annotated" this as a keyword. + return ANK_Success; + + case Sema::NC_Unknown: + // It's not something we know about. Leave it unannotated. + break; + + case Sema::NC_Type: + Tok.setKind(tok::annot_typename); + setTypeAnnotation(Tok, Classification.getType()); + Tok.setAnnotationEndLoc(NameLoc); + if (SS.isNotEmpty()) + Tok.setLocation(SS.getBeginLoc()); + PP.AnnotateCachedTokens(Tok); + return ANK_Success; + + case Sema::NC_Expression: + Tok.setKind(tok::annot_primary_expr); + setExprAnnotation(Tok, Classification.getExpression()); + Tok.setAnnotationEndLoc(NameLoc); + if (SS.isNotEmpty()) + Tok.setLocation(SS.getBeginLoc()); + PP.AnnotateCachedTokens(Tok); + return ANK_Success; + + case Sema::NC_TypeTemplate: + if (Next.isNot(tok::less)) { + // This may be a type template being used as a template template argument. + if (SS.isNotEmpty()) + AnnotateScopeToken(SS, !WasScopeAnnotation); + return ANK_TemplateName; + } + // Fall through. + case Sema::NC_FunctionTemplate: { + // We have a type or function template followed by '<'. + ConsumeToken(); + UnqualifiedId Id; + Id.setIdentifier(Name, NameLoc); + if (AnnotateTemplateIdToken( + TemplateTy::make(Classification.getTemplateName()), + Classification.getTemplateNameKind(), SS, SourceLocation(), Id)) + return ANK_Error; + return ANK_Success; + } + + case Sema::NC_NestedNameSpecifier: + llvm_unreachable("already parsed nested name specifier"); + } + + // Unable to classify the name, but maybe we can annotate a scope specifier. + if (SS.isNotEmpty()) + AnnotateScopeToken(SS, !WasScopeAnnotation); + return ANK_Unresolved; +} + /// TryAnnotateTypeOrScopeToken - If the current token position is on a /// typename (possibly qualified in C++) or a C++ scope specifier not followed /// by a typename, TryAnnotateTypeOrScopeToken will replace one or more tokens @@ -1377,8 +1535,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) { return true; } - ASTTemplateArgsPtr TemplateArgsPtr(Actions, - TemplateId->getTemplateArgs(), + ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), TemplateId->NumArgs); Ty = Actions.ActOnTypenameType(getCurScope(), TypenameLoc, SS, @@ -1404,13 +1561,24 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) { } // Remembers whether the token was originally a scope annotation. - bool wasScopeAnnotation = Tok.is(tok::annot_cxxscope); + bool WasScopeAnnotation = Tok.is(tok::annot_cxxscope); CXXScopeSpec SS; if (getLangOpts().CPlusPlus) if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), EnteringContext)) return true; + return TryAnnotateTypeOrScopeTokenAfterScopeSpec(EnteringContext, NeedType, + SS, !WasScopeAnnotation); +} + +/// \brief Try to annotate a type or scope token, having already parsed an +/// optional scope specifier. \p IsNewScope should be \c true unless the scope +/// specifier was extracted from an existing tok::annot_cxxscope annotation. +bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(bool EnteringContext, + bool NeedType, + CXXScopeSpec &SS, + bool IsNewScope) { if (Tok.is(tok::identifier)) { IdentifierInfo *CorrectedII = 0; // Determine whether the identifier is a type name. @@ -1492,21 +1660,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) { return false; // A C++ scope specifier that isn't followed by a typename. - // Push the current token back into the token stream (or revert it if it is - // cached) and use an annotation scope token for current token. - if (PP.isBacktrackEnabled()) - PP.RevertCachedTokens(1); - else - PP.EnterToken(Tok); - Tok.setKind(tok::annot_cxxscope); - Tok.setAnnotationValue(Actions.SaveNestedNameSpecifierAnnotation(SS)); - Tok.setAnnotationRange(SS.getRange()); - - // In case the tokens were cached, have Preprocessor replace them - // with the annotation token. We don't need to do this if we've - // just reverted back to the state we were in before being called. - if (!wasScopeAnnotation) - PP.AnnotateCachedTokens(Tok); + AnnotateScopeToken(SS, IsNewScope); return false; } @@ -1529,19 +1683,7 @@ bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) { if (SS.isEmpty()) return false; - // Push the current token back into the token stream (or revert it if it is - // cached) and use an annotation scope token for current token. - if (PP.isBacktrackEnabled()) - PP.RevertCachedTokens(1); - else - PP.EnterToken(Tok); - Tok.setKind(tok::annot_cxxscope); - Tok.setAnnotationValue(Actions.SaveNestedNameSpecifierAnnotation(SS)); - Tok.setAnnotationRange(SS.getRange()); - - // In case the tokens were cached, have Preprocessor replace them with the - // annotation token. - PP.AnnotateCachedTokens(Tok); + AnnotateScopeToken(SS, true); return false; } @@ -1798,8 +1940,8 @@ bool BalancedDelimiterTracker::diagnoseMissingClose() { } P.Diag(P.Tok, DID); P.Diag(LOpen, diag::note_matching) << LHSName; - if (P.SkipUntil(Close)) - LClose = P.Tok.getLocation(); + if (P.SkipUntil(Close, /*StopAtSemi*/ true, /*DontConsume*/ true)) + LClose = P.ConsumeAnyToken(); return true; } diff --git a/lib/Parse/RAIIObjectsForParser.h b/lib/Parse/RAIIObjectsForParser.h index 455c4af..060fd20 100644 --- a/lib/Parse/RAIIObjectsForParser.h +++ b/lib/Parse/RAIIObjectsForParser.h @@ -87,9 +87,8 @@ namespace clang { Sema::ParsingDeclState State; bool Popped; - // Do not implement. - ParsingDeclRAIIObject(const ParsingDeclRAIIObject &other); - ParsingDeclRAIIObject &operator=(const ParsingDeclRAIIObject &other); + ParsingDeclRAIIObject(const ParsingDeclRAIIObject &) LLVM_DELETED_FUNCTION; + void operator=(const ParsingDeclRAIIObject &) LLVM_DELETED_FUNCTION; public: enum NoParent_t { NoParent }; @@ -245,8 +244,9 @@ namespace clang { /// the way they used to be. This is used to handle __extension__ in the /// parser. class ExtensionRAIIObject { - void operator=(const ExtensionRAIIObject &); // DO NOT IMPLEMENT - ExtensionRAIIObject(const ExtensionRAIIObject&); // DO NOT IMPLEMENT + ExtensionRAIIObject(const ExtensionRAIIObject &) LLVM_DELETED_FUNCTION; + void operator=(const ExtensionRAIIObject &) LLVM_DELETED_FUNCTION; + DiagnosticsEngine &Diags; public: ExtensionRAIIObject(DiagnosticsEngine &diags) : Diags(diags) { |