aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/cplusplus/TypeResolver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/cplusplus/TypeResolver.cpp')
-rw-r--r--src/libs/cplusplus/TypeResolver.cpp93
1 files changed, 92 insertions, 1 deletions
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();
}