Skip to content

Commit 0b553e0

Browse files
authored
[Clang] Fix missed initializer instantiation bug for variable templates (#138122)
Fixes #135032 Due to nested templates, when instantiating the outer layer (the template class), the inner layer (the template variable) uses delayed instantiation. This causes the declaration (VarDecl) of the template variable to retain the type from the original template declaration (i.e., auto), and it loses the initializer. Later, when instantiating the template variable, its VarTemplateSpecializationDecl type depends on the VarDecl type. Thus, the VarTemplateSpecializationDecl also has no initializer, and its type remains auto. Ultimately, when building the reference expression in Sema::BuildDeclarationNameExpr, the expression's type is auto and stays as auto until code generation, triggering llvm_unreachable in CodeGenTypes::ConvertType. Since I noticed that the deduction of auto type is caused by the initializer I plan to do special processing for template variables of type auto, that is, to prevent their delayed instantiation so that their initializers will not be lost when the outer template class is instantiated
1 parent f686770 commit 0b553e0

File tree

4 files changed

+30
-3
lines changed

4 files changed

+30
-3
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,7 @@ Bug Fixes to C++ Support
725725
in a ``constexpr`` function. (#GH131432)
726726
- Fixed an incorrect TreeTransform for calls to ``consteval`` functions if a conversion template is present. (#GH137885)
727727
- Clang now emits a warning when class template argument deduction for alias templates is used in C++17. (#GH133806)
728+
- Fix missed initializer instantiation bug for variable templates. (#GH138122)
728729
- Fix a crash when checking the template template parameters of a dependent lambda appearing in an alias declaration.
729730
(#GH136432), (#GH137014), (#GH138018)
730731
- Fixed an assertion when trying to constant-fold various builtins when the argument

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6032,11 +6032,11 @@ void Sema::BuildVariableInstantiation(
60326032
Context.setStaticLocalNumber(NewVar, Context.getStaticLocalNumber(OldVar));
60336033

60346034
// Figure out whether to eagerly instantiate the initializer.
6035-
if (InstantiatingVarTemplate || InstantiatingVarTemplatePartialSpec) {
6036-
// We're producing a template. Don't instantiate the initializer yet.
6037-
} else if (NewVar->getType()->isUndeducedType()) {
6035+
if (NewVar->getType()->isUndeducedType()) {
60386036
// We need the type to complete the declaration of the variable.
60396037
InstantiateVariableInitializer(NewVar, OldVar, TemplateArgs);
6038+
} else if (InstantiatingVarTemplate || InstantiatingVarTemplatePartialSpec) {
6039+
// We're producing a template. Don't instantiate the initializer yet.
60406040
} else if (InstantiatingSpecFromTemplate ||
60416041
(OldVar->isInline() && OldVar->isThisDeclarationADefinition() &&
60426042
!NewVar->isThisDeclarationADefinition())) {

clang/test/CodeGenCXX/cxx1z-inline-variables.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
// RUN: %clang_cc1 -std=c++1z %s -emit-llvm -o - -triple x86_64-linux-gnu | FileCheck %s
22

3+
template <typename T> struct InlineAuto {
4+
template <typename G> inline static auto var = 5;
5+
};
6+
int inlineauto = InlineAuto<int>::var<int>;
7+
// CHECK: @_ZN10InlineAutoIiE3varIiEE = {{.*}}i32 5{{.*}}comdat
8+
//
9+
template <typename> struct PartialInlineAuto {
10+
template <typename, typename> inline static auto var = 6;
11+
template <typename T> inline static auto var<int, T> = 7;
12+
};
13+
14+
int partialinlineauto = PartialInlineAuto<int>::var<int, int>;
15+
// CHECK: @_ZN17PartialInlineAutoIiE3varIiiEE = {{.*}}i32 7{{.*}}comdat
16+
317
struct Q {
418
// CHECK: @_ZN1Q1kE = linkonce_odr constant i32 5, comdat
519
static constexpr int k = 5;

clang/test/SemaTemplate/cxx17-inline-variables.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,15 @@ template <typename T> constexpr int A<T>::n = sizeof(A) + sizeof(T);
2727
template <typename T> inline constexpr int A<T>::m = sizeof(A) + sizeof(T);
2828
static_assert(A<int>().f() == 5);
2929
static_assert(A<int>().g() == 5);
30+
31+
template <typename T> struct InlineAuto {
32+
template <typename G> inline static auto var = 5;
33+
};
34+
35+
template <typename> struct PartialInlineAuto {
36+
template <typename, typename> inline static auto var = 6;
37+
template <typename T> inline static auto var<int, T> = 7;
38+
};
39+
40+
int inlineauto = InlineAuto<int>::var<int>;
41+
int partialinlineauto = PartialInlineAuto<int>::var<int, int>;

0 commit comments

Comments
 (0)