Skip to content

Commit ece10a6

Browse files
authored
Allow some attributes on declarations after definitions (#135791)
The deprecated, maybe_unused, and nodiscard standard attributes may all be applied to a redeclaration after a definition has already appeared. We were previously dropping the attribute in that case, now we retain the attribute after the redeclaration. Note: someday we may want to tablegen this as part of information from Attr.td. We may also want to relax the restriction here so that the syntax used does not matter. This is an intentionally conservative fix. Fixes #135481
1 parent 98534ee commit ece10a6

File tree

3 files changed

+61
-0
lines changed

3 files changed

+61
-0
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,11 @@ Bug Fixes to Attribute Support
439439
- No longer crashing on ``__attribute__((align_value(N)))`` during template
440440
instantiation when the function parameter type is not a pointer or reference.
441441
(#GH26612)
442+
- Now allowing the ``[[deprecated]]``, ``[[maybe_unused]]``, and
443+
``[[nodiscard]]`` to be applied to a redeclaration after a definition in both
444+
C and C++ mode for the standard spellings (other spellings, such as
445+
``__attribute__((unused))`` are still ignored after the definition, though
446+
this behavior may be relaxed in the future). (#GH135481)
442447

443448
Bug Fixes to C++ Support
444449
^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaDecl.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2996,6 +2996,21 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) {
29962996
// msvc will allow a subsequent definition to add an uuid to a class
29972997
++I;
29982998
continue;
2999+
} else if (isa<DeprecatedAttr, WarnUnusedResultAttr, UnusedAttr>(
3000+
NewAttribute) &&
3001+
NewAttribute->isStandardAttributeSyntax()) {
3002+
// C++14 [dcl.attr.deprecated]p3: A name or entity declared without the
3003+
// deprecated attribute can later be re-declared with the attribute and
3004+
// vice-versa.
3005+
// C++17 [dcl.attr.unused]p4: A name or entity declared without the
3006+
// maybe_unused attribute can later be redeclared with the attribute and
3007+
// vice versa.
3008+
// C++20 [dcl.attr.nodiscard]p2: A name or entity declared without the
3009+
// nodiscard attribute can later be redeclared with the attribute and
3010+
// vice-versa.
3011+
// C23 6.7.13.3p3, 6.7.13.4p3. and 6.7.13.5p5 give the same allowances.
3012+
++I;
3013+
continue;
29993014
} else if (const AlignedAttr *AA = dyn_cast<AlignedAttr>(NewAttribute)) {
30003015
if (AA->isAlignas()) {
30013016
// C++11 [dcl.align]p6:
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// RUN: %clang_cc1 -fsyntax-only -Wignored-attributes -verify -std=c23 %s
2+
// RUN: %clang_cc1 -fsyntax-only -Wignored-attributes -verify -x c++ %s
3+
// RUN: %clang_cc1 -fsyntax-only -ast-dump %s | FileCheck %s
4+
5+
inline int frob(int x) { return x; }
6+
7+
[[deprecated]] int frob(int); // expected-note 2 {{'frob' has been explicitly marked deprecated here}}
8+
9+
void use1() {
10+
// Using this should give a deprecation warning, but not a nodiscard warning.
11+
frob(0); // expected-warning {{'frob' is deprecated}}
12+
}
13+
14+
[[nodiscard]] int frob(int);
15+
16+
void use2() {
17+
// This should give both warnings.
18+
frob(0); // expected-warning {{'frob' is deprecated}} \
19+
expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
20+
}
21+
22+
[[maybe_unused]] int frob(int);
23+
24+
// Currently, this is only allowed for the standard spelling of the attributes.
25+
void blob() {} // expected-note {{previous definition is here}}
26+
__attribute__((deprecated)) void blob(); // expected-warning {{attribute declaration must precede definition}}
27+
28+
// CHECK: FunctionDecl {{.*}} frob
29+
30+
// CHECK: FunctionDecl {{.*}} prev {{.*}} frob
31+
// CHECK: DeprecatedAttr
32+
33+
// CHECK: FunctionDecl {{.*}} prev {{.*}} frob
34+
// CHECK: DeprecatedAttr
35+
// CHECK: WarnUnusedResultAttr
36+
37+
// CHECK: FunctionDecl {{.*}} prev {{.*}} frob
38+
// CHECK: DeprecatedAttr
39+
// CHECK: WarnUnusedResultAttr
40+
// CHECK: UnusedAttr
41+

0 commit comments

Comments
 (0)