[clang] [Clang] diagnose unknown attribute namespaces (PR #138519)
Oleksandr T. via cfe-commits
cfe-commits at lists.llvm.org
Wed May 7 05:01:07 PDT 2025
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.tarasiuk at outlook.com>
Date: Mon, 5 May 2025 15:30:14 +0300
Subject: [PATCH 1/2] [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 at +2 {{'patchable_function_entry' attribute is not yet supported on AIX}}
-// expected-warning at +1 {{unknown attribute 'patchable_function_entry' ignored}}
+// expected-warning at +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 at -1 {{unknown attribute 'no_unique_address' ignored}}
+ // unsupported-warning at -1 {{unknown attribute 'msvc::no_unique_address' ignored}}
};
struct CStructMSVCNoUniqueAddress2 {
int one;
[[msvc::no_unique_address]] int two;
- // unsupported-warning at -1 {{unknown attribute 'no_unique_address' ignored}}
+ // unsupported-warning at -1 {{unknown attribute 'msvc::no_unique_address' ignored}}
};
static_assert(__has_cpp_attribute(no_unique_address) == 0);
>From bd8cfae6ebf8d53ddc023c122a39ede88fca6e65 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.tarasiuk at outlook.com>
Date: Wed, 7 May 2025 15:00:52 +0300
Subject: [PATCH 2/2] update release notes
---
clang/docs/ReleaseNotes.rst | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index e096e5fdf6a23..93ba493304460 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -392,8 +392,6 @@ 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
-----------------------------------
@@ -506,6 +504,8 @@ Improvements to Clang's diagnostics
behavior of the C99 feature as it was introduced into C++20. Fixes #GH47037
- ``-Wreserved-identifier`` now fires on reserved parameter names in a function
declaration which is not a definition.
+- Clang now prints the namespace for an attribute, if any,
+ when emitting an unknown attribute diagnostic.
Improvements to Clang's time-trace
----------------------------------
More information about the cfe-commits
mailing list