From: Aaron Ballman Date: Mon, 4 Aug 2014 17:03:51 +0000 (+0000) Subject: Diagnose GNU-style attributes preceding virt-specifiers, but only when the attribute... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=30d47b46c3682ac7cfb1b8d20cc0664cd665a1da;p=clang Diagnose GNU-style attributes preceding virt-specifiers, but only when the attribute is known to GCC. Clang accepts attributes in this position, but GCC does not, so this is a GCC-compat warning. If the attribute is not known to GCC, then the diagnostic is suppressed. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@214730 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 6b73b3b93f..9fc67d475d 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -167,6 +167,9 @@ def err_expected_fn_body : Error< def warn_attribute_on_function_definition : Warning< "GCC does not allow %0 attribute in this position on a function definition">, InGroup; +def warn_gcc_attribute_location : Warning< + "GCC does not allow an attribute in this position on a function declaration">, + InGroup; def warn_attribute_no_decl : Warning< "attribute %0 ignored, because it is not attached to a declaration">, InGroup; diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 6200363b3b..7baa6684e2 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -1953,10 +1953,19 @@ void Parser::ParseCXXMemberDeclaratorBeforeInitializer( // 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()) + if (BitfieldSize.isUnset() && VS.isUnset()) { ParseOptionalCXX11VirtSpecifierSeq(VS, getCurrentClass().IsInterface); + if (!VS.isUnset()) { + // If we saw any GNU-style attributes that are known to GCC followed by a + // virt-specifier, issue a GCC-compat warning. + const AttributeList *Attr = DeclaratorInfo.getAttributes(); + while (Attr) { + if (Attr->isKnownToGCC() && !Attr->isCXX11Attribute()) + Diag(Attr->getLoc(), diag::warn_gcc_attribute_location); + Attr = Attr->getNext(); + } + } + } } /// ParseCXXClassMemberDeclaration - Parse a C++ class member declaration. diff --git a/test/SemaCXX/attr-gnu.cpp b/test/SemaCXX/attr-gnu.cpp index 3d23ed945e..b4e9f4609f 100644 --- a/test/SemaCXX/attr-gnu.cpp +++ b/test/SemaCXX/attr-gnu.cpp @@ -11,3 +11,19 @@ void f() { } void g(int a[static [[]] 5]); // expected-error {{static array size is a C99 feature, not permitted in C++}} + +namespace { +class B { +public: + virtual void test() {} + virtual void test2() {} + virtual void test3() {} +}; + +class D : public B { +public: + void test() __attribute__((deprecated)) final {} // expected-warning {{GCC does not allow an attribute in this position on a function declaration}} + void test2() [[]] override {} // Ok + void test3() __attribute__((cf_unknown_transfer)) override {} // Ok, not known to GCC. +}; +}