From 231edff7907cf151f1d046f287d3ee4ad90037cc Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Thu, 12 Nov 2009 17:40:13 +0000 Subject: [PATCH] When instantiating a reference to a non-type template parameter of pointer to member type (e.g., T Class::*Member), build a pointer-to-member constant expression. Previously, we we just building a simple declaration reference expression, which meant that the expression was not treated as a pointer to member. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@87000 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaTemplateInstantiate.cpp | 34 +++++++++++++++++-- .../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(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(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; template struct X2; // expected-note{{instantiation}} template struct X2; // expected-note{{instantiation}} + +template +struct X3 { + X3 &operator=(const T& value) { + return *this; + } +}; + +X3 x3; -- 2.50.1