erik.pilkington updated this revision to Diff 212026.
erik.pilkington added a comment.

Fix the type of the MemberExpr/DeclRefExpr after instantiating the variable 
initializer.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65022/new/

https://reviews.llvm.org/D65022

Files:
  clang/lib/Sema/SemaExpr.cpp
  clang/lib/Sema/SemaExprMember.cpp
  clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp


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,34 @@
   }
   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{};
+
+  template <class T, int i = v<T>>
+  void implicit() {
+    double d = v2<T>;
+    int i2 = v<short>;
+  }
+
+  void implicit_nondep() {
+    int i = v<unsigned char>;
+    double d = v2<signed char>;
+  }
+};
+
+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>;
+
+  x.implicit<double>();
+  x.implicit_nondep();
+}
+}
+#endif
Index: clang/lib/Sema/SemaExprMember.cpp
===================================================================
--- clang/lib/Sema/SemaExprMember.cpp
+++ clang/lib/Sema/SemaExprMember.cpp
@@ -1160,11 +1160,17 @@
   }
   if (VarTemplateDecl *VarTempl = dyn_cast<VarTemplateDecl>(MemberDecl)) {
     if (VarDecl *Var = getVarTemplateSpecialization(
-            *this, VarTempl, TemplateArgs, MemberNameInfo, TemplateKWLoc))
-      return BuildMemberExpr(
+            *this, VarTempl, TemplateArgs, MemberNameInfo, TemplateKWLoc)) {
+      MemberExpr *ME = BuildMemberExpr(
           BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, Var, FoundDecl,
           /*HadMultipleCandidates=*/false, MemberNameInfo,
           Var->getType().getNonReferenceType(), VK_LValue, OK_Ordinary);
+
+      // BuildMemberExpr may have deduced an auto variable's type. Patch back
+      // that type to avoid forming an expression with undeduced type.
+      ME->setType(Var->getType().getNonReferenceType());
+      return ME;
+    }
     return ExprError();
   }
 
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -3163,9 +3163,15 @@
       break;
     }
 
-    return BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS, FoundD,
-                            /*FIXME: TemplateKWLoc*/ SourceLocation(),
-                            TemplateArgs);
+    DeclRefExpr *DRE = BuildDeclRefExpr(
+        VD, type, valueKind, NameInfo, &SS, FoundD,
+        /*FIXME: TemplateKWLoc*/ SourceLocation(), TemplateArgs);
+
+    // BuildDeclRefExpr may have deduced an auto variable's type. Patch back
+    // that type to avoid forming an expression with undeduced type.
+    if (isa<VarTemplateSpecializationDecl>(VD))
+      DRE->setType(VD->getType().getNonReferenceType());
+    return DRE;
   }
 }
 


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,34 @@
   }
   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{};
+
+  template <class T, int i = v<T>>
+  void implicit() {
+    double d = v2<T>;
+    int i2 = v<short>;
+  }
+
+  void implicit_nondep() {
+    int i = v<unsigned char>;
+    double d = v2<signed char>;
+  }
+};
+
+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>;
+
+  x.implicit<double>();
+  x.implicit_nondep();
+}
+}
+#endif
Index: clang/lib/Sema/SemaExprMember.cpp
===================================================================
--- clang/lib/Sema/SemaExprMember.cpp
+++ clang/lib/Sema/SemaExprMember.cpp
@@ -1160,11 +1160,17 @@
   }
   if (VarTemplateDecl *VarTempl = dyn_cast<VarTemplateDecl>(MemberDecl)) {
     if (VarDecl *Var = getVarTemplateSpecialization(
-            *this, VarTempl, TemplateArgs, MemberNameInfo, TemplateKWLoc))
-      return BuildMemberExpr(
+            *this, VarTempl, TemplateArgs, MemberNameInfo, TemplateKWLoc)) {
+      MemberExpr *ME = BuildMemberExpr(
           BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, Var, FoundDecl,
           /*HadMultipleCandidates=*/false, MemberNameInfo,
           Var->getType().getNonReferenceType(), VK_LValue, OK_Ordinary);
+
+      // BuildMemberExpr may have deduced an auto variable's type. Patch back
+      // that type to avoid forming an expression with undeduced type.
+      ME->setType(Var->getType().getNonReferenceType());
+      return ME;
+    }
     return ExprError();
   }
 
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -3163,9 +3163,15 @@
       break;
     }
 
-    return BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS, FoundD,
-                            /*FIXME: TemplateKWLoc*/ SourceLocation(),
-                            TemplateArgs);
+    DeclRefExpr *DRE = BuildDeclRefExpr(
+        VD, type, valueKind, NameInfo, &SS, FoundD,
+        /*FIXME: TemplateKWLoc*/ SourceLocation(), TemplateArgs);
+
+    // BuildDeclRefExpr may have deduced an auto variable's type. Patch back
+    // that type to avoid forming an expression with undeduced type.
+    if (isa<VarTemplateSpecializationDecl>(VD))
+      DRE->setType(VD->getType().getNonReferenceType());
+    return DRE;
   }
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to