Skip to content

Commit 5029dce

Browse files
committed
Implement WG14 N2764 the [[noreturn]] attribute
This adds support for http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2764.pdf, which was adopted at the Feb 2022 WG14 meeting. That paper adds [[noreturn]] and [[_Noreturn]] to the list of supported attributes in C2x. These attributes have the same semantics as the [[noreturn]] attribute in C++. The [[_Noreturn]] attribute was added as a deprecated feature so that translation units which include <stdnoreturn.h> do not get an error on use of [[noreturn]] because the macro expands to _Noreturn. Users can use -Wno-deprecated-attributes to silence the diagnostic. Use of <stdnotreturn.h> or the noreturn macro were both deprecated. Users can define the _CLANG_DISABLE_CRT_DEPRECATION_WARNINGS macro to suppress the deprecation diagnostics coming from the header file.
1 parent 6398903 commit 5029dce

File tree

7 files changed

+97
-3
lines changed

7 files changed

+97
-3
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ Windows Support
9292
C Language Changes in Clang
9393
---------------------------
9494

95+
C2x Feature Support
96+
-------------------
97+
98+
- Implemented `WG14 N2674 The noreturn attribute <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2764.pdf>`_.
99+
95100
C++ Language Changes in Clang
96101
-----------------------------
97102

clang/include/clang/Basic/Attr.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,10 +1209,10 @@ def C11NoReturn : InheritableAttr {
12091209
}
12101210

12111211
def CXX11NoReturn : InheritableAttr {
1212-
let Spellings = [CXX11<"", "noreturn", 200809>];
1212+
let Spellings = [CXX11<"", "noreturn", 200809>,
1213+
C2x<"", "noreturn", 202202>, C2x<"", "_Noreturn", 202202>];
12131214
let Subjects = SubjectList<[Function], ErrorDiag>;
12141215
let Documentation = [CXX11NoReturnDocs];
1215-
let SimpleHandler = 1;
12161216
}
12171217

12181218
// Similar to CUDA, OpenCL attributes do not receive a [[]] spelling because

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4027,6 +4027,9 @@ def warn_vector_mode_deprecated : Warning<
40274027
"specifying vector types with the 'mode' attribute is deprecated; "
40284028
"use the 'vector_size' attribute instead">,
40294029
InGroup<DeprecatedAttributes>;
4030+
def warn_deprecated_noreturn_spelling : Warning<
4031+
"the '[[_Noreturn]]' attribute spelling is deprecated in C2x; use "
4032+
"'[[noreturn]]' instead">, InGroup<DeprecatedAttributes>;
40304033
def err_complex_mode_vector_type : Error<
40314034
"type of machine mode does not support base vector types">;
40324035
def err_enum_mode_vector_type : Error<

clang/lib/Headers/stdnoreturn.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,13 @@
1313
#define noreturn _Noreturn
1414
#define __noreturn_is_defined 1
1515

16+
#if __STDC_VERSION__ > 201710L && \
17+
!defined(_CLANG_DISABLE_CRT_DEPRECATION_WARNINGS)
18+
/* The noreturn macro is deprecated in C2x. */
19+
#pragma clang deprecated(noreturn)
20+
21+
/* Including the header file in C2x is also deprecated. */
22+
#warning "the '<stdnoreturn.h>' header is deprecated in C2x"
23+
#endif
24+
1625
#endif /* __STDNORETURN_H */

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2175,6 +2175,16 @@ static void handleNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &Attrs) {
21752175
D->addAttr(::new (S.Context) NoReturnAttr(S.Context, Attrs));
21762176
}
21772177

