On Mon, Feb 22, 2016 at 6:46 AM, Faisal Vali <fais...@gmail.com> wrote: > On Sun, Feb 21, 2016 at 11:45 PM, Richard Smith <rich...@metafoo.co.uk> wrote: >> 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. >> > > I see what you mean. I'll pass the TemplateArgs through to > BuildDeclRefExpr so it is preserved within that node. Does it make > sense to squirrel the FoundDecl (the template) within the > DeclRefExpr node too? >
FYI, I think we should, since the FoundDecl could be a using member declaration for a base class' variable template. (Not sure why this wasn't being preserved for the non-variable template case either?) > > >>> 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