[clang] [C++] Fix a crash with __thread and dependent types (PR #140542)
Aaron Ballman via cfe-commits
cfe-commits at lists.llvm.org
Mon May 19 07:17:54 PDT 2025
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 <aaron at 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 <aaron at 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
-
More information about the cfe-commits
mailing list