https://github.com/a-tarasyuk updated https://github.com/llvm/llvm-project/pull/138519
>From cbbca4d26b8d00eb103f110c2341fab2e4a2e40d Mon Sep 17 00:00:00 2001 From: Oleksandr Tarasiuk <oleksandr.taras...@outlook.com> Date: Mon, 5 May 2025 15:30:14 +0300 Subject: [PATCH] [Clang] diagnose unknown attribute namespaces --- clang/docs/ReleaseNotes.rst | 2 ++ clang/include/clang/Basic/AttributeCommonInfo.h | 1 + clang/lib/Basic/Attributes.cpp | 4 ++++ clang/lib/Sema/SemaDeclAttr.cpp | 17 ++++++++++------- clang/test/CXX/module/module.interface/p3.cpp | 2 +- clang/test/OpenMP/openmp_attribute_parsing.cpp | 10 +++++----- clang/test/Parser/c2x-attributes.c | 2 +- clang/test/Parser/cxx0x-attributes.cpp | 6 +++--- .../test/Sema/patchable-function-entry-attr.cpp | 2 +- clang/test/Sema/unknown-attributes.c | 12 ++++++++++++ .../test/SemaCXX/cxx2a-ms-no-unique-address.cpp | 4 ++-- 11 files changed, 42 insertions(+), 20 deletions(-) create mode 100644 clang/test/Sema/unknown-attributes.c diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index a80fedebf8f89..fba357afede74 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -385,6 +385,8 @@ related warnings within the method body. - Clang now disallows the use of attributes applied before an ``extern template`` declaration (#GH79893). +- Clang now diagnoses unknown attribute namespaces. + Improvements to Clang's diagnostics ----------------------------------- diff --git a/clang/include/clang/Basic/AttributeCommonInfo.h b/clang/include/clang/Basic/AttributeCommonInfo.h index 4af5a8fd1852c..6db7b53317e7d 100644 --- a/clang/include/clang/Basic/AttributeCommonInfo.h +++ b/clang/include/clang/Basic/AttributeCommonInfo.h @@ -196,6 +196,7 @@ class AttributeCommonInfo { /// with surrounding underscores removed as appropriate (e.g. /// __gnu__::__attr__ will be normalized to gnu::attr). std::string getNormalizedFullName() const; + SourceRange getNormalizedRange() const; bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; } bool isMicrosoftAttribute() const { return SyntaxUsed == AS_Microsoft; } diff --git a/clang/lib/Basic/Attributes.cpp b/clang/lib/Basic/Attributes.cpp index 6a070a99c8d96..8ff5cc54ccc93 100644 --- a/clang/lib/Basic/Attributes.cpp +++ b/clang/lib/Basic/Attributes.cpp @@ -181,6 +181,10 @@ std::string AttributeCommonInfo::getNormalizedFullName() const { normalizeName(getAttrName(), getScopeName(), getSyntax())); } +SourceRange AttributeCommonInfo::getNormalizedRange() const { + return hasScope() ? SourceRange(ScopeLoc, AttrRange.getEnd()) : AttrRange; +} + static AttributeCommonInfo::Scope getScopeFromNormalizedScopeName(StringRef ScopeName) { return llvm::StringSwitch<AttributeCommonInfo::Scope>(ScopeName) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index bfb3ee9dcbd16..c481c338b27d6 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -6861,13 +6861,16 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, // though they were unknown attributes. if (AL.getKind() == ParsedAttr::UnknownAttribute || !AL.existsInTarget(S.Context.getTargetInfo())) { - S.Diag(AL.getLoc(), - AL.isRegularKeywordAttribute() - ? (unsigned)diag::err_keyword_not_supported_on_target - : AL.isDeclspecAttribute() - ? (unsigned)diag::warn_unhandled_ms_attribute_ignored - : (unsigned)diag::warn_unknown_attribute_ignored) - << AL << AL.getRange(); + if (AL.isRegularKeywordAttribute() || AL.isDeclspecAttribute()) { + S.Diag(AL.getLoc(), AL.isRegularKeywordAttribute() + ? diag::err_keyword_not_supported_on_target + : diag::warn_unhandled_ms_attribute_ignored) + << AL.getAttrName() << AL.getRange(); + } else { + S.Diag(AL.getNormalizedRange().getBegin(), + diag::warn_unknown_attribute_ignored) + << "'" + AL.getNormalizedFullName() + "'" << AL.getNormalizedRange(); + } return; } diff --git a/clang/test/CXX/module/module.interface/p3.cpp b/clang/test/CXX/module/module.interface/p3.cpp index 32819b2dccb11..0b61eb783dcd0 100644 --- a/clang/test/CXX/module/module.interface/p3.cpp +++ b/clang/test/CXX/module/module.interface/p3.cpp @@ -40,7 +40,7 @@ export { // No diagnostic after P2615R1 DR extern "C++" {} // No diagnostic after P2615R1 DR } export [[]]; // No diagnostic after P2615R1 DR -export [[example::attr]]; // expected-warning {{unknown attribute 'attr'}} +export [[example::attr]]; // expected-warning {{unknown attribute 'example::attr' ignored}} // [...] shall not declare a name with internal linkage export static int a; // expected-error {{declaration of 'a' with internal linkage cannot be exported}} diff --git a/clang/test/OpenMP/openmp_attribute_parsing.cpp b/clang/test/OpenMP/openmp_attribute_parsing.cpp index e273702dfadcb..45cb3d69994d6 100644 --- a/clang/test/OpenMP/openmp_attribute_parsing.cpp +++ b/clang/test/OpenMP/openmp_attribute_parsing.cpp @@ -10,9 +10,9 @@ // attribute name. So this means we never hit the omp-specific parsing and // instead handle this through the usual Sema attribute handling in // SemaDeclAttr.cpp, which diagnoses this as an unknown attribute. -[[omp::directive]]; // expected-warning {{unknown attribute 'directive' ignored}} -[[omp::sequence]]; // expected-warning {{unknown attribute 'sequence' ignored}} -[[omp::unknown]]; // expected-warning {{unknown attribute 'unknown' ignored}} +[[omp::directive]]; // expected-warning {{unknown attribute 'omp::directive' ignored}} +[[omp::sequence]]; // expected-warning {{unknown attribute 'omp::sequence' ignored}} +[[omp::unknown]]; // expected-warning {{unknown attribute 'omp::unknown' ignored}} [[omp::directive()]]; // expected-error {{expected an OpenMP directive}} [[omp::sequence()]]; // expected-error {{expected an OpenMP 'directive' or 'sequence' attribute argument}} @@ -49,8 +49,8 @@ // Test that we give a sensible error on an unknown attribute in the omp // namespace that has an argument list. -[[omp::unknown()]]; // expected-warning {{unknown attribute 'unknown' ignored}} -[[using omp: unknown()]]; // expected-warning {{unknown attribute 'unknown' ignored}} +[[omp::unknown()]]; // expected-warning {{unknown attribute 'omp::unknown' ignored}} +[[using omp: unknown()]]; // expected-warning {{unknown attribute 'omp::unknown' ignored}} // Test that unknown arguments to the omp::sequence are rejected, regardless of // what level they're at. diff --git a/clang/test/Parser/c2x-attributes.c b/clang/test/Parser/c2x-attributes.c index be039e40f98ef..b291cb75818c0 100644 --- a/clang/test/Parser/c2x-attributes.c +++ b/clang/test/Parser/c2x-attributes.c @@ -133,7 +133,7 @@ void f11(void) { } [[attr]] void f12(void); // expected-warning {{unknown attribute 'attr' ignored}} -[[vendor::attr]] void f13(void); // expected-warning {{unknown attribute 'attr' ignored}} +[[vendor::attr]] void f13(void); // expected-warning {{unknown attribute 'vendor::attr' ignored}} // Ensure that asm statements properly handle double colons. void test_asm(void) { diff --git a/clang/test/Parser/cxx0x-attributes.cpp b/clang/test/Parser/cxx0x-attributes.cpp index fad3010c98b9c..6f2db3a655a95 100644 --- a/clang/test/Parser/cxx0x-attributes.cpp +++ b/clang/test/Parser/cxx0x-attributes.cpp @@ -46,7 +46,7 @@ int & [[noreturn]] ref_attr_3 = after_attr; // expected-error {{'noreturn' attri int && [[]] rref_attr = 0; int array_attr [1] [[]]; alignas(8) int aligned_attr; -[[test::valid(for 42 [very] **** '+' symbols went on a trip and had a "good"_time; the end.)]] int garbage_attr; // expected-warning {{unknown attribute 'valid' ignored}} +[[test::valid(for 42 [very] **** '+' symbols went on a trip and had a "good"_time; the end.)]] int garbage_attr; // expected-warning {{unknown attribute 'test::valid' ignored}} [[,,,static, class, namespace,, inline, constexpr, mutable,, bitand, bitor::compl(!.*_ Cx.!U^*R),,,]] int more_garbage_attr; // expected-warning {{unknown attribute 'static' ignored}} \ // expected-warning {{unknown attribute 'class' ignored}} \ // expected-warning {{unknown attribute 'namespace' ignored}} \ @@ -54,7 +54,7 @@ alignas(8) int aligned_attr; // expected-warning {{unknown attribute 'constexpr' ignored}} \ // expected-warning {{unknown attribute 'mutable' ignored}} \ // expected-warning {{unknown attribute 'bitand' ignored}} \ - // expected-warning {{unknown attribute 'compl' ignored}} + // expected-warning {{unknown attribute 'bitor::compl' ignored}} [[u8"invalid!"]] int invalid_string_attr; // expected-error {{expected ']'}} void fn_attr () [[]]; void noexcept_fn_attr () noexcept [[]]; @@ -269,7 +269,7 @@ template <int... Is> void variadic_nttp() { void baz [[clang::no_sanitize(Is...)]] (); // expected-error {{expected string literal as argument of 'no_sanitize' attribute}} void bor [[clang::annotate("A", "V" ...)]] (); // expected-error {{pack expansion does not contain any unexpanded parameter packs}} void bir [[clang::annotate("B", {1, 2, 3, 4})]] (); // expected-error {{'annotate' attribute requires parameter 1 to be a constant expression}} expected-note {{subexpression not valid in a constant expression}} - void boo [[unknown::foo(Is...)]] (); // expected-warning {{unknown attribute 'foo' ignored}} + void boo [[unknown::foo(Is...)]] (); // expected-warning {{unknown attribute 'unknown::foo' ignored}} void faz [[clang::annotate("C", (Is + ...))]] (); // expected-warning {{pack fold expression is a C++17 extension}} void far [[clang::annotate("D", Is...)]] (); void foz [[clang::annotate("E", 1, 2, 3, Is...)]] (); diff --git a/clang/test/Sema/patchable-function-entry-attr.cpp b/clang/test/Sema/patchable-function-entry-attr.cpp index bd4d57a7e3093..efc9fe0e41130 100644 --- a/clang/test/Sema/patchable-function-entry-attr.cpp +++ b/clang/test/Sema/patchable-function-entry-attr.cpp @@ -15,5 +15,5 @@ // silence-no-diagnostics // AIX-error@+2 {{'patchable_function_entry' attribute is not yet supported on AIX}} -// expected-warning@+1 {{unknown attribute 'patchable_function_entry' ignored}} +// expected-warning@+1 {{unknown attribute 'gnu::patchable_function_entry' ignored}} [[gnu::patchable_function_entry(0)]] void f(); diff --git a/clang/test/Sema/unknown-attributes.c b/clang/test/Sema/unknown-attributes.c new file mode 100644 index 0000000000000..1f6708fc7219f --- /dev/null +++ b/clang/test/Sema/unknown-attributes.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -Wunknown-attributes -fsyntax-only -verify %s +// RUN: %clang_cc1 -x c++ -fsyntax-only -Wunknown-attributes -verify %s + +[[foo::a]] // expected-warning {{unknown attribute 'foo::a' ignored}} +int f1(void) { + return 0; +} + +[[clan::deprecated]] // expected-warning {{unknown attribute 'clan::deprecated' ignored}} +int f2(void) { + return 0; +} diff --git a/clang/test/SemaCXX/cxx2a-ms-no-unique-address.cpp b/clang/test/SemaCXX/cxx2a-ms-no-unique-address.cpp index 822ed752fa9c7..726cfa30a0959 100644 --- a/clang/test/SemaCXX/cxx2a-ms-no-unique-address.cpp +++ b/clang/test/SemaCXX/cxx2a-ms-no-unique-address.cpp @@ -27,13 +27,13 @@ struct CStructNoUniqueAddress { struct CStructMSVCNoUniqueAddress { int one; [[msvc::no_unique_address]] int two; - // unsupported-warning@-1 {{unknown attribute 'no_unique_address' ignored}} + // unsupported-warning@-1 {{unknown attribute 'msvc::no_unique_address' ignored}} }; struct CStructMSVCNoUniqueAddress2 { int one; [[msvc::no_unique_address]] int two; - // unsupported-warning@-1 {{unknown attribute 'no_unique_address' ignored}} + // unsupported-warning@-1 {{unknown attribute 'msvc::no_unique_address' ignored}} }; static_assert(__has_cpp_attribute(no_unique_address) == 0); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits