Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/DiagnosticGroups.td
Original file line number Diff line number Diff line change
Expand Up @@ -1401,7 +1401,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", [StaticInInline]>;
def C2y : DiagGroup<"c2y-extensions", [StaticInInline, StaticLocalInInline]>;

// 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.
Expand Down
10 changes: 7 additions & 3 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -6339,9 +6339,13 @@ 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<CPre2yCompat>, DefaultIgnore;
def warn_static_local_in_extern_inline : Warning<
"non-constant static local variable in inline function may be different "
"in different files">, InGroup<StaticLocalInInline>;
def ext_static_local_in_extern_inline : ExtWarn<
"non-constant static local variable in an inline function with "
"external linkage is a C2y extension">, InGroup<StaticLocalInInline>;
def warn_c2y_compat_static_local_in_extern_inline : Warning<
"non-constant static local variable in an inline function with "
"external linkage is incompatible with standards before C2y">,
InGroup<CPre2yCompat>, DefaultIgnore;
def note_convert_inline_to_static : Note<
"use 'static' to give inline function %0 internal linkage">;

Expand Down
14 changes: 12 additions & 2 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8111,6 +8111,11 @@ NamedDecl *Sema::ActOnVariableDeclarator(
// An inline definition of a function with external linkage shall
// not contain a definition of a modifiable object with static or
// thread storage duration...
//
// 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.
Comment on lines +8116 to +8118
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary comment? We should issue "incompatible" diagnostic for all features.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do see your point. However, I wanted to ensure it was as consistent as possible with the linked commit.

// We only apply this when the function is required to be defined
// elsewhere, i.e. when the function is not 'extern inline'. Note
// that a local variable with thread storage duration still has to
Expand All @@ -8120,8 +8125,13 @@ NamedDecl *Sema::ActOnVariableDeclarator(
!NewVD->getType().isConstQualified()) {
FunctionDecl *CurFD = getCurFunctionDecl();
if (CurFD && isFunctionDefinitionDiscarded(*this, CurFD)) {
Diag(D.getDeclSpec().getStorageClassSpecLoc(),
diag::warn_static_local_in_extern_inline);
unsigned DiagID;
if (getLangOpts().C2y)
DiagID = diag::warn_c2y_compat_static_local_in_extern_inline;
else
DiagID = diag::ext_static_local_in_extern_inline;

Diag(D.getDeclSpec().getStorageClassSpecLoc(), DiagID);
MaybeSuggestAddingStaticToDecl(CurFD);
}
}
Expand Down
25 changes: 25 additions & 0 deletions clang/test/C/C2y/n3622_1.c
Original file line number Diff line number Diff line change
@@ -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 static local variables in extern inline functions
*
* This verifies that a constraint from previous standards is no longer
* triggered in C2y mode. The constraint is regarding static local
* variables in inline functions with external linkage.
*/

inline void func1(void) { // expected-note {{use 'static' to give inline function 'func1' internal linkage}}
static int x = 0; /* ped-warning {{non-constant static local variable in an inline function with external linkage is a C2y extension}}
compat-warning {{non-constant static local variable in an inline function with external linkage is incompatible with standards before C2y}}
*/
(void)x;
}

inline void func2(void) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this test used for?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first test is to ensure that the new C2y feature works with the specified diagnostics. The second test is to ensure that no false positives have popped up during the process.

static const int x = 0;
(void)x;
}
4 changes: 2 additions & 2 deletions clang/test/Sema/inline.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ inline int useStaticAgain (void) { // expected-note 2 {{use 'static' to give inl

#pragma clang diagnostic pop

inline void defineStaticVar(void) { // expected-note {{use 'static' to give inline function 'defineStaticVar' internal linkage}}
inline void defineStaticVar(void) { // ok (no -pedantic)
static const int x = 0; // ok
static int y = 0; // expected-warning {{non-constant static local variable in inline function may be different in different files}}
static int y = 0; // ok (no -pedantic)
}

extern inline void defineStaticVarInExtern(void) {
Expand Down