From e321795c60c58756a58da7fadb180747d1c9d632 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Sat, 17 Dec 2011 00:36:09 +0000 Subject: [PATCH] Remove a non-gcc-compatible extension that would apply attributes on declarations without a declarator to structs. Add a warning for ignored attributes. Patch by Michael Han. llvm-svn: 146796 --- clang/include/clang/Basic/DiagnosticGroups.td | 1 + clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 ++ clang/lib/Sema/SemaDecl.cpp | 24 +++++++++++++++++++--- .../test/CXX/temp/temp.decls/temp.variadic/p5.cpp | 3 +-- clang/test/CodeGenCXX/visibility.cpp | 2 +- clang/test/Sema/attr-declspec-ignored.c | 12 +++++++++++ clang/test/Sema/attr-deprecated.c | 4 ++-- clang/test/Sema/warn-cast-align.c | 2 +- clang/test/SemaCXX/attr-cxx0x.cpp | 2 +- clang/test/SemaCXX/attr-declspec-ignored.cpp | 19 +++++++++++++++++ 10 files changed, 61 insertions(+), 10 deletions(-) create mode 100644 clang/test/Sema/attr-declspec-ignored.c create mode 100644 clang/test/SemaCXX/attr-declspec-ignored.cpp diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index e69312e..d9c078f 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -186,6 +186,7 @@ def UninitializedMaybe : DiagGroup<"conditional-uninitialized">; def UnknownPragmas : DiagGroup<"unknown-pragmas">; def NSobjectAttribute : DiagGroup<"NSObject-attribute">; def UnknownAttributes : DiagGroup<"attributes">; +def IgnoredAttributes : DiagGroup<"ignored-attributes">; def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args", [CXX98CompatUnnamedTypeTemplateArgs]>; def UnusedArgument : DiagGroup<"unused-argument">; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index aa6fe86..c0676dd 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1465,6 +1465,8 @@ def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning< def warn_attribute_ignored : Warning<"%0 attribute ignored">; def warn_unknown_attribute_ignored : Warning< "unknown attribute %0 ignored">, InGroup; +def warn_declspec_attribute_ignored : Warning< + "attribute %0 is ignored, place it after \"%select{class|struct|union|enum}1\" to apply attribute to type declaration">, InGroup; def warn_attribute_precede_definition : Warning< "attribute declaration must precede definition">; def warn_attribute_void_function_method : Warning< diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 5edeab4..a0291af 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2367,8 +2367,6 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, bool emittedWarning = false; if (RecordDecl *Record = dyn_cast_or_null(Tag)) { - ProcessDeclAttributeList(S, Record, DS.getAttributes().getList()); - if (!Record->getDeclName() && Record->isCompleteDefinition() && DS.getStorageClassSpec() != DeclSpec::SCS_typedef) { if (getLangOptions().CPlusPlus || @@ -2463,7 +2461,27 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, << Tag->getTagKind() << FixItHint::CreateRemoval(DS.getModulePrivateSpecLoc()); - // FIXME: Warn on useless attributes + // Warn about ignored type attributes, for example: + // __attribute__((aligned)) struct A; + // Attributes should be placed after tag to apply to type declaration. + if (!DS.getAttributes().empty()) { + DeclSpec::TST TypeSpecType = DS.getTypeSpecType(); + if (TypeSpecType == DeclSpec::TST_class || + TypeSpecType == DeclSpec::TST_struct || + TypeSpecType == DeclSpec::TST_union || + TypeSpecType == DeclSpec::TST_enum) { + AttributeList* attrs = DS.getAttributes().getList(); + while (attrs) { + Diag(attrs->getScopeLoc(), + diag::warn_declspec_attribute_ignored) + << attrs->getName() + << (TypeSpecType == DeclSpec::TST_class ? 0 : + TypeSpecType == DeclSpec::TST_struct ? 1 : + TypeSpecType == DeclSpec::TST_union ? 2 : 3); + attrs = attrs->getNext(); + } + } + } return TagD; } diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp index a0b5580..bbdf489 100644 --- a/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp @@ -162,8 +162,7 @@ struct TestUnexpandedTTP { // Test for unexpanded parameter packs in declarations. template // FIXME: this should test that the diagnostic reads "type contains..." -alignas(Types) // expected-error{{expression contains unexpanded parameter pack 'Types'}} -struct TestUnexpandedDecls : T{ +struct alignas(Types) TestUnexpandedDecls : T{ // expected-error{{expression contains unexpanded parameter pack 'Types'}} void member_function(Types); // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} void member_function () throw(Types); // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} operator Types() const; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} diff --git a/clang/test/CodeGenCXX/visibility.cpp b/clang/test/CodeGenCXX/visibility.cpp index 0f36a6a..0da55c6 100644 --- a/clang/test/CodeGenCXX/visibility.cpp +++ b/clang/test/CodeGenCXX/visibility.cpp @@ -156,7 +156,7 @@ namespace Test9 { namespace Test10 { struct A; - DEFAULT class B { + class DEFAULT B { void foo(A*); }; diff --git a/clang/test/Sema/attr-declspec-ignored.c b/clang/test/Sema/attr-declspec-ignored.c new file mode 100644 index 0000000..e1bce47 --- /dev/null +++ b/clang/test/Sema/attr-declspec-ignored.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only + +__attribute__((visibility("hidden"))) __attribute__((aligned)) struct A; // expected-warning{{attribute 'visibility' is ignored, place it after "struct" to apply attribute to type declaration}} \ +// expected-warning{{attribute 'aligned' is ignored, place it after "struct" to apply attribute to type declaration}} +__attribute__((visibility("hidden"))) __attribute__((aligned)) union B; // expected-warning{{attribute 'visibility' is ignored, place it after "union" to apply attribute to type declaration}} \ +// expected-warning{{attribute 'aligned' is ignored, place it after "union" to apply attribute to type declaration}} +__attribute__((visibility("hidden"))) __attribute__((aligned)) enum C {C}; // expected-warning{{attribute 'visibility' is ignored, place it after "enum" to apply attribute to type declaration}} \ +// expected-warning{{attribute 'aligned' is ignored, place it after "enum" to apply attribute to type declaration}} + +__attribute__((visibility("hidden"))) __attribute__((aligned)) struct D {} d; +__attribute__((visibility("hidden"))) __attribute__((aligned)) union E {} e; +__attribute__((visibility("hidden"))) __attribute__((aligned)) enum F {F} f; diff --git a/clang/test/Sema/attr-deprecated.c b/clang/test/Sema/attr-deprecated.c index 86ee80e..4760dab 100644 --- a/clang/test/Sema/attr-deprecated.c +++ b/clang/test/Sema/attr-deprecated.c @@ -44,8 +44,8 @@ void test1(struct foo *F) { typedef struct foo foo_dep __attribute__((deprecated)); foo_dep *test2; // expected-warning {{'foo_dep' is deprecated}} -struct bar_dep __attribute__((deprecated, - invalid_attribute)); // expected-warning {{unknown attribute 'invalid_attribute' ignored}} +struct __attribute__((deprecated, + invalid_attribute)) bar_dep ; // expected-warning {{unknown attribute 'invalid_attribute' ignored}} struct bar_dep *test3; // expected-warning {{'bar_dep' is deprecated}} diff --git a/clang/test/Sema/warn-cast-align.c b/clang/test/Sema/warn-cast-align.c index 93352c2..9d64699 100644 --- a/clang/test/Sema/warn-cast-align.c +++ b/clang/test/Sema/warn-cast-align.c @@ -28,7 +28,7 @@ void test1(void *P) { } // Aligned struct. -__attribute__((aligned(16))) struct A { +struct __attribute__((aligned(16))) A { char buffer[16]; }; void test2(char *P) { diff --git a/clang/test/SemaCXX/attr-cxx0x.cpp b/clang/test/SemaCXX/attr-cxx0x.cpp index c697a7d..4281895 100644 --- a/clang/test/SemaCXX/attr-cxx0x.cpp +++ b/clang/test/SemaCXX/attr-cxx0x.cpp @@ -9,7 +9,7 @@ struct align_member { int member alignas(8); }; -template alignas(A) struct align_class_template {}; +template struct alignas(A) align_class_template {}; // FIXME: these should not error template alignas(T...) struct align_class_temp_pack_type {}; // expected-error{{pack expansions in alignment specifiers are not supported yet}} diff --git a/clang/test/SemaCXX/attr-declspec-ignored.cpp b/clang/test/SemaCXX/attr-declspec-ignored.cpp new file mode 100644 index 0000000..c6745c4 --- /dev/null +++ b/clang/test/SemaCXX/attr-declspec-ignored.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only + +namespace test1 { + __attribute__((visibility("hidden"))) __attribute__((aligned)) class A; // expected-warning{{attribute 'visibility' is ignored, place it after "class" to apply attribute to type declaration}} \ + // expected-warning{{attribute 'aligned' is ignored, place it after "class" to apply attribute to type declaration}} + __attribute__((visibility("hidden"))) __attribute__((aligned)) struct B; // expected-warning{{attribute 'visibility' is ignored, place it after "struct" to apply attribute to type declaration}} \ + // expected-warning{{attribute 'aligned' is ignored, place it after "struct" to apply attribute to type declaration}} + __attribute__((visibility("hidden"))) __attribute__((aligned)) union C; // expected-warning{{attribute 'visibility' is ignored, place it after "union" to apply attribute to type declaration}} \ + // expected-warning{{attribute 'aligned' is ignored, place it after "union" to apply attribute to type declaration}} + __attribute__((visibility("hidden"))) __attribute__((aligned)) enum D {D}; // expected-warning{{attribute 'visibility' is ignored, place it after "enum" to apply attribute to type declaration}} \ + // expected-warning{{attribute 'aligned' is ignored, place it after "enum" to apply attribute to type declaration}} +} + +namespace test2 { + __attribute__((visibility("hidden"))) __attribute__((aligned)) class A {} a; + __attribute__((visibility("hidden"))) __attribute__((aligned)) struct B {} b; + __attribute__((visibility("hidden"))) __attribute__((aligned)) union C {} c; + __attribute__((visibility("hidden"))) __attribute__((aligned)) enum D {D} d; +} -- 2.7.4