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. llvm-svn: 84974
This commit is contained in:
parent
e2530ec0c0
commit
091f04256a
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5361,8 +5361,14 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) {
|
|||
Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) {
|
||||
if (ParenExpr *PE = dyn_cast<ParenExpr>(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<ImplicitCastExpr>(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<UnaryOperator>(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<DeclRefExpr>(E)) {
|
||||
assert((isa<OverloadedFunctionDecl>(DR->getDecl()) ||
|
||||
isa<FunctionTemplateDecl>(DR->getDecl())) &&
|
||||
"Expected overloaded function or function template");
|
||||
isa<FunctionTemplateDecl>(DR->getDecl()) ||
|
||||
isa<FunctionDecl>(DR->getDecl())) &&
|
||||
"Expected function or function template");
|
||||
DR->setDecl(Fn);
|
||||
E->setType(Fn->getType());
|
||||
} else if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(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<UnresolvedFunctionNameExpr>(E)) {
|
||||
return DeclRefExpr::Create(Context,
|
||||
/*Qualifier=*/0,
|
||||
/*QualifierRange=*/SourceRange(),
|
||||
Fn, E->getLocStart(),
|
||||
Fn->getType(), false, false);
|
||||
} else {
|
||||
assert(false && "Invalid reference to overloaded function");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
// RUN: clang-cc -fsyntax-only -ast-print %s | FileCheck %s
|
||||
namespace N {
|
||||
template<typename T, typename U> void f(U);
|
||||
template<int> void f();
|
||||
}
|
||||
|
||||
void g() {
|
||||
// CHECK: N::f<int>(3.14
|
||||
N::f<int>(3.14);
|
||||
|
||||
// CHECK: N::f<double>
|
||||
void (*fp)(int) = N::f<double>;
|
||||
}
|
Loading…
Reference in New Issue