diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 99aa545831240..65b086caf3652 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -180,6 +180,9 @@ C Language Changes C2y Feature Support ^^^^^^^^^^^^^^^^^^^ +- No longer triggering ``-Wstatic-in-inline`` in C2y mode; use of a static + function or variable within an extern inline function is no longer a + constraint per `WG14 N3622 `_. - Clang now supports `N3355 `_ Named Loops. C23 Feature Support diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 4b27a42c6dd81..ef3f59f4f2263 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -1400,7 +1400,7 @@ def C23 : DiagGroup<"c23-extensions", [VariadicMacroArgumentsOmitted]>; def : DiagGroup<"c2x-extensions", [C23]>; // A warning group for warnings about using C2y features as extensions. -def C2y : DiagGroup<"c2y-extensions">; +def C2y : DiagGroup<"c2y-extensions", [StaticInInline]>; // Previously supported warning group which is no longer pertinent as binary // literals are a C++14 and C23 extension now instead of a GNU extension. diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 5be63c027cba7..3df28f2ef3334 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -6326,11 +6326,14 @@ def warn_internal_linkage_local_storage : Warning< InGroup; def ext_internal_in_extern_inline : ExtWarn< - "static %select{function|variable}0 %1 is used in an inline function with " - "external linkage">, InGroup; + "using static %select{function|variable}0 %1 in an inline function with " + "external linkage is a C2y extension">, InGroup; def ext_internal_in_extern_inline_quiet : Extension< - "static %select{function|variable}0 %1 is used in an inline function with " - "external linkage">, InGroup; + ext_internal_in_extern_inline.Summary>, InGroup; +def warn_c2y_compat_internal_in_extern_inline : Warning< + "using static %select{function|variable}0 %1 in an inline function with " + "external linkage is incompatible with standards before C2y">, + InGroup, DefaultIgnore; def warn_static_local_in_extern_inline : Warning< "non-constant static local variable in inline function may be different " "in different files">, InGroup; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 4230ea702e128..01abc1fb2cd37 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -166,6 +166,11 @@ static void diagnoseUseOfInternalDeclInInlineFunction(Sema &S, // This is disabled under C++; there are too many ways for this to fire in // contexts where the warning is a false positive, or where it is technically // correct but benign. + // + // WG14 N3622 which removed the constraint entirely in C2y. It is left + // enabled in earlier language modes because this is a constraint in those + // language modes. But in C2y mode, we still want to issue the "incompatible + // with previous standards" diagnostic, too. if (S.getLangOpts().CPlusPlus) return; @@ -190,16 +195,17 @@ static void diagnoseUseOfInternalDeclInInlineFunction(Sema &S, // This last can give us false negatives, but it's better than warning on // wrappers for simple C library functions. const FunctionDecl *UsedFn = dyn_cast(D); - bool DowngradeWarning = S.getSourceManager().isInMainFile(Loc); - if (!DowngradeWarning && UsedFn) - DowngradeWarning = UsedFn->isInlined() || UsedFn->hasAttr(); - - S.Diag(Loc, DowngradeWarning ? diag::ext_internal_in_extern_inline_quiet - : diag::ext_internal_in_extern_inline) - << /*IsVar=*/!UsedFn << D; + unsigned DiagID; + if (S.getLangOpts().C2y) + DiagID = diag::warn_c2y_compat_internal_in_extern_inline; + else if ((UsedFn && (UsedFn->isInlined() || UsedFn->hasAttr())) || + S.getSourceManager().isInMainFile(Loc)) + DiagID = diag::ext_internal_in_extern_inline_quiet; + else + DiagID = diag::ext_internal_in_extern_inline; + S.Diag(Loc, DiagID) << /*IsVar=*/!UsedFn << D; S.MaybeSuggestAddingStaticToDecl(Current); - S.Diag(D->getCanonicalDecl()->getLocation(), diag::note_entity_declared_at) << D; } diff --git a/clang/test/C/C2y/n3622.c b/clang/test/C/C2y/n3622.c new file mode 100644 index 0000000000000..95b92e8f235a8 --- /dev/null +++ b/clang/test/C/C2y/n3622.c @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -verify=good -pedantic -Wall -std=c2y %s +// RUN: %clang_cc1 -verify=compat,expected -pedantic -Wall -Wpre-c2y-compat -std=c2y %s +// RUN: %clang_cc1 -verify=ped,expected -pedantic -Wall -std=c23 %s +// RUN: %clang_cc1 -verify=ped,expected -pedantic -Wall -std=c17 %s +// good-no-diagnostics + +/* WG14 N3622: Clang 22 + * Allow calling static inline within extern inline + * + * This verifies that a constraint from previous standards is no longer + * triggered in C2y mode. The constraint is with calling a static function + * or using a static variable from an inline function with external linkage. + */ + +static void static_func(void) {} // expected-note {{declared here}} +static int static_var; // expected-note {{declared here}} + +extern inline void test(void) { + static_func(); /* ped-warning {{using static function 'static_func' in an inline function with external linkage is a C2y extension}} + compat-warning {{using static function 'static_func' in an inline function with external linkage is incompatible with standards before C2y}} + */ + static_var = 12; /* ped-warning {{using static variable 'static_var' in an inline function with external linkage is a C2y extension}} + compat-warning {{using static variable 'static_var' in an inline function with external linkage is incompatible with standards before C2y}} + */ +} diff --git a/clang/test/Sema/inline.c b/clang/test/Sema/inline.c index 804c51015405e..6361db8496c2d 100644 --- a/clang/test/Sema/inline.c +++ b/clang/test/Sema/inline.c @@ -11,14 +11,14 @@ static int staticFunction(void); // expected-note + {{'staticFunction' declared static struct { int x; } staticStruct; // expected-note + {{'staticStruct' declared here}} inline int useStatic (void) { // expected-note 3 {{use 'static' to give inline function 'useStatic' internal linkage}} - staticFunction(); // expected-warning{{static function 'staticFunction' is used in an inline function with external linkage}} - (void)staticStruct.x; // expected-warning{{static variable 'staticStruct' is used in an inline function with external linkage}} - return staticVar; // expected-warning{{static variable 'staticVar' is used in an inline function with external linkage}} + staticFunction(); // expected-warning{{using static function 'staticFunction' in an inline function with external linkage is a C2y extension}} + (void)staticStruct.x; // expected-warning{{using static variable 'staticStruct' in an inline function with external linkage is a C2y extension}} + return staticVar; // expected-warning{{using static variable 'staticVar' in an inline function with external linkage is a C2y extension}} } extern inline int useStaticFromExtern (void) { // no suggestions - staticFunction(); // expected-warning{{static function 'staticFunction' is used in an inline function with external linkage}} - return staticVar; // expected-warning{{static variable 'staticVar' is used in an inline function with external linkage}} + staticFunction(); // expected-warning{{using static function 'staticFunction' in an inline function with external linkage is a C2y extension}} + return staticVar; // expected-warning{{using static variable 'staticVar' in an inline function with external linkage is a C2y extension}} } static inline int useStaticFromStatic (void) { @@ -67,8 +67,8 @@ inline int useStaticMainFile (void) { #pragma clang diagnostic warning "-Wstatic-in-inline" inline int useStaticAgain (void) { // expected-note 2 {{use 'static' to give inline function 'useStaticAgain' internal linkage}} - staticFunction(); // expected-warning{{static function 'staticFunction' is used in an inline function with external linkage}} - return staticVar; // expected-warning{{static variable 'staticVar' is used in an inline function with external linkage}} + staticFunction(); // expected-warning{{using static function 'staticFunction' in an inline function with external linkage is a C2y extension}} + return staticVar; // expected-warning{{using static variable 'staticVar' in an inline function with external linkage is a C2y extension}} } #pragma clang diagnostic pop @@ -86,8 +86,8 @@ extern inline void defineStaticVarInExtern(void) { // Check behavior of line markers. # 1 "XXX.h" 1 inline int useStaticMainFileInLineMarker(void) { // expected-note 2 {{use 'static' to give inline function 'useStaticMainFileInLineMarker' internal linkage}} - staticFunction(); // expected-warning{{static function 'staticFunction' is used in an inline function with external linkage}} - return staticVar; // expected-warning{{static variable 'staticVar' is used in an inline function with external linkage}} + staticFunction(); // expected-warning{{using static function 'staticFunction' in an inline function with external linkage is a C2y extension}} + return staticVar; // expected-warning{{using static variable 'staticVar' in an inline function with external linkage is a C2y extension}} } # 100 "inline.c" 2 diff --git a/clang/www/c_status.html b/clang/www/c_status.html index a6bcd4c197133..b8039622fe694 100644 --- a/clang/www/c_status.html +++ b/clang/www/c_status.html @@ -349,7 +349,7 @@

C2y implementation status

Allow calling static inline within extern inline N3622 - Unknown + Clang 22 Generic replacement (v. 2 of quasi-literals)