r261506 - Fix PR24473 : Teach clang to remember to substitute into member variable templates referred to within dependent qualified ids.

Faisal Vali via cfe-commits cfe-commits at lists.llvm.org
Mon Feb 22 04:46:40 PST 2016


On Sun, Feb 21, 2016 at 11:45 PM, Richard Smith <richard at metafoo.co.uk> wrote:
> 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.
>

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 at lists.llvm.org
>> >> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


More information about the cfe-commits mailing list