https://github.com/a-tarasyuk updated https://github.com/llvm/llvm-project/pull/138519
>From 7d376b33f09801be504ec65a2853679dff8b726c 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 1/3] [Clang] diagnose unknown attribute namespaces --- clang/docs/ReleaseNotes.rst | 2 ++ .../include/clang/Basic/AttributeCommonInfo.h | 4 +++- .../clang/Basic/DiagnosticCommonKinds.td | 3 +++ clang/lib/Basic/Attributes.cpp | 9 ++++++++- clang/lib/Sema/SemaDeclAttr.cpp | 19 ++++++++++++------- clang/test/CXX/module/module.interface/p3.cpp | 2 +- clang/test/Parser/c2x-attributes.c | 2 +- clang/test/Parser/cxx0x-attributes.cpp | 6 +++--- clang/test/Sema/unknown-attributes.c | 12 ++++++++++++ 9 files changed, 45 insertions(+), 14 deletions(-) create mode 100644 clang/test/Sema/unknown-attributes.c diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index a80fedebf8f89..d01fc5d1bf46f 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..ddb022c493bdf 100644 --- a/clang/include/clang/Basic/AttributeCommonInfo.h +++ b/clang/include/clang/Basic/AttributeCommonInfo.h @@ -67,7 +67,7 @@ class AttributeCommonInfo { IgnoredAttribute, UnknownAttribute, }; - enum class Scope { NONE, CLANG, GNU, MSVC, OMP, HLSL, GSL, RISCV }; + enum class Scope { NONE, CLANG, GNU, MSVC, OMP, HLSL, GSL, RISCV, UNKNOWN }; enum class AttrArgsInfo { None, Optional, @@ -234,6 +234,8 @@ class AttributeCommonInfo { return SyntaxUsed == AS_ContextSensitiveKeyword; } + bool isUnknownScopeName() const; + unsigned getAttributeSpellingListIndex() const { assert((isAttributeSpellingListCalculated() || AttrName) && "Spelling cannot be found"); diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td index f26c906b46447..63f4c229b2e76 100644 --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -177,6 +177,9 @@ def err_opencl_unknown_type_specifier : Error< "%0 does not support the '%1' " "%select{type qualifier|storage class specifier}2">; +def warn_unknown_attribute_namespace : Warning< + "unknown attribute namespace '%0'; attribute '%0::%1' ignored">, + InGroup<UnknownAttributes>; def warn_unknown_attribute_ignored : Warning< "unknown attribute %0 ignored">, InGroup<UnknownAttributes>; def warn_attribute_ignored : Warning<"%0 attribute ignored">, diff --git a/clang/lib/Basic/Attributes.cpp b/clang/lib/Basic/Attributes.cpp index 6a070a99c8d96..c41cbf0fb61f6 100644 --- a/clang/lib/Basic/Attributes.cpp +++ b/clang/lib/Basic/Attributes.cpp @@ -191,7 +191,8 @@ getScopeFromNormalizedScopeName(StringRef ScopeName) { .Case("hlsl", AttributeCommonInfo::Scope::HLSL) .Case("msvc", AttributeCommonInfo::Scope::MSVC) .Case("omp", AttributeCommonInfo::Scope::OMP) - .Case("riscv", AttributeCommonInfo::Scope::RISCV); + .Case("riscv", AttributeCommonInfo::Scope::RISCV) + .Default(AttributeCommonInfo::Scope::UNKNOWN); } unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const { @@ -206,3 +207,9 @@ unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const { #include "clang/Sema/AttrSpellingListIndex.inc" } + +bool AttributeCommonInfo::isUnknownScopeName() const { + return getScopeFromNormalizedScopeName( + normalizeAttrScopeName(getScopeName(), getSyntax())) == + AttributeCommonInfo::Scope::UNKNOWN; +} diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index bfb3ee9dcbd16..7dc5a04923946 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -6861,13 +6861,18 @@ 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.isUnknownScopeName()) + S.Diag(AL.getScopeLoc(), diag::warn_unknown_attribute_namespace) + << AL.getScopeName()->getName() << AL.getAttrName()->getName() + << SourceRange(AL.getScopeLoc(), AL.getRange().getEnd()); + else + 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(); return; } diff --git a/clang/test/CXX/module/module.interface/p3.cpp b/clang/test/CXX/module/module.interface/p3.cpp index 32819b2dccb11..18758edaf1be7 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 namespace 'example'; 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/Parser/c2x-attributes.c b/clang/test/Parser/c2x-attributes.c index be039e40f98ef..b5f502c5790d3 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 namespace 'vendor'; 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..7a0a8b989851f 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 namespace 'test'; 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 namespace 'bitor'; 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 namespace '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/unknown-attributes.c b/clang/test/Sema/unknown-attributes.c new file mode 100644 index 0000000000000..833ac2f919ea6 --- /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 namespace 'foo'; attribute 'foo::a' ignored}} +int f1(void) { + return 0; +} + +[[clan::deprecated]] // expected-warning {{unknown attribute namespace 'clan'; attribute 'clan::deprecated' ignored}} +int f2(void) { + return 0; +} >From 956e469683c5ec9e94571a1a5e4a5bcad3d6f09b Mon Sep 17 00:00:00 2001 From: Oleksandr Tarasiuk <oleksandr.taras...@outlook.com> Date: Mon, 5 May 2025 18:58:21 +0300 Subject: [PATCH 2/3] reuse existing diagnostic message --- clang/docs/ReleaseNotes.rst | 2 +- .../clang/Basic/DiagnosticCommonKinds.td | 3 --- clang/lib/Sema/SemaDeclAttr.cpp | 21 ++++++++++--------- clang/test/CXX/module/module.interface/p3.cpp | 2 +- clang/test/Parser/c2x-attributes.c | 2 +- clang/test/Parser/cxx0x-attributes.cpp | 6 +++--- clang/test/Sema/unknown-attributes.c | 4 ++-- 7 files changed, 19 insertions(+), 21 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index d01fc5d1bf46f..fba357afede74 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -385,7 +385,7 @@ 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 +- Clang now diagnoses unknown attribute namespaces. Improvements to Clang's diagnostics ----------------------------------- diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td index 63f4c229b2e76..f26c906b46447 100644 --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -177,9 +177,6 @@ def err_opencl_unknown_type_specifier : Error< "%0 does not support the '%1' " "%select{type qualifier|storage class specifier}2">; -def warn_unknown_attribute_namespace : Warning< - "unknown attribute namespace '%0'; attribute '%0::%1' ignored">, - InGroup<UnknownAttributes>; def warn_unknown_attribute_ignored : Warning< "unknown attribute %0 ignored">, InGroup<UnknownAttributes>; def warn_attribute_ignored : Warning<"%0 attribute ignored">, diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 7dc5a04923946..b16dcba6c06ba 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -6861,18 +6861,19 @@ 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())) { + auto D = 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); + if (AL.isUnknownScopeName()) - S.Diag(AL.getScopeLoc(), diag::warn_unknown_attribute_namespace) - << AL.getScopeName()->getName() << AL.getAttrName()->getName() - << SourceRange(AL.getScopeLoc(), AL.getRange().getEnd()); + D << "'" + AL.getNormalizedFullName() + "'" + << SourceRange(AL.getScopeLoc(), AL.getRange().getEnd()); else - 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(); + D << AL.getAttrName() << AL.getRange(); + return; } diff --git a/clang/test/CXX/module/module.interface/p3.cpp b/clang/test/CXX/module/module.interface/p3.cpp index 18758edaf1be7..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 namespace 'example'; attribute 'example::attr' ignored}} +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/Parser/c2x-attributes.c b/clang/test/Parser/c2x-attributes.c index b5f502c5790d3..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 namespace 'vendor'; attribute 'vendor::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 7a0a8b989851f..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 namespace 'test'; attribute 'test::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 namespace 'bitor'; attribute 'bitor::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 namespace 'unknown'; attribute 'unknown::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/unknown-attributes.c b/clang/test/Sema/unknown-attributes.c index 833ac2f919ea6..1f6708fc7219f 100644 --- a/clang/test/Sema/unknown-attributes.c +++ b/clang/test/Sema/unknown-attributes.c @@ -1,12 +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 namespace 'foo'; attribute 'foo::a' ignored}} +[[foo::a]] // expected-warning {{unknown attribute 'foo::a' ignored}} int f1(void) { return 0; } -[[clan::deprecated]] // expected-warning {{unknown attribute namespace 'clan'; attribute 'clan::deprecated' ignored}} +[[clan::deprecated]] // expected-warning {{unknown attribute 'clan::deprecated' ignored}} int f2(void) { return 0; } >From 8d93bc3e562c3b58bc1243823d4fb104b8694a74 Mon Sep 17 00:00:00 2001 From: Oleksandr Tarasiuk <oleksandr.taras...@outlook.com> Date: Mon, 5 May 2025 19:45:06 +0300 Subject: [PATCH 3/3] remove useless casts --- clang/lib/Sema/SemaDeclAttr.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index b16dcba6c06ba..0bbedb245746b 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -6861,12 +6861,11 @@ 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())) { - auto D = 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); + auto D = S.Diag(AL.getLoc(), AL.isRegularKeywordAttribute() + ? diag::err_keyword_not_supported_on_target + : AL.isDeclspecAttribute() + ? diag::warn_unhandled_ms_attribute_ignored + : diag::warn_unknown_attribute_ignored); if (AL.isUnknownScopeName()) D << "'" + AL.getNormalizedFullName() + "'" _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits