forked from qt-creator/qt-creator
Added some initial support for function overloading.
This commit is contained in:
@@ -42,6 +42,9 @@
|
||||
#include <AST.h>
|
||||
#include <Scope.h>
|
||||
#include <SymbolVisitor.h>
|
||||
#include <NameVisitor.h>
|
||||
#include <TypeVisitor.h>
|
||||
#include <CoreTypes.h>
|
||||
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QBitArray>
|
||||
@@ -789,9 +792,8 @@ Symbol *Snapshot::findMatchingDefinition(Symbol *declaration) const
|
||||
Function *best = 0;
|
||||
|
||||
foreach (Function *fun, viableFunctions) {
|
||||
if (fun->unqualifiedName()->isEqualTo(declaration->unqualifiedName()))
|
||||
if (! (fun->unqualifiedName() && fun->unqualifiedName()->isEqualTo(declaration->unqualifiedName())))
|
||||
continue;
|
||||
|
||||
else if (fun->argumentCount() == declarationTy->argumentCount()) {
|
||||
if (! best)
|
||||
best = fun;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -45,7 +45,8 @@ public:
|
||||
virtual ~ResolveExpression();
|
||||
|
||||
QList<LookupItem> operator()(ExpressionAST *ast, Scope *scope);
|
||||
QList<LookupItem> resolve(ExpressionAST *ast, Scope *scope);
|
||||
QList<LookupItem> resolve(ExpressionAST *ast, Scope *scope, bool ref = false);
|
||||
QList<LookupItem> reference(ExpressionAST *ast, Scope *scope);
|
||||
|
||||
ClassOrNamespace *baseExpression(const QList<LookupItem> &baseResults,
|
||||
int accessOp,
|
||||
@@ -56,7 +57,7 @@ public:
|
||||
protected:
|
||||
ClassOrNamespace *findClass(const FullySpecifiedType &ty, Scope *scope) const;
|
||||
|
||||
QList<LookupItem> resolve(ExpressionAST *ast);
|
||||
QList<LookupItem> expression(ExpressionAST *ast);
|
||||
|
||||
QList<LookupItem> switchResults(const QList<LookupItem> &symbols);
|
||||
FullySpecifiedType instantiate(const Name *className, Symbol *candidate) const;
|
||||
@@ -69,7 +70,8 @@ protected:
|
||||
void addResults(const QList<Symbol *> &symbols);
|
||||
void addResults(const QList<LookupItem> &items);
|
||||
|
||||
bool maybeValidPrototype(Function *funTy, unsigned actualArgumentCount) const;
|
||||
static bool maybeValidPrototype(Function *funTy, unsigned actualArgumentCount);
|
||||
bool implicitConversion(const FullySpecifiedType &sourceTy, const FullySpecifiedType &targetTy) const;
|
||||
|
||||
using ASTVisitor::visit;
|
||||
|
||||
@@ -119,6 +121,7 @@ private:
|
||||
LookupContext _context;
|
||||
Bind bind;
|
||||
QList<LookupItem> _results;
|
||||
bool _reference;
|
||||
};
|
||||
|
||||
} // end of namespace CPlusPlus
|
||||
|
||||
@@ -84,6 +84,20 @@ QList<LookupItem> TypeOfExpression::operator()(const QString &expression,
|
||||
scope);
|
||||
}
|
||||
|
||||
QList<LookupItem> TypeOfExpression::reference(const QString &expression,
|
||||
Scope *scope,
|
||||
PreprocessMode mode)
|
||||
{
|
||||
QString code = expression;
|
||||
|
||||
if (mode == Preprocess)
|
||||
code = preprocessedExpression(expression);
|
||||
|
||||
Document::Ptr expressionDoc = documentForExpression(code);
|
||||
expressionDoc->check();
|
||||
return reference(extractExpressionAST(expressionDoc), expressionDoc, scope);
|
||||
}
|
||||
|
||||
QList<LookupItem> TypeOfExpression::operator()(ExpressionAST *expression,
|
||||
Document::Ptr document,
|
||||
Scope *scope)
|
||||
@@ -104,6 +118,26 @@ QList<LookupItem> TypeOfExpression::operator()(ExpressionAST *expression,
|
||||
return items;
|
||||
}
|
||||
|
||||
QList<LookupItem> TypeOfExpression::reference(ExpressionAST *expression,
|
||||
Document::Ptr document,
|
||||
Scope *scope)
|
||||
{
|
||||
m_ast = expression;
|
||||
|
||||
m_scope = scope;
|
||||
|
||||
m_lookupContext = LookupContext(document, m_thisDocument, m_snapshot);
|
||||
m_lookupContext.setBindings(m_bindings);
|
||||
|
||||
ResolveExpression resolve(m_lookupContext);
|
||||
const QList<LookupItem> items = resolve.reference(m_ast, scope);
|
||||
|
||||
if (! m_bindings)
|
||||
m_lookupContext = resolve.context();
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
QString TypeOfExpression::preprocess(const QString &expression) const
|
||||
{
|
||||
return preprocessedExpression(expression);
|
||||
@@ -179,3 +213,4 @@ QString TypeOfExpression::preprocessedExpression(const QString &expression) cons
|
||||
const QByteArray preprocessedCode = preproc("<expression>", code);
|
||||
return QString::fromUtf8(preprocessedCode.constData(), preprocessedCode.size());
|
||||
}
|
||||
|
||||
|
||||
@@ -98,6 +98,14 @@ public:
|
||||
Document::Ptr document,
|
||||
Scope *scope);
|
||||
|
||||
QList<LookupItem> reference(const QString &expression,
|
||||
Scope *scope,
|
||||
PreprocessMode mode = NoPreprocess);
|
||||
|
||||
QList<LookupItem> reference(ExpressionAST *expression,
|
||||
Document::Ptr document,
|
||||
Scope *scope);
|
||||
|
||||
QString preprocess(const QString &expression) const;
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user