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
Sun Feb 21 20:20:36 PST 2016


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