-
Notifications
You must be signed in to change notification settings - Fork 14.5k
[clang-tidy] Teach cppcoreguidelines-interfaces-global-init
about constinit
#148334
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clang-tidy @llvm/pr-subscribers-clang-tools-extra Author: Victor Chernyakin (localspook) ChangesThis check already understands how Full diff: https://github.com/llvm/llvm-project/pull/148334.diff 3 Files Affected:
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;
-
|
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/interfaces-global-init.cpp
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
This check already understands how
constexpr
makes initialization order problems impossible, and C++20'sconstinit
provides the exact same guarantees.