2178+
static void handleStandardNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &A) {
2179+
// The [[_Noreturn]] spelling is deprecated in C2x, so if that was used,
2180+
// issue an appropriate diagnostic.
2181+
if (!S.getLangOpts().CPlusPlus &&
2182+
A.getSemanticSpelling() == CXX11NoReturnAttr::C2x_Noreturn)
2183+
S.Diag(A.getLoc(), diag::warn_deprecated_noreturn_spelling) << A.getRange();
2184+
2185+
D->addAttr(::new (S.Context) CXX11NoReturnAttr(S.Context, A));
2186+
}
2187+
21782188
static void handleNoCfCheckAttr(Sema &S, Decl *D, const ParsedAttr &Attrs) {
21792189
if (!S.getLangOpts().CFProtectionBranch)
21802190
S.Diag(Attrs.getLoc(), diag::warn_nocf_check_attribute_ignored);
@@ -8432,6 +8442,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
84328442
case ParsedAttr::AT_NoReturn:
84338443
handleNoReturnAttr(S, D, AL);
84348444
break;
8445+
case ParsedAttr::AT_CXX11NoReturn:
8446+
handleStandardNoReturnAttr(S, D, AL);
8447+
break;
84358448
case ParsedAttr::AT_AnyX86NoCfCheck:
84368449
handleNoCfCheckAttr(S, D, AL);
84378450
break;

clang/test/AST/ast-dump-lambda.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ template <typename... Ts> void test(Ts... a) {
305305
// CHECK-NEXT: | | `-Destructor simple irrelevant trivial needs_implicit
306306
// CHECK-NEXT: | |-CXXMethodDecl {{.*}} <col:20, col:23> col:3{{( imported)?}} operator() 'auto () const' inline
307307
// CHECK-NEXT: | | |-CompoundStmt {{.*}} <col:22, col:23>
308-
// CHECK-NEXT: | | `-CXX11NoReturnAttr {{.*}} <col:8>
308+
// CHECK-NEXT: | | `-CXX11NoReturnAttr {{.*}} <col:8> noreturn
309309
// CHECK-NEXT: | |-CXXConversionDecl {{.*}} <col:3, col:23> col:3{{( imported)?}} implicit constexpr operator auto (*)() 'auto (*() const noexcept)()' inline
310310
// CHECK-NEXT: | `-CXXMethodDecl {{.*}} <col:3, col:23> col:3{{( imported)?}} implicit __invoke 'auto ()' static inline
311311
// CHECK-NEXT: `-CompoundStmt {{.*}} <col:22, col:23>

clang/test/Sema/c2x-noreturn.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// RUN: %clang_cc1 -verify=all,c2x -std=c2x -fsyntax-only %s
2+
// RUN: %clang_cc1 -verify=all -std=c17 -fdouble-square-bracket-attributes -fsyntax-only %s
3+
// RUN: %clang_cc1 -verify=none -Wno-deprecated-attributes -D_CLANG_DISABLE_CRT_DEPRECATION_WARNINGS -std=c2x -fsyntax-only %s
4+
// RUN: %clang_cc1 -verify=none -Wno-deprecated-attributes -D_CLANG_DISABLE_CRT_DEPRECATION_WARNINGS -std=c17 -fdouble-square-bracket-attributes -fsyntax-only %s
5+
// none-no-diagnostics
6+
7+
// Test preprocessor functionality.
8+
#if !__has_c_attribute(noreturn)
9+
#error "No noreturn attribute support?"
10+
#endif
11+
12+
#if !__has_c_attribute(_Noreturn)
13+
#error "No _Noreturn attribute support?"
14+
#endif
15+
16+
#if __has_c_attribute(noreturn) != __has_c_attribute(_Noreturn) || \
17+
__has_c_attribute(noreturn) != 202202L
18+
#error "Wrong value for __has_c_attribute(noreturn)"
19+
#endif
20+
21+
// If we're testings with deprecations disabled, we don't care about testing
22+
// the scenarios that trigger errors because we're only interested in the
23+
// deprecation warning behaviors.
24+
#ifndef _CLANG_DISABLE_CRT_DEPRECATION_WARNINGS
25+
// Test that the attribute accepts no args, applies to the correct subject, etc.
26+
[[noreturn(12)]] void func4(void); // all-error {{attribute 'noreturn' cannot have an argument list}}
27+
[[noreturn]] int not_a_func; // all-error {{'noreturn' attribute only applies to functions}}
28+
void func5(void) [[noreturn]]; // all-error {{'noreturn' attribute cannot be applied to types}}
29+
#endif
30+
31+
_Noreturn void func1(void); // ok, using the function specifier
32+
[[noreturn]] void func2(void);
33+
34+
// This is deprecated because it's only for compatibility with inclusion of the
35+
// <stdnoreturn.h> header where the noreturn macro expands to _Noreturn.
36+
[[_Noreturn]] void func3(void); // all-warning {{the '[[_Noreturn]]' attribute spelling is deprecated in C2x; use '[[noreturn]]' instead}}
37+
38+
// Test the behavior of including <stdnoreturn.h>
39+
#include <stdnoreturn.h> // [email protected]:* {{the '<stdnoreturn.h>' header is deprecated in C2x}}
40+
41+
[[noreturn]] void func6(void); // all-warning {{the '[[_Noreturn]]' attribute spelling is deprecated in C2x; use '[[noreturn]]' instead}} \
42+
// c2x-warning {{macro 'noreturn' has been marked as deprecated}} \
43+
// [email protected]:* {{macro marked 'deprecated' here}}
44+
45+
void func7 [[noreturn]] (void); // all-warning {{the '[[_Noreturn]]' attribute spelling is deprecated in C2x; use '[[noreturn]]' instead}} \
46+
// c2x-warning {{macro 'noreturn' has been marked as deprecated}} \
47+
// [email protected]:* {{macro marked 'deprecated' here}}
48+
49+
noreturn void func8(void); // c2x-warning {{macro 'noreturn' has been marked as deprecated}} \
50+
// [email protected]:* {{macro marked 'deprecated' here}}
51+
52+
// Ensure the function specifier form still works
53+
void noreturn func9(void); // c2x-warning {{macro 'noreturn' has been marked as deprecated}} \
54+
// [email protected]:* {{macro marked 'deprecated' here}}
55+
56+
// Test preprocessor functionality after including <stdnoreturn.h>.
57+
#if !__has_c_attribute(noreturn) // c2x-warning {{macro 'noreturn' has been marked as deprecated}} \
58+
// [email protected]:* {{macro marked 'deprecated' here}}
59+
#error "No noreturn attribute support?"
60+
#endif
61+
62+
#if !__has_c_attribute(_Noreturn)
63+
#error "No _Noreturn attribute support?"
64+
#endif

0 commit comments

Comments
 (0)