llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-tools-extra

Author: Prabhu Rajasekaran (Prabhuk)

<details>
<summary>Changes</summary>

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.


---
Full diff: https://github.com/llvm/llvm-project/pull/175814.diff


7 Files Affected:

- (modified) clang-tools-extra/clang-tidy/misc/CMakeLists.txt (+1) 
- (modified) clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp (+3) 
- (added) clang-tools-extra/clang-tidy/misc/StaticInConstexprCheck.cpp (+39) 
- (added) clang-tools-extra/clang-tidy/misc/StaticInConstexprCheck.h (+33) 
- (added) clang-tools-extra/docs/clang-tidy/checks/misc/static-in-constexpr.rst 
(+6) 
- (added) 
clang-tools-extra/test/clang-tidy/checkers/misc/static-in-constexpr.cpp (+40) 
- (modified) libcxx/.clang-tidy (+1) 


``````````diff
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..6e4e5f458f8b3
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/static-in-constexpr.cpp
@@ -0,0 +1,40 @@
+// 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,

``````````

</details>


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

Reply via email to