[prev in list] [next in list] [prev in thread] [next in thread] 

List:       cfe-commits
Subject:    Re: r261506 - Fix PR24473 : Teach clang to remember to substitute into member variable templates ref
From:       Faisal Vali via cfe-commits <cfe-commits () lists ! llvm ! org>
Date:       2016-02-22 12:46:40
Message-ID: CABsSThp=dn+EAyG-BE_rq-AHg5tkN-8Apqg-UP+s9PnFELLSNg () mail ! gmail ! com
[Download RAW message or body]

On Sun, Feb 21, 2016 at 11:45 PM, Richard Smith <richard@metafoo.co.uk> wrote:
> On 21 Feb 2016 8:21 p.m., "Faisal Vali" <faisalv@gmail.com> wrote:
> > 
> > On Sun, Feb 21, 2016 at 10:06 PM, Richard Smith <richard@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?



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


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic