Added some initial support for function overloading.

This commit is contained in:
Roberto Raggi
2010-12-10 10:32:46 +01:00
parent 610023f893
commit 63138eb808
10 changed files with 195 additions and 48 deletions

View File

@@ -75,7 +75,8 @@ ResolveExpression::ResolveExpression(const LookupContext &context)
: ASTVisitor(context.expressionDocument()->translationUnit()),
_scope(0),
_context(context),
bind(context.expressionDocument()->translationUnit())
bind(context.expressionDocument()->translationUnit()),
_reference(false)
{ }
ResolveExpression::~ResolveExpression()
@@ -84,19 +85,26 @@ ResolveExpression::~ResolveExpression()
QList<LookupItem> ResolveExpression::operator()(ExpressionAST *ast, Scope *scope)
{ return resolve(ast, scope); }
QList<LookupItem> ResolveExpression::resolve(ExpressionAST *ast, Scope *scope)
QList<LookupItem> ResolveExpression::reference(ExpressionAST *ast, Scope *scope)
{ return resolve(ast, scope, true); }
QList<LookupItem> ResolveExpression::resolve(ExpressionAST *ast, Scope *scope, bool ref)
{
if (! scope)
return QList<LookupItem>();
Scope *previousVisibleSymbol = _scope;
_scope = scope;
const QList<LookupItem> result = resolve(ast);
_scope = previousVisibleSymbol;
std::swap(_scope, scope);
std::swap(_reference, ref);
const QList<LookupItem> result = expression(ast);
std::swap(_reference, ref);
std::swap(_scope, scope);
return result;
}
QList<LookupItem> ResolveExpression::resolve(ExpressionAST *ast)
QList<LookupItem> ResolveExpression::expression(ExpressionAST *ast)
{
const QList<LookupItem> previousResults = switchResults(QList<LookupItem>());
accept(ast);
@@ -441,27 +449,18 @@ bool ResolveExpression::visit(ConversionFunctionIdAST *)
return false;
}
bool ResolveExpression::maybeValidPrototype(Function *funTy, unsigned actualArgumentCount) const
bool ResolveExpression::maybeValidPrototype(Function *funTy, unsigned actualArgumentCount)
{
unsigned minNumberArguments = 0;
return funTy->maybeValidPrototype(actualArgumentCount);
}
for (; minNumberArguments < funTy->argumentCount(); ++minNumberArguments) {
Argument *arg = funTy->argumentAt(minNumberArguments)->asArgument();
if (arg->hasInitializer())
break;
}
if (actualArgumentCount < minNumberArguments) {
// not enough arguments.
return false;
} else if (! funTy->isVariadic() && actualArgumentCount > funTy->argumentCount()) {
// too many arguments.
return false;
}
return true;
bool ResolveExpression::implicitConversion(const FullySpecifiedType &sourceTy, const FullySpecifiedType &targetTy) const
{
if (sourceTy.isEqualTo(targetTy))
return true;
else if (sourceTy.simplified().isEqualTo(targetTy.simplified()))
return true;
return false;
}
bool ResolveExpression::visit(CallAST *ast)
@@ -469,14 +468,55 @@ bool ResolveExpression::visit(CallAST *ast)
const QList<LookupItem> baseResults = resolve(ast->base_expression, _scope);
// Compute the types of the actual arguments.
int actualArgumentCount = 0;
unsigned actualArgumentCount = 0;
//QList< QList<Result> > arguments;
QList< QList<LookupItem> > arguments;
for (ExpressionListAST *exprIt = ast->expression_list; exprIt; exprIt = exprIt->next) {
//arguments.append(resolve(exprIt->expression));
if (_reference)
arguments.append(resolve(exprIt->value, _scope));
++actualArgumentCount;
}
if (_reference) {
_results.clear();
foreach (const LookupItem &base, baseResults) {
if (Function *funTy = base.type()->asFunctionType()) {
if (! maybeValidPrototype(funTy, actualArgumentCount))
continue;
int score = 0;
for (unsigned i = 0; i < funTy->argumentCount(); ++i) {
const FullySpecifiedType formalTy = funTy->argumentAt(i)->type();
FullySpecifiedType actualTy;
if (i < unsigned(arguments.size())) {
const QList<LookupItem> actual = arguments.at(i);
if (actual.isEmpty())
continue;
actualTy = actual.first().type();
} else
actualTy = formalTy;
if (implicitConversion(actualTy, formalTy))
++score;
}
if (score)
_results.prepend(base);
else
_results.append(base);
}
}
if (_results.isEmpty())
_results = baseResults;
return false;
}
const Name *functionCallOp = control()->operatorNameId(OperatorNameId::FunctionCallOp);
foreach (const LookupItem &result, baseResults) {
@@ -513,7 +553,7 @@ bool ResolveExpression::visit(CallAST *ast)
bool ResolveExpression::visit(ArrayAccessAST *ast)
{
const QList<LookupItem> baseResults = resolve(ast->base_expression, _scope);
const QList<LookupItem> indexResults = resolve(ast->expression);
const QList<LookupItem> indexResults = resolve(ast->expression, _scope);
const Name *arrayAccessOp = control()->operatorNameId(OperatorNameId::ArrayAccessOp);
@@ -709,7 +749,7 @@ bool ResolveExpression::visit(PostIncrDecrAST *ast)
bool ResolveExpression::visit(ObjCMessageExpressionAST *ast)
{
const QList<LookupItem> receiverResults = resolve(ast->receiver_expression);
const QList<LookupItem> receiverResults = resolve(ast->receiver_expression, _scope);
foreach (const LookupItem &result, receiverResults) {
FullySpecifiedType ty = result.type().simplified();