summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libs/cplusplus/CppDocument.cpp6
-rw-r--r--src/libs/cplusplus/ResolveExpression.cpp102
-rw-r--r--src/libs/cplusplus/ResolveExpression.h9
-rw-r--r--src/libs/cplusplus/TypeOfExpression.cpp35
-rw-r--r--src/libs/cplusplus/TypeOfExpression.h8
-rw-r--r--src/plugins/cppeditor/cppeditor.cpp38
-rw-r--r--src/shared/cplusplus/Control.cpp16
-rw-r--r--src/shared/cplusplus/Control.h3
-rw-r--r--src/shared/cplusplus/Symbols.cpp24
-rw-r--r--src/shared/cplusplus/Symbols.h2
10 files changed, 195 insertions, 48 deletions
diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp
index 8383beef3b..6af10cf761 100644
--- a/src/libs/cplusplus/CppDocument.cpp
+++ b/src/libs/cplusplus/CppDocument.cpp
@@ -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;
diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp
index 13547593ca..965d399d3e 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();
diff --git a/src/libs/cplusplus/ResolveExpression.h b/src/libs/cplusplus/ResolveExpression.h
index de42964176..70fad7ef3e 100644
--- a/src/libs/cplusplus/ResolveExpression.h
+++ b/src/libs/cplusplus/ResolveExpression.h
@@ -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
diff --git a/src/libs/cplusplus/TypeOfExpression.cpp b/src/libs/cplusplus/TypeOfExpression.cpp
index 2177cdd930..1a0d84bd05 100644
--- a/src/libs/cplusplus/TypeOfExpression.cpp
+++ b/src/libs/cplusplus/TypeOfExpression.cpp
@@ -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());
}
+
diff --git a/src/libs/cplusplus/TypeOfExpression.h b/src/libs/cplusplus/TypeOfExpression.h
index c1ab1288aa..bb28c6f938 100644
--- a/src/libs/cplusplus/TypeOfExpression.h
+++ b/src/libs/cplusplus/TypeOfExpression.h
@@ -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;
/**
diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index 10672b0e8d..f80b61291f 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -76,6 +76,7 @@
#include <extensionsystem/pluginmanager.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <texteditor/basetextdocument.h>
+#include <texteditor/basetextdocumentlayout.h>
#include <texteditor/fontsettings.h>
#include <texteditor/tabsettings.h>
#include <texteditor/texteditorconstants.h>
@@ -1265,6 +1266,13 @@ CPPEditor::Link CPPEditor::attemptFuncDeclDef(const QTextCursor &cursor, const D
return result;
}
+ for (int i = path.size() - 1; i != -1; --i) {
+ AST *node = path.at(i);
+
+ if (node->asParameterDeclaration() != 0)
+ return result;
+ }
+
AST *declParent = 0;
DeclaratorAST *decl = 0;
for (int i = path.size() - 2; i > 0; --i) {
@@ -1431,11 +1439,27 @@ CPPEditor::Link CPPEditor::findLinkAt(const QTextCursor &cursor,
// Evaluate the type of the expression under the cursor
ExpressionUnderCursor expressionUnderCursor;
- const QString expression = expressionUnderCursor(tc);
+ QString expression = expressionUnderCursor(tc);
+
+ for (int pos = tc.position();; ++pos) {
+ const QChar ch = characterAt(pos);
+ if (ch.isSpace())
+ continue;
+ else {
+ if (ch == QLatin1Char('(') && ! expression.isEmpty()) {
+ tc.setPosition(pos);
+ if (TextEditor::TextBlockUserData::findNextClosingParenthesis(&tc, true)) {
+ expression.append(tc.selectedText());
+ }
+ }
+
+ break;
+ }
+ }
TypeOfExpression typeOfExpression;
typeOfExpression.init(doc, snapshot);
- const QList<LookupItem> resolvedSymbols = typeOfExpression(expression, scope, TypeOfExpression::Preprocess);
+ const QList<LookupItem> resolvedSymbols = typeOfExpression.reference(expression, scope, TypeOfExpression::Preprocess);
if (!resolvedSymbols.isEmpty()) {
LookupItem result = skipForwardDeclarations(resolvedSymbols);
@@ -1473,16 +1497,6 @@ CPPEditor::Link CPPEditor::findLinkAt(const QTextCursor &cursor,
link.begin = beginOfToken;
link.end = endOfToken;
return link;
-
- // This would jump to the type of a name
-#if 0
- } else if (NamedType *namedType = firstType->asNamedType()) {
- QList<Symbol *> candidates = context.resolve(namedType->name());
- if (!candidates.isEmpty()) {
- Symbol *s = candidates.takeFirst();
- openCppEditorAt(s->fileName(), s->line(), s->column());
- }
-#endif
}
} else {
// Handle macro uses
diff --git a/src/shared/cplusplus/Control.cpp b/src/shared/cplusplus/Control.cpp
index 4cfd8de636..d36e8b809f 100644
--- a/src/shared/cplusplus/Control.cpp
+++ b/src/shared/cplusplus/Control.cpp
@@ -759,6 +759,22 @@ const Identifier *Control::objcCopyId() const
const Identifier *Control::objcNonatomicId() const
{ return d->objcNonatomicId; }
+Symbol **Control::firstSymbol() const
+{
+ if (d->symbols.empty())
+ return 0;
+
+ return &*d->symbols.begin();
+}
+
+Symbol **Control::lastSymbol() const
+{
+ if (d->symbols.empty())
+ return 0;
+
+ return &*d->symbols.begin() + d->symbols.size();
+}
+
bool Control::hasSymbol(Symbol *symbol) const
{
return std::find(d->symbols.begin(), d->symbols.end(), symbol) != d->symbols.end();
diff --git a/src/shared/cplusplus/Control.h b/src/shared/cplusplus/Control.h
index e475a17567..461c6453f6 100644
--- a/src/shared/cplusplus/Control.h
+++ b/src/shared/cplusplus/Control.h
@@ -212,6 +212,9 @@ public:
const NumericLiteral *numericLiteral(const char *chars, unsigned size);
const NumericLiteral *numericLiteral(const char *chars);
+ Symbol **firstSymbol() const;
+ Symbol **lastSymbol() const;
+
bool hasSymbol(Symbol *symbol) const;
void squeeze();
diff --git a/src/shared/cplusplus/Symbols.cpp b/src/shared/cplusplus/Symbols.cpp
index 0bb231e796..d2b402ea5f 100644
--- a/src/shared/cplusplus/Symbols.cpp
+++ b/src/shared/cplusplus/Symbols.cpp
@@ -362,6 +362,30 @@ void Function::visitSymbol0(SymbolVisitor *visitor)
}
}
+bool Function::maybeValidPrototype(unsigned actualArgumentCount) const
+{
+ unsigned minNumberArguments = 0;
+
+ for (; minNumberArguments < this->argumentCount(); ++minNumberArguments) {
+ Argument *arg = this->argumentAt(minNumberArguments)->asArgument();
+
+ if (arg->hasInitializer())
+ break;
+ }
+
+ if (actualArgumentCount < minNumberArguments) {
+ // not enough arguments.
+ return false;
+
+ } else if (! this->isVariadic() && actualArgumentCount > this->argumentCount()) {
+ // too many arguments.
+ return false;
+ }
+
+ return true;
+}
+
+
Block::Block(TranslationUnit *translationUnit, unsigned sourceLocation)
: Scope(translationUnit, sourceLocation, /*name = */ 0)
{ }
diff --git a/src/shared/cplusplus/Symbols.h b/src/shared/cplusplus/Symbols.h
index cd618a9c87..f27502796a 100644
--- a/src/shared/cplusplus/Symbols.h
+++ b/src/shared/cplusplus/Symbols.h
@@ -350,6 +350,8 @@ public:
bool isAmbiguous() const; // internal
void setAmbiguous(bool isAmbiguous); // internal
+ bool maybeValidPrototype(unsigned actualArgumentCount) const;
+
protected:
virtual void visitSymbol0(SymbolVisitor *visitor);
virtual void accept0(TypeVisitor *visitor);