On 21 Feb 2016 8:21 p.m., "Faisal Vali" <fais...@gmail.com> wrote: > > On Sun, Feb 21, 2016 at 10:06 PM, Richard Smith <rich...@metafoo.co.uk> wrote: > > On 21 Feb 2016 6:29 p.m., "Faisal Vali via cfe-commits" > > <cfe-commits@lists.llvm.org> wrote: > >> > >> Author: faisalv > >> Date: Sun Feb 21 20:24:29 2016 > >> New Revision: 261506 > >> > >> URL: http://llvm.org/viewvc/llvm-project?rev=261506&view=rev > >> Log: > >> Fix PR24473 : Teach clang to remember to substitute into member variable > >> templates referred to within dependent qualified ids. > >> > >> In passing also fix a semi-related bug that allows access to variable > >> templates through member access notation. > >> > >> > >> Modified: > >> cfe/trunk/lib/Sema/SemaExprMember.cpp > >> cfe/trunk/test/SemaCXX/cxx1y-variable-templates_in_class.cpp > >> > >> Modified: cfe/trunk/lib/Sema/SemaExprMember.cpp > >> URL: > >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprMember.cpp?rev=261506&r1=261505&r2=261506&view=diff > >> > >> ============================================================================== > >> --- cfe/trunk/lib/Sema/SemaExprMember.cpp (original) > >> +++ cfe/trunk/lib/Sema/SemaExprMember.cpp Sun Feb 21 20:24:29 2016 > >> @@ -902,6 +902,32 @@ static bool IsInFnTryBlockHandler(const > >> return false; > >> } > >> > >> +static VarDecl * > >> +getVarTemplateSpecialization(Sema &S, VarTemplateDecl *VarTempl, > >> + const TemplateArgumentListInfo *TemplateArgs, > >> + const DeclarationNameInfo &MemberNameInfo, > >> + SourceLocation TemplateKWLoc) { > >> + > >> + if (!TemplateArgs) { > >> + S.Diag(MemberNameInfo.getBeginLoc(), diag::err_template_decl_ref) > >> + << /*Variable template*/ 1 << MemberNameInfo.getName() > >> + << MemberNameInfo.getSourceRange(); > >> + > >> + S.Diag(VarTempl->getLocation(), diag::note_template_decl_here); > >> + > >> + return nullptr; > >> + } > >> + DeclResult VDecl = S.CheckVarTemplateId( > >> + VarTempl, TemplateKWLoc, MemberNameInfo.getLoc(), *TemplateArgs); > >> + if (VDecl.isInvalid()) > >> + return nullptr; > >> + VarDecl *Var = cast<VarDecl>(VDecl.get()); > >> + if (!Var->getTemplateSpecializationKind()) > >> + Var->setTemplateSpecializationKind(TSK_ImplicitInstantiation, > >> + MemberNameInfo.getLoc()); > >> + return Var; > >> +} > >> + > >> ExprResult > >> Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, > >> SourceLocation OpLoc, bool IsArrow, > >> @@ -1069,9 +1095,20 @@ Sema::BuildMemberReferenceExpr(Expr *Bas > >> // Handle the implicit-member-access case. > >> if (!BaseExpr) { > >> // If this is not an instance member, convert to a non-member access. > >> - if (!MemberDecl->isCXXInstanceMember()) > >> + if (!MemberDecl->isCXXInstanceMember()) { > >> + // If this is a variable template, get the instantiated variable > >> + // declaration corresponding to the supplied template arguments > >> + // (while emitting diagnostics as necessary) that will be > >> referenced > >> + // by this expression. > >> + if (isa<VarTemplateDecl>(MemberDecl)) { > >> + MemberDecl = getVarTemplateSpecialization( > >> + *this, cast<VarTemplateDecl>(MemberDecl), TemplateArgs, > >> + R.getLookupNameInfo(), TemplateKWLoc); > >> + if (!MemberDecl) > >> + return ExprError(); > >> + } > >> return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), > >> MemberDecl); > > > > Does this properly preserve the template argument list as written? > > > > Shouldn't it? Since it passes on the passed in template argument list > (that I'm assuming is preserved) to CheckVarTemplateId?
None of the three arguments passed to BuildDeclarationNameExpr references the template argument list as written. Passing it to CheckVarTemplateId is insufficient -- that can't preserve the template arguments from each use, because it produces the same result for all uses. > Perhaps you have an example in mind? > > Thanks! > > >> - > >> + } > >> SourceLocation Loc = R.getNameLoc(); > >> if (SS.getRange().isValid()) > >> Loc = SS.getRange().getBegin(); > >> @@ -1127,6 +1164,15 @@ Sema::BuildMemberReferenceExpr(Expr *Bas > >> TemplateKWLoc, Enum, FoundDecl, > >> MemberNameInfo, > >> Enum->getType(), VK_RValue, OK_Ordinary); > >> } > >> + if (VarTemplateDecl *VarTempl = dyn_cast<VarTemplateDecl>(MemberDecl)) > >> { > >> + if (VarDecl *Var = getVarTemplateSpecialization( > >> + *this, VarTempl, TemplateArgs, MemberNameInfo, > >> TemplateKWLoc)) > >> + return BuildMemberExpr(*this, Context, BaseExpr, IsArrow, OpLoc, > >> SS, > >> + TemplateKWLoc, Var, FoundDecl, > >> MemberNameInfo, > >> + Var->getType().getNonReferenceType(), > >> VK_LValue, > >> + OK_Ordinary); > >> + return ExprError(); > >> + } > >> > >> // We found something that we didn't expect. Complain. > >> if (isa<TypeDecl>(MemberDecl)) > >> > >> Modified: cfe/trunk/test/SemaCXX/cxx1y-variable-templates_in_class.cpp > >> URL: > >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1y-variable-templates_in_class.cpp?rev=261506&r1=261505&r2=261506&view=diff > >> > >> ============================================================================== > >> --- cfe/trunk/test/SemaCXX/cxx1y-variable-templates_in_class.cpp > >> (original) > >> +++ cfe/trunk/test/SemaCXX/cxx1y-variable-templates_in_class.cpp Sun Feb > >> 21 20:24:29 2016 > >> @@ -1,6 +1,6 @@ > >> // RUN: %clang_cc1 -verify -fsyntax-only %s -Wno-c++11-extensions > >> -Wno-c++1y-extensions -DPRECXX11 > >> // RUN: %clang_cc1 -std=c++11 -verify -fsyntax-only -Wno-c++1y-extensions > >> %s > >> -// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only %s > >> +// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only %s -DCPP1Y > >> > >> #define CONST const > >> > >> @@ -338,3 +338,47 @@ namespace b20896909 { > >> A<int> ai; // expected-note {{in instantiation of}} > >> } > >> } > >> +namespace member_access_is_ok { > >> +#ifdef CPP1Y > >> + namespace ns1 { > >> + struct A { > >> + template<class T, T N> constexpr static T Var = N; > >> + }; > >> + static_assert(A{}.Var<int,5> == 5,""); > >> + } // end ns1 > >> +#endif // CPP1Y > >> + > >> +namespace ns2 { > >> + template<class T> struct A { > >> + template<class U, T N, U M> static T&& Var; > >> + }; > >> + template<class T> template<class U, T N, U M> T&& A<T>::Var = T(N + M); > >> + int *AV = &A<int>().Var<char, 5, 'A'>; > >> + > >> +} //end ns2 > >> +} // end ns member_access_is_ok > >> + > >> +#ifdef CPP1Y > >> +namespace PR24473 { > >> +struct Value > >> +{ > >> + template<class T> > >> + static constexpr T value = 0; > >> +}; > >> + > >> +template<typename TValue> > >> +struct Something > >> +{ > >> + void foo() { > >> + static_assert(TValue::template value<int> == 0, ""); // error > >> + } > >> +}; > >> + > >> +int main() { > >> + Something<Value>{}.foo(); > >> + return 0; > >> +} > >> + > >> +} // end ns PR24473 > >> +#endif // CPP1Y > >> + > >> > >> > >> _______________________________________________ > >> cfe-commits mailing list > >> cfe-commits@lists.llvm.org > >> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits