Skip to content

Commit 92ef8e3

Browse files
authored
[clang-tidy] Teach cppcoreguidelines-interfaces-global-init about constinit (#148334)
This check already understands how `constexpr` makes initialization order problems impossible, and C++20's `constinit` provides the exact same guarantees.
1 parent 2464313 commit 92ef8e3

File tree

3 files changed

+38
-2
lines changed

3 files changed

+38
-2
lines changed

clang-tools-extra/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ void InterfacesGlobalInitCheck::registerMatchers(MatchFinder *Finder) {
1919
hasDeclContext(anyOf(translationUnitDecl(), // Global scope.
2020
namespaceDecl(), // Namespace scope.
2121
recordDecl())), // Class scope.
22-
unless(isConstexpr()));
22+
unless(isConstexpr()), unless(isConstinit()));
2323

2424
const auto ReferencesUndefinedGlobalVar = declRefExpr(hasDeclaration(
2525
varDecl(GlobalVarDecl, unless(isDefinition())).bind("referencee")));

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,10 @@ Changes in existing checks
232232
<clang-tidy/checks/cppcoreguidelines/avoid-goto>` check by adding the option
233233
`IgnoreMacros` to ignore ``goto`` labels defined in macros.
234234

235+
- Improved :doc:`cppcoreguidelines-interfaces-global-init
236+
<clang-tidy/checks/cppcoreguidelines/interfaces-global-init>` check by
237+
fixing false positives on uses of ``constinit`` variables.
238+
235239
- Improved :doc:`cppcoreguidelines-missing-std-forward
236240
<clang-tidy/checks/cppcoreguidelines/missing-std-forward>` check by adding a
237241
flag to specify the function used for forwarding instead of ``std::forward``.

clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/interfaces-global-init.cpp

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,23 @@ static int GlobalScopeBadInit3 = takesIntPtr(&ExternGlobal);
1414
static int GlobalScopeBadInit4 = 3 * (ExternGlobal + 2);
1515
// CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal'
1616

17+
#if __cplusplus >= 202002L
18+
extern constinit int ExternConstinitGlobal;
19+
static int GlobalScopeConstinit1 = ExternConstinitGlobal;
20+
static int GlobalScopeConstinit2 = takesInt(ExternConstinitGlobal);
21+
static int GlobalScopeConstinit3 = takesIntPtr(&ExternConstinitGlobal);
22+
static int GlobalScopeConstinit4 = 3 * (ExternConstinitGlobal + 2);
23+
#endif
24+
1725
namespace ns {
1826
static int NamespaceScope = makesInt();
1927
static int NamespaceScopeBadInit = takesInt(ExternGlobal);
2028
// CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal'
2129

30+
#if __cplusplus >= 202002L
31+
static int NamespaceScopeConstinit = takesInt(ExternConstinitGlobal);
32+
#endif
33+
2234
struct A {
2335
static int ClassScope;
2436
static int ClassScopeBadInit;
@@ -29,6 +41,17 @@ int A::ClassScopeBadInit = takesInt(ExternGlobal);
2941

3042
static int FromClassBadInit = takesInt(A::ClassScope);
3143
// CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ClassScope'
44+
45+
#if __cplusplus >= 202002L
46+
struct B {
47+
static constinit int ClassScopeConstinit;
48+
static int ClassScopeFromConstinit;
49+
};
50+
51+
int B::ClassScopeFromConstinit = takesInt(ExternConstinitGlobal);
52+
static int FromClassScopeConstinit = takesInt(B::ClassScopeConstinit);
53+
#endif
54+
3255
} // namespace ns
3356

3457
// "const int B::I;" is fine, it just ODR-defines B::I. See [9.4.3] Static
@@ -42,6 +65,16 @@ const int B1::J;
4265
// CHECK-MESSAGES: [[@LINE-1]]:15: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'I'
4366
const int B1::I;
4467

68+
#if __cplusplus >= 202002L
69+
class D {
70+
static const constinit int I = 0;
71+
static const int J = I;
72+
};
73+
74+
const int D::J;
75+
const int D::I;
76+
#endif
77+
4578
void f() {
4679
// This is fine, it's executed after dynamic initialization occurs.
4780
static int G = takesInt(ExternGlobal);
@@ -81,4 +114,3 @@ class B2 {
81114
};
82115
const int B2::I;
83116
const int B2::J;
84-

0 commit comments

Comments
 (0)