Commit 6750a1c8 authored by Leandro Melo's avatar Leandro Melo

C++: Fix crash when deducing auto (with invalid ids)

Task-number: QTCREATORBUG-7801

Change-Id: I61436148ed1428a50a6840ba9109310a57dabaa4
Reviewed-by: default avatarRoberto Raggi <roberto.raggi@nokia.com>
parent 8ba422d0
......@@ -88,7 +88,9 @@ static void path_helper(Symbol *symbol, QList<const Name *> *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<const Name *> &path, const QList<const Name *> &other)
{
if (path.length() != other.length())
......
......@@ -252,6 +252,7 @@ private:
QSharedPointer<Control> _control;
};
bool CPLUSPLUS_EXPORT compareName(const Name *name, const Name *other);
bool CPLUSPLUS_EXPORT compareFullyQualifiedName(const QList<const Name *> &path,
const QList<const Name *> &other);
......
......@@ -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<LookupItem> 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<LookupItem> &typeItems = resolve(exprAST, decl->enclosingScope());
_blockedIds.erase(ast->name->identifier());
if (typeItems.empty())
continue;
......
......@@ -36,6 +36,7 @@
#include <ASTVisitor.h>
#include <FullySpecifiedType.h>
#include <Bind.h>
#include <set>
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<LookupItem> _results;
bool _reference;
std::set<const Identifier *, IdentifierComp> _blockedIds; // Replace by a hash impl.
};
} // namespace CPlusPlus
......
......@@ -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("<completion>"));
doc->setUtf8Source(utf8code);
doc->parse(Document::ParseExpression);
return doc;
}
void TypeOfExpression::processEnvironment(Document::Ptr doc, Environment *env,
QSet<QString> *processed) const
{
......@@ -210,3 +193,24 @@ QByteArray TypeOfExpression::preprocessedExpression(const QByteArray &utf8code)
Preprocessor preproc(0, m_environment.data());
return preproc.run("<expression>", 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("<completion>"));
doc->setUtf8Source(utf8code);
doc->parse(Document::ParseExpression);
return doc;
}
} // namespace CPlusPlus
......@@ -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<QString> *processed) const;
QByteArray preprocessedExpression(const QByteArray &utf8code) const;
private:
Document::Ptr m_thisDocument;
......@@ -142,6 +140,9 @@ private:
mutable QSharedPointer<Environment> m_environment;
};
ExpressionAST CPLUSPLUS_EXPORT *extractExpressionAST(Document::Ptr doc);
Document::Ptr CPLUSPLUS_EXPORT documentForExpression(const QByteArray &utf8code);
} // namespace CPlusPlus
#endif // CPLUSPLUS_TYPEOFEXPRESSION_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment