From 6750a1c8290bccfa4698b615928fbe64fd68faa4 Mon Sep 17 00:00:00 2001 From: Leandro Melo Date: Tue, 4 Sep 2012 15:21:03 +0200 Subject: [PATCH] C++: Fix crash when deducing auto (with invalid ids) Task-number: QTCREATORBUG-7801 Change-Id: I61436148ed1428a50a6840ba9109310a57dabaa4 Reviewed-by: Roberto Raggi --- src/libs/cplusplus/LookupContext.cpp | 6 ++-- src/libs/cplusplus/LookupContext.h | 1 + src/libs/cplusplus/ResolveExpression.cpp | 21 +++++++++---- src/libs/cplusplus/ResolveExpression.h | 9 ++++++ src/libs/cplusplus/TypeOfExpression.cpp | 38 +++++++++++++----------- src/libs/cplusplus/TypeOfExpression.h | 7 +++-- 6 files changed, 54 insertions(+), 28 deletions(-) diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index 8dbaf72cf83..909e02b5e06 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -88,7 +88,9 @@ static void path_helper(Symbol *symbol, QList *names) } } -static bool compareName(const Name *name, const Name *other) +namespace CPlusPlus { + +bool compareName(const Name *name, const Name *other) { if (name == other) return true; @@ -104,8 +106,6 @@ static bool compareName(const Name *name, const Name *other) return false; } -namespace CPlusPlus { - bool compareFullyQualifiedName(const QList &path, const QList &other) { if (path.length() != other.length()) diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h index b2fa81c5609..fef317fd614 100644 --- a/src/libs/cplusplus/LookupContext.h +++ b/src/libs/cplusplus/LookupContext.h @@ -252,6 +252,7 @@ private: QSharedPointer _control; }; +bool CPLUSPLUS_EXPORT compareName(const Name *name, const Name *other); bool CPLUSPLUS_EXPORT compareFullyQualifiedName(const QList &path, const QList &other); diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index 961795c95d5..a64a61a0bc1 100644 --- a/src/libs/cplusplus/ResolveExpression.cpp +++ b/src/libs/cplusplus/ResolveExpression.cpp @@ -473,27 +473,38 @@ bool ResolveExpression::visit(SimpleNameAST *ast) if (item.declaration() == 0) continue; - if (item.type().isAuto()) { + if (item.type().isAuto() + && _blockedIds.find(ast->name->identifier()) == _blockedIds.end()) { const Declaration *decl = item.declaration()->asDeclaration(); if (!decl) continue; - Document::Ptr doc = _context.snapshot().document(decl->fileName()); - const StringLiteral *initializationString = decl->getInitializer(); if (initializationString == 0) continue; - QByteArray initializer = QByteArray::fromRawData(initializationString->chars(), initializationString->size()).trimmed(); + const QByteArray &initializer = + QByteArray::fromRawData(initializationString->chars(), + initializationString->size()).trimmed(); // Skip lambda-function initializers if (initializer.length() > 0 && initializer[0] == '[') continue; TypeOfExpression exprTyper; + Document::Ptr doc = _context.snapshot().document(decl->fileName()); exprTyper.init(doc, _context.snapshot(), _context.bindings()); - QList typeItems = exprTyper(initializer, decl->enclosingScope(), TypeOfExpression::Preprocess); + Document::Ptr exprDoc = + documentForExpression(exprTyper.preprocessedExpression(initializer)); + exprDoc->check(); + ExpressionAST *exprAST = extractExpressionAST(exprDoc); + if (!exprAST) + continue; + + _blockedIds.insert(ast->name->identifier()); + const QList &typeItems = resolve(exprAST, decl->enclosingScope()); + _blockedIds.erase(ast->name->identifier()); if (typeItems.empty()) continue; diff --git a/src/libs/cplusplus/ResolveExpression.h b/src/libs/cplusplus/ResolveExpression.h index e792d6c2832..3809f04afc0 100644 --- a/src/libs/cplusplus/ResolveExpression.h +++ b/src/libs/cplusplus/ResolveExpression.h @@ -36,6 +36,7 @@ #include #include #include +#include namespace CPlusPlus { @@ -118,12 +119,20 @@ protected: // Objective-C expressions virtual bool visit(ObjCMessageExpressionAST *ast); + 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 _results; bool _reference; + std::set _blockedIds; // Replace by a hash impl. }; } // namespace CPlusPlus diff --git a/src/libs/cplusplus/TypeOfExpression.cpp b/src/libs/cplusplus/TypeOfExpression.cpp index 6ff53618c20..792ecb1cbac 100644 --- a/src/libs/cplusplus/TypeOfExpression.cpp +++ b/src/libs/cplusplus/TypeOfExpression.cpp @@ -163,23 +163,6 @@ ExpressionAST *TypeOfExpression::expressionAST() const return extractExpressionAST(m_lookupContext.expressionDocument()); } -ExpressionAST *TypeOfExpression::extractExpressionAST(Document::Ptr doc) const -{ - if (! doc->translationUnit()->ast()) - return 0; - - return doc->translationUnit()->ast()->asExpression(); -} - -Document::Ptr TypeOfExpression::documentForExpression(const QByteArray &utf8code) const -{ - // create the expression's AST. - Document::Ptr doc = Document::create(QLatin1String("")); - doc->setUtf8Source(utf8code); - doc->parse(Document::ParseExpression); - return doc; -} - void TypeOfExpression::processEnvironment(Document::Ptr doc, Environment *env, QSet *processed) const { @@ -210,3 +193,24 @@ QByteArray TypeOfExpression::preprocessedExpression(const QByteArray &utf8code) Preprocessor preproc(0, m_environment.data()); return preproc.run("", utf8code); } + +namespace CPlusPlus { + +ExpressionAST *extractExpressionAST(Document::Ptr doc) +{ + if (! doc->translationUnit()->ast()) + return 0; + + return doc->translationUnit()->ast()->asExpression(); +} + +Document::Ptr documentForExpression(const QByteArray &utf8code) +{ + // create the expression's AST. + Document::Ptr doc = Document::create(QLatin1String("")); + doc->setUtf8Source(utf8code); + doc->parse(Document::ParseExpression); + return doc; +} + +} // namespace CPlusPlus diff --git a/src/libs/cplusplus/TypeOfExpression.h b/src/libs/cplusplus/TypeOfExpression.h index 3e3a134ba2e..430202910f8 100644 --- a/src/libs/cplusplus/TypeOfExpression.h +++ b/src/libs/cplusplus/TypeOfExpression.h @@ -122,15 +122,13 @@ public: Scope *scope() const; ExpressionAST *expressionAST() const; + QByteArray preprocessedExpression(const QByteArray &utf8code) const; private: - ExpressionAST *extractExpressionAST(Document::Ptr doc) const; - Document::Ptr documentForExpression(const QByteArray &utf8code) const; void processEnvironment(Document::Ptr doc, Environment *env, QSet *processed) const; - QByteArray preprocessedExpression(const QByteArray &utf8code) const; private: Document::Ptr m_thisDocument; @@ -142,6 +140,9 @@ private: mutable QSharedPointer m_environment; }; +ExpressionAST CPLUSPLUS_EXPORT *extractExpressionAST(Document::Ptr doc); +Document::Ptr CPLUSPLUS_EXPORT documentForExpression(const QByteArray &utf8code); + } // namespace CPlusPlus #endif // CPLUSPLUS_TYPEOFEXPRESSION_H