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); - + } 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