https://github.com/localspook updated https://github.com/llvm/llvm-project/pull/148334
>From e6b9c9ab548986d26fe24a91ab360e7c0363817d Mon Sep 17 00:00:00 2001 From: Victor Chernyakin <chernyakin.victo...@outlook.com> Date: Fri, 11 Jul 2025 21:09:22 -0700 Subject: [PATCH 1/2] [clang-tidy] Teach `cppcoreguidelines-interfaces-global-init` about `constinit` --- .../InterfacesGlobalInitCheck.cpp | 2 +- clang-tools-extra/docs/ReleaseNotes.rst | 4 +++ .../interfaces-global-init.cpp | 28 +++++++++++++++++-- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.cpp index e8a2e7b8ef86d..e9f0bd98cad16 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.cpp @@ -19,7 +19,7 @@ void InterfacesGlobalInitCheck::registerMatchers(MatchFinder *Finder) { hasDeclContext(anyOf(translationUnitDecl(), // Global scope. namespaceDecl(), // Namespace scope. recordDecl())), // Class scope. - unless(isConstexpr())); + unless(isConstexpr()), unless(isConstinit())); const auto ReferencesUndefinedGlobalVar = declRefExpr(hasDeclaration( varDecl(GlobalVarDecl, unless(isDefinition())).bind("referencee"))); diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index ad869265a2db5..bff7cfa4fe525 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -212,6 +212,10 @@ Changes in existing checks <clang-tidy/checks/cppcoreguidelines/avoid-goto>` check by adding the option `IgnoreMacros` to ignore ``goto`` labels defined in macros. +- Improved :doc:`cppcoreguidelines-interfaces-global-init + <clang-tidy/checks/cppcoreguidelines/interfaces-global-init>` check by + fixing false positives on uses of ``constinit`` variables. + - Improved :doc:`cppcoreguidelines-missing-std-forward <clang-tidy/checks/cppcoreguidelines/missing-std-forward>` check by adding a flag to specify the function used for forwarding instead of ``std::forward``. diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/interfaces-global-init.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/interfaces-global-init.cpp index 51f79e522c0ca..38d02c6a7f186 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/interfaces-global-init.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/interfaces-global-init.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy %s cppcoreguidelines-interfaces-global-init %t +// RUN: %check_clang_tidy -std=c++20 %s cppcoreguidelines-interfaces-global-init %t constexpr int makesInt() { return 3; } constexpr int takesInt(int i) { return i + 1; } @@ -14,11 +14,19 @@ static int GlobalScopeBadInit3 = takesIntPtr(&ExternGlobal); static int GlobalScopeBadInit4 = 3 * (ExternGlobal + 2); // CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal' +extern constinit int ExternConstinitGlobal; +static int GlobalScopeConstinit1 = ExternConstinitGlobal; +static int GlobalScopeConstinit2 = takesInt(ExternConstinitGlobal); +static int GlobalScopeConstinit3 = takesIntPtr(&ExternConstinitGlobal); +static int GlobalScopeConstinit4 = 3 * (ExternConstinitGlobal + 2); + namespace ns { static int NamespaceScope = makesInt(); static int NamespaceScopeBadInit = takesInt(ExternGlobal); // CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal' +static int NamespaceScopeConstinit = takesInt(ExternConstinitGlobal); + struct A { static int ClassScope; static int ClassScopeBadInit; @@ -29,6 +37,15 @@ int A::ClassScopeBadInit = takesInt(ExternGlobal); static int FromClassBadInit = takesInt(A::ClassScope); // CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ClassScope' + +struct B { + static constinit int ClassScopeConstinit; + static int ClassScopeFromConstinit; +}; + +int B::ClassScopeFromConstinit = takesInt(ExternConstinitGlobal); +static int FromClassScopeConstinit = takesInt(B::ClassScopeConstinit); + } // namespace ns // "const int B::I;" is fine, it just ODR-defines B::I. See [9.4.3] Static @@ -42,6 +59,14 @@ const int B1::J; // CHECK-MESSAGES: [[@LINE-1]]:15: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'I' const int B1::I; +class D { + static const constinit int I = 0; + static const int J = I; +}; + +const int D::J; +const int D::I; + void f() { // This is fine, it's executed after dynamic initialization occurs. static int G = takesInt(ExternGlobal); @@ -81,4 +106,3 @@ class B2 { }; const int B2::I; const int B2::J; - >From 2a30a82c553b7ece9fc005a98c58187a0333b9a8 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin <chernyakin.victo...@outlook.com> Date: Fri, 11 Jul 2025 23:09:05 -0700 Subject: [PATCH 2/2] Reenable for all modes --- .../cppcoreguidelines/interfaces-global-init.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/interfaces-global-init.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/interfaces-global-init.cpp index 38d02c6a7f186..8ce42994e1172 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/interfaces-global-init.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/interfaces-global-init.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy -std=c++20 %s cppcoreguidelines-interfaces-global-init %t +// RUN: %check_clang_tidy %s cppcoreguidelines-interfaces-global-init %t constexpr int makesInt() { return 3; } constexpr int takesInt(int i) { return i + 1; } @@ -14,18 +14,22 @@ static int GlobalScopeBadInit3 = takesIntPtr(&ExternGlobal); static int GlobalScopeBadInit4 = 3 * (ExternGlobal + 2); // CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal' +#if __cplusplus >= 202002L extern constinit int ExternConstinitGlobal; static int GlobalScopeConstinit1 = ExternConstinitGlobal; static int GlobalScopeConstinit2 = takesInt(ExternConstinitGlobal); static int GlobalScopeConstinit3 = takesIntPtr(&ExternConstinitGlobal); static int GlobalScopeConstinit4 = 3 * (ExternConstinitGlobal + 2); +#endif namespace ns { static int NamespaceScope = makesInt(); static int NamespaceScopeBadInit = takesInt(ExternGlobal); // CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal' +#if __cplusplus >= 202002L static int NamespaceScopeConstinit = takesInt(ExternConstinitGlobal); +#endif struct A { static int ClassScope; @@ -38,6 +42,7 @@ int A::ClassScopeBadInit = takesInt(ExternGlobal); static int FromClassBadInit = takesInt(A::ClassScope); // CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ClassScope' +#if __cplusplus >= 202002L struct B { static constinit int ClassScopeConstinit; static int ClassScopeFromConstinit; @@ -45,6 +50,7 @@ struct B { int B::ClassScopeFromConstinit = takesInt(ExternConstinitGlobal); static int FromClassScopeConstinit = takesInt(B::ClassScopeConstinit); +#endif } // namespace ns @@ -59,6 +65,7 @@ const int B1::J; // CHECK-MESSAGES: [[@LINE-1]]:15: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'I' const int B1::I; +#if __cplusplus >= 202002L class D { static const constinit int I = 0; static const int J = I; @@ -66,6 +73,7 @@ class D { const int D::J; const int D::I; +#endif void f() { // This is fine, it's executed after dynamic initialization occurs. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits