diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-01-23 23:53:27 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-01-23 23:53:27 +0000 |
commit | 72553fc19b1e57c08d77ccde1a6a6f7bcf22c08f (patch) | |
tree | da5db34b28f49d8e44f195608ba494a82ebf963d /clang/lib | |
parent | 50b75dbf1a48b3ab8b6e4b06bbf2a3f3940fc9df (diff) | |
download | bcm5719-llvm-72553fc19b1e57c08d77ccde1a6a6f7bcf22c08f.tar.gz bcm5719-llvm-72553fc19b1e57c08d77ccde1a6a6f7bcf22c08f.zip |
Factor out repeated parsing of a member-declarator when parsing a
member-declaration. In the process, fix a couple of bugs that had crept in
where we would parse the first and subsequent member-declarators differently
(in particular, we didn't accept an asm-label on a member function definition
within a class, and we would accept virt-specifiers and attributes in the wrong
order on the first declarator but not on subsequent ones).
llvm-svn: 199957
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 146 |
1 files changed, 77 insertions, 69 deletions
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 2361bc1774e..86db40b28d8 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1888,6 +1888,46 @@ bool Parser::isCXX11FinalKeyword() const { Specifier == VirtSpecifiers::VS_Sealed; } +/// \brief Parse a C++ member-declarator up to, but not including, the optional +/// brace-or-equal-initializer or pure-specifier. +void Parser::ParseCXXMemberDeclaratorBeforeInitializer( + Declarator &DeclaratorInfo, VirtSpecifiers &VS, ExprResult &BitfieldSize, + LateParsedAttrList &LateParsedAttrs) { + // member-declarator: + // declarator pure-specifier[opt] + // declarator brace-or-equal-initializer[opt] + // identifier[opt] ':' constant-expression + if (Tok.isNot(tok::colon)) { + // Don't parse FOO:BAR as if it were a typo for FOO::BAR, in this context it + // is a bitfield. + // FIXME: This should only apply when parsing the id-expression (see + // PR18587). + ColonProtectionRAIIObject X(*this); + ParseDeclarator(DeclaratorInfo); + } + + if (!DeclaratorInfo.isFunctionDeclarator() && TryConsumeToken(tok::colon)) { + BitfieldSize = ParseConstantExpression(); + if (BitfieldSize.isInvalid()) + SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch); + } else + ParseOptionalCXX11VirtSpecifierSeq(VS, getCurrentClass().IsInterface); + + // If a simple-asm-expr is present, parse it. + if (Tok.is(tok::kw_asm)) { + SourceLocation Loc; + ExprResult AsmLabel(ParseSimpleAsm(&Loc)); + if (AsmLabel.isInvalid()) + SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch); + + DeclaratorInfo.setAsmLabel(AsmLabel.release()); + DeclaratorInfo.SetRangeEnd(Loc); + } + + // If attributes exist after the declarator, but before an '{', parse them. + MaybeParseGNUAttributes(DeclaratorInfo, &LateParsedAttrs); +} + /// ParseCXXClassMemberDeclaration - Parse a C++ class member declaration. /// /// member-declaration: @@ -2013,10 +2053,6 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, TemplateInfo, TemplateDiags); } - // Don't parse FOO:BAR as if it were a typo for FOO::BAR, in this context it - // is a bitfield. - ColonProtectionRAIIObject X(*this); - ParsedAttributesWithRange attrs(AttrFactory); ParsedAttributesWithRange FnAttrs(AttrFactory); // Optional C++11 attribute-specifier @@ -2055,8 +2091,14 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, DS.takeAttributesFrom(attrs); if (MalformedTypeSpec) DS.SetTypeSpecError(); - ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class, - &CommonLateParsedAttrs); + + { + // Don't parse FOO:BAR as if it were a typo for FOO::BAR, in this context it + // is a bitfield. + ColonProtectionRAIIObject X(*this); + ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class, + &CommonLateParsedAttrs); + } // If we had a free-standing type definition with a missing semicolon, we // may get this far before the problem becomes obvious. @@ -2089,29 +2131,31 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, SourceLocation EqualLoc; bool HasInitializer = false; ExprResult Init; - if (Tok.isNot(tok::colon)) { - // Don't parse FOO:BAR as if it were a typo for FOO::BAR. - ColonProtectionRAIIObject X(*this); - // Parse the first declarator. - ParseDeclarator(DeclaratorInfo); - // Error parsing the declarator? - if (!DeclaratorInfo.hasName()) { - // If so, skip until the semi-colon or a }. - SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); - TryConsumeToken(tok::semi); - return; - } + SmallVector<Decl *, 8> DeclsInGroup; + ExprResult BitfieldSize; + bool ExpectSemi = true; - ParseOptionalCXX11VirtSpecifierSeq(VS, getCurrentClass().IsInterface); + // Parse the first declarator. + ParseCXXMemberDeclaratorBeforeInitializer(DeclaratorInfo, VS, BitfieldSize, + LateParsedAttrs); - // If attributes exist after the declarator, but before an '{', parse them. - MaybeParseGNUAttributes(DeclaratorInfo, &LateParsedAttrs); + // If this has neither a name nor a bit width, something has gone seriously + // wrong. Skip until the semi-colon or }. + if (!DeclaratorInfo.hasName() && !BitfieldSize.isInvalid() && + !BitfieldSize.isUsable()) { + // If so, skip until the semi-colon or a }. + SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); + TryConsumeToken(tok::semi); + return; + } - // MSVC permits pure specifier on inline functions declared at class scope. + // Check for a member function definition. + if (!BitfieldSize.isInvalid() && !BitfieldSize.isUsable()) { + // 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() && + DeclaratorInfo.isFunctionDeclarator() && NextToken().is(tok::numeric_constant)) { EqualLoc = ConsumeToken(); Init = ParseInitializer(); @@ -2196,39 +2240,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // member-declarator // member-declarator-list ',' member-declarator - SmallVector<Decl *, 8> DeclsInGroup; - ExprResult BitfieldSize; - bool ExpectSemi = true; - while (1) { - // member-declarator: - // declarator pure-specifier[opt] - // declarator brace-or-equal-initializer[opt] - // identifier[opt] ':' constant-expression - if (TryConsumeToken(tok::colon)) { - BitfieldSize = ParseConstantExpression(); - if (BitfieldSize.isInvalid()) - SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch); - } - - // If a simple-asm-expr is present, parse it. - if (Tok.is(tok::kw_asm)) { - SourceLocation Loc; - ExprResult AsmLabel(ParseSimpleAsm(&Loc)); - if (AsmLabel.isInvalid()) - SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch); - - DeclaratorInfo.setAsmLabel(AsmLabel.release()); - DeclaratorInfo.SetRangeEnd(Loc); - } - - // If attributes exist after the declarator, parse them. - MaybeParseGNUAttributes(DeclaratorInfo, &LateParsedAttrs); - - // FIXME: When g++ adds support for this, we'll need to check whether it - // goes before or after the GNU attributes and __asm__. - ParseOptionalCXX11VirtSpecifierSeq(VS, getCurrentClass().IsInterface); - InClassInitStyle HasInClassInit = ICIS_NoInit; if ((Tok.is(tok::equal) || Tok.is(tok::l_brace)) && !HasInitializer) { if (BitfieldSize.get()) { @@ -2249,22 +2261,18 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, NamedDecl *ThisDecl = 0; if (DS.isFriendSpecified()) { - // C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains + // C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains // to a friend declaration, that declaration shall be a definition. // - // Diagnose attributes appear after friend member function declarator: - // foo [[]] (); + // Diagnose attributes that appear in a friend member function declarator: + // friend int foo [[]] (); SmallVector<SourceRange, 4> Ranges; DeclaratorInfo.getCXX11AttributeRanges(Ranges); - if (!Ranges.empty()) { - for (SmallVectorImpl<SourceRange>::iterator I = Ranges.begin(), - E = Ranges.end(); I != E; ++I) { - Diag((*I).getBegin(), diag::err_attributes_not_allowed) - << *I; - } - } + for (SmallVectorImpl<SourceRange>::iterator I = Ranges.begin(), + E = Ranges.end(); I != E; ++I) + Diag((*I).getBegin(), diag::err_attributes_not_allowed) << *I; - // TODO: handle initializers, bitfields, 'delete' + // TODO: handle initializers, VS, bitfields, 'delete' ThisDecl = Actions.ActOnFriendFunctionDecl(getCurScope(), DeclaratorInfo, TemplateParams); } else { @@ -2368,11 +2376,11 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, HasInitializer = false; DeclaratorInfo.setCommaLoc(CommaLoc); - // Attributes are only allowed on the second declarator. + // GNU attributes are allowed before the second and subsequent declarator. MaybeParseGNUAttributes(DeclaratorInfo); - if (Tok.isNot(tok::colon)) - ParseDeclarator(DeclaratorInfo); + ParseCXXMemberDeclaratorBeforeInitializer(DeclaratorInfo, VS, BitfieldSize, + LateParsedAttrs); } if (ExpectSemi && |