Skip to content

Commit 7cf2860

Browse files
authored
[C++] Fix a crash with __thread and dependent types (#140542)
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
1 parent 37ece04 commit 7cf2860

File tree

3 files changed

+37
-0
lines changed

3 files changed

+37
-0
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,9 @@ Improvements to Clang's diagnostics
558558
between different Unicode character types (``char8_t``, ``char16_t``, ``char32_t``).
559559
This warning only triggers in C++ as these types are aliases in C. (#GH138526)
560560

561+
- Fixed a crash when checking a ``__thread``-specified variable declaration
562+
with a dependent type in C++. (#GH140509)
563+
561564
Improvements to Clang's time-trace
562565
----------------------------------
563566

clang/lib/Sema/SemaDecl.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14608,6 +14608,10 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
1460814608
std::optional<bool> CacheHasConstInit;
1460914609
const Expr *CacheCulprit = nullptr;
1461014610
auto checkConstInit = [&]() mutable {
14611+
const Expr *Init = var->getInit();
14612+
if (Init->isInstantiationDependent())
14613+
return true;
14614+
1461114615
if (!CacheHasConstInit)
1461214616
CacheHasConstInit = var->getInit()->isConstantInitializer(
1461314617
Context, var->getType()->isReferenceType(), &CacheCulprit);
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// RUN: %clang_cc1 -fsyntax-only -std=c++23 -verify %s
2+
3+
namespace GH140509 {
4+
template <typename T>
5+
void not_instantiated() {
6+
static __thread T my_wrapper;
7+
}
8+
9+
template <typename T>
10+
void instantiated() {
11+
static __thread T my_wrapper = T{}; // expected-error {{initializer for thread-local variable must be a constant expression}} \
12+
expected-note {{use 'thread_local' to allow this}}
13+
}
14+
15+
template <typename T>
16+
void nondependent_var() {
17+
// Verify that the dependence of the initializer is what really matters.
18+
static __thread int my_wrapper = T{};
19+
}
20+
21+
struct S {
22+
S() {}
23+
};
24+
25+
void f() {
26+
instantiated<int>();
27+
instantiated<S>(); // expected-note {{in instantiation of function template specialization 'GH140509::instantiated<GH140509::S>' requested here}}
28+
nondependent_var<int>();
29+
}
30+
} // namespace GH140509

0 commit comments

Comments
 (0)