diff --git a/clang/lib/Headers/stdnoreturn.h b/clang/lib/Headers/stdnoreturn.h index 92fd4a98a87bf..944e6904c7df6 100644 --- a/clang/lib/Headers/stdnoreturn.h +++ b/clang/lib/Headers/stdnoreturn.h @@ -15,11 +15,13 @@ #if __STDC_VERSION__ > 201710L && \ !defined(_CLANG_DISABLE_CRT_DEPRECATION_WARNINGS) -/* The noreturn macro is deprecated in C2x. */ -#pragma clang deprecated(noreturn) - -/* Including the header file in C2x is also deprecated. */ -#warning "the '' header is deprecated in C2x" +/* The noreturn macro is deprecated in C2x. We do not mark it as such because + including the header file in C2x is also deprecated and we do not want to + issue a confusing diagnostic for code which includes + followed by code that writes [[noreturn]]. The issue with such code is not + with the attribute, or the use of 'noreturn', but the inclusion of the + header. */ +#warning "the '' header is deprecated in C2x; either use the '_Noreturn' keyword or the '[[noreturn]]' attribute" #endif #endif /* __STDNORETURN_H */ diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 6d0c8f0974767..3034abdf04028 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -2177,9 +2177,14 @@ static void handleNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &Attrs) { static void handleStandardNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &A) { // The [[_Noreturn]] spelling is deprecated in C2x, so if that was used, - // issue an appropriate diagnostic. + // issue an appropriate diagnostic. However, don't issue a diagnostic if the + // attribute name comes from a macro expansion. We don't want to punish users + // who write [[noreturn]] after including (where 'noreturn' + // is defined as a macro which expands to '_Noreturn'). if (!S.getLangOpts().CPlusPlus && - A.getSemanticSpelling() == CXX11NoReturnAttr::C2x_Noreturn) + A.getSemanticSpelling() == CXX11NoReturnAttr::C2x_Noreturn && + !(A.getLoc().isMacroID() && + S.getSourceManager().isInSystemMacro(A.getLoc()))) S.Diag(A.getLoc(), diag::warn_deprecated_noreturn_spelling) << A.getRange(); D->addAttr(::new (S.Context) CXX11NoReturnAttr(S.Context, A)); diff --git a/clang/test/Sema/c2x-noreturn.c b/clang/test/Sema/c2x-noreturn.c index e522a43cf6eba..6c119736f6454 100644 --- a/clang/test/Sema/c2x-noreturn.c +++ b/clang/test/Sema/c2x-noreturn.c @@ -36,29 +36,30 @@ _Noreturn void func1(void); // ok, using the function specifier [[_Noreturn]] void func3(void); // all-warning {{the '[[_Noreturn]]' attribute spelling is deprecated in C2x; use '[[noreturn]]' instead}} // Test the behavior of including -#include // c2x-warning@stdnoreturn.h:* {{the '' header is deprecated in C2x}} +#include // c2x-warning@stdnoreturn.h:* {{the '' header is deprecated in C2x; either use the '_Noreturn' keyword or the '[[noreturn]]' attribute}} -[[noreturn]] void func6(void); // all-warning {{the '[[_Noreturn]]' attribute spelling is deprecated in C2x; use '[[noreturn]]' instead}} \ - // c2x-warning {{macro 'noreturn' has been marked as deprecated}} \ - // c2x-note@stdnoreturn.h:* {{macro marked 'deprecated' here}} +[[noreturn]] void func6(void); -void func7 [[noreturn]] (void); // all-warning {{the '[[_Noreturn]]' attribute spelling is deprecated in C2x; use '[[noreturn]]' instead}} \ - // c2x-warning {{macro 'noreturn' has been marked as deprecated}} \ - // c2x-note@stdnoreturn.h:* {{macro marked 'deprecated' here}} +void func7 [[noreturn]] (void); -noreturn void func8(void); // c2x-warning {{macro 'noreturn' has been marked as deprecated}} \ - // c2x-note@stdnoreturn.h:* {{macro marked 'deprecated' here}} +noreturn void func8(void); -// Ensure the function specifier form still works -void noreturn func9(void); // c2x-warning {{macro 'noreturn' has been marked as deprecated}} \ - // c2x-note@stdnoreturn.h:* {{macro marked 'deprecated' here}} +// Ensure the function specifier form still works. +void noreturn func9(void); + +// Ensure that spelling the deprecated form of the attribute is still diagnosed. +[[_Noreturn]] void func10(void); // all-warning {{the '[[_Noreturn]]' attribute spelling is deprecated in C2x; use '[[noreturn]]' instead}} // Test preprocessor functionality after including . -#if !__has_c_attribute(noreturn) // c2x-warning {{macro 'noreturn' has been marked as deprecated}} \ - // c2x-note@stdnoreturn.h:* {{macro marked 'deprecated' here}} +#if !__has_c_attribute(noreturn) #error "No noreturn attribute support?" #endif #if !__has_c_attribute(_Noreturn) #error "No _Noreturn attribute support?" #endif + +// Test that a macro which expands to _Noreturn is still diagnosed when it +// doesn't come from a system header. +#define NORETURN _Noreturn +[[NORETURN]] void func11(void); // all-warning {{the '[[_Noreturn]]' attribute spelling is deprecated in C2x; use '[[noreturn]]' instead}}