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