diff options
| author | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-06-30 01:28:56 +0000 |
|---|---|---|
| committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-06-30 01:28:56 +0000 |
| commit | 9ba0fec83e7f2eb76cbe53c899126a69827fa78d (patch) | |
| tree | 72acb0a28b854a9e0f43ecd9365b388255f7e02f /clang/lib/Parse | |
| parent | a5cb3893378f7ea78bc8c9bd727809b0976207aa (diff) | |
| download | bcm5719-llvm-9ba0fec83e7f2eb76cbe53c899126a69827fa78d.tar.gz bcm5719-llvm-9ba0fec83e7f2eb76cbe53c899126a69827fa78d.zip | |
Rework parsing of pure-specifiers. Perform the grammar matching and
disambiguation in the parser rather than trying to do it in Sema.
llvm-svn: 241032
Diffstat (limited to 'clang/lib/Parse')
| -rw-r--r-- | clang/lib/Parse/ParseCXXInlineMethods.cpp | 10 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 95 |
2 files changed, 64 insertions, 41 deletions
diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp index ea67a52f1fc..ab1f97d31a6 100644 --- a/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -27,7 +27,7 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D, const ParsedTemplateInfo &TemplateInfo, const VirtSpecifiers& VS, - ExprResult& Init) { + SourceLocation PureSpecLoc) { assert(D.isFunctionDeclarator() && "This isn't a function declarator!"); assert(Tok.isOneOf(tok::l_brace, tok::colon, tok::kw_try, tok::equal) && "Current token not a '{', ':', '=', or 'try'!"); @@ -47,12 +47,8 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, VS, ICIS_NoInit); if (FnD) { Actions.ProcessDeclAttributeList(getCurScope(), FnD, AccessAttrs); - bool TypeSpecContainsAuto = D.getDeclSpec().containsPlaceholderType(); - if (Init.isUsable()) - Actions.AddInitializerToDecl(FnD, Init.get(), false, - TypeSpecContainsAuto); - else - Actions.ActOnUninitializedDecl(FnD, TypeSpecContainsAuto); + if (PureSpecLoc.isValid()) + Actions.ActOnPureSpecifier(FnD, PureSpecLoc); } } diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 6531f7b902d..137e6abc6b4 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -2372,8 +2372,28 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, LateParsedAttrList LateParsedAttrs; SourceLocation EqualLoc; - bool HasInitializer = false; - ExprResult Init; + SourceLocation PureSpecLoc; + + auto TryConsumePureSpecifier = [&] (bool AllowDefinition = false) { + if (Tok.isNot(tok::equal)) + return false; + + auto &Zero = NextToken(); + SmallString<8> Buffer; + if (Zero.isNot(tok::numeric_constant) || Zero.getLength() != 1 || + PP.getSpelling(Zero, Buffer) != "0") + return false; + + auto &After = GetLookAheadToken(2); + if (!After.isOneOf(tok::semi, tok::comma) && + !(AllowDefinition && + After.isOneOf(tok::l_brace, tok::colon, tok::kw_try))) + return false; + + EqualLoc = ConsumeToken(); + PureSpecLoc = ConsumeToken(); + return true; + }; SmallVector<Decl *, 8> DeclsInGroup; ExprResult BitfieldSize; @@ -2390,16 +2410,8 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (BitfieldSize.isUnset()) { // MSVC permits pure specifier on inline functions defined at class scope. // Hence check for =0 before checking for function definition. - if (getLangOpts().MicrosoftExt && Tok.is(tok::equal) && - DeclaratorInfo.isFunctionDeclarator() && - NextToken().is(tok::numeric_constant)) { - EqualLoc = ConsumeToken(); - Init = ParseInitializer(); - if (Init.isInvalid()) - SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch); - else - HasInitializer = true; - } + if (getLangOpts().MicrosoftExt && DeclaratorInfo.isDeclarationOfFunction()) + TryConsumePureSpecifier(/*AllowDefinition*/ true); FunctionDefinitionKind DefinitionKind = FDK_Declaration; // function-definition: @@ -2453,7 +2465,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, Decl *FunDecl = ParseCXXInlineMethodDef(AS, AccessAttrs, DeclaratorInfo, TemplateInfo, - VS, Init); + VS, PureSpecLoc); if (FunDecl) { for (unsigned i = 0, ni = CommonLateParsedAttrs.size(); i < ni; ++i) { @@ -2479,16 +2491,25 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, while (1) { InClassInitStyle HasInClassInit = ICIS_NoInit; - if (Tok.isOneOf(tok::equal, tok::l_brace) && !HasInitializer) { + bool HasStaticInitializer = false; + if (Tok.isOneOf(tok::equal, tok::l_brace) && PureSpecLoc.isInvalid()) { if (BitfieldSize.get()) { Diag(Tok, diag::err_bitfield_member_init); SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch); + } else if (DeclaratorInfo.isDeclarationOfFunction()) { + // It's a pure-specifier. + if (!TryConsumePureSpecifier(/*AllowFunctionDefinition*/ false)) + // Parse it as an expression so that Sema can diagnose it. + HasStaticInitializer = true; + } else if (DeclaratorInfo.getDeclSpec().getStorageClassSpec() != + DeclSpec::SCS_static && + DeclaratorInfo.getDeclSpec().getStorageClassSpec() != + DeclSpec::SCS_typedef && + !DS.isFriendSpecified()) { + // It's a default member initializer. + HasInClassInit = Tok.is(tok::equal) ? ICIS_CopyInit : ICIS_ListInit; } else { - HasInitializer = true; - if (!DeclaratorInfo.isDeclarationOfFunction() && - DeclaratorInfo.getDeclSpec().getStorageClassSpec() - != DeclSpec::SCS_typedef) - HasInClassInit = Tok.is(tok::equal) ? ICIS_CopyInit : ICIS_ListInit; + HasStaticInitializer = true; } } @@ -2528,10 +2549,20 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, Actions.ProcessDeclAttributeList(getCurScope(), ThisDecl, AccessAttrs); } - // Handle the initializer. + // Error recovery might have converted a non-static member into a static + // member. if (HasInClassInit != ICIS_NoInit && - DeclaratorInfo.getDeclSpec().getStorageClassSpec() != - DeclSpec::SCS_static) { + DeclaratorInfo.getDeclSpec().getStorageClassSpec() == + DeclSpec::SCS_static) { + HasInClassInit = ICIS_NoInit; + HasStaticInitializer = true; + } + + if (ThisDecl && PureSpecLoc.isValid()) + Actions.ActOnPureSpecifier(ThisDecl, PureSpecLoc); + + // Handle the initializer. + if (HasInClassInit != ICIS_NoInit) { // The initializer was deferred; parse it and cache the tokens. Diag(Tok, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_nonstatic_member_init @@ -2551,11 +2582,10 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, ThisDecl->setInvalidDecl(); } else ParseCXXNonStaticMemberInitializer(ThisDecl); - } else if (HasInitializer) { + } else if (HasStaticInitializer) { // Normal initializer. - if (!Init.isUsable()) - Init = ParseCXXMemberInitializer( - ThisDecl, DeclaratorInfo.isDeclarationOfFunction(), EqualLoc); + ExprResult Init = ParseCXXMemberInitializer( + ThisDecl, DeclaratorInfo.isDeclarationOfFunction(), EqualLoc); if (Init.isInvalid()) SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch); @@ -2608,8 +2638,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, DeclaratorInfo.clear(); VS.clear(); BitfieldSize = ExprResult(/*Invalid=*/false); - Init = ExprResult(/*Invalid=*/false); - HasInitializer = false; + EqualLoc = PureSpecLoc = SourceLocation(); DeclaratorInfo.setCommaLoc(CommaLoc); // GNU attributes are allowed before the second and subsequent declarator. @@ -2632,13 +2661,11 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup); } -/// ParseCXXMemberInitializer - Parse the brace-or-equal-initializer or -/// pure-specifier. Also detect and reject any attempted defaulted/deleted -/// function definition. The location of the '=', if any, will be placed in -/// EqualLoc. +/// ParseCXXMemberInitializer - Parse the brace-or-equal-initializer. +/// Also detect and reject any attempted defaulted/deleted function definition. +/// The location of the '=', if any, will be placed in EqualLoc. /// -/// pure-specifier: -/// '= 0' +/// This does not check for a pure-specifier; that's handled elsewhere. /// /// brace-or-equal-initializer: /// '=' initializer-expression |

