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(VD)) + DRE->setType(VD->getType().getNonReferenceType()); + return DRE; } } 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(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/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 struct S { + template static constexpr auto v = 1; + template static constexpr auto v2 = T{}; + + template > + void implicit() { + double d = v2; + int i2 = v; + } + + void implicit_nondep() { + int i = v; + double d = v2; + } +}; + +void useit() { + S x; + // We used to fail to instantiate the initializer, leading to an auto type + // leaking through here. + int i = x.v; + float j = x.v2; + + x.implicit(); + x.implicit_nondep(); +} +} +#endif