diff options
author | Leandro Melo <[email protected]> | 2012-09-05 14:26:11 +0200 |
---|---|---|
committer | Eike Ziller <[email protected]> | 2012-09-05 14:34:59 +0200 |
commit | c5097ed18389e357c1333ca7713f701d9751dce3 (patch) | |
tree | 2e374d45cf10028f3865498c82ffc28f140796e7 | |
parent | efa91f005b221da4c366202280aa97ee2a8a7493 (diff) |
C++: Fix crash in auto deducing mechanism
There was an inconsistency, since the AST used in ResolveExpression
was not really the same previously computed. In the particular issue
below a crash could occur, for example, when using auto in a for
range loop.
Task-number: QTCREATORBUG-7828
Change-Id: I02958f434c3cf3b50609546003fc141674ee78d5
Reviewed-by: Eike Ziller <[email protected]>
-rw-r--r-- | src/libs/cplusplus/ResolveExpression.cpp | 55 | ||||
-rw-r--r-- | src/libs/cplusplus/ResolveExpression.h | 7 |
2 files changed, 48 insertions, 14 deletions
diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index a64a61a0bc1..0309c3bcf91 100644 --- a/src/libs/cplusplus/ResolveExpression.cpp +++ b/src/libs/cplusplus/ResolveExpression.cpp @@ -460,6 +460,48 @@ 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); @@ -473,8 +515,7 @@ bool ResolveExpression::visit(SimpleNameAST *ast) if (item.declaration() == 0) continue; - if (item.type().isAuto() - && _blockedIds.find(ast->name->identifier()) == _blockedIds.end()) { + if (item.type().isAuto()) { const Declaration *decl = item.declaration()->asDeclaration(); if (!decl) continue; @@ -498,13 +539,13 @@ bool ResolveExpression::visit(SimpleNameAST *ast) Document::Ptr exprDoc = documentForExpression(exprTyper.preprocessedExpression(initializer)); exprDoc->check(); - ExpressionAST *exprAST = extractExpressionAST(exprDoc); - if (!exprAST) + + DeduceAutoCheck deduceAuto(ast->name->identifier(), exprDoc->translationUnit()); + if (deduceAuto._block) continue; - _blockedIds.insert(ast->name->identifier()); - const QList<LookupItem> &typeItems = resolve(exprAST, decl->enclosingScope()); - _blockedIds.erase(ast->name->identifier()); + const QList<LookupItem> &typeItems = + exprTyper(extractExpressionAST(exprDoc), exprDoc, decl->enclosingScope()); if (typeItems.empty()) continue; diff --git a/src/libs/cplusplus/ResolveExpression.h b/src/libs/cplusplus/ResolveExpression.h index 3809f04afc0..6c3a47524fa 100644 --- a/src/libs/cplusplus/ResolveExpression.h +++ b/src/libs/cplusplus/ResolveExpression.h @@ -121,18 +121,11 @@ protected: private: - struct IdentifierComp - { - bool operator()(const Identifier *a, const Identifier *b) const - { return strcmp(a->chars(), b->chars()) < 0; } - }; - Scope *_scope; LookupContext _context; Bind bind; QList<LookupItem> _results; bool _reference; - std::set<const Identifier *, IdentifierComp> _blockedIds; // Replace by a hash impl. }; } // namespace CPlusPlus |