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:
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
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.
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();
// 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()) {
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 {
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 &&