diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-02-04 17:21:48 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-02-04 17:21:48 +0000 |
commit | 86a7625062abbd40fffa186f2f5d305cc89615b8 (patch) | |
tree | f554d720991c71f4dfabe5998bfa4f4c3523aa6e /lib/Sema/SemaTemplateInstantiate.cpp | |
parent | 72119a887c4af39c90f10b6bdc158389071f42ea (diff) |
When substituting the template argument for a pointer non-type
template parameter, perform array/function decay (if needed), take the
address of the argument (if needed), perform qualification conversions
(if needed), and remove any top-level cv-qualifiers from the resulting
expression. Fixes PR6226.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95309 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 51 |
1 files changed, 41 insertions, 10 deletions
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 3efb52e91b..b560fad25e 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -718,7 +718,8 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) { if (!VD) return SemaRef.ExprError(); - if (VD->getDeclContext()->isRecord()) { + if (VD->getDeclContext()->isRecord() && + (isa<CXXMethodDecl>(VD) || isa<FieldDecl>(VD))) { // 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 @@ -746,21 +747,51 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) { move(RefExpr)); } } - if (NTTP->getType()->isPointerType() && - !VD->getType()->isPointerType()) { - // If the template argument is expected to be a pointer and value - // isn't inherently of pointer type, then it is specified with '&...' - // to indicate its address should be used. Build an expression to - // take the address of the argument. + if (NTTP->getType()->isPointerType()) { + // If the template argument is expected to be a pointer + // type, we may have to decay array/pointer references, take + // the address of the argument, or perform cv-qualification + // adjustments to get the type of the rvalue right. Do so. OwningExprResult RefExpr = SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), E->getLocation()); if (RefExpr.isInvalid()) return SemaRef.ExprError(); - return SemaRef.CreateBuiltinUnaryOp(E->getLocation(), - UnaryOperator::AddrOf, - move(RefExpr)); + // Decay functions and arrays. + Expr *RefE = (Expr *)RefExpr.get(); + SemaRef.DefaultFunctionArrayConversion(RefE); + if (RefE != RefExpr.get()) { + RefExpr.release(); + RefExpr = SemaRef.Owned(RefE); + } + + // If the unqualified types are different and a a + // qualification conversion won't fix them types, we need to + // take the address. FIXME: Should we encode these steps in + // the template argument, then replay them here, like a + // miniature InitializationSequence? + if (!SemaRef.Context.hasSameUnqualifiedType(RefE->getType(), + NTTP->getType()) && + !SemaRef.IsQualificationConversion(RefE->getType(), + NTTP->getType())) { + RefExpr = SemaRef.CreateBuiltinUnaryOp(E->getLocation(), + UnaryOperator::AddrOf, + move(RefExpr)); + if (RefExpr.isInvalid()) + return SemaRef.ExprError(); + + RefE = (Expr *)RefExpr.get(); + assert(SemaRef.IsQualificationConversion(RefE->getType(), + NTTP->getType())); + } + + // Strip top-level cv-qualifiers off the type. + RefExpr.release(); + SemaRef.ImpCastExprToType(RefE, + NTTP->getType().getUnqualifiedType(), + CastExpr::CK_NoOp); + return SemaRef.Owned(RefE); } return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), |