aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/cplusplus
diff options
context:
space:
mode:
authorOrgad Shaneh <[email protected]>2015-03-25 22:32:46 +0200
committerOrgad Shaneh <[email protected]>2015-04-11 17:27:44 +0000
commitaedfbd571065be9410788b7402a04139135729c3 (patch)
treef48f582c42b8bc75e30b0cf4cb61b300249d58d5 /src/libs/cplusplus
parent7ba2210102ce12ae845cccfa17624d59a1ba66bd (diff)
C++: Extract TypedefsResolver out of ResolveExpression
... and rename it TypeResolver Change-Id: I5cb076812d2e3ac132f18ea884ec69328b69999c Reviewed-by: Przemyslaw Gorszkowski <[email protected]>
Diffstat (limited to 'src/libs/cplusplus')
-rw-r--r--src/libs/cplusplus/ResolveExpression.cpp143
-rw-r--r--src/libs/cplusplus/TypeResolver.cpp160
-rw-r--r--src/libs/cplusplus/TypeResolver.h64
-rw-r--r--src/libs/cplusplus/cplusplus-lib.pri2
-rw-r--r--src/libs/cplusplus/cplusplus.qbs1
5 files changed, 234 insertions, 136 deletions
diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp
index adaac12ab5f..e38d634b8cd 100644
--- a/src/libs/cplusplus/ResolveExpression.cpp
+++ b/src/libs/cplusplus/ResolveExpression.cpp
@@ -35,6 +35,7 @@
#include "DeprecatedGenTemplateInstance.h"
#include "CppRewriter.h"
#include "TypeOfExpression.h"
+#include "TypeResolver.h"
#include <cplusplus/Control.h>
#include <cplusplus/AST.h>
@@ -75,131 +76,6 @@ static QList<T> removeDuplicates(const QList<T> &results)
return uniqueList;
}
-class TypedefsResolver
-{
-public:
- TypedefsResolver(const LookupContext &context) : _context(context) {}
- void resolve(FullySpecifiedType *type, Scope **scope, ClassOrNamespace *binding)
- {
- QSet<Symbol *> visited;
- _binding = binding;
- // Use a hard limit when trying to resolve typedefs. Typedefs in templates can refer to
- // each other, each time enhancing the template argument and thus making it impossible to
- // use an "alreadyResolved" container. FIXME: We might overcome this by resolving the
- // template parameters.
- unsigned maxDepth = 15;
- for (NamedType *namedTy = 0; maxDepth && (namedTy = getNamedType(*type)); --maxDepth) {
- QList<LookupItem> namedTypeItems = getNamedTypeItems(namedTy->name(), *scope, _binding);
-
- if (Q_UNLIKELY(debug))
- qDebug() << "-- we have" << namedTypeItems.size() << "candidates";
-
- if (!findTypedef(namedTypeItems, type, scope, visited))
- break;
- }
- }
-
-private:
- NamedType *getNamedType(FullySpecifiedType& type) const
- {
- NamedType *namedTy = type->asNamedType();
- if (! namedTy) {
- if (PointerType *pointerTy = type->asPointerType())
- namedTy = pointerTy->elementType()->asNamedType();
- }
- return namedTy;
- }
-
- QList<LookupItem> getNamedTypeItems(const Name *name, Scope *scope,
- ClassOrNamespace *binding) const
- {
- QList<LookupItem> namedTypeItems = typedefsFromScopeUpToFunctionScope(name, scope);
- if (namedTypeItems.isEmpty()) {
- if (binding)
- namedTypeItems = binding->lookup(name);
- if (ClassOrNamespace *scopeCon = _context.lookupType(scope))
- namedTypeItems += scopeCon->lookup(name);
- }
-
- return namedTypeItems;
- }
-
- /// Return all typedefs with given name from given scope up to function scope.
- static QList<LookupItem> typedefsFromScopeUpToFunctionScope(const Name *name, Scope *scope)
- {
- QList<LookupItem> results;
- if (!scope)
- return results;
- Scope *enclosingBlockScope = 0;
- for (Block *block = scope->asBlock(); block;
- block = enclosingBlockScope ? enclosingBlockScope->asBlock() : 0) {
- const unsigned memberCount = block->memberCount();
- for (unsigned i = 0; i < memberCount; ++i) {
- Symbol *symbol = block->memberAt(i);
- if (Declaration *declaration = symbol->asDeclaration()) {
- if (isTypedefWithName(declaration, name)) {
- LookupItem item;
- item.setDeclaration(declaration);
- item.setScope(block);
- item.setType(declaration->type());
- results.append(item);
- }
- }
- }
- enclosingBlockScope = block->enclosingScope();
- }
- return results;
- }
-
- static bool isTypedefWithName(const Declaration *declaration, const Name *name)
- {
- if (declaration->isTypedef()) {
- const Identifier *identifier = declaration->name()->identifier();
- if (name->identifier()->match(identifier))
- return true;
- }
- return false;
- }
-
- bool findTypedef(const QList<LookupItem>& namedTypeItems, FullySpecifiedType *type,
- Scope **scope, QSet<Symbol *>& visited)
- {
- bool foundTypedef = false;
- foreach (const LookupItem &it, namedTypeItems) {
- Symbol *declaration = it.declaration();
- if (declaration && declaration->isTypedef()) {
- if (visited.contains(declaration))
- break;
- visited.insert(declaration);
-
- // continue working with the typedefed type and scope
- if (type->type()->isPointerType()) {
- *type = FullySpecifiedType(
- _context.bindings()->control()->pointerType(declaration->type()));
- } else if (type->type()->isReferenceType()) {
- *type = FullySpecifiedType(
- _context.bindings()->control()->referenceType(
- declaration->type(),
- declaration->type()->asReferenceType()->isRvalueReference()));
- } else {
- *type = declaration->type();
- }
-
- *scope = it.scope();
- _binding = it.binding();
- foundTypedef = true;
- break;
- }
- }
-
- return foundTypedef;
- }
-
- const LookupContext &_context;
- // binding has to be remembered in case of resolving typedefs for templates
- ClassOrNamespace *_binding;
-};
-
static int evaluateFunctionArgument(const FullySpecifiedType &actualTy,
const FullySpecifiedType &formalTy)
{
@@ -916,8 +792,8 @@ bool ResolveExpression::visit(ArrayAccessAST *ast)
FullySpecifiedType ty = result.type().simplified();
Scope *scope = result.scope();
- TypedefsResolver typedefsResolver(_context);
- typedefsResolver.resolve(&ty, &scope, result.binding());
+ TypeResolver typeResolver(_context);
+ typeResolver.resolve(&ty, &scope, result.binding());
if (PointerType *ptrTy = ty->asPointerType()) {
addResult(ptrTy->elementType().simplified(), scope);
@@ -1047,7 +923,7 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas
qDebug() << "In ResolveExpression::baseExpression with" << baseResults.size() << "results...";
int i = 0;
Overview oo;
- TypedefsResolver typedefsResolver(_context);
+ TypeResolver typeResolver(_context);
foreach (const LookupItem &r, baseResults) {
if (!r.type().type() || !r.scope())
@@ -1056,15 +932,10 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas
FullySpecifiedType originalType = ty;
Scope *scope = r.scope();
- if (Q_UNLIKELY(debug)) {
+ if (Q_UNLIKELY(debug))
qDebug("trying result #%d", ++i);
- qDebug() << "- before typedef resolving we have:" << oo(ty);
- }
- typedefsResolver.resolve(&ty, &scope, r.binding());
-
- if (Q_UNLIKELY(debug))
- qDebug() << "- after typedef resolving:" << oo(ty);
+ typeResolver.resolve(&ty, &scope, r.binding());
if (accessOp == T_ARROW) {
if (PointerType *ptrTy = ty->asPointerType()) {
@@ -1105,7 +976,7 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas
FullySpecifiedType retTy
= instantiatedFunction->returnType().simplified();
- typedefsResolver.resolve(&retTy, &functionScope, r.binding());
+ typeResolver.resolve(&retTy, &functionScope, r.binding());
if (! retTy->isPointerType() && ! retTy->isNamedType())
continue;
diff --git a/src/libs/cplusplus/TypeResolver.cpp b/src/libs/cplusplus/TypeResolver.cpp
new file mode 100644
index 00000000000..80ae16f2efd
--- /dev/null
+++ b/src/libs/cplusplus/TypeResolver.cpp
@@ -0,0 +1,160 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** 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 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "TypeResolver.h"
+#include "Overview.h"
+
+#include <QDebug>
+
+static const bool debug = ! qgetenv("QTC_LOOKUPCONTEXT_DEBUG").isEmpty();
+
+namespace CPlusPlus {
+
+void TypeResolver::resolve(FullySpecifiedType *type, Scope **scope, ClassOrNamespace *binding)
+{
+ QSet<Symbol *> visited;
+ _binding = binding;
+ // Use a hard limit when trying to resolve typedefs. Typedefs in templates can refer to
+ // each other, each time enhancing the template argument and thus making it impossible to
+ // use an "alreadyResolved" container. FIXME: We might overcome this by resolving the
+ // template parameters.
+ unsigned maxDepth = 15;
+ Overview oo;
+ if (Q_UNLIKELY(debug))
+ qDebug() << "- before typedef resolving we have:" << oo(*type);
+ for (NamedType *namedTy = 0; maxDepth && (namedTy = getNamedType(*type)); --maxDepth) {
+ QList<LookupItem> namedTypeItems = getNamedTypeItems(namedTy->name(), *scope, _binding);
+
+ if (Q_UNLIKELY(debug))
+ qDebug() << "-- we have" << namedTypeItems.size() << "candidates";
+
+ if (!findTypedef(namedTypeItems, type, scope, visited))
+ break;
+ }
+ if (Q_UNLIKELY(debug))
+ qDebug() << "- after typedef resolving:" << oo(*type);
+}
+
+NamedType *TypeResolver::getNamedType(FullySpecifiedType &type) const
+{
+ NamedType *namedTy = type->asNamedType();
+ if (! namedTy) {
+ if (PointerType *pointerTy = type->asPointerType())
+ namedTy = pointerTy->elementType()->asNamedType();
+ }
+ return namedTy;
+}
+
+QList<LookupItem> TypeResolver::getNamedTypeItems(const Name *name, Scope *scope,
+ ClassOrNamespace *binding) const
+{
+ QList<LookupItem> namedTypeItems = typedefsFromScopeUpToFunctionScope(name, scope);
+ if (namedTypeItems.isEmpty()) {
+ if (binding)
+ namedTypeItems = binding->lookup(name);
+ if (ClassOrNamespace *scopeCon = _context.lookupType(scope))
+ namedTypeItems += scopeCon->lookup(name);
+ }
+
+ return namedTypeItems;
+}
+
+/// Return all typedefs with given name from given scope up to function scope.
+QList<LookupItem> TypeResolver::typedefsFromScopeUpToFunctionScope(const Name *name, Scope *scope)
+{
+ QList<LookupItem> results;
+ if (!scope)
+ return results;
+ Scope *enclosingBlockScope = 0;
+ for (Block *block = scope->asBlock(); block;
+ block = enclosingBlockScope ? enclosingBlockScope->asBlock() : 0) {
+ const unsigned memberCount = block->memberCount();
+ for (unsigned i = 0; i < memberCount; ++i) {
+ Symbol *symbol = block->memberAt(i);
+ if (Declaration *declaration = symbol->asDeclaration()) {
+ if (isTypedefWithName(declaration, name)) {
+ LookupItem item;
+ item.setDeclaration(declaration);
+ item.setScope(block);
+ item.setType(declaration->type());
+ results.append(item);
+ }
+ }
+ }
+ enclosingBlockScope = block->enclosingScope();
+ }
+ return results;
+}
+
+bool TypeResolver::isTypedefWithName(const Declaration *declaration, const Name *name)
+{
+ if (declaration->isTypedef()) {
+ const Identifier *identifier = declaration->name()->identifier();
+ if (name->identifier()->match(identifier))
+ return true;
+ }
+ return false;
+}
+
+bool TypeResolver::findTypedef(const QList<LookupItem> &namedTypeItems, FullySpecifiedType *type,
+ Scope **scope, QSet<Symbol *> &visited)
+{
+ bool foundTypedef = false;
+ foreach (const LookupItem &it, namedTypeItems) {
+ Symbol *declaration = it.declaration();
+ if (!declaration || !declaration->isTypedef())
+ continue;
+ if (visited.contains(declaration))
+ break;
+ visited.insert(declaration);
+
+ // continue working with the typedefed type and scope
+ if (type->type()->isPointerType()) {
+ *type = FullySpecifiedType(
+ _context.bindings()->control()->pointerType(declaration->type()));
+ } else if (type->type()->isReferenceType()) {
+ *type = FullySpecifiedType(
+ _context.bindings()->control()->referenceType(
+ declaration->type(),
+ declaration->type()->asReferenceType()->isRvalueReference()));
+ } else {
+ *type = declaration->type();
+ }
+
+ *scope = it.scope();
+ _binding = it.binding();
+ foundTypedef = true;
+ break;
+ }
+
+ return foundTypedef;
+}
+
+} // namespace CPlusPlus
diff --git a/src/libs/cplusplus/TypeResolver.h b/src/libs/cplusplus/TypeResolver.h
new file mode 100644
index 00000000000..85f54ab54af
--- /dev/null
+++ b/src/libs/cplusplus/TypeResolver.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** 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 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef TYPERESOLVER_H
+#define TYPERESOLVER_H
+
+#include "LookupContext.h"
+
+namespace CPlusPlus {
+
+class TypeResolver
+{
+public:
+ TypeResolver(const LookupContext &context) : _context(context) {}
+ void resolve(FullySpecifiedType *type, Scope **scope, ClassOrNamespace *binding);
+
+private:
+ NamedType *getNamedType(FullySpecifiedType& type) const;
+
+ QList<LookupItem> getNamedTypeItems(const Name *name, Scope *scope,
+ ClassOrNamespace *binding) const;
+
+ static QList<LookupItem> typedefsFromScopeUpToFunctionScope(const Name *name, Scope *scope);
+
+ static bool isTypedefWithName(const Declaration *declaration, const Name *name);
+
+ bool findTypedef(const QList<LookupItem>& namedTypeItems, FullySpecifiedType *type,
+ Scope **scope, QSet<Symbol *>& visited);
+
+ const LookupContext &_context;
+ // binding has to be remembered in case of resolving typedefs for templates
+ ClassOrNamespace *_binding;
+};
+
+} // namespace CPlusPlus
+
+#endif // TYPERESOLVER_H
diff --git a/src/libs/cplusplus/cplusplus-lib.pri b/src/libs/cplusplus/cplusplus-lib.pri
index 826d9dfa10c..f58256e4d68 100644
--- a/src/libs/cplusplus/cplusplus-lib.pri
+++ b/src/libs/cplusplus/cplusplus-lib.pri
@@ -36,6 +36,7 @@ HEADERS += \
$$PWD/NamePrettyPrinter.h \
$$PWD/TypeOfExpression.h \
$$PWD/TypePrettyPrinter.h \
+ $$PWD/TypeResolver.h \
$$PWD/ResolveExpression.h \
$$PWD/LookupItem.h \
$$PWD/AlreadyConsideredClassContainer.h \
@@ -68,6 +69,7 @@ SOURCES += \
$$PWD/NamePrettyPrinter.cpp \
$$PWD/TypeOfExpression.cpp \
$$PWD/TypePrettyPrinter.cpp \
+ $$PWD/TypeResolver.cpp \
$$PWD/ResolveExpression.cpp \
$$PWD/LookupItem.cpp \
$$PWD/LookupContext.cpp \
diff --git a/src/libs/cplusplus/cplusplus.qbs b/src/libs/cplusplus/cplusplus.qbs
index de6f93eb5dc..9891aeb4aba 100644
--- a/src/libs/cplusplus/cplusplus.qbs
+++ b/src/libs/cplusplus/cplusplus.qbs
@@ -118,6 +118,7 @@ QtcLibrary {
"SymbolNameVisitor.cpp", "SymbolNameVisitor.h",
"TypeOfExpression.cpp", "TypeOfExpression.h",
"TypePrettyPrinter.cpp", "TypePrettyPrinter.h",
+ "TypeResolver.cpp", "TypeResolver.h",
"cplusplus.qrc",
"findcdbbreakpoint.cpp", "findcdbbreakpoint.h",
"pp-cctype.h",