https://github.com/AaronBallman updated 
https://github.com/llvm/llvm-project/pull/140542

>From a7aa9409530b5a11811149a612886f3d2f4bc977 Mon Sep 17 00:00:00 2001
From: Aaron Ballman <aa...@aaronballman.com>
Date: Mon, 19 May 2025 09:31:51 -0400
Subject: [PATCH 1/2] [C++] Fix a crash with __thread and dependent types

We were checking whether the initializer is a valid constant expression
even if the variable was dependent. Now we delay that checking until
after the template has been instantiated.

Fixes #140509
---
 clang/docs/ReleaseNotes.rst             |  3 +++
 clang/lib/Sema/SemaDecl.cpp             |  3 ++-
 clang/test/SemaCXX/thread-specifier.cpp | 24 ++++++++++++++++++++++++
 3 files changed, 29 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/SemaCXX/thread-specifier.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 4a3c1bee82831..472b70b46fcc0 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -558,6 +558,9 @@ Improvements to Clang's diagnostics
   between different Unicode character types (``char8_t``, ``char16_t``, 
``char32_t``).
   This warning only triggers in C++ as these types are aliases in C. 
(#GH138526)
 
+- Fixed a crash when checking a ``__thread``-specified variable declaration
+  with a dependent type in C++. (#GH140509)
+
 Improvements to Clang's time-trace
 ----------------------------------
 
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 6dae243b520f0..3f52d1b1a65cb 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -14622,7 +14622,8 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl 
*var) {
       Diag(var->getLocation(), diag::err_thread_nontrivial_dtor);
       if (getLangOpts().CPlusPlus11)
         Diag(var->getLocation(), diag::note_use_thread_local);
-    } else if (getLangOpts().CPlusPlus && var->hasInit()) {
+    } else if (getLangOpts().CPlusPlus && var->hasInit() &&
+               !var->getType()->isDependentType()) {
       if (!checkConstInit()) {
         // GNU C++98 edits for __thread, [basic.start.init]p4:
         //   An object of thread storage duration shall not require dynamic
diff --git a/clang/test/SemaCXX/thread-specifier.cpp 
b/clang/test/SemaCXX/thread-specifier.cpp
new file mode 100644
index 0000000000000..8e245987063ff
--- /dev/null
+++ b/clang/test/SemaCXX/thread-specifier.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++23 -verify %s
+
+namespace GH140509 {
+template <typename T>
+void not_instantiated() {
+  static __thread T my_wrapper;
+}
+
+template <typename T>
+void instantiated() {
+  static __thread T my_wrapper = T{}; // expected-error {{initializer for 
thread-local variable must be a constant expression}} \
+                                         expected-note {{use 'thread_local' to 
allow this}}
+}
+
+struct S {
+  S() {}
+};
+
+void f() {
+  instantiated<int>();
+  instantiated<S>(); // expected-note {{in instantiation of function template 
specialization 'GH140509::instantiated<GH140509::S>' requested here}}
+}
+} // namespace GH140509
+

>From 31757ae0a0c62f7ff46d5790528b4a78088e7be1 Mon Sep 17 00:00:00 2001
From: Aaron Ballman <aa...@aaronballman.com>
Date: Mon, 19 May 2025 10:17:27 -0400
Subject: [PATCH 2/2] New approach, now with more testing

---
 clang/lib/Sema/SemaDecl.cpp             | 7 +++++--
 clang/test/SemaCXX/thread-specifier.cpp | 8 +++++++-
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 3f52d1b1a65cb..a996a5c868851 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -14608,6 +14608,10 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl 
*var) {
   std::optional<bool> CacheHasConstInit;
   const Expr *CacheCulprit = nullptr;
   auto checkConstInit = [&]() mutable {
+    const Expr *Init = var->getInit();
+    if (Init->isInstantiationDependent())
+      return true;
+
     if (!CacheHasConstInit)
       CacheHasConstInit = var->getInit()->isConstantInitializer(
             Context, var->getType()->isReferenceType(), &CacheCulprit);
@@ -14622,8 +14626,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl 
*var) {
       Diag(var->getLocation(), diag::err_thread_nontrivial_dtor);
       if (getLangOpts().CPlusPlus11)
         Diag(var->getLocation(), diag::note_use_thread_local);
-    } else if (getLangOpts().CPlusPlus && var->hasInit() &&
-               !var->getType()->isDependentType()) {
+    } else if (getLangOpts().CPlusPlus && var->hasInit()) {
       if (!checkConstInit()) {
         // GNU C++98 edits for __thread, [basic.start.init]p4:
         //   An object of thread storage duration shall not require dynamic
diff --git a/clang/test/SemaCXX/thread-specifier.cpp 
b/clang/test/SemaCXX/thread-specifier.cpp
index 8e245987063ff..2b909ecd175d0 100644
--- a/clang/test/SemaCXX/thread-specifier.cpp
+++ b/clang/test/SemaCXX/thread-specifier.cpp
@@ -12,6 +12,12 @@ void instantiated() {
                                          expected-note {{use 'thread_local' to 
allow this}}
 }
 
+template <typename T>
+void nondependent_var() {
+  // Verify that the dependence of the initializer is what really matters.
+  static __thread int my_wrapper = T{};
+}
+
 struct S {
   S() {}
 };
@@ -19,6 +25,6 @@ struct S {
 void f() {
   instantiated<int>();
   instantiated<S>(); // expected-note {{in instantiation of function template 
specialization 'GH140509::instantiated<GH140509::S>' requested here}}
+  nondependent_var<int>();
 }
 } // namespace GH140509
-

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to