r261506 - Fix PR24473 : Teach clang to remember to substitute into member variable templates referred to within dependent qualified ids.
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Sun Feb 21 21:45:42 PST 2016
On 21 Feb 2016 8:21 p.m., "Faisal Vali" <faisalv at gmail.com> wrote:
>
> On Sun, Feb 21, 2016 at 10:06 PM, Richard Smith <richard at metafoo.co.uk>
wrote:
> > On 21 Feb 2016 6:29 p.m., "Faisal Vali via cfe-commits"
> > <cfe-commits at 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 at lists.llvm.org
> >> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20160221/5417e4f2/attachment.html>
More information about the cfe-commits
mailing list