aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs
diff options
context:
space:
mode:
authorOrgad Shaneh <orgad.shaneh@audiocodes.com>2015-05-18 23:19:32 +0300
committerOrgad Shaneh <orgads@gmail.com>2015-05-20 10:45:31 +0000
commitde68ac54073cc3389abcc4cdaa0131bca7a44874 (patch)
treeb47119b05b81694b142188b7164d8492ff092e85 /src/libs
parent57e3714db45920287118dddb9bc5d9df691110ec (diff)
C++: fix code completion for decltyped type
example: struct Foo { int bar; }; Foo foo() { return Foo; } typedef decltype(foo()) TypedefedFooWithDecltype; void fun() { decltype(foo()) decltypeFoo; decltypeFoo.;// code completion should work here TypedefedFooWithDecltype typedefedFooWithDecltype; typedefedFooWithDecltype.;// code completion should work here } Started-by: Przemyslaw Gorszkowski <pgorszkowski@gmail.com> Task-number: QTCREATORBUG-14483 Change-Id: I296ceed9d896c68cf0651265afb08a1fc42f9a68 Reviewed-by: Nikolai Kosjar <nikolai.kosjar@theqtcompany.com>
Diffstat (limited to 'src/libs')
-rw-r--r--src/libs/3rdparty/cplusplus/Bind.cpp17
-rw-r--r--src/libs/3rdparty/cplusplus/FullySpecifiedType.cpp6
-rw-r--r--src/libs/3rdparty/cplusplus/FullySpecifiedType.h4
-rw-r--r--src/libs/cplusplus/LookupContext.h8
-rw-r--r--src/libs/cplusplus/ResolveExpression.cpp77
-rw-r--r--src/libs/cplusplus/TypeResolver.cpp93
-rw-r--r--src/libs/cplusplus/TypeResolver.h4
7 files changed, 135 insertions, 74 deletions
diff --git a/src/libs/3rdparty/cplusplus/Bind.cpp b/src/libs/3rdparty/cplusplus/Bind.cpp
index a0a0e1a065..e3fd96de98 100644
--- a/src/libs/3rdparty/cplusplus/Bind.cpp
+++ b/src/libs/3rdparty/cplusplus/Bind.cpp
@@ -1921,9 +1921,22 @@ bool Bind::visit(SimpleDeclarationAST *ast)
methodKey = methodKeyForInvokableToken(tokenKind(ast->qt_invokable_token));
// unsigned qt_invokable_token = ast->qt_invokable_token;
+ unsigned declTypeStartOfExpression = 0;
+ unsigned declTypeEndOfExpression = 0;
+ bool isTypedef = false;
FullySpecifiedType type;
for (SpecifierListAST *it = ast->decl_specifier_list; it; it = it->next) {
type = this->specifier(it->value, type);
+ if (type.isTypedef())
+ isTypedef = true;
+
+ type.setTypedef(isTypedef);
+ if (type.isDecltype()) {
+ if (DecltypeSpecifierAST *decltypeSpec = it->value->asDecltypeSpecifier()) {
+ declTypeStartOfExpression = decltypeSpec->expression->firstToken();
+ declTypeEndOfExpression = decltypeSpec->expression->lastToken();
+ }
+ }
}
List<Symbol *> **symbolTail = &ast->symbols;
@@ -1982,6 +1995,9 @@ bool Bind::visit(SimpleDeclarationAST *ast)
unsigned endOfExpression = initializer->lastToken();
decl->setInitializer(asStringLiteral(startOfExpression, endOfExpression));
}
+ } else if (declTy.isDecltype()) {
+ decl->setInitializer(asStringLiteral(declTypeStartOfExpression,
+ declTypeEndOfExpression));
}
if (_scope->isClass()) {
@@ -3028,6 +3044,7 @@ bool Bind::visit(TypeofSpecifierAST *ast)
bool Bind::visit(DecltypeSpecifierAST *ast)
{
_type = this->expression(ast->expression);
+ _type.setDecltype(true);
return false;
}
diff --git a/src/libs/3rdparty/cplusplus/FullySpecifiedType.cpp b/src/libs/3rdparty/cplusplus/FullySpecifiedType.cpp
index f78e4e9338..ea88140314 100644
--- a/src/libs/3rdparty/cplusplus/FullySpecifiedType.cpp
+++ b/src/libs/3rdparty/cplusplus/FullySpecifiedType.cpp
@@ -100,6 +100,12 @@ bool FullySpecifiedType::isAuto() const
void FullySpecifiedType::setAuto(bool isAuto)
{ f._isAuto = isAuto; }
+bool FullySpecifiedType::isDecltype() const
+{ return f._isDecltype; }
+
+void FullySpecifiedType::setDecltype(bool isDecltype)
+{ f._isDecltype = isDecltype; }
+
bool FullySpecifiedType::isRegister() const
{ return f._isRegister; }
diff --git a/src/libs/3rdparty/cplusplus/FullySpecifiedType.h b/src/libs/3rdparty/cplusplus/FullySpecifiedType.h
index 7526a923c9..498e190330 100644
--- a/src/libs/3rdparty/cplusplus/FullySpecifiedType.h
+++ b/src/libs/3rdparty/cplusplus/FullySpecifiedType.h
@@ -58,6 +58,9 @@ public:
bool isAuto() const;
void setAuto(bool isAuto);
+ bool isDecltype() const;
+ void setDecltype(bool isDecltype);
+
bool isRegister() const;
void setRegister(bool isRegister);
@@ -125,6 +128,7 @@ private:
// storage class specifiers
unsigned _isFriend: 1;
unsigned _isAuto: 1;
+ unsigned _isDecltype: 1;
unsigned _isRegister: 1;
unsigned _isStatic: 1;
unsigned _isExtern: 1;
diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h
index 1eeb2367b6..3e39e31504 100644
--- a/src/libs/cplusplus/LookupContext.h
+++ b/src/libs/cplusplus/LookupContext.h
@@ -41,6 +41,7 @@
#include <cplusplus/Control.h>
#include <cplusplus/Name.h>
+#include <QEnableSharedFromThis>
#include <QSet>
#include <QMap>
@@ -99,7 +100,9 @@ private:
friend class CreateBindings;
};
-class CPLUSPLUS_EXPORT CreateBindings: protected SymbolVisitor
+class CPLUSPLUS_EXPORT CreateBindings
+ : protected SymbolVisitor
+ , public QEnableSharedFromThis<CreateBindings>
{
Q_DISABLE_COPY(CreateBindings)
@@ -119,6 +122,9 @@ public:
QSharedPointer<Control> control() const
{ return _control; }
+ Snapshot &snapshot()
+ { return _snapshot; }
+
/// Adds an expression document in order to keep their symbols and names alive
void addExpressionDocument(Document::Ptr document)
{ _expressionDocuments.append(document); }
diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp
index c32dacbb1c..7612e7f51d 100644
--- a/src/libs/cplusplus/ResolveExpression.cpp
+++ b/src/libs/cplusplus/ResolveExpression.cpp
@@ -526,48 +526,6 @@ bool ResolveExpression::visit(QualifiedNameAST *ast)
return false;
}
-namespace {
-
-class DeduceAutoCheck : public ASTVisitor
-{
-public:
- DeduceAutoCheck(const Identifier *id, TranslationUnit *tu)
- : ASTVisitor(tu), _id(id), _block(false)
- {
- accept(tu->ast());
- }
-
- virtual bool preVisit(AST *)
- {
- if (_block)
- return false;
-
- return true;
- }
-
- virtual bool visit(SimpleNameAST *ast)
- {
- if (ast->name
- && ast->name->identifier()
- && strcmp(ast->name->identifier()->chars(), _id->chars()) == 0) {
- _block = true;
- }
-
- return false;
- }
-
- virtual bool visit(MemberAccessAST *ast)
- {
- accept(ast->base_expression);
- return false;
- }
-
- const Identifier *_id;
- bool _block;
-};
-
-} // namespace anonymous
-
bool ResolveExpression::visit(SimpleNameAST *ast)
{
QList<LookupItem> candidates = _context.lookup(ast->name, _scope);
@@ -581,7 +539,7 @@ bool ResolveExpression::visit(SimpleNameAST *ast)
if (item.declaration() == 0)
continue;
- if (item.type().isAuto()) {
+ if (item.type().isAuto() || item.type().isDecltype()) {
const Declaration *decl = item.declaration()->asDeclaration();
if (!decl)
continue;
@@ -590,35 +548,10 @@ bool ResolveExpression::visit(SimpleNameAST *ast)
if (_autoDeclarationsBeingResolved.contains(decl))
continue;
- const StringLiteral *initializationString = decl->getInitializer();
- if (initializationString == 0)
- continue;
-
- const QByteArray &initializer =
- QByteArray::fromRawData(initializationString->chars(),
- initializationString->size()).trimmed();
-
- // Skip lambda-function initializers
- if (initializer.length() > 0 && initializer[0] == '[')
- continue;
-
- TypeOfExpression exprTyper;
- exprTyper.setExpandTemplates(true);
- Document::Ptr doc = _context.document(QString::fromLocal8Bit(decl->fileName()));
- exprTyper.init(doc, _context.snapshot(), _context.bindings(),
- QSet<const Declaration* >(_autoDeclarationsBeingResolved) << decl);
-
- Document::Ptr exprDoc =
- documentForExpression(exprTyper.preprocessedExpression(initializer));
- exprDoc->check();
- _context.bindings()->addExpressionDocument(exprDoc);
-
- DeduceAutoCheck deduceAuto(ast->name->identifier(), exprDoc->translationUnit());
- if (deduceAuto._block)
- continue;
-
- newCandidates += exprTyper(extractExpressionAST(exprDoc), exprDoc,
- decl->enclosingScope());
+ newCandidates +=
+ TypeResolver::resolveDeclInitializer(*_context.bindings(), decl,
+ _autoDeclarationsBeingResolved << decl,
+ ast->name->identifier());
} else {
item.setType(item.declaration()->type());
item.setScope(item.declaration()->enclosingScope());
diff --git a/src/libs/cplusplus/TypeResolver.cpp b/src/libs/cplusplus/TypeResolver.cpp
index fcc21662a4..dab2016b38 100644
--- a/src/libs/cplusplus/TypeResolver.cpp
+++ b/src/libs/cplusplus/TypeResolver.cpp
@@ -30,6 +30,7 @@
#include "TypeResolver.h"
#include "Overview.h"
+#include "TypeOfExpression.h"
#include <QDebug>
@@ -37,6 +38,48 @@ static const bool debug = ! qgetenv("QTC_LOOKUPCONTEXT_DEBUG").isEmpty();
namespace CPlusPlus {
+namespace {
+
+class DeduceAutoCheck : public ASTVisitor
+{
+public:
+ DeduceAutoCheck(const Identifier *id, TranslationUnit *tu)
+ : ASTVisitor(tu), _id(id), _block(false)
+ {
+ accept(tu->ast());
+ }
+
+ virtual bool preVisit(AST *)
+ {
+ if (_block)
+ return false;
+
+ return true;
+ }
+
+ virtual bool visit(SimpleNameAST *ast)
+ {
+ if (ast->name
+ && ast->name->identifier()
+ && strcmp(ast->name->identifier()->chars(), _id->chars()) == 0) {
+ _block = true;
+ }
+
+ return false;
+ }
+
+ virtual bool visit(MemberAccessAST *ast)
+ {
+ accept(ast->base_expression);
+ return false;
+ }
+
+ const Identifier *_id;
+ bool _block;
+};
+
+} // namespace anonymous
+
void TypeResolver::resolve(FullySpecifiedType *type, Scope **scope, LookupScope *binding)
{
QSet<Symbol *> visited;
@@ -115,6 +158,43 @@ QList<LookupItem> TypeResolver::typedefsFromScopeUpToFunctionScope(const Name *n
return results;
}
+// Resolves auto and decltype initializer string
+QList<LookupItem> TypeResolver::resolveDeclInitializer(
+ CreateBindings &factory, const Declaration *decl,
+ const QSet<const Declaration* > &declarationsBeingResolved,
+ const Identifier *id)
+{
+ const StringLiteral *initializationString = decl->getInitializer();
+ if (initializationString == 0)
+ return QList<LookupItem>();
+
+ const QByteArray &initializer =
+ QByteArray::fromRawData(initializationString->chars(),
+ initializationString->size()).trimmed();
+
+ // Skip lambda-function initializers
+ if (initializer.length() > 0 && initializer[0] == '[')
+ return QList<LookupItem>();
+
+ TypeOfExpression exprTyper;
+ exprTyper.setExpandTemplates(true);
+ Document::Ptr doc = factory.snapshot().document(QString::fromLocal8Bit(decl->fileName()));
+ exprTyper.init(doc, factory.snapshot(), factory.sharedFromThis(), declarationsBeingResolved);
+
+ Document::Ptr exprDoc =
+ documentForExpression(exprTyper.preprocessedExpression(initializer));
+ factory.addExpressionDocument(exprDoc);
+ exprDoc->check();
+
+ if (id) {
+ DeduceAutoCheck deduceAuto(id, exprDoc->translationUnit());
+ if (deduceAuto._block)
+ return QList<LookupItem>();
+ }
+
+ return exprTyper(extractExpressionAST(exprDoc), exprDoc, decl->enclosingScope());
+}
+
bool TypeResolver::isTypedefWithName(const Declaration *declaration, const Name *name)
{
if (declaration->isTypedef()) {
@@ -130,7 +210,7 @@ bool TypeResolver::findTypedef(const QList<LookupItem> &namedTypeItems, FullySpe
{
foreach (const LookupItem &it, namedTypeItems) {
Symbol *declaration = it.declaration();
- if (!declaration || !declaration->isTypedef())
+ if (!declaration || (!declaration->isTypedef() && !declaration->type().isDecltype()))
continue;
if (visited.contains(declaration))
break;
@@ -145,6 +225,17 @@ bool TypeResolver::findTypedef(const QList<LookupItem> &namedTypeItems, FullySpe
_factory.control()->referenceType(
declaration->type(),
declaration->type()->asReferenceType()->isRvalueReference()));
+ } else if (declaration->type().isDecltype()) {
+ Declaration *decl = declaration->asDeclaration();
+ const QList<LookupItem> resolved =
+ resolveDeclInitializer(_factory, decl, QSet<const Declaration* >() << decl);
+ if (!resolved.isEmpty()) {
+ LookupItem item = resolved.first();
+ *type = item.type();
+ *scope = item.scope();
+ _binding = item.binding();
+ return true;
+ }
} else {
*type = declaration->type();
}
diff --git a/src/libs/cplusplus/TypeResolver.h b/src/libs/cplusplus/TypeResolver.h
index 164d7e3ada..bf25e468c6 100644
--- a/src/libs/cplusplus/TypeResolver.h
+++ b/src/libs/cplusplus/TypeResolver.h
@@ -40,6 +40,10 @@ class TypeResolver
public:
TypeResolver(CreateBindings &factory) : _factory(factory) {}
void resolve(FullySpecifiedType *type, Scope **scope, LookupScope *binding);
+ static QList<LookupItem> resolveDeclInitializer(
+ CreateBindings &factory, const Declaration *decl,
+ const QSet<const Declaration *> &declarationsBeingResolved,
+ const Identifier *id = 0);
private:
NamedType *getNamedType(FullySpecifiedType& type) const;