Move the overloading logic of Sema::ActOnCallExpr to a separate function

llvm-svn: 60093
This commit is contained in:
Douglas Gregor 2008-11-26 05:54:23 +00:00
parent 3336b1f06b
commit 99dcbff154
3 changed files with 56 additions and 30 deletions

View File

@ -447,6 +447,12 @@ public:
bool Complain);
void FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn);
Expr *ResolveOverloadedCallFn(Expr *Fn, OverloadedFunctionDecl *Ovl,
SourceLocation LParenLoc,
Expr **Args, unsigned NumArgs,
SourceLocation *CommaLocs,
SourceLocation RParenLoc);
ExprResult
BuildCallToObjectOfClassType(Expr *Object, SourceLocation LParenLoc,
Expr **Args, unsigned NumArgs,

View File

@ -1294,39 +1294,13 @@ ActOnCallExpr(ExprTy *fn, SourceLocation LParenLoc,
}
}
// If we have a set of overloaded functions, perform overload
// resolution to pick the function.
if (Ovl) {
OverloadCandidateSet CandidateSet;
AddOverloadCandidates(Ovl, Args, NumArgs, CandidateSet);
OverloadCandidateSet::iterator Best;
switch (BestViableFunction(CandidateSet, Best)) {
case OR_Success:
{
// Success! Let the remainder of this function build a call to
// the function selected by overload resolution.
FDecl = Best->Function;
Expr *NewFn = new DeclRefExpr(FDecl, FDecl->getType(),
Fn->getSourceRange().getBegin());
delete Fn;
Fn = NewFn;
}
break;
case OR_No_Viable_Function:
Diag(Fn->getSourceRange().getBegin(),
diag::err_ovl_no_viable_function_in_call)
<< Ovl->getDeclName() << (unsigned)CandidateSet.size()
<< Fn->getSourceRange();
PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false);
Fn = ResolveOverloadedCallFn(Fn, Ovl, LParenLoc, Args, NumArgs, CommaLocs,
RParenLoc);
if (!Fn)
return true;
case OR_Ambiguous:
Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_ambiguous_call)
<< Ovl->getDeclName() << Fn->getSourceRange();
PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
return true;
}
// Fall through and build the call to Fn.
}
if (getLangOptions().CPlusPlus && Fn->getType()->isRecordType())

View File

@ -2963,6 +2963,52 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
return 0;
}
/// ResolveOverloadedCallFn - Given the call expression that calls Fn
/// (which eventually refers to the set of overloaded functions in
/// Ovl) and the call arguments Args/NumArgs, attempt to resolve the
/// function call down to a specific function. If overload resolution
/// succeeds, returns an expression that refers to a specific function
/// and deletes Fn. Otherwise, emits diagnostics, deletes all of the
/// arguments and Fn, and returns NULL.
Expr *Sema::ResolveOverloadedCallFn(Expr *Fn, OverloadedFunctionDecl *Ovl,
SourceLocation LParenLoc,
Expr **Args, unsigned NumArgs,
SourceLocation *CommaLocs,
SourceLocation RParenLoc) {
OverloadCandidateSet CandidateSet;
AddOverloadCandidates(Ovl, Args, NumArgs, CandidateSet);
OverloadCandidateSet::iterator Best;
switch (BestViableFunction(CandidateSet, Best)) {
case OR_Success: {
Expr *NewFn = new DeclRefExpr(Best->Function, Best->Function->getType(),
Fn->getSourceRange().getBegin());
Fn->Destroy(Context);
return NewFn;
}
case OR_No_Viable_Function:
Diag(Fn->getSourceRange().getBegin(),
diag::err_ovl_no_viable_function_in_call)
<< Ovl->getDeclName() << (unsigned)CandidateSet.size()
<< Fn->getSourceRange();
PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false);
break;
case OR_Ambiguous:
Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_ambiguous_call)
<< Ovl->getDeclName() << Fn->getSourceRange();
PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
break;
}
// Overload resolution failed. Destroy all of the subexpressions and
// return NULL.
Fn->Destroy(Context);
for (unsigned Arg = 0; Arg < NumArgs; ++Arg)
Args[Arg]->Destroy(Context);
return 0;
}
/// BuildCallToObjectOfClassType - Build a call to an object of class
/// type (C++ [over.call.object]), which can end up invoking an
/// overloaded function call operator (@c operator()) or performing a