]> granicus.if.org Git - clang/commitdiff
Allow virt-specifiers after GNU attributes in member-declarators. GCC doesn't
authorRichard Smith <richard-llvm@metafoo.co.uk>
Fri, 24 Jan 2014 22:34:35 +0000 (22:34 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Fri, 24 Jan 2014 22:34:35 +0000 (22:34 +0000)
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

include/clang/Sema/DeclSpec.h
include/clang/Sema/Ownership.h
lib/Parse/ParseDeclCXX.cpp
test/Parser/cxx0x-decl.cpp

index e3b78314d7798aa10c66c88832e7ed5da8c75073..bdba54430a41981bc88247655bb178c677180746 100644 (file)
@@ -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; }
 
index b7d7710eb12159b8f244dc12eeca57b30ccea783..4bbefcb8fe15a6686cc985c8dc7fa81df7bfc464 100644 (file)
@@ -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);
index 86db40b28d8d4904904837036de084ea5808d0e5..083d682428ec53ab20bc4823766eb7bdf5c5d815 100644 (file)
@@ -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) &&
index 84eaafeee59225839e5635c4c6d6bd1d4964c76a..a0334cdde29231aece159b5e2ac0816a31115efb 100644 (file)
@@ -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 {}
 };