https://github.com/Prabhuk updated https://github.com/llvm/llvm-project/pull/175814
>From dbaa2b79b8251c9a9045b51180c3830b23633395 Mon Sep 17 00:00:00 2001 From: prabhukr <[email protected]> Date: Tue, 13 Jan 2026 19:00:52 +0000 Subject: [PATCH] [clang-tools-extra]: Check for static in constexpr Static variables in constexpr functions create a warning in Clang and is currently an error in GCC. Add a clang tidy check to catch such cases to prevent these cases slipping through in libcxx code. --- .../clang-tidy/misc/CMakeLists.txt | 1 + .../clang-tidy/misc/MiscTidyModule.cpp | 3 ++ .../misc/StaticInConstexprCheck.cpp | 39 ++++++++++++++++++ .../clang-tidy/misc/StaticInConstexprCheck.h | 33 +++++++++++++++ .../checks/misc/static-in-constexpr.rst | 6 +++ .../checkers/misc/static-in-constexpr.cpp | 41 +++++++++++++++++++ libcxx/.clang-tidy | 1 + 7 files changed, 124 insertions(+) create mode 100644 clang-tools-extra/clang-tidy/misc/StaticInConstexprCheck.cpp create mode 100644 clang-tools-extra/clang-tidy/misc/StaticInConstexprCheck.h create mode 100644 clang-tools-extra/docs/clang-tidy/checks/misc/static-in-constexpr.rst create mode 100644 clang-tools-extra/test/clang-tidy/checkers/misc/static-in-constexpr.cpp diff --git a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt index e34b0cf687be3..bb11f5c5836e1 100644 --- a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt @@ -38,6 +38,7 @@ add_clang_library(clangTidyMiscModule STATIC PredictableRandCheck.cpp RedundantExpressionCheck.cpp StaticAssertCheck.cpp + StaticInConstexprCheck.cpp ThrowByValueCatchByReferenceCheck.cpp UnconventionalAssignOperatorCheck.cpp UniqueptrResetReleaseCheck.cpp diff --git a/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp b/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp index f8550b30b9789..3918c70f4fb9a 100644 --- a/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp @@ -27,6 +27,7 @@ #include "PredictableRandCheck.h" #include "RedundantExpressionCheck.h" #include "StaticAssertCheck.h" +#include "StaticInConstexprCheck.h" #include "ThrowByValueCatchByReferenceCheck.h" #include "UnconventionalAssignOperatorCheck.h" #include "UniqueptrResetReleaseCheck.h" @@ -76,6 +77,8 @@ class MiscModule : public ClangTidyModule { CheckFactories.registerCheck<RedundantExpressionCheck>( "misc-redundant-expression"); CheckFactories.registerCheck<StaticAssertCheck>("misc-static-assert"); + CheckFactories.registerCheck<StaticInConstexprCheck>( + "misc-static-in-constexpr"); CheckFactories.registerCheck<ThrowByValueCatchByReferenceCheck>( "misc-throw-by-value-catch-by-reference"); CheckFactories.registerCheck<UnconventionalAssignOperatorCheck>( diff --git a/clang-tools-extra/clang-tidy/misc/StaticInConstexprCheck.cpp b/clang-tools-extra/clang-tidy/misc/StaticInConstexprCheck.cpp new file mode 100644 index 0000000000000..5427f7e80cd33 --- /dev/null +++ b/clang-tools-extra/clang-tidy/misc/StaticInConstexprCheck.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// 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 "StaticInConstexprCheck.h" +#include "clang/AST/Decl.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang::tidy::misc { + +void StaticInConstexprCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher(varDecl(isStaticLocal()).bind("var"), this); +} + +void StaticInConstexprCheck::check(const MatchFinder::MatchResult &Result) { + const auto *Var = Result.Nodes.getNodeAs<VarDecl>("var"); + const DeclContext *DC = Var->getDeclContext(); + + while (DC && !DC->isFunctionOrMethod()) + DC = DC->getParent(); + + const auto *FD = dyn_cast_or_null<FunctionDecl>(DC); + if (!FD) + return; + + if (FD->isConstexpr()) { + diag(Var->getLocation(), + "variable of static or thread storage duration inside constexpr " + "function"); + } +} + +} // namespace clang::tidy::misc \ No newline at end of file diff --git a/clang-tools-extra/clang-tidy/misc/StaticInConstexprCheck.h b/clang-tools-extra/clang-tidy/misc/StaticInConstexprCheck.h new file mode 100644 index 0000000000000..862255c9eeb1d --- /dev/null +++ b/clang-tools-extra/clang-tidy/misc/StaticInConstexprCheck.h @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// 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 LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_STATICINCONSTEXPRCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_STATICINCONSTEXPRCHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang::tidy::misc { + +/// Checks for static variables declared inside constexpr functions. +/// +/// For the user-facing documentation see: +/// https://clang.llvm.org/extra/clang-tidy/checks/misc/static-in-constexpr.html +class StaticInConstexprCheck : public ClangTidyCheck { +public: + StaticInConstexprCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { + return LangOpts.CPlusPlus; + } +}; + +} // namespace clang::tidy::misc + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_STATICINCONSTEXPRCHECK_H diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc/static-in-constexpr.rst b/clang-tools-extra/docs/clang-tidy/checks/misc/static-in-constexpr.rst new file mode 100644 index 0000000000000..4aeaa4e661866 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/misc/static-in-constexpr.rst @@ -0,0 +1,6 @@ +.. title:: clang-tidy - misc-static-in-constexpr + +misc-static-in-constexpr +======================== + +FIXME: Describe what patterns does the check detect and why. Give examples. diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/static-in-constexpr.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/static-in-constexpr.cpp new file mode 100644 index 0000000000000..9b6c38a4cabfe --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/misc/static-in-constexpr.cpp @@ -0,0 +1,41 @@ +// RUN: %check_clang_tidy -std=c++20 %s misc-static-in-constexpr %t +// RUN: %check_clang_tidy -std=c++23 %s misc-static-in-constexpr %t + +void normal_func() { + static int x = 0; + thread_local int y = 0; +} + +constexpr void constexpr_func() { + static int x = 0; + // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: variable of static or thread storage duration inside constexpr function [misc-static-in-constexpr] + + thread_local int y = 0; + // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: variable of static or thread storage duration inside constexpr function [misc-static-in-constexpr] +} + +consteval void consteval_func() { + static int x = 0; + // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: variable of static or thread storage duration inside constexpr function [misc-static-in-constexpr] +} + +constexpr void constexpr_with_lambda() { + auto l = []() { + static int x = 0; + // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: variable of static or thread storage duration inside constexpr function [misc-static-in-constexpr] + }; +} + +constexpr void constexpr_with_constexpr_lambda() { + auto l = []() constexpr { + static int x = 0; + // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: variable of static or thread storage duration inside constexpr function [misc-static-in-constexpr] + }; +} + +struct S { + static constexpr void static_member_func() { + static int x = 0; + // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: variable of static or thread storage duration inside constexpr function [misc-static-in-constexpr] + } +}; \ No newline at end of file diff --git a/libcxx/.clang-tidy b/libcxx/.clang-tidy index ebbfab0379265..685773e4095cd 100644 --- a/libcxx/.clang-tidy +++ b/libcxx/.clang-tidy @@ -13,6 +13,7 @@ Checks: > misc-definitions-in-headers, misc-misplaced-const, misc-non-copyable-objects, + misc-static-in-constexpr, misc-uniqueptr-reset-release, modernize-loop-convert, _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
