diff options
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 34 | ||||
-rw-r--r-- | test/SemaTemplate/instantiate-member-pointers.cpp | 10 |
2 files changed, 41 insertions, 3 deletions
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index b303dce06f..721bfb9004 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -700,7 +700,6 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E, NamedDecl *D = E->getDecl(); if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) { if (NTTP->getDepth() < TemplateArgs.getNumLevels()) { - // If the corresponding template argument is NULL or non-existent, it's // because we are performing instantiation from explicitly-specified // template arguments in a function template, but there were some @@ -725,7 +724,38 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E, if (!VD) return SemaRef.ExprError(); - return SemaRef.BuildDeclRefExpr(VD, VD->getType(), E->getLocation(), + if (VD->getDeclContext()->isRecord()) { + // If the value is a class member, we might have a pointer-to-member. + // Determine whether the non-type template template parameter is of + // pointer-to-member type. If so, we need to build an appropriate + // expression for a pointer-to-member, since a "normal" DeclRefExpr + // would refer to the member itself. + if (NTTP->getType()->isMemberPointerType()) { + QualType ClassType + = SemaRef.Context.getTypeDeclType( + cast<RecordDecl>(VD->getDeclContext())); + NestedNameSpecifier *Qualifier + = NestedNameSpecifier::Create(SemaRef.Context, 0, false, + ClassType.getTypePtr()); + CXXScopeSpec SS; + SS.setScopeRep(Qualifier); + OwningExprResult RefExpr + = SemaRef.BuildDeclRefExpr(VD, + VD->getType().getNonReferenceType(), + E->getLocation(), + /*FIXME:*/false, /*FIXME:*/false, + &SS); + if (RefExpr.isInvalid()) + return SemaRef.ExprError(); + + return SemaRef.CreateBuiltinUnaryOp(E->getLocation(), + UnaryOperator::AddrOf, + move(RefExpr)); + } + } + + return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), + E->getLocation(), /*FIXME:*/false, /*FIXME:*/false); } diff --git a/test/SemaTemplate/instantiate-member-pointers.cpp b/test/SemaTemplate/instantiate-member-pointers.cpp index b3ddb3fafa..63e6dac096 100644 --- a/test/SemaTemplate/instantiate-member-pointers.cpp +++ b/test/SemaTemplate/instantiate-member-pointers.cpp @@ -1,5 +1,4 @@ // RUN: clang-cc -fsyntax-only -verify %s - struct Y { int x; }; @@ -25,3 +24,12 @@ struct X2 { template struct X2<int, Y>; template struct X2<int&, Y>; // expected-note{{instantiation}} template struct X2<const void, Y>; // expected-note{{instantiation}} + +template<typename T, typename Class, T Class::*Ptr> +struct X3 { + X3<T, Class, Ptr> &operator=(const T& value) { + return *this; + } +}; + +X3<int, Y, &Y::x> x3; |