Author: Younan Zhang
Date: 2025-05-22T14:05:52+08:00
New Revision: bf6d24a34db4c3d04beb188542e08e7852d9680f

URL: 
https://github.com/llvm/llvm-project/commit/bf6d24a34db4c3d04beb188542e08e7852d9680f
DIFF: 
https://github.com/llvm/llvm-project/commit/bf6d24a34db4c3d04beb188542e08e7852d9680f.diff

LOG: [Clang] Do not defer variable template instantiation for undeduced types 
(#141009)

The previous approach broke the instantiation convention for templated
substitutions, as we were attempting to instantiate the initializer
even when it was still dependent.

We deferred variable template instantiation until the end of the TU.
However, type deduction requires the initializer immediately,
similar to how constant evaluation does.

Fixes https://github.com/llvm/llvm-project/issues/140773
Fixes #135032
Fixes #134526

Reapplies https://github.com/llvm/llvm-project/pull/138122

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/Sema/SemaExpr.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 95f5d055b08ed..8bd6e924fca37 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -743,6 +743,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)
+- Fixed a missed initializer instantiation bug for variable templates. 
(#GH134526), (#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/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 414a986dd6196..452dbbfe23c5b 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -20158,9 +20158,10 @@ static void DoMarkVarDeclReferenced(
           Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
       }
 
-      if (UsableInConstantExpr) {
+      if (UsableInConstantExpr || Var->getType()->isUndeducedType()) {
         // Do not defer instantiations of variables that could be used in a
         // constant expression.
+        // The type deduction also needs a complete initializer.
         SemaRef.runWithSufficientStackSpace(PointOfInstantiation, [&] {
           SemaRef.InstantiateVariableDefinition(PointOfInstantiation, Var);
         });

diff  --git a/clang/test/CodeGenCXX/cxx1z-inline-variables.cpp 
b/clang/test/CodeGenCXX/cxx1z-inline-variables.cpp
index 812e438f30c9a..9b1a6e4647e85 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..d51588bd492ee 100644
--- a/clang/test/SemaTemplate/cxx17-inline-variables.cpp
+++ b/clang/test/SemaTemplate/cxx17-inline-variables.cpp
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -std=c++17 -verify %s
-// expected-no-diagnostics
+
 template<bool> struct DominatorTreeBase {
   static constexpr bool IsPostDominator = true;
 };
@@ -27,3 +27,45 @@ 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);
+
+namespace GH135032 {
+
+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 inline_auto = InlineAuto<int>::var<int>;
+int partial_inline_auto = PartialInlineAuto<int>::var<int, int>;
+
+}
+
+namespace GH140773 {
+template <class T> class ConstString { // #ConstString
+  ConstString(typename T::type) {} // #ConstString-Ctor
+};
+
+template <class = int>
+struct Foo {
+  template <char>
+  static constexpr ConstString kFilename{[] { // #kFileName
+    return 42;
+  }};
+};
+
+// We don't want to instantiate the member template until it's used!
+Foo<> foo;
+
+auto X = Foo<>::kFilename<'a'>;
+// expected-error@#kFileName {{no viable constructor}}
+// expected-note@-2 {{in instantiation of static data member}}
+// expected-note@#ConstString-Ctor {{candidate template ignored}}
+// expected-note@#ConstString-Ctor {{implicit deduction guide}}
+// expected-note@#ConstString {{candidate template ignored}}
+// expected-note@#ConstString {{implicit deduction guide}}
+
+}


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to