diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 2557dfeb89731ea101f5da6db71c99bfd4e1e25e..4a6d01b4e24aa5ce493869e9926b07a1227c4a9f 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -2615,7 +2615,8 @@ public: DeclaratorInfo *Arg); bool CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg, NamedDecl *&Entity); - bool CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member); + bool CheckTemplateArgumentPointerToMember(Expr *Arg, + TemplateArgument &Converted); bool CheckTemplateArgument(NonTypeTemplateParmDecl *Param, QualType InstantiatedParamType, Expr *&Arg, TemplateArgument &Converted); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index af7634ae86aa2a63ac7cf483af63de7c29f2d533..07d7839455f0b646e0dd0076a185f25e70ba0b23 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -1187,11 +1187,10 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, QualType CanonType; - if (TemplateSpecializationType::anyDependentTemplateArguments( + if (Name.isDependent() || + TemplateSpecializationType::anyDependentTemplateArguments( TemplateArgs, - NumTemplateArgs) || - isa(Template) || - Template->getDeclContext()->isDependentContext()) { + NumTemplateArgs)) { // This class template specialization is a dependent // type. Therefore, its canonical type is another class template // specialization type that contains all of the converted @@ -2088,8 +2087,8 @@ bool Sema::CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg, /// \brief Checks whether the given template argument is a pointer to /// member constant according to C++ [temp.arg.nontype]p1. -bool -Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member) { +bool Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, + TemplateArgument &Converted) { bool Invalid = false; // See through any implicit casts we added to fix the type. @@ -2120,13 +2119,33 @@ Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member) { Arg = Parens->getSubExpr(); } - if (UnaryOperator *UnOp = dyn_cast(Arg)) + // A pointer-to-member constant written &Class::member. + if (UnaryOperator *UnOp = dyn_cast(Arg)) { if (UnOp->getOpcode() == UnaryOperator::AddrOf) { DRE = dyn_cast(UnOp->getSubExpr()); if (DRE && !DRE->getQualifier()) DRE = 0; } - + } + // A constant of pointer-to-member type. + else if ((DRE = dyn_cast(Arg))) { + if (ValueDecl *VD = dyn_cast(DRE->getDecl())) { + if (VD->getType()->isMemberPointerType()) { + if (isa(VD) || + (isa(VD) && + Context.getCanonicalType(VD->getType()).isConstQualified())) { + if (Arg->isTypeDependent() || Arg->isValueDependent()) + Converted = TemplateArgument(Arg->Retain()); + else + Converted = TemplateArgument(VD->getCanonicalDecl()); + return Invalid; + } + } + } + + DRE = 0; + } + if (!DRE) return Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_not_pointer_to_member_form) @@ -2139,7 +2158,10 @@ Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member) { // Okay: this is the address of a non-static member, and therefore // a member pointer constant. - Member = DRE->getDecl(); + if (Arg->isTypeDependent() || Arg->isValueDependent()) + Converted = TemplateArgument(Arg->Retain()); + else + Converted = TemplateArgument(DRE->getDecl()->getCanonicalDecl()); return Invalid; } @@ -2343,16 +2365,8 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, return true; } - if (ParamType->isMemberPointerType()) { - NamedDecl *Member = 0; - if (CheckTemplateArgumentPointerToMember(Arg, Member)) - return true; - - if (Member) - Member = cast(Member->getCanonicalDecl()); - Converted = TemplateArgument(Member); - return false; - } + if (ParamType->isMemberPointerType()) + return CheckTemplateArgumentPointerToMember(Arg, Converted); NamedDecl *Entity = 0; if (CheckTemplateArgumentAddressOfObjectOrFunction(Arg, Entity)) @@ -2465,14 +2479,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, return true; } - NamedDecl *Member = 0; - if (CheckTemplateArgumentPointerToMember(Arg, Member)) - return true; - - if (Member) - Member = cast(Member->getCanonicalDecl()); - Converted = TemplateArgument(Member); - return false; + return CheckTemplateArgumentPointerToMember(Arg, Converted); } /// \brief Check a template argument against its corresponding diff --git a/clang/test/SemaTemplate/instantiate-member-pointers.cpp b/clang/test/SemaTemplate/instantiate-member-pointers.cpp index 63e6dac096e10ab0875c478157855085887af69b..826ea1e3eb5e083510c1fb811c288f3cee3a83da 100644 --- a/clang/test/SemaTemplate/instantiate-member-pointers.cpp +++ b/clang/test/SemaTemplate/instantiate-member-pointers.cpp @@ -33,3 +33,16 @@ struct X3 { }; X3 x3; + +typedef int Y::*IntMember; + +template +struct X4 { + X3 member; + + int &getMember(Y& y) { return y.*Member; } +}; + +int &get_X4(X4<&Y::x> x4, Y& y) { + return x4.getMember(y); +}