[libcxx-commits] [libcxx] [clang-tools-extra]: Check for static in constexpr (PR #175814)

Prabhu Rajasekaran via libcxx-commits libcxx-commits at lists.llvm.org
Tue Jan 13 21:12:16 PST 2026


https://github.com/Prabhuk updated https://github.com/llvm/llvm-project/pull/175814

>From d5f622c8862da9ce61bb6de2a881dc0ed1610b7b Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Wed, 14 Jan 2026 04:30:16 +0000
Subject: [PATCH] [libc++] Add libcpp-static-in-constexpr clang-tidy check

---
 .../tools/clang_tidy_checks/CMakeLists.txt    |  1 +
 .../tools/clang_tidy_checks/libcpp_module.cpp |  2 +
 .../clang_tidy_checks/static-in-constexpr.cpp | 40 ++++++++++++++++++
 .../clang_tidy_checks/static_in_constexpr.cpp | 42 +++++++++++++++++++
 .../clang_tidy_checks/static_in_constexpr.hpp | 26 ++++++++++++
 5 files changed, 111 insertions(+)
 create mode 100644 libcxx/test/tools/clang_tidy_checks/static-in-constexpr.cpp
 create mode 100644 libcxx/test/tools/clang_tidy_checks/static_in_constexpr.cpp
 create mode 100644 libcxx/test/tools/clang_tidy_checks/static_in_constexpr.hpp

diff --git a/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt b/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt
index 521a60c0fc498..34078cf9b5ecd 100644
--- a/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt
+++ b/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt
@@ -97,6 +97,7 @@ set(SOURCES
     proper_version_checks.cpp
     robust_against_adl.cpp
     robust_against_operator_ampersand.cpp
+    static_in_constexpr.cpp
     uglify_attributes.cpp
 
     libcpp_module.cpp
diff --git a/libcxx/test/tools/clang_tidy_checks/libcpp_module.cpp b/libcxx/test/tools/clang_tidy_checks/libcpp_module.cpp
index 2cf39e2b626f8..53e0092ec0375 100644
--- a/libcxx/test/tools/clang_tidy_checks/libcpp_module.cpp
+++ b/libcxx/test/tools/clang_tidy_checks/libcpp_module.cpp
@@ -17,6 +17,7 @@
 #include "proper_version_checks.hpp"
 #include "robust_against_adl.hpp"
 #include "robust_against_operator_ampersand.hpp"
+#include "static_in_constexpr.hpp"
 #include "uglify_attributes.hpp"
 
 namespace {
@@ -32,6 +33,7 @@ class LibcxxTestModule : public clang::tidy::ClangTidyModule {
     check_factories.registerCheck<libcpp::robust_against_adl_check>("libcpp-robust-against-adl");
     check_factories.registerCheck<libcpp::robust_against_operator_ampersand>(
         "libcpp-robust-against-operator-ampersand");
+    check_factories.registerCheck<libcpp::static_in_constexpr>("libcpp-static-in-constexpr");
     check_factories.registerCheck<libcpp::uglify_attributes>("libcpp-uglify-attributes");
   }
 };
diff --git a/libcxx/test/tools/clang_tidy_checks/static-in-constexpr.cpp b/libcxx/test/tools/clang_tidy_checks/static-in-constexpr.cpp
new file mode 100644
index 0000000000000..4c98fb3116cdc
--- /dev/null
+++ b/libcxx/test/tools/clang_tidy_checks/static-in-constexpr.cpp
@@ -0,0 +1,40 @@
+// RUN: %{clang-tidy} %s -checks='-*,libcpp-static-in-constexpr' -- | FileCheck %s
+
+void normal_func() {
+  static int x = 0;
+  thread_local int y = 0;
+}
+
+constexpr void constexpr_func() {
+  static constexpr int x = 0;
+  // CHECK: :[[@LINE-1]]:24: warning: variable of static or thread storage duration inside constexpr function [libcpp-static-in-constexpr]
+  
+  thread_local int y = 0;
+  // CHECK: :[[@LINE-1]]:20: warning: variable of static or thread storage duration inside constexpr function [libcpp-static-in-constexpr]
+}
+
+consteval void consteval_func() {
+  static constexpr int x = 0;
+  // CHECK: :[[@LINE-1]]:24: warning: variable of static or thread storage duration inside constexpr function [libcpp-static-in-constexpr]
+}
+
+constexpr void constexpr_with_lambda() {
+  auto l = []() {
+    static constexpr int x = 0;
+    // CHECK: :[[@LINE-1]]:26: warning: variable of static or thread storage duration inside constexpr function [libcpp-static-in-constexpr]
+  };
+}
+
+constexpr void constexpr_with_constexpr_lambda() {
+  auto l = []() constexpr {
+    static constexpr int x = 0;
+    // CHECK: :[[@LINE-1]]:26: warning: variable of static or thread storage duration inside constexpr function [libcpp-static-in-constexpr]
+  };
+}
+
+struct S {
+    static constexpr void static_member_func() {
+        static constexpr int x = 0;
+        // CHECK: :[[@LINE-1]]:30: warning: variable of static or thread storage duration inside constexpr function [libcpp-static-in-constexpr]
+    }
+};
\ No newline at end of file
diff --git a/libcxx/test/tools/clang_tidy_checks/static_in_constexpr.cpp b/libcxx/test/tools/clang_tidy_checks/static_in_constexpr.cpp
new file mode 100644
index 0000000000000..a9fa35d62a53e
--- /dev/null
+++ b/libcxx/test/tools/clang_tidy_checks/static_in_constexpr.cpp
@@ -0,0 +1,42 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "static_in_constexpr.hpp"
+#include "clang/AST/Decl.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace libcpp {
+
+void static_in_constexpr::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(varDecl(isStaticLocal()).bind("var"), this);
+}
+
+void static_in_constexpr::check(const MatchFinder::MatchResult &Result) {
+  const auto *Var = Result.Nodes.getNodeAs<clang::VarDecl>("var");
+  if (!Var)
+      return;
+
+  const clang::DeclContext *DC = Var->getDeclContext();
+
+  while (DC && !DC->isFunctionOrMethod())
+    DC = DC->getParent();
+
+  const auto *FD = llvm::dyn_cast_or_null<clang::FunctionDecl>(DC);
+  if (!FD)
+    return;
+
+  if (FD->isConstexpr()) {
+    diag(Var->getLocation(),
+         "variable of static or thread storage duration inside constexpr "
+         "function");
+  }
+}
+
+} // namespace libcpp
diff --git a/libcxx/test/tools/clang_tidy_checks/static_in_constexpr.hpp b/libcxx/test/tools/clang_tidy_checks/static_in_constexpr.hpp
new file mode 100644
index 0000000000000..23b7bc78274fa
--- /dev/null
+++ b/libcxx/test/tools/clang_tidy_checks/static_in_constexpr.hpp
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LIBCXX_TEST_TOOLS_CLANG_TIDY_CHECKS_STATIC_IN_CONSTEXPR_HPP
+#define LIBCXX_TEST_TOOLS_CLANG_TIDY_CHECKS_STATIC_IN_CONSTEXPR_HPP
+
+#include "clang-tidy/ClangTidyCheck.h"
+
+namespace libcpp {
+
+class static_in_constexpr : public clang::tidy::ClangTidyCheck {
+public:
+  static_in_constexpr(llvm::StringRef name, clang::tidy::ClangTidyContext* context)
+      : clang::tidy::ClangTidyCheck(name, context) {}
+  void registerMatchers(clang::ast_matchers::MatchFinder* finder) override;
+  void check(const clang::ast_matchers::MatchFinder::MatchResult& result) override;
+};
+
+} // namespace libcpp
+
+#endif // LIBCXX_TEST_TOOLS_CLANG_TIDY_CHECKS_STATIC_IN_CONSTEXPR_HPP
\ No newline at end of file



More information about the libcxx-commits mailing list