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