From 63138eb808762e3f5b2f16ea21b860b7936af216 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Fri, 10 Dec 2010 10:32:46 +0100 Subject: Added some initial support for function overloading. --- src/libs/cplusplus/ResolveExpression.cpp | 102 +++++++++++++++++++++---------- 1 file changed, 71 insertions(+), 31 deletions(-) (limited to 'src/libs/cplusplus/ResolveExpression.cpp') diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index 13547593ca1..965d399d3e7 100644 --- a/src/libs/cplusplus/ResolveExpression.cpp +++ b/src/libs/cplusplus/ResolveExpression.cpp @@ -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 ResolveExpression::operator()(ExpressionAST *ast, Scope *scope) { return resolve(ast, scope); } -QList ResolveExpression::resolve(ExpressionAST *ast, Scope *scope) +QList ResolveExpression::reference(ExpressionAST *ast, Scope *scope) +{ return resolve(ast, scope, true); } + +QList ResolveExpression::resolve(ExpressionAST *ast, Scope *scope, bool ref) { if (! scope) return QList(); - Scope *previousVisibleSymbol = _scope; - _scope = scope; - const QList result = resolve(ast); - _scope = previousVisibleSymbol; + std::swap(_scope, scope); + std::swap(_reference, ref); + + const QList result = expression(ast); + + std::swap(_reference, ref); + std::swap(_scope, scope); + return result; } -QList ResolveExpression::resolve(ExpressionAST *ast) +QList ResolveExpression::expression(ExpressionAST *ast) { const QList previousResults = switchResults(QList()); 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; - - 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 funTy->maybeValidPrototype(actualArgumentCount); +} - 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 baseResults = resolve(ast->base_expression, _scope); // Compute the types of the actual arguments. - int actualArgumentCount = 0; + unsigned actualArgumentCount = 0; - //QList< QList > arguments; + QList< QList > 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 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 baseResults = resolve(ast->base_expression, _scope); - const QList indexResults = resolve(ast->expression); + const QList 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 receiverResults = resolve(ast->receiver_expression); + const QList receiverResults = resolve(ast->receiver_expression, _scope); foreach (const LookupItem &result, receiverResults) { FullySpecifiedType ty = result.type().simplified(); -- cgit v1.2.3