Author: dty2 Date: 2025-05-18T18:42:07+08:00 New Revision: 0b553e055ad01ca6a2c88f7da92157df29e42fd0
URL: https://github.com/llvm/llvm-project/commit/0b553e055ad01ca6a2c88f7da92157df29e42fd0 DIFF: https://github.com/llvm/llvm-project/commit/0b553e055ad01ca6a2c88f7da92157df29e42fd0.diff LOG: [Clang] Fix missed initializer instantiation bug for variable templates (#138122) Fixes https://github.com/llvm/llvm-project/issues/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 Added: Modified: clang/docs/ReleaseNotes.rst clang/lib/Sema/SemaTemplateInstantiateDecl.cpp clang/test/CodeGenCXX/cxx1z-inline-variables.cpp clang/test/SemaTemplate/cxx17-inline-variables.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 537f29521fb7f..4a3c1bee82831 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -725,6 +725,7 @@ Bug Fixes to C++ Support in a ``constexpr`` function. (#GH131432) - Fixed an incorrect TreeTransform for calls to ``consteval`` functions if a conversion template is present. (#GH137885) - Clang now emits a warning when class template argument deduction for alias templates is used in C++17. (#GH133806) +- Fix missed initializer instantiation bug for variable templates. (#GH138122) - Fix a crash when checking the template template parameters of a dependent lambda appearing in an alias declaration. (#GH136432), (#GH137014), (#GH138018) - Fixed an assertion when trying to constant-fold various builtins when the argument diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index d4f99c1fa16f6..b12085c6f6935 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -6032,11 +6032,11 @@ void Sema::BuildVariableInstantiation( Context.setStaticLocalNumber(NewVar, Context.getStaticLocalNumber(OldVar)); // Figure out whether to eagerly instantiate the initializer. - if (InstantiatingVarTemplate || InstantiatingVarTemplatePartialSpec) { - // We're producing a template. Don't instantiate the initializer yet. - } else if (NewVar->getType()->isUndeducedType()) { + if (NewVar->getType()->isUndeducedType()) { // We need the type to complete the declaration of the variable. InstantiateVariableInitializer(NewVar, OldVar, TemplateArgs); + } else if (InstantiatingVarTemplate || InstantiatingVarTemplatePartialSpec) { + // We're producing a template. Don't instantiate the initializer yet. } else if (InstantiatingSpecFromTemplate || (OldVar->isInline() && OldVar->isThisDeclarationADefinition() && !NewVar->isThisDeclarationADefinition())) { diff --git a/clang/test/CodeGenCXX/cxx1z-inline-variables.cpp b/clang/test/CodeGenCXX/cxx1z-inline-variables.cpp index 812e438f30c9a..1cb30b178e06f 100644 --- a/clang/test/CodeGenCXX/cxx1z-inline-variables.cpp +++ b/clang/test/CodeGenCXX/cxx1z-inline-variables.cpp @@ -1,5 +1,19 @@ // RUN: %clang_cc1 -std=c++1z %s -emit-llvm -o - -triple x86_64-linux-gnu | FileCheck %s +template <typename T> struct InlineAuto { + template <typename G> inline static auto var = 5; +}; +int inlineauto = InlineAuto<int>::var<int>; +// CHECK: @_ZN10InlineAutoIiE3varIiEE = {{.*}}i32 5{{.*}}comdat +// +template <typename> struct PartialInlineAuto { + template <typename, typename> inline static auto var = 6; + template <typename T> inline static auto var<int, T> = 7; +}; + +int partialinlineauto = PartialInlineAuto<int>::var<int, int>; +// CHECK: @_ZN17PartialInlineAutoIiE3varIiiEE = {{.*}}i32 7{{.*}}comdat + struct Q { // CHECK: @_ZN1Q1kE = linkonce_odr constant i32 5, comdat static constexpr int k = 5; diff --git a/clang/test/SemaTemplate/cxx17-inline-variables.cpp b/clang/test/SemaTemplate/cxx17-inline-variables.cpp index 7fc0aa8eeeb0c..06f1ec17fb7a8 100644 --- a/clang/test/SemaTemplate/cxx17-inline-variables.cpp +++ b/clang/test/SemaTemplate/cxx17-inline-variables.cpp @@ -27,3 +27,15 @@ template <typename T> constexpr int A<T>::n = sizeof(A) + sizeof(T); template <typename T> inline constexpr int A<T>::m = sizeof(A) + sizeof(T); static_assert(A<int>().f() == 5); static_assert(A<int>().g() == 5); + +template <typename T> struct InlineAuto { + template <typename G> inline static auto var = 5; +}; + +template <typename> struct PartialInlineAuto { + template <typename, typename> inline static auto var = 6; + template <typename T> inline static auto var<int, T> = 7; +}; + +int inlineauto = InlineAuto<int>::var<int>; +int partialinlineauto = PartialInlineAuto<int>::var<int, int>; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits