forked from qt-creator/qt-creator
C++: Fix crash when deducing auto (with invalid ids)
Task-number: QTCREATORBUG-7801 Change-Id: I61436148ed1428a50a6840ba9109310a57dabaa4 Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
This commit is contained in:
@@ -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)
|
if (name == other)
|
||||||
return true;
|
return true;
|
||||||
@@ -104,8 +106,6 @@ static bool compareName(const Name *name, const Name *other)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace CPlusPlus {
|
|
||||||
|
|
||||||
bool compareFullyQualifiedName(const QList<const Name *> &path, const QList<const Name *> &other)
|
bool compareFullyQualifiedName(const QList<const Name *> &path, const QList<const Name *> &other)
|
||||||
{
|
{
|
||||||
if (path.length() != other.length())
|
if (path.length() != other.length())
|
||||||
|
@@ -252,6 +252,7 @@ private:
|
|||||||
QSharedPointer<Control> _control;
|
QSharedPointer<Control> _control;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool CPLUSPLUS_EXPORT compareName(const Name *name, const Name *other);
|
||||||
bool CPLUSPLUS_EXPORT compareFullyQualifiedName(const QList<const Name *> &path,
|
bool CPLUSPLUS_EXPORT compareFullyQualifiedName(const QList<const Name *> &path,
|
||||||
const QList<const Name *> &other);
|
const QList<const Name *> &other);
|
||||||
|
|
||||||
|
@@ -473,27 +473,38 @@ bool ResolveExpression::visit(SimpleNameAST *ast)
|
|||||||
if (item.declaration() == 0)
|
if (item.declaration() == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (item.type().isAuto()) {
|
if (item.type().isAuto()
|
||||||
|
&& _blockedIds.find(ast->name->identifier()) == _blockedIds.end()) {
|
||||||
const Declaration *decl = item.declaration()->asDeclaration();
|
const Declaration *decl = item.declaration()->asDeclaration();
|
||||||
if (!decl)
|
if (!decl)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Document::Ptr doc = _context.snapshot().document(decl->fileName());
|
|
||||||
|
|
||||||
const StringLiteral *initializationString = decl->getInitializer();
|
const StringLiteral *initializationString = decl->getInitializer();
|
||||||
if (initializationString == 0)
|
if (initializationString == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
QByteArray initializer = QByteArray::fromRawData(initializationString->chars(), initializationString->size()).trimmed();
|
const QByteArray &initializer =
|
||||||
|
QByteArray::fromRawData(initializationString->chars(),
|
||||||
|
initializationString->size()).trimmed();
|
||||||
|
|
||||||
// Skip lambda-function initializers
|
// Skip lambda-function initializers
|
||||||
if (initializer.length() > 0 && initializer[0] == '[')
|
if (initializer.length() > 0 && initializer[0] == '[')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
TypeOfExpression exprTyper;
|
TypeOfExpression exprTyper;
|
||||||
|
Document::Ptr doc = _context.snapshot().document(decl->fileName());
|
||||||
exprTyper.init(doc, _context.snapshot(), _context.bindings());
|
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())
|
if (typeItems.empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@@ -36,6 +36,7 @@
|
|||||||
#include <ASTVisitor.h>
|
#include <ASTVisitor.h>
|
||||||
#include <FullySpecifiedType.h>
|
#include <FullySpecifiedType.h>
|
||||||
#include <Bind.h>
|
#include <Bind.h>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
namespace CPlusPlus {
|
namespace CPlusPlus {
|
||||||
|
|
||||||
@@ -118,12 +119,20 @@ protected:
|
|||||||
// Objective-C expressions
|
// Objective-C expressions
|
||||||
virtual bool visit(ObjCMessageExpressionAST *ast);
|
virtual bool visit(ObjCMessageExpressionAST *ast);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct IdentifierComp
|
||||||
|
{
|
||||||
|
bool operator()(const Identifier *a, const Identifier *b) const
|
||||||
|
{ return strcmp(a->chars(), b->chars()) < 0; }
|
||||||
|
};
|
||||||
|
|
||||||
Scope *_scope;
|
Scope *_scope;
|
||||||
LookupContext _context;
|
LookupContext _context;
|
||||||
Bind bind;
|
Bind bind;
|
||||||
QList<LookupItem> _results;
|
QList<LookupItem> _results;
|
||||||
bool _reference;
|
bool _reference;
|
||||||
|
std::set<const Identifier *, IdentifierComp> _blockedIds; // Replace by a hash impl.
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace CPlusPlus
|
} // namespace CPlusPlus
|
||||||
|
@@ -163,23 +163,6 @@ ExpressionAST *TypeOfExpression::expressionAST() const
|
|||||||
return extractExpressionAST(m_lookupContext.expressionDocument());
|
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,
|
void TypeOfExpression::processEnvironment(Document::Ptr doc, Environment *env,
|
||||||
QSet<QString> *processed) const
|
QSet<QString> *processed) const
|
||||||
{
|
{
|
||||||
@@ -210,3 +193,24 @@ QByteArray TypeOfExpression::preprocessedExpression(const QByteArray &utf8code)
|
|||||||
Preprocessor preproc(0, m_environment.data());
|
Preprocessor preproc(0, m_environment.data());
|
||||||
return preproc.run("<expression>", utf8code);
|
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;
|
Scope *scope() const;
|
||||||
|
|
||||||
ExpressionAST *expressionAST() const;
|
ExpressionAST *expressionAST() const;
|
||||||
|
QByteArray preprocessedExpression(const QByteArray &utf8code) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ExpressionAST *extractExpressionAST(Document::Ptr doc) const;
|
|
||||||
Document::Ptr documentForExpression(const QByteArray &utf8code) const;
|
|
||||||
|
|
||||||
void processEnvironment(Document::Ptr doc, Environment *env,
|
void processEnvironment(Document::Ptr doc, Environment *env,
|
||||||
QSet<QString> *processed) const;
|
QSet<QString> *processed) const;
|
||||||
|
|
||||||
QByteArray preprocessedExpression(const QByteArray &utf8code) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Document::Ptr m_thisDocument;
|
Document::Ptr m_thisDocument;
|
||||||
@@ -142,6 +140,9 @@ private:
|
|||||||
mutable QSharedPointer<Environment> m_environment;
|
mutable QSharedPointer<Environment> m_environment;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ExpressionAST CPLUSPLUS_EXPORT *extractExpressionAST(Document::Ptr doc);
|
||||||
|
Document::Ptr CPLUSPLUS_EXPORT documentForExpression(const QByteArray &utf8code);
|
||||||
|
|
||||||
} // namespace CPlusPlus
|
} // namespace CPlusPlus
|
||||||
|
|
||||||
#endif // CPLUSPLUS_TYPEOFEXPRESSION_H
|
#endif // CPLUSPLUS_TYPEOFEXPRESSION_H
|
||||||
|
Reference in New Issue
Block a user