From: Douglas Gregor Date: Fri, 20 Nov 2009 19:42:02 +0000 (+0000) Subject: Teach FixOverloadedFunctionReference to build new expression ASTs rather X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=699ee52b2f383b62865013c3575510b520055811;p=clang Teach FixOverloadedFunctionReference to build new expression ASTs rather than tweaking existing ASTs, since we were (*gasp*) stomping on ASTs within templates. I'm glad we found this little stick of TNT early... git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89475 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index daf5b7f360..8d479606aa 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -5238,7 +5238,12 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, return true; } - FixOverloadedFunctionReference(MemExpr, Method); + MemExprE = FixOverloadedFunctionReference(MemExprE, Method); + if (ParenExpr *ParenE = dyn_cast(MemExprE)) + MemExpr = dyn_cast(ParenE->getSubExpr()); + else + MemExpr = dyn_cast(MemExprE); + } else { Method = dyn_cast(MemExpr->getMemberDecl()); } @@ -5604,16 +5609,28 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) { /// refer (possibly indirectly) to Fn. Returns the new expr. Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) { if (ParenExpr *PE = dyn_cast(E)) { - Expr *NewExpr = FixOverloadedFunctionReference(PE->getSubExpr(), Fn); - PE->setSubExpr(NewExpr); - PE->setType(NewExpr->getType()); - } else if (ImplicitCastExpr *ICE = dyn_cast(E)) { - Expr *NewExpr = FixOverloadedFunctionReference(ICE->getSubExpr(), Fn); + Expr *SubExpr = FixOverloadedFunctionReference(PE->getSubExpr(), Fn); + if (SubExpr == PE->getSubExpr()) + return PE->Retain(); + + return new (Context) ParenExpr(PE->getLParen(), PE->getRParen(), SubExpr); + } + + if (ImplicitCastExpr *ICE = dyn_cast(E)) { + Expr *SubExpr = FixOverloadedFunctionReference(ICE->getSubExpr(), Fn); assert(Context.hasSameType(ICE->getSubExpr()->getType(), - NewExpr->getType()) && + SubExpr->getType()) && "Implicit cast type cannot be determined from overload"); - ICE->setSubExpr(NewExpr); - } else if (UnaryOperator *UnOp = dyn_cast(E)) { + if (SubExpr == ICE->getSubExpr()) + return ICE->Retain(); + + return new (Context) ImplicitCastExpr(ICE->getType(), + ICE->getCastKind(), + SubExpr, + ICE->isLvalueCast()); + } + + if (UnaryOperator *UnOp = dyn_cast(E)) { assert(UnOp->getOpcode() == UnaryOperator::AddrOf && "Can only take the address of an overloaded function"); if (CXXMethodDecl *Method = dyn_cast(Fn)) { @@ -5625,59 +5642,109 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) { // We have taken the address of a pointer to member // function. Perform the computation here so that we get the // appropriate pointer to member type. - DRE->setDecl(Fn); - DRE->setType(Fn->getType()); QualType ClassType - = Context.getTypeDeclType(cast(Method->getDeclContext())); - E->setType(Context.getMemberPointerType(Fn->getType(), - ClassType.getTypePtr())); - return E; + = Context.getTypeDeclType( + cast(Method->getDeclContext())); + QualType MemPtrType + = Context.getMemberPointerType(Fn->getType(), + ClassType.getTypePtr()); + + DeclRefExpr *NewDRE + = DeclRefExpr::Create(Context, + DRE->getQualifier(), + DRE->getQualifierRange(), + Fn, + DRE->getLocation(), + DRE->hasExplicitTemplateArgumentList(), + DRE->getLAngleLoc(), + DRE->getTemplateArgs(), + DRE->getNumTemplateArgs(), + DRE->getRAngleLoc(), + Fn->getType(), + DRE->isTypeDependent(), + DRE->isValueDependent()); + + return new (Context) UnaryOperator(NewDRE, UnaryOperator::AddrOf, + MemPtrType, + UnOp->getOperatorLoc()); } } // FIXME: TemplateIdRefExpr referring to a member function template // specialization! } - Expr *NewExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), Fn); - UnOp->setSubExpr(NewExpr); - UnOp->setType(Context.getPointerType(NewExpr->getType())); + Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), Fn); + if (SubExpr == UnOp->getSubExpr()) + return UnOp->Retain(); - return UnOp; - } else if (DeclRefExpr *DR = dyn_cast(E)) { - assert((isa(DR->getDecl()) || - isa(DR->getDecl()) || - isa(DR->getDecl())) && + return new (Context) UnaryOperator(SubExpr, UnaryOperator::AddrOf, + Context.getPointerType(SubExpr->getType()), + UnOp->getOperatorLoc()); + } + + if (DeclRefExpr *DRE = dyn_cast(E)) { + assert((isa(DRE->getDecl()) || + isa(DRE->getDecl()) || + isa(DRE->getDecl())) && "Expected function or function template"); - DR->setDecl(Fn); - E->setType(Fn->getType()); - } else if (MemberExpr *MemExpr = dyn_cast(E)) { - MemExpr->setMemberDecl(Fn); - E->setType(Fn->getType()); - } else if (TemplateIdRefExpr *TID = dyn_cast(E)) { - E = DeclRefExpr::Create(Context, - TID->getQualifier(), TID->getQualifierRange(), - Fn, TID->getTemplateNameLoc(), - true, - TID->getLAngleLoc(), - TID->getTemplateArgs(), - TID->getNumTemplateArgs(), - TID->getRAngleLoc(), - Fn->getType(), - /*FIXME?*/false, /*FIXME?*/false); - + return DeclRefExpr::Create(Context, + DRE->getQualifier(), + DRE->getQualifierRange(), + Fn, + DRE->getLocation(), + DRE->hasExplicitTemplateArgumentList(), + DRE->getLAngleLoc(), + DRE->getTemplateArgs(), + DRE->getNumTemplateArgs(), + DRE->getRAngleLoc(), + Fn->getType(), + DRE->isTypeDependent(), + DRE->isValueDependent()); + } + + if (MemberExpr *MemExpr = dyn_cast(E)) { + assert((isa(MemExpr->getMemberDecl()) || + isa(MemExpr->getMemberDecl()) || + isa(MemExpr->getMemberDecl())) && + "Expected member function or member function template"); + return MemberExpr::Create(Context, MemExpr->getBase()->Retain(), + MemExpr->isArrow(), + MemExpr->getQualifier(), + MemExpr->getQualifierRange(), + Fn, + MemExpr->getMemberLoc(), + MemExpr->hasExplicitTemplateArgumentList(), + MemExpr->getLAngleLoc(), + MemExpr->getTemplateArgs(), + MemExpr->getNumTemplateArgs(), + MemExpr->getRAngleLoc(), + Fn->getType()); + } + + if (TemplateIdRefExpr *TID = dyn_cast(E)) { // FIXME: Don't destroy TID here, since we need its template arguments // to survive. // TID->Destroy(Context); - } else if (isa(E)) { + return DeclRefExpr::Create(Context, + TID->getQualifier(), TID->getQualifierRange(), + Fn, TID->getTemplateNameLoc(), + true, + TID->getLAngleLoc(), + TID->getTemplateArgs(), + TID->getNumTemplateArgs(), + TID->getRAngleLoc(), + Fn->getType(), + /*FIXME?*/false, /*FIXME?*/false); + } + + if (isa(E)) return DeclRefExpr::Create(Context, /*Qualifier=*/0, /*QualifierRange=*/SourceRange(), Fn, E->getLocStart(), Fn->getType(), false, false); - } else { - assert(false && "Invalid reference to overloaded function"); - } - return E; + assert(false && "Invalid reference to overloaded function"); + return E->Retain(); } } // end namespace clang diff --git a/test/SemaTemplate/instantiate-member-template.cpp b/test/SemaTemplate/instantiate-member-template.cpp index 95556bcc22..04ced92634 100644 --- a/test/SemaTemplate/instantiate-member-template.cpp +++ b/test/SemaTemplate/instantiate-member-template.cpp @@ -116,3 +116,18 @@ struct X2 { X2 x2a; // expected-note{{instantiation}} X2 x2b; // expected-note{{instantiation}} + +namespace N0 { + template + struct X0 { }; + + struct X1 { + template void f(X0& vals) { g(vals); } + template void g(X0& vals) { } + }; + + void test(X1 x1, X0 x0i, X0 x0l) { + x1.f(x0i); + x1.f(x0l); + } +}