[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