Skip to content

Commit 61b435e

Browse files
authored
[Clang] show attribute namespace in diagnostics (#138519)
This patch enhances Clang's diagnosis of an unknown attribute by printing the attribute's namespace in the diagnostic text. e.g., ```cpp [[foo::nodiscard]] int f(); // warning: unknown attribute 'foo::nodiscard' ignored ```
1 parent 856632b commit 61b435e

File tree

11 files changed

+42
-20
lines changed

11 files changed

+42
-20
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,8 @@ Improvements to Clang's diagnostics
506506
behavior of the C99 feature as it was introduced into C++20. Fixes #GH47037
507507
- ``-Wreserved-identifier`` now fires on reserved parameter names in a function
508508
declaration which is not a definition.
509+
- Clang now prints the namespace for an attribute, if any,
510+
when emitting an unknown attribute diagnostic.
509511

510512
- Several compatibility diagnostics that were incorrectly being grouped under
511513
``-Wpre-c++20-compat`` are now part of ``-Wc++20-compat``. (#GH138775)

clang/include/clang/Basic/AttributeCommonInfo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ class AttributeCommonInfo {
196196
/// with surrounding underscores removed as appropriate (e.g.
197197
/// __gnu__::__attr__ will be normalized to gnu::attr).
198198
std::string getNormalizedFullName() const;
199+
SourceRange getNormalizedRange() const;
199200

200201
bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; }
201202
bool isMicrosoftAttribute() const { return SyntaxUsed == AS_Microsoft; }

clang/lib/Basic/Attributes.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,10 @@ std::string AttributeCommonInfo::getNormalizedFullName() const {
181181
normalizeName(getAttrName(), getScopeName(), getSyntax()));
182182
}
183183

184+
SourceRange AttributeCommonInfo::getNormalizedRange() const {
185+
return hasScope() ? SourceRange(ScopeLoc, AttrRange.getEnd()) : AttrRange;
186+
}
187+
184188
static AttributeCommonInfo::Scope
185189
getScopeFromNormalizedScopeName(StringRef ScopeName) {
186190
return llvm::StringSwitch<AttributeCommonInfo::Scope>(ScopeName)

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6862,13 +6862,16 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
68626862
// though they were unknown attributes.
68636863
if (AL.getKind() == ParsedAttr::UnknownAttribute ||
68646864
!AL.existsInTarget(S.Context.getTargetInfo())) {
6865-
S.Diag(AL.getLoc(),
6866-
AL.isRegularKeywordAttribute()
6867-
? (unsigned)diag::err_keyword_not_supported_on_target
6868-
: AL.isDeclspecAttribute()
6869-
? (unsigned)diag::warn_unhandled_ms_attribute_ignored
6870-
: (unsigned)diag::warn_unknown_attribute_ignored)
6871-
<< AL << AL.getRange();
6865+
if (AL.isRegularKeywordAttribute() || AL.isDeclspecAttribute()) {
6866+
S.Diag(AL.getLoc(), AL.isRegularKeywordAttribute()
6867+
? diag::err_keyword_not_supported_on_target
6868+
: diag::warn_unhandled_ms_attribute_ignored)
6869+
<< AL.getAttrName() << AL.getRange();
6870+
} else {
6871+
S.Diag(AL.getNormalizedRange().getBegin(),
6872+
diag::warn_unknown_attribute_ignored)
6873+
<< "'" + AL.getNormalizedFullName() + "'" << AL.getNormalizedRange();
6874+
}
68726875
return;
68736876
}
68746877

clang/test/CXX/module/module.interface/p3.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export { // No diagnostic after P2615R1 DR
4040
extern "C++" {} // No diagnostic after P2615R1 DR
4141
}
4242
export [[]]; // No diagnostic after P2615R1 DR
43-
export [[example::attr]]; // expected-warning {{unknown attribute 'attr'}}
43+
export [[example::attr]]; // expected-warning {{unknown attribute 'example::attr' ignored}}
4444

4545
// [...] shall not declare a name with internal linkage
4646
export static int a; // expected-error {{declaration of 'a' with internal linkage cannot be exported}}

clang/test/OpenMP/openmp_attribute_parsing.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
// attribute name. So this means we never hit the omp-specific parsing and
1111
// instead handle this through the usual Sema attribute handling in
1212
// SemaDeclAttr.cpp, which diagnoses this as an unknown attribute.
13-
[[omp::directive]]; // expected-warning {{unknown attribute 'directive' ignored}}
14-
[[omp::sequence]]; // expected-warning {{unknown attribute 'sequence' ignored}}
15-
[[omp::unknown]]; // expected-warning {{unknown attribute 'unknown' ignored}}
13+
[[omp::directive]]; // expected-warning {{unknown attribute 'omp::directive' ignored}}
14+
[[omp::sequence]]; // expected-warning {{unknown attribute 'omp::sequence' ignored}}
15+
[[omp::unknown]]; // expected-warning {{unknown attribute 'omp::unknown' ignored}}
1616

1717
[[omp::directive()]]; // expected-error {{expected an OpenMP directive}}
1818
[[omp::sequence()]]; // expected-error {{expected an OpenMP 'directive' or 'sequence' attribute argument}}
@@ -49,8 +49,8 @@
4949

5050
// Test that we give a sensible error on an unknown attribute in the omp
5151
// namespace that has an argument list.
52-
[[omp::unknown()]]; // expected-warning {{unknown attribute 'unknown' ignored}}
53-
[[using omp: unknown()]]; // expected-warning {{unknown attribute 'unknown' ignored}}
52+
[[omp::unknown()]]; // expected-warning {{unknown attribute 'omp::unknown' ignored}}
53+
[[using omp: unknown()]]; // expected-warning {{unknown attribute 'omp::unknown' ignored}}
5454

5555
// Test that unknown arguments to the omp::sequence are rejected, regardless of
5656
// what level they're at.

clang/test/Parser/c2x-attributes.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ void f11(void) {
133133
}
134134

135135
[[attr]] void f12(void); // expected-warning {{unknown attribute 'attr' ignored}}
136-
[[vendor::attr]] void f13(void); // expected-warning {{unknown attribute 'attr' ignored}}
136+
[[vendor::attr]] void f13(void); // expected-warning {{unknown attribute 'vendor::attr' ignored}}
137137

138138
// Ensure that asm statements properly handle double colons.
139139
void test_asm(void) {

clang/test/Parser/cxx0x-attributes.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,15 @@ int & [[noreturn]] ref_attr_3 = after_attr; // expected-error {{'noreturn' attri
4646
int && [[]] rref_attr = 0;
4747
int array_attr [1] [[]];
4848
alignas(8) int aligned_attr;
49-
[[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}}
49+
[[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}}
5050
[[,,,static, class, namespace,, inline, constexpr, mutable,, bitand, bitor::compl(!.*_ Cx.!U^*R),,,]] int more_garbage_attr; // expected-warning {{unknown attribute 'static' ignored}} \
5151
// expected-warning {{unknown attribute 'class' ignored}} \
5252
// expected-warning {{unknown attribute 'namespace' ignored}} \
5353
// expected-warning {{unknown attribute 'inline' ignored}} \
5454
// expected-warning {{unknown attribute 'constexpr' ignored}} \
5555
// expected-warning {{unknown attribute 'mutable' ignored}} \
5656
// expected-warning {{unknown attribute 'bitand' ignored}} \
57-
// expected-warning {{unknown attribute 'compl' ignored}}
57+
// expected-warning {{unknown attribute 'bitor::compl' ignored}}
5858
[[u8"invalid!"]] int invalid_string_attr; // expected-error {{expected ']'}}
5959
void fn_attr () [[]];
6060
void noexcept_fn_attr () noexcept [[]];
@@ -269,7 +269,7 @@ template <int... Is> void variadic_nttp() {
269269
void baz [[clang::no_sanitize(Is...)]] (); // expected-error {{expected string literal as argument of 'no_sanitize' attribute}}
270270
void bor [[clang::annotate("A", "V" ...)]] (); // expected-error {{pack expansion does not contain any unexpanded parameter packs}}
271271
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}}
272-
void boo [[unknown::foo(Is...)]] (); // expected-warning {{unknown attribute 'foo' ignored}}
272+
void boo [[unknown::foo(Is...)]] (); // expected-warning {{unknown attribute 'unknown::foo' ignored}}
273273
void faz [[clang::annotate("C", (Is + ...))]] (); // expected-warning {{pack fold expression is a C++17 extension}}
274274
void far [[clang::annotate("D", Is...)]] ();
275275
void foz [[clang::annotate("E", 1, 2, 3, Is...)]] ();

clang/test/Sema/patchable-function-entry-attr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@
1515
// silence-no-diagnostics
1616

1717
// AIX-error@+2 {{'patchable_function_entry' attribute is not yet supported on AIX}}
18-
// expected-warning@+1 {{unknown attribute 'patchable_function_entry' ignored}}
18+
// expected-warning@+1 {{unknown attribute 'gnu::patchable_function_entry' ignored}}
1919
[[gnu::patchable_function_entry(0)]] void f();

clang/test/Sema/unknown-attributes.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: %clang_cc1 -Wunknown-attributes -fsyntax-only -verify %s
2+
// RUN: %clang_cc1 -x c++ -fsyntax-only -Wunknown-attributes -verify %s
3+
4+
[[foo::a]] // expected-warning {{unknown attribute 'foo::a' ignored}}
5+
int f1(void) {
6+
return 0;
7+
}
8+
9+
[[clan::deprecated]] // expected-warning {{unknown attribute 'clan::deprecated' ignored}}
10+
int f2(void) {
11+
return 0;
12+
}

0 commit comments

Comments
 (0)