aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/cplusplus/ResolveExpression.cpp
diff options
context:
space:
mode:
authorRoberto Raggi <[email protected]>2010-12-10 10:32:46 +0100
committerRoberto Raggi <[email protected]>2010-12-10 10:32:46 +0100
commit63138eb808762e3f5b2f16ea21b860b7936af216 (patch)
tree0b7b873c5cb5d87d5b61c9d1c70a14681a7cc0a2 /src/libs/cplusplus/ResolveExpression.cpp
parent610023f893d92db04964ac5243237161623c64f6 (diff)
Added some initial support for function overloading.
Diffstat (limited to 'src/libs/cplusplus/ResolveExpression.cpp')
-rw-r--r--src/libs/cplusplus/ResolveExpression.cpp102
1 files changed, 71 insertions, 31 deletions
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<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;
-
- 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<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();