Index: cfe/trunk/include/clang/Sema/Sema.h =================================================================== --- cfe/trunk/include/clang/Sema/Sema.h +++ cfe/trunk/include/clang/Sema/Sema.h @@ -8191,6 +8191,11 @@ LocalInstantiationScope *StartingScope, bool InstantiatingVarTemplate = false, VarTemplateSpecializationDecl *PrevVTSD = nullptr); + + VarDecl *getVarTemplateSpecialization( + VarTemplateDecl *VarTempl, const TemplateArgumentListInfo *TemplateArgs, + const DeclarationNameInfo &MemberNameInfo, SourceLocation TemplateKWLoc); + void InstantiateVariableInitializer( VarDecl *Var, VarDecl *OldVar, const MultiLevelTemplateArgumentList &TemplateArgs); Index: cfe/trunk/lib/Sema/SemaExprMember.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaExprMember.cpp +++ cfe/trunk/lib/Sema/SemaExprMember.cpp @@ -934,19 +934,19 @@ return false; } -static VarDecl * -getVarTemplateSpecialization(Sema &S, VarTemplateDecl *VarTempl, +VarDecl * +Sema::getVarTemplateSpecialization(VarTemplateDecl *VarTempl, const TemplateArgumentListInfo *TemplateArgs, const DeclarationNameInfo &MemberNameInfo, SourceLocation TemplateKWLoc) { if (!TemplateArgs) { - S.diagnoseMissingTemplateArguments(TemplateName(VarTempl), - MemberNameInfo.getBeginLoc()); + diagnoseMissingTemplateArguments(TemplateName(VarTempl), + MemberNameInfo.getBeginLoc()); return nullptr; } - DeclResult VDecl = S.CheckVarTemplateId( - VarTempl, TemplateKWLoc, MemberNameInfo.getLoc(), *TemplateArgs); + DeclResult VDecl = CheckVarTemplateId(VarTempl, TemplateKWLoc, + MemberNameInfo.getLoc(), *TemplateArgs); if (VDecl.isInvalid()) return nullptr; VarDecl *Var = cast(VDecl.get()); @@ -1095,7 +1095,7 @@ "How did we get template arguments here sans a variable template"); if (isa(MemberDecl)) { MemberDecl = getVarTemplateSpecialization( - *this, cast(MemberDecl), TemplateArgs, + cast(MemberDecl), TemplateArgs, R.getLookupNameInfo(), TemplateKWLoc); if (!MemberDecl) return ExprError(); @@ -1160,7 +1160,7 @@ } if (VarTemplateDecl *VarTempl = dyn_cast(MemberDecl)) { if (VarDecl *Var = getVarTemplateSpecialization( - *this, VarTempl, TemplateArgs, MemberNameInfo, TemplateKWLoc)) + VarTempl, TemplateArgs, MemberNameInfo, TemplateKWLoc)) return BuildMemberExpr( BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, Var, FoundDecl, /*HadMultipleCandidates=*/false, MemberNameInfo, Index: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -5217,11 +5217,11 @@ /// template struct X; /// \endcode /// -/// In the instantiation of X::getKind(), we need to map the -/// \p EnumConstantDecl for \p KnownValue (which refers to -/// X::::KnownValue) to its instantiation -/// (X::::KnownValue). \p FindInstantiatedDecl performs -/// this mapping from within the instantiation of X. +/// In the instantiation of X::getKind(), we need to map the \p +/// EnumConstantDecl for \p KnownValue (which refers to +/// X::::KnownValue) to its instantiation (X::::KnownValue). +/// \p FindInstantiatedDecl performs this mapping from within the instantiation +/// of X. NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, const MultiLevelTemplateArgumentList &TemplateArgs, bool FindingInstantiatedContext) { @@ -5312,20 +5312,6 @@ return cast(Inst); } - // For variable template specializations, update those that are still - // type-dependent. - if (VarTemplateSpecializationDecl *VarSpec = - dyn_cast(D)) { - bool InstantiationDependent = false; - const TemplateArgumentListInfo &VarTemplateArgs = - VarSpec->getTemplateArgsInfo(); - if (TemplateSpecializationType::anyDependentTemplateArguments( - VarTemplateArgs, InstantiationDependent)) - D = cast( - SubstDecl(D, VarSpec->getDeclContext(), TemplateArgs)); - return D; - } - if (CXXRecordDecl *Record = dyn_cast(D)) { if (!Record->isDependentContext()) return D; @@ -5450,11 +5436,23 @@ // find it. Does that ever matter? if (auto Name = D->getDeclName()) { DeclarationNameInfo NameInfo(Name, D->getLocation()); - Name = SubstDeclarationNameInfo(NameInfo, TemplateArgs).getName(); + DeclarationNameInfo NewNameInfo = + SubstDeclarationNameInfo(NameInfo, TemplateArgs); + Name = NewNameInfo.getName(); if (!Name) return nullptr; DeclContext::lookup_result Found = ParentDC->lookup(Name); - Result = findInstantiationOf(Context, D, Found.begin(), Found.end()); + + if (auto *VTSD = dyn_cast(D)) { + VarTemplateDecl *Templ = cast_or_null( + findInstantiationOf(Context, VTSD->getSpecializedTemplate(), + Found.begin(), Found.end())); + if (!Templ) + return nullptr; + Result = getVarTemplateSpecialization( + Templ, &VTSD->getTemplateArgsInfo(), NewNameInfo, SourceLocation()); + } else + Result = findInstantiationOf(Context, D, Found.begin(), Found.end()); } else { // Since we don't have a name for the entity we're looking for, // our only option is to walk through all of the declarations to Index: cfe/trunk/test/SemaCXX/cxx1y-variable-templates_in_class.cpp =================================================================== --- cfe/trunk/test/SemaCXX/cxx1y-variable-templates_in_class.cpp +++ cfe/trunk/test/SemaCXX/cxx1y-variable-templates_in_class.cpp @@ -395,3 +395,32 @@ } int &t = B::template n; // expected-error {{use of variable template 'n' requires template arguments}} } + +#ifndef PRECXX11 +namespace template_vars_in_template { +template struct TakesInt {}; + +template +struct S { + template + static constexpr int v = 42; + + template + void mf() { + constexpr int val = v; + } + + void mf2() { + constexpr int val = v; + TakesInt ti; + (void)ti.x; // expected-error{{no member named 'x' in 'template_vars_in_template::TakesInt<42>'}} + } +}; + +void useit() { + S x; + x.mf(); + x.mf2(); // expected-note{{in instantiation of member function 'template_vars_in_template::S::mf2' requested here}} +} +} +#endif