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

Reply via email to