From: Douglas Gregor Date: Fri, 23 Oct 2009 22:18:25 +0000 (+0000) Subject: Migrate Sema::ActOnCallExpr to Sema::FixOverloadedFunctionReference, X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=097bfb11759be2187732329ecf4c0849609cdf57;p=clang Migrate Sema::ActOnCallExpr to Sema::FixOverloadedFunctionReference, so that we maintain better source information after template argument deduction and overloading resolves down to a specific declaration. Found and dealt with a few more cases that FixOverloadedFunctionReference didn't cope with. (Finally) added a test case that puts together this change with the DeclRefExpr change to (optionally) include nested-name-specifiers and explicit template argument lists. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@84974 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 490c73896e..b1915750c9 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -2922,13 +2922,7 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, if (!FDecl) return ExprError(); - // Update Fn to refer to the actual function selected. - // FIXME: Use FixOverloadedFunctionReference? - Expr *NewFn = DeclRefExpr::Create(Context, Qualifier, QualifierRange, FDecl, - Fn->getLocStart(), FDecl->getType(), false, - false); - Fn->Destroy(Context); - Fn = NewFn; + Fn = FixOverloadedFunctionReference(Fn, FDecl); } } diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 5e946eb762..7ed79f3073 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -5361,8 +5361,14 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) { Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) { if (ParenExpr *PE = dyn_cast(E)) { Expr *NewExpr = FixOverloadedFunctionReference(PE->getSubExpr(), Fn); - NewExpr->setType(PE->getSubExpr()->getType()); - return NewExpr; + PE->setSubExpr(NewExpr); + PE->setType(NewExpr->getType()); + } else if (ImplicitCastExpr *ICE = dyn_cast(E)) { + Expr *NewExpr = FixOverloadedFunctionReference(ICE->getSubExpr(), Fn); + assert(Context.hasSameType(ICE->getSubExpr()->getType(), + NewExpr->getType()) && + "Implicit cast type cannot be determined from overload"); + ICE->setSubExpr(NewExpr); } else if (UnaryOperator *UnOp = dyn_cast(E)) { assert(UnOp->getOpcode() == UnaryOperator::AddrOf && "Can only take the address of an overloaded function"); @@ -5394,8 +5400,9 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) { return UnOp; } else if (DeclRefExpr *DR = dyn_cast(E)) { assert((isa(DR->getDecl()) || - isa(DR->getDecl())) && - "Expected overloaded function or function template"); + isa(DR->getDecl()) || + isa(DR->getDecl())) && + "Expected function or function template"); DR->setDecl(Fn); E->setType(Fn->getType()); } else if (MemberExpr *MemExpr = dyn_cast(E)) { @@ -5416,6 +5423,12 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) { // 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, + /*Qualifier=*/0, + /*QualifierRange=*/SourceRange(), + Fn, E->getLocStart(), + Fn->getType(), false, false); } else { assert(false && "Invalid reference to overloaded function"); } diff --git a/test/SemaTemplate/template-id-printing.cpp b/test/SemaTemplate/template-id-printing.cpp new file mode 100644 index 0000000000..13250943e9 --- /dev/null +++ b/test/SemaTemplate/template-id-printing.cpp @@ -0,0 +1,13 @@ +// RUN: clang-cc -fsyntax-only -ast-print %s | FileCheck %s +namespace N { + template void f(U); + template void f(); +} + +void g() { + // CHECK: N::f(3.14 + N::f(3.14); + + // CHECK: N::f + void (*fp)(int) = N::f; +}