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? 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