Allow virt-specifiers after GNU attributes in member-declarators. GCC doesn't
allow this, and we should warn on it, but it turns out that people were already relying on this. We should introduce a -Wgcc-compat warning for this if the attributes are known to GCC, but we don't currently track enough information about attributes to do so reliably. llvm-svn: 200045
This commit is contained in:
parent
7449bda3d9
commit
4b5a949834
@ -2142,6 +2142,8 @@ public:
|
||||
bool SetSpecifier(Specifier VS, SourceLocation Loc,
|
||||
const char *&PrevSpec);
|
||||
|
||||
bool isUnset() const { return Specifiers == 0; }
|
||||
|
||||
bool isOverrideSpecified() const { return Specifiers & VS_Override; }
|
||||
SourceLocation getOverrideLoc() const { return VS_overrideLoc; }
|
||||
|
||||
|
||||
@ -158,6 +158,7 @@ namespace clang {
|
||||
|
||||
bool isInvalid() const { return Invalid; }
|
||||
bool isUsable() const { return !Invalid && Val; }
|
||||
bool isUnset() const { return !Invalid && !Val; }
|
||||
|
||||
PtrTy get() const { return Val; }
|
||||
// FIXME: Replace with get.
|
||||
@ -199,6 +200,7 @@ namespace clang {
|
||||
|
||||
bool isInvalid() const { return PtrWithInvalid & 0x01; }
|
||||
bool isUsable() const { return PtrWithInvalid > 0x01; }
|
||||
bool isUnset() const { return PtrWithInvalid == 0; }
|
||||
|
||||
PtrTy get() const {
|
||||
void *VP = reinterpret_cast<void *>(PtrWithInvalid & ~0x01);
|
||||
|
||||
@ -1926,6 +1926,13 @@ void Parser::ParseCXXMemberDeclaratorBeforeInitializer(
|
||||
|
||||
// If attributes exist after the declarator, but before an '{', parse them.
|
||||
MaybeParseGNUAttributes(DeclaratorInfo, &LateParsedAttrs);
|
||||
|
||||
// For compatibility with code written to older Clang, also accept a
|
||||
// virt-specifier *after* the GNU attributes.
|
||||
// FIXME: If we saw any attributes that are known to GCC followed by a
|
||||
// virt-specifier, issue a GCC-compat warning.
|
||||
if (BitfieldSize.isUnset() && VS.isUnset())
|
||||
ParseOptionalCXX11VirtSpecifierSeq(VS, getCurrentClass().IsInterface);
|
||||
}
|
||||
|
||||
/// ParseCXXClassMemberDeclaration - Parse a C++ class member declaration.
|
||||
@ -2142,8 +2149,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
|
||||
|
||||
// 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 (!DeclaratorInfo.hasName() && BitfieldSize.isUnset()) {
|
||||
// If so, skip until the semi-colon or a }.
|
||||
SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
|
||||
TryConsumeToken(tok::semi);
|
||||
@ -2151,7 +2157,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
|
||||
}
|
||||
|
||||
// Check for a member function definition.
|
||||
if (!BitfieldSize.isInvalid() && !BitfieldSize.isUsable()) {
|
||||
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) &&
|
||||
|
||||
@ -119,5 +119,6 @@ namespace DuplicateSpecifier {
|
||||
struct Base { virtual void f() = 0; virtual void g() = 0; virtual void h() = 0; };
|
||||
struct MemberComponentOrder : Base {
|
||||
void f() override __asm__("foobar") __attribute__(( )) {}
|
||||
void g() __attribute__(( )) override; // expected-error {{expected ';'}}
|
||||
void g() __attribute__(( )) override;
|
||||
void h() __attribute__(( )) override {}
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user