Author: mitchell
Date: 2026-01-10T12:57:11+08:00
New Revision: 65ba5276e79f774b07fbdd9398236fc2c5965b50

URL: 
https://github.com/llvm/llvm-project/commit/65ba5276e79f774b07fbdd9398236fc2c5965b50
DIFF: 
https://github.com/llvm/llvm-project/commit/65ba5276e79f774b07fbdd9398236fc2c5965b50.diff

LOG: [clang-tidy] Support C++20 constinit in 
bugprone-dynamic-static-initializers (#174744)

Variables marked with `constinit` are guaranteed to be statically
initialized. This patch add support for these.

Added: 
    
clang-tools-extra/test/clang-tidy/checkers/bugprone/dynamic-static-initializers-constinit.hpp

Modified: 
    clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.cpp
    clang-tools-extra/docs/ReleaseNotes.rst
    
clang-tools-extra/test/clang-tidy/checkers/bugprone/dynamic-static-initializers.hpp

Removed: 
    


################################################################################
diff  --git 
a/clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.cpp
index d00c8d0ffb925..d40662ab0e7ad 100644
--- a/clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.cpp
@@ -18,7 +18,10 @@ namespace clang::tidy::bugprone {
 namespace {
 
 AST_MATCHER(clang::VarDecl, hasConstantDeclaration) {
-  if (Node.isConstexpr())
+  if (Node.isConstexpr() || Node.hasAttr<ConstInitAttr>())
+    return true;
+  if (const VarDecl *Def = Node.getDefinition();
+      Def && (Def->isConstexpr() || Def->hasAttr<ConstInitAttr>()))
     return true;
   const Expr *Init = Node.getInit();
   if (Init && !Init->isValueDependent())

diff  --git a/clang-tools-extra/docs/ReleaseNotes.rst 
b/clang-tools-extra/docs/ReleaseNotes.rst
index 76fd1244ea950..d30a7d3549188 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -408,9 +408,12 @@ Changes in existing checks
   expansions.
 
 - Improved :doc:`bugprone-dynamic-static-initializers
-  <clang-tidy/checks/bugprone/dynamic-static-initializers>` check by
-  avoiding false positives for ``constexpr`` variables whose
-  initializers are value-dependent.
+  <clang-tidy/checks/bugprone/dynamic-static-initializers>` check:
+
+  - Avoided false positives for ``constexpr`` variables whose initializers
+    are value-dependent.
+
+  - Added support for C++20 ``constinit`` variables.
 
 - Improved :doc:`bugprone-easily-swappable-parameters
   <clang-tidy/checks/bugprone/easily-swappable-parameters>` check by

diff  --git 
a/clang-tools-extra/test/clang-tidy/checkers/bugprone/dynamic-static-initializers-constinit.hpp
 
b/clang-tools-extra/test/clang-tidy/checkers/bugprone/dynamic-static-initializers-constinit.hpp
new file mode 100644
index 0000000000000..cb7930608f398
--- /dev/null
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/bugprone/dynamic-static-initializers-constinit.hpp
@@ -0,0 +1,59 @@
+// RUN: %check_clang_tidy -std=c++20-or-later %s 
bugprone-dynamic-static-initializers %t -- -- -fno-threadsafe-statics 
-fno-delayed-template-parsing
+
+constexpr int const_func() { return 42; }
+
+constinit int a = const_func(); // no warning
+
+constinit int b = 123; // no warning
+
+struct S {
+  static constinit int c;
+};
+constinit int S::c = const_func(); // no warning
+
+int runtime_func() { return 42; }
+
+int e = runtime_func();
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: static variable 'e' may be 
dynamically initialized in this header file 
[bugprone-dynamic-static-initializers]
+
+template <typename T>
+struct TemplateS {
+  static constinit int x;
+};
+template <typename T>
+constinit int TemplateS<T>::x = const_func(); // no warning
+
+template <typename T>
+void template_func() {
+  static constinit int v = const_func(); // no warning
+}
+
+void call_template_func() {
+  template_func<int>();
+}
+
+template <int V>
+struct Value {
+  static constinit int v;
+};
+template <int V>
+constinit int Value<V>::v = V; // no warning
+
+thread_local constinit int tl = const_func(); // no warning
+
+struct InlineS {
+  static inline constinit int i = 42; // no warning
+};
+
+auto lambda = []() {
+  static constinit int l = const_func(); // no warning
+  return l;
+};
+
+struct Separate {
+  static constinit int s;
+};
+constinit int Separate::s = 100; // no warning
+
+extern int late_constinit;
+constinit int late_constinit = 42; // no warning

diff  --git 
a/clang-tools-extra/test/clang-tidy/checkers/bugprone/dynamic-static-initializers.hpp
 
b/clang-tools-extra/test/clang-tidy/checkers/bugprone/dynamic-static-initializers.hpp
index 7a3211512fd84..e0e8a85571e34 100644
--- 
a/clang-tools-extra/test/clang-tidy/checkers/bugprone/dynamic-static-initializers.hpp
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/bugprone/dynamic-static-initializers.hpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s bugprone-dynamic-static-initializers %t -- -- 
-fno-threadsafe-statics
+// RUN: %check_clang_tidy %s bugprone-dynamic-static-initializers %t -- -- 
-fno-threadsafe-statics -fno-delayed-template-parsing
 
 int fact(int n) {
   return (n == 0) ? 1 : n * fact(n - 1);
@@ -63,3 +63,6 @@ struct TemplateStruct {
 
 template <typename T>
 constexpr T kGlobalMin{std::numeric_limits<T>::min()}; // no warning
+
+extern const int late_constexpr;
+constexpr int late_constexpr = 42; // no warning


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to