summaryrefslogtreecommitdiff
path: root/src/libs/cplusplus
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/cplusplus')
-rw-r--r--src/libs/cplusplus/CppDocument.cpp41
-rw-r--r--src/libs/cplusplus/CppRewriter.cpp186
-rw-r--r--src/libs/cplusplus/CppRewriter.h5
-rw-r--r--src/libs/cplusplus/LookupContext.cpp4
-rw-r--r--src/libs/cplusplus/ResolveExpression.cpp102
-rw-r--r--src/libs/cplusplus/ResolveExpression.h9
-rw-r--r--src/libs/cplusplus/SnapshotSymbolVisitor.cpp60
-rw-r--r--src/libs/cplusplus/SnapshotSymbolVisitor.h57
-rw-r--r--src/libs/cplusplus/SymbolNameVisitor.cpp55
-rw-r--r--src/libs/cplusplus/SymbolNameVisitor.h52
-rw-r--r--src/libs/cplusplus/TypeOfExpression.cpp35
-rw-r--r--src/libs/cplusplus/TypeOfExpression.h8
-rw-r--r--src/libs/cplusplus/cplusplus-lib.pri4
-rw-r--r--src/libs/cplusplus/cplusplus.pri4
14 files changed, 571 insertions, 51 deletions
diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp
index 53105fd5b4..ef159e9370 100644
--- a/src/libs/cplusplus/CppDocument.cpp
+++ b/src/libs/cplusplus/CppDocument.cpp
@@ -46,6 +46,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>
@@ -691,11 +694,17 @@ namespace {
class FindMatchingDefinition: public SymbolVisitor
{
Symbol *_declaration;
+ const OperatorNameId *_oper;
QList<Function *> _result;
public:
FindMatchingDefinition(Symbol *declaration)
- : _declaration(declaration) {}
+ : _declaration(declaration)
+ , _oper(0)
+ {
+ if (_declaration->name())
+ _oper = _declaration->name()->asOperatorNameId();
+ }
QList<Function *> result() const { return _result; }
@@ -703,8 +712,15 @@ public:
virtual bool visit(Function *fun)
{
- if (_declaration->identifier()->isEqualTo(fun->identifier()))
- _result.append(fun);
+ if (_oper) {
+ if (const Name *name = fun->unqualifiedName()) {
+ if (_oper->isEqualTo(name))
+ _result.append(fun);
+ }
+ } else if (const Identifier *id = _declaration->identifier()) {
+ if (id->isEqualTo(fun->identifier()))
+ _result.append(fun);
+ }
return false;
}
@@ -718,7 +734,7 @@ public:
Symbol *Snapshot::findMatchingDefinition(Symbol *declaration) const
{
- if (! (declaration && declaration->identifier()))
+ if (!declaration)
return 0;
Document::Ptr thisDocument = document(QString::fromUtf8(declaration->fileName(), declaration->fileNameLength()));
@@ -734,9 +750,19 @@ Symbol *Snapshot::findMatchingDefinition(Symbol *declaration) const
}
foreach (Document::Ptr doc, *this) {
- if (! doc->control()->findIdentifier(declaration->identifier()->chars(),
- declaration->identifier()->size()))
+ const Identifier *id = declaration->identifier();
+ if (id && ! doc->control()->findIdentifier(id->chars(),
+ id->size()))
continue;
+ if (!id) {
+ if (!declaration->name())
+ continue;
+ const OperatorNameId *oper = declaration->name()->asOperatorNameId();
+ if (!oper)
+ continue;
+ if (!doc->control()->findOperatorNameId(oper->kind()))
+ continue;
+ }
FindMatchingDefinition candidates(declaration);
candidates.accept(doc->globalNamespace());
@@ -770,9 +796,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/CppRewriter.cpp b/src/libs/cplusplus/CppRewriter.cpp
index 8c11c03a02..40b360abda 100644
--- a/src/libs/cplusplus/CppRewriter.cpp
+++ b/src/libs/cplusplus/CppRewriter.cpp
@@ -41,11 +41,12 @@
#include <Overview.h>
#include <QtCore/QVarLengthArray>
+#include <QtCore/QRegExp>
#include <QtCore/QDebug>
-using namespace CPlusPlus;
+namespace CPlusPlus {
-class CPlusPlus::Rewrite
+class Rewrite
{
public:
Rewrite(Control *control, SubstitutionEnvironment *env)
@@ -418,18 +419,187 @@ FullySpecifiedType UseQualifiedNames::apply(const Name *name, Rewrite *rewrite)
}
-FullySpecifiedType CPlusPlus::rewriteType(const FullySpecifiedType &type,
- SubstitutionEnvironment *env,
- Control *control)
+FullySpecifiedType rewriteType(const FullySpecifiedType &type,
+ SubstitutionEnvironment *env,
+ Control *control)
{
Rewrite rewrite(control, env);
return rewrite.rewriteType(type);
}
-const Name *CPlusPlus::rewriteName(const Name *name,
- SubstitutionEnvironment *env,
- Control *control)
+const Name *rewriteName(const Name *name,
+ SubstitutionEnvironment *env,
+ Control *control)
{
Rewrite rewrite(control, env);
return rewrite.rewriteName(name);
}
+
+// Simplify complicated STL template types,
+// such as 'std::basic_string<char,std::char_traits<char>,std::allocator<char> >'
+// -> 'std::string' and helpers.
+
+static QString chopConst(QString type)
+{
+ while (1) {
+ if (type.startsWith(QLatin1String("const")))
+ type = type.mid(5);
+ else if (type.startsWith(QLatin1Char(' ')))
+ type = type.mid(1);
+ else if (type.endsWith(QLatin1String("const")))
+ type.chop(5);
+ else if (type.endsWith(QLatin1Char(' ')))
+ type.chop(1);
+ else
+ break;
+ }
+ return type;
+}
+
+static inline QRegExp stdStringRegExp(const QString &charType)
+{
+ QString rc = QLatin1String("basic_string<");
+ rc += charType;
+ rc += QLatin1String(",[ ]?std::char_traits<");
+ rc += charType;
+ rc += QLatin1String(">,[ ]?std::allocator<");
+ rc += charType;
+ rc += QLatin1String("> >");
+ const QRegExp re(rc);
+ Q_ASSERT(re.isValid());
+ return re;
+}
+
+// Simplify string types in a type
+// 'std::set<std::basic_string<char... > >' -> std::set<std::string>'
+static inline void simplifyStdString(const QString &charType, const QString &replacement,
+ QString *type)
+{
+ QRegExp stringRegexp = stdStringRegExp(charType);
+ const int replacementSize = replacement.size();
+ for (int pos = 0; pos < type->size(); ) {
+ // Check next match
+ const int matchPos = stringRegexp.indexIn(*type, pos);
+ if (matchPos == -1)
+ break;
+ const int matchedLength = stringRegexp.matchedLength();
+ type->replace(matchPos, matchedLength, replacement);
+ pos = matchPos + replacementSize;
+ // If we were inside an 'allocator<std::basic_string..char > >'
+ // kill the following blank -> 'allocator<std::string>'
+ if (pos + 1 < type->size() && type->at(pos) == QLatin1Char(' ')
+ && type->at(pos + 1) == QLatin1Char('>'))
+ type->remove(pos, 1);
+ }
+}
+
+// Fix 'std::allocator<std::string >' -> 'std::allocator<std::string>',
+// which can happen when replacing/simplifying
+static inline QString fixNestedTemplates(QString s)
+{
+ const int size = s.size();
+ if (size > 3
+ && s.at(size - 1) == QLatin1Char('>')
+ && s.at(size - 2) == QLatin1Char(' ')
+ && s.at(size - 3) != QLatin1Char('>'))
+ s.remove(size - 2, 1);
+ return s;
+}
+
+CPLUSPLUS_EXPORT QString simplifySTLType(const QString &typeIn)
+{
+ QString type = typeIn;
+ if (type.startsWith("class ")) // MSVC prepends class,struct
+ type.remove(0, 6);
+ if (type.startsWith("struct "))
+ type.remove(0, 7);
+
+ type.replace(QLatin1Char('*'), QLatin1Char('@'));
+
+ for (int i = 0; i < 10; ++i) {
+ int start = type.indexOf("std::allocator<");
+ if (start == -1)
+ break;
+ // search for matching '>'
+ int pos;
+ int level = 0;
+ for (pos = start + 12; pos < type.size(); ++pos) {
+ int c = type.at(pos).unicode();
+ if (c == '<') {
+ ++level;
+ } else if (c == '>') {
+ --level;
+ if (level == 0)
+ break;
+ }
+ }
+ const QString alloc = fixNestedTemplates(type.mid(start, pos + 1 - start).trimmed());
+ const QString inner = fixNestedTemplates(alloc.mid(15, alloc.size() - 16).trimmed());
+ if (inner == QLatin1String("char")) { // std::string
+ simplifyStdString(QLatin1String("char"), QLatin1String("string"), &type);
+ } else if (inner == QLatin1String("wchar_t")) { // std::wstring
+ simplifyStdString(QLatin1String("wchar_t"), QLatin1String("wstring"), &type);
+ } else if (inner == QLatin1String("unsigned short")) { // std::wstring/MSVC
+ simplifyStdString(QLatin1String("unsigned short"), QLatin1String("wstring"), &type);
+ }
+ // std::vector, std::deque, std::list
+ const QRegExp re1(QString::fromLatin1("(vector|list|deque)<%1, ?%2\\s*>").arg(inner, alloc));
+ Q_ASSERT(re1.isValid());
+ if (re1.indexIn(type) != -1)
+ type.replace(re1.cap(0), QString::fromLatin1("%1<%2>").arg(re1.cap(1), inner));
+
+ // std::stack
+ QRegExp stackRE(QString::fromLatin1("stack<%1, ?std::deque<%2> >").arg(inner, inner));
+ stackRE.setMinimal(true);
+ Q_ASSERT(stackRE.isValid());
+ if (stackRE.indexIn(type) != -1)
+ type.replace(stackRE.cap(0), QString::fromLatin1("stack<%1>").arg(inner));
+
+ // std::set
+ QRegExp setRE(QString::fromLatin1("set<%1, ?std::less<%2>, ?%3\\s*>").arg(inner, inner, alloc));
+ setRE.setMinimal(true);
+ Q_ASSERT(setRE.isValid());
+ if (setRE.indexIn(type) != -1)
+ type.replace(setRE.cap(0), QString::fromLatin1("set<%1>").arg(inner));
+
+ // std::map
+ if (inner.startsWith("std::pair<")) {
+ // search for outermost ',', split key and value
+ int pos;
+ int level = 0;
+ for (pos = 10; pos < inner.size(); ++pos) {
+ int c = inner.at(pos).unicode();
+ if (c == '<')
+ ++level;
+ else if (c == '>')
+ --level;
+ else if (c == ',' && level == 0)
+ break;
+ }
+ const QString key = chopConst(inner.mid(10, pos - 10));
+ // Get value: MSVC: 'pair<a const ,b>', gcc: 'pair<const a, b>'
+ if (inner.at(++pos) == QLatin1Char(' '))
+ pos++;
+ QString value = inner.mid(pos, inner.size() - pos - 1).trimmed();
+ QRegExp mapRE1(QString("map<%1, ?%2, ?std::less<%3 ?>, ?%4\\s*>")
+ .arg(key, value, key, alloc));
+ mapRE1.setMinimal(true);
+ Q_ASSERT(mapRE1.isValid());
+ if (mapRE1.indexIn(type) != -1) {
+ type.replace(mapRE1.cap(0), QString("map<%1, %2>").arg(key, value));
+ } else {
+ QRegExp mapRE2(QString("map<const %1, ?%2, ?std::less<const %3>, ?%4\\s*>")
+ .arg(key, value, key, alloc));
+ mapRE2.setMinimal(true);
+ if (mapRE2.indexIn(type) != -1) {
+ type.replace(mapRE2.cap(0), QString("map<const %1, %2>").arg(key, value));
+ }
+ }
+ }
+ }
+ type.replace(QLatin1Char('@'), QLatin1Char('*'));
+ type.replace(QLatin1String(" >"), QLatin1String(">"));
+ return type;
+}
+
+} // namespace CPlusPlus
diff --git a/src/libs/cplusplus/CppRewriter.h b/src/libs/cplusplus/CppRewriter.h
index 93326ffee3..fa5264310c 100644
--- a/src/libs/cplusplus/CppRewriter.h
+++ b/src/libs/cplusplus/CppRewriter.h
@@ -108,6 +108,11 @@ CPLUSPLUS_EXPORT const Name *rewriteName(const Name *name,
SubstitutionEnvironment *env,
Control *control);
+// Simplify complicated STL template types, such as
+// 'std::basic_string<char,std::char_traits<char>,std::allocator<char> > '->
+// 'std::string'.
+CPLUSPLUS_EXPORT QString simplifySTLType(const QString &typeIn);
+
} // end of namespace CPlusPlus
#endif
diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp
index d14413e5b5..cdf95bc9dc 100644
--- a/src/libs/cplusplus/LookupContext.cpp
+++ b/src/libs/cplusplus/LookupContext.cpp
@@ -460,6 +460,8 @@ void ClassOrNamespace::lookup_helper(const Name *name, ClassOrNamespace *binding
foreach (Symbol *s, binding->symbols()) {
if (s->isFriend())
continue;
+ else if (s->isUsingNamespaceDirective())
+ continue;
if (Scope *scope = s->asScope()) {
if (Class *klass = scope->asClass()) {
@@ -513,6 +515,8 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope,
for (Symbol *s = scope->find(id); s; s = s->next()) {
if (s->isFriend())
continue; // skip friends
+ else if (s->isUsingNamespaceDirective())
+ continue; // skip using namespace directives
else if (! id->isEqualTo(s->identifier()))
continue;
else if (s->name()->isQualifiedNameId())
diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp
index 890ee12c3d..cad552f923 100644
--- a/src/libs/cplusplus/ResolveExpression.cpp
+++ b/src/libs/cplusplus/ResolveExpression.cpp
@@ -79,7 +79,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()
@@ -88,19 +89,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);
@@ -445,27 +453,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)
@@ -473,14 +472,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) {
@@ -517,7 +557,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);
@@ -713,7 +753,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 49b79e9e38..1c0215462c 100644
--- a/src/libs/cplusplus/ResolveExpression.h
+++ b/src/libs/cplusplus/ResolveExpression.h
@@ -49,7 +49,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,
@@ -60,7 +61,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;
@@ -73,7 +74,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;
@@ -123,6 +125,7 @@ private:
LookupContext _context;
Bind bind;
QList<LookupItem> _results;
+ bool _reference;
};
} // end of namespace CPlusPlus
diff --git a/src/libs/cplusplus/SnapshotSymbolVisitor.cpp b/src/libs/cplusplus/SnapshotSymbolVisitor.cpp
new file mode 100644
index 0000000000..7962d3f928
--- /dev/null
+++ b/src/libs/cplusplus/SnapshotSymbolVisitor.cpp
@@ -0,0 +1,60 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "SnapshotSymbolVisitor.h"
+#include <Symbols.h>
+
+using namespace CPlusPlus;
+
+SnapshotSymbolVisitor::SnapshotSymbolVisitor(const Snapshot &snapshot)
+ : _snapshot(snapshot)
+{
+}
+
+void SnapshotSymbolVisitor::accept(Document::Ptr doc)
+{
+ QSet<QString> processed;
+ accept(doc, &processed);
+}
+
+void SnapshotSymbolVisitor::accept(Document::Ptr doc, QSet<QString> *processed)
+{
+ if (doc && doc->globalNamespace() && ! processed->contains(doc->fileName())) {
+ processed->insert(doc->fileName());
+
+ foreach (const Document::Include &i, doc->includes()) {
+ if (Document::Ptr incl = _snapshot.document(i.fileName()))
+ accept(incl, processed);
+ }
+
+ std::swap(_document, doc);
+ accept(_document->globalNamespace());
+ std::swap(_document, doc);
+ }
+}
diff --git a/src/libs/cplusplus/SnapshotSymbolVisitor.h b/src/libs/cplusplus/SnapshotSymbolVisitor.h
new file mode 100644
index 0000000000..13d639aea1
--- /dev/null
+++ b/src/libs/cplusplus/SnapshotSymbolVisitor.h
@@ -0,0 +1,57 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef CPLUSPLUS_SNAPSHOTSYMBOLVISITOR_H
+#define CPLUSPLUS_SNAPSHOTSYMBOLVISITOR_H
+
+#include "CppDocument.h"
+#include <SymbolVisitor.h>
+#include <QtCore/QSet>
+
+namespace CPlusPlus {
+
+class CPLUSPLUS_EXPORT SnapshotSymbolVisitor : public CPlusPlus::SymbolVisitor
+{
+public:
+ SnapshotSymbolVisitor(const Snapshot &snapshot);
+
+ void accept(Document::Ptr doc);
+ using SymbolVisitor::accept;
+
+protected:
+ void accept(Document::Ptr doc, QSet<QString> *processed);
+
+private:
+ Snapshot _snapshot;
+ Document::Ptr _document;
+};
+
+} // end of namespace CPlusPlus
+
+#endif // CPLUSPLUS_SNAPSHOTSYMBOLVISITOR_H
diff --git a/src/libs/cplusplus/SymbolNameVisitor.cpp b/src/libs/cplusplus/SymbolNameVisitor.cpp
new file mode 100644
index 0000000000..c384e36dcd
--- /dev/null
+++ b/src/libs/cplusplus/SymbolNameVisitor.cpp
@@ -0,0 +1,55 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "SymbolNameVisitor.h"
+#include <Symbols.h>
+#include <Names.h>
+
+using namespace CPlusPlus;
+
+SymbolNameVisitor::SymbolNameVisitor()
+ : _symbol(0)
+{
+}
+
+void SymbolNameVisitor::accept(Symbol *symbol)
+{
+ if (symbol) {
+ if (Scope *scope = symbol->enclosingScope())
+ accept(scope);
+
+ if (! symbol->isTemplate()) {
+ if (const Name *name = symbol->name()) {
+ std::swap(_symbol, symbol);
+ accept(name);
+ std::swap(_symbol, symbol);
+ }
+ }
+ }
+}
diff --git a/src/libs/cplusplus/SymbolNameVisitor.h b/src/libs/cplusplus/SymbolNameVisitor.h
new file mode 100644
index 0000000000..8b41be18c9
--- /dev/null
+++ b/src/libs/cplusplus/SymbolNameVisitor.h
@@ -0,0 +1,52 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef CPLUSPLUS_SYMBOLNAMEVISITOR_H
+#define CPLUSPLUS_SYMBOLNAMEVISITOR_H
+
+#include <NameVisitor.h>
+
+namespace CPlusPlus {
+
+class CPLUSPLUS_EXPORT SymbolNameVisitor : public CPlusPlus::NameVisitor
+{
+public:
+ SymbolNameVisitor();
+
+ void accept(Symbol *symbol);
+
+ using NameVisitor::accept;
+
+private:
+ Symbol *_symbol;
+};
+
+} // end of namespace CPlusPlus
+
+#endif // CPLUSPLUS_SYMBOLNAMEVISITOR_H
diff --git a/src/libs/cplusplus/TypeOfExpression.cpp b/src/libs/cplusplus/TypeOfExpression.cpp
index adf84ae41d..7a268c4402 100644
--- a/src/libs/cplusplus/TypeOfExpression.cpp
+++ b/src/libs/cplusplus/TypeOfExpression.cpp
@@ -88,6 +88,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)
@@ -108,6 +122,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);
@@ -183,3 +217,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 6ca59f690e..4852baa152 100644
--- a/src/libs/cplusplus/TypeOfExpression.h
+++ b/src/libs/cplusplus/TypeOfExpression.h
@@ -102,6 +102,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/libs/cplusplus/cplusplus-lib.pri b/src/libs/cplusplus/cplusplus-lib.pri
index 2a718d5712..395636a23c 100644
--- a/src/libs/cplusplus/cplusplus-lib.pri
+++ b/src/libs/cplusplus/cplusplus-lib.pri
@@ -37,6 +37,8 @@ HEADERS += \
$$PWD/LookupContext.h \
$$PWD/ASTParent.h \
$$PWD/ASTPath.h \
+ $$PWD/SnapshotSymbolVisitor.h \
+ $$PWD/SymbolNameVisitor.h \
$$PWD/DeprecatedGenTemplateInstance.h \
$$PWD/FindUsages.h \
$$PWD/DependencyTable.h \
@@ -63,6 +65,8 @@ SOURCES += \
$$PWD/LookupContext.cpp \
$$PWD/ASTParent.cpp \
$$PWD/ASTPath.cpp \
+ $$PWD/SnapshotSymbolVisitor.cpp \
+ $$PWD/SymbolNameVisitor.cpp \
$$PWD/DeprecatedGenTemplateInstance.cpp \
$$PWD/FindUsages.cpp \
$$PWD/DependencyTable.cpp \
diff --git a/src/libs/cplusplus/cplusplus.pri b/src/libs/cplusplus/cplusplus.pri
index 50a03111e9..85cb972095 100644
--- a/src/libs/cplusplus/cplusplus.pri
+++ b/src/libs/cplusplus/cplusplus.pri
@@ -1,3 +1,5 @@
INCLUDEPATH += $$IDE_SOURCE_TREE/src/shared/cplusplus
DEPENDPATH += $$IDE_SOURCE_TREE/src/shared/cplusplus
-LIBS *= -l$$qtLibraryTarget(CPlusPlus)
+INCLUDEPATH += $$IDE_SOURCE_TREE/src/libs/cplusplus
+DEPENDPATH += $$IDE_SOURCE_TREE/src/libs/cplusplus
+LIBS *= -l$$qtLibraryName(CPlusPlus)