[PATCH] D65022: [Sema] Always instantiate the initializer of a variable template with undeduced type (8.0 regression)

Erik Pilkington via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri Jul 19 14:50:09 PDT 2019

erik.pilkington created this revision.
erik.pilkington added reviewers: rsmith, rjmccall.
Herald added subscribers: dexonsmith, jkorous.
Herald added a project: clang.

This patch fixes a regression introduced in r359947. Here:

  template <class T2> struct Outer {
    template <class T1> static constexpr auto x = 1;
  int main() {
    Outer<int> x;
    int i = x.x<int>;

We'd defer the instantiation of the initializer of the variable template when instantiating Outer<int> (leaving the variable template with an undeduced type). We do eventually instantiate the initializer and deduce the type of the variable when we're marking `Outer<int>::x<int>` referenced, but not before forming a MemberExpr that refers to the undeduced type. I think we could avoid instantiating the initializer of the variable template here, but that doesn't appear to be the intent of r359947, so this patch just falls back to the 8.0 behaviour.

Fixes rdar://52619644

Thanks for taking a look!

  rC Clang



Index: clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
--- clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
+++ clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
@@ -395,3 +395,20 @@
   int &t = B::template n; // expected-error {{use of variable template 'n' requires template arguments}}
+#ifndef PRECXX11
+namespace auto_variable_instantiate_initializer {
+template <class T2> struct S {
+  template <class T> static constexpr auto v = 1;
+  template <class T> static constexpr auto v2 = T{};
+void useit() {
+  S<int> x;
+  // We used to fail to instantiate the initializer, leading to an auto type
+  // leaking through here.
+  int i = x.v<float>;
+  float j = x.v2<float>;
Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -4506,11 +4506,11 @@
   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())) {

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D65022.210905.patch
Type: text/x-patch
Size: 1923 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20190719/1d4f454b/attachment.bin>

More information about the cfe-commits mailing list