From: Richard Smith Date: Fri, 24 Jan 2014 22:34:35 +0000 (+0000) Subject: Allow virt-specifiers after GNU attributes in member-declarators. GCC doesn't X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2f9e642a746ce7a8adc6da9ed9a5a56711bee101;p=clang 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@200045 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index e3b78314d7..bdba54430a 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -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; } diff --git a/include/clang/Sema/Ownership.h b/include/clang/Sema/Ownership.h index b7d7710eb1..4bbefcb8fe 100644 --- a/include/clang/Sema/Ownership.h +++ b/include/clang/Sema/Ownership.h @@ -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(PtrWithInvalid & ~0x01); diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 86db40b28d..083d682428 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -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) && diff --git a/test/Parser/cxx0x-decl.cpp b/test/Parser/cxx0x-decl.cpp index 84eaafeee5..a0334cdde2 100644 --- a/test/Parser/cxx0x-decl.cpp +++ b/test/Parser/cxx0x-decl.cpp @@ -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 {} };