forked from qt-creator/qt-creator
C++: Fix crash in code completion.
Caused by a dangling pointer of a template instantiation which had been cloned into the wrong control. The fix is to remove that control and refer to the control of the bindings (which is the correct one). Change-Id: I951a60f2e613aae1e4ac901ce99c820212018709 Reviewed-by: Nikolai Kosjar <nikolai.kosjar@digia.com> Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
This commit is contained in:
committed by
Erik Verbruggen
parent
6999e3c339
commit
8e18adc70f
@@ -151,38 +151,34 @@ uint qHash(const FullyQualifiedName &fullyQualifiedName)
|
|||||||
// LookupContext
|
// LookupContext
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
LookupContext::LookupContext()
|
LookupContext::LookupContext()
|
||||||
: _control(new Control())
|
: m_expandTemplates(false)
|
||||||
, m_expandTemplates(false)
|
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
LookupContext::LookupContext(Document::Ptr thisDocument,
|
LookupContext::LookupContext(Document::Ptr thisDocument,
|
||||||
const Snapshot &snapshot)
|
const Snapshot &snapshot)
|
||||||
: _expressionDocument(Document::create(QLatin1String("<LookupContext>"))),
|
: _expressionDocument(Document::create(QLatin1String("<LookupContext>")))
|
||||||
_thisDocument(thisDocument),
|
, _thisDocument(thisDocument)
|
||||||
_snapshot(snapshot),
|
, _snapshot(snapshot)
|
||||||
_control(new Control()),
|
, m_expandTemplates(false)
|
||||||
m_expandTemplates(false)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
LookupContext::LookupContext(Document::Ptr expressionDocument,
|
LookupContext::LookupContext(Document::Ptr expressionDocument,
|
||||||
Document::Ptr thisDocument,
|
Document::Ptr thisDocument,
|
||||||
const Snapshot &snapshot)
|
const Snapshot &snapshot)
|
||||||
: _expressionDocument(expressionDocument),
|
: _expressionDocument(expressionDocument)
|
||||||
_thisDocument(thisDocument),
|
, _thisDocument(thisDocument)
|
||||||
_snapshot(snapshot),
|
, _snapshot(snapshot)
|
||||||
_control(new Control()),
|
, m_expandTemplates(false)
|
||||||
m_expandTemplates(false)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
LookupContext::LookupContext(const LookupContext &other)
|
LookupContext::LookupContext(const LookupContext &other)
|
||||||
: _expressionDocument(other._expressionDocument),
|
: _expressionDocument(other._expressionDocument)
|
||||||
_thisDocument(other._thisDocument),
|
, _thisDocument(other._thisDocument)
|
||||||
_snapshot(other._snapshot),
|
, _snapshot(other._snapshot)
|
||||||
_bindings(other._bindings),
|
, _bindings(other._bindings)
|
||||||
_control(other._control),
|
, m_expandTemplates(other.m_expandTemplates)
|
||||||
m_expandTemplates(other.m_expandTemplates)
|
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
LookupContext &LookupContext::operator=(const LookupContext &other)
|
LookupContext &LookupContext::operator=(const LookupContext &other)
|
||||||
@@ -191,7 +187,6 @@ LookupContext &LookupContext::operator = (const LookupContext &other)
|
|||||||
_thisDocument = other._thisDocument;
|
_thisDocument = other._thisDocument;
|
||||||
_snapshot = other._snapshot;
|
_snapshot = other._snapshot;
|
||||||
_bindings = other._bindings;
|
_bindings = other._bindings;
|
||||||
_control = other._control;
|
|
||||||
m_expandTemplates = other.m_expandTemplates;
|
m_expandTemplates = other.m_expandTemplates;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -250,7 +245,7 @@ const Name *LookupContext::minimalName(Symbol *symbol, ClassOrNamespace *target,
|
|||||||
QSharedPointer<CreateBindings> LookupContext::bindings() const
|
QSharedPointer<CreateBindings> LookupContext::bindings() const
|
||||||
{
|
{
|
||||||
if (! _bindings) {
|
if (! _bindings) {
|
||||||
_bindings = QSharedPointer<CreateBindings>(new CreateBindings(_thisDocument, _snapshot, control()));
|
_bindings = QSharedPointer<CreateBindings>(new CreateBindings(_thisDocument, _snapshot));
|
||||||
_bindings->setExpandTemplates(m_expandTemplates);
|
_bindings->setExpandTemplates(m_expandTemplates);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,11 +257,6 @@ void LookupContext::setBindings(QSharedPointer<CreateBindings> bindings)
|
|||||||
_bindings = bindings;
|
_bindings = bindings;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSharedPointer<Control> LookupContext::control() const
|
|
||||||
{
|
|
||||||
return _control;
|
|
||||||
}
|
|
||||||
|
|
||||||
Document::Ptr LookupContext::expressionDocument() const
|
Document::Ptr LookupContext::expressionDocument() const
|
||||||
{ return _expressionDocument; }
|
{ return _expressionDocument; }
|
||||||
|
|
||||||
@@ -649,7 +639,7 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (templateId && (s->isDeclaration() || s->isFunction())) {
|
if (templateId && (s->isDeclaration() || s->isFunction())) {
|
||||||
FullySpecifiedType ty = DeprecatedGenTemplateInstance::instantiate(templateId, s, _control);
|
FullySpecifiedType ty = DeprecatedGenTemplateInstance::instantiate(templateId, s, control());
|
||||||
item.setType(ty); // override the type.
|
item.setType(ty); // override the type.
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1215,8 +1205,10 @@ ClassOrNamespace *ClassOrNamespace::findOrCreateType(const Name *name, ClassOrNa
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateBindings::CreateBindings(Document::Ptr thisDocument, const Snapshot &snapshot, QSharedPointer<Control> control)
|
CreateBindings::CreateBindings(Document::Ptr thisDocument, const Snapshot &snapshot)
|
||||||
: _snapshot(snapshot), _control(control), _expandTemplates(false)
|
: _snapshot(snapshot)
|
||||||
|
, _control(QSharedPointer<Control>(new Control))
|
||||||
|
, _expandTemplates(false)
|
||||||
{
|
{
|
||||||
_globalNamespace = allocClassOrNamespace(/*parent = */ 0);
|
_globalNamespace = allocClassOrNamespace(/*parent = */ 0);
|
||||||
_currentClassOrNamespace = _globalNamespace;
|
_currentClassOrNamespace = _globalNamespace;
|
||||||
@@ -1277,11 +1269,6 @@ void CreateBindings::process(Symbol *symbol)
|
|||||||
_currentClassOrNamespace->addTodo(symbol);
|
_currentClassOrNamespace->addTodo(symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
QSharedPointer<Control> CreateBindings::control() const
|
|
||||||
{
|
|
||||||
return _control;
|
|
||||||
}
|
|
||||||
|
|
||||||
ClassOrNamespace *CreateBindings::allocClassOrNamespace(ClassOrNamespace *parent)
|
ClassOrNamespace *CreateBindings::allocClassOrNamespace(ClassOrNamespace *parent)
|
||||||
{
|
{
|
||||||
ClassOrNamespace *e = new ClassOrNamespace(this, parent);
|
ClassOrNamespace *e = new ClassOrNamespace(this, parent);
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ class CPLUSPLUS_EXPORT CreateBindings: protected SymbolVisitor
|
|||||||
Q_DISABLE_COPY(CreateBindings)
|
Q_DISABLE_COPY(CreateBindings)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CreateBindings(Document::Ptr thisDocument, const Snapshot &snapshot, QSharedPointer<Control> control);
|
CreateBindings(Document::Ptr thisDocument, const Snapshot &snapshot);
|
||||||
virtual ~CreateBindings();
|
virtual ~CreateBindings();
|
||||||
|
|
||||||
/// Returns the binding for the global namespace.
|
/// Returns the binding for the global namespace.
|
||||||
@@ -187,7 +187,8 @@ public:
|
|||||||
|
|
||||||
/// Returns the Control that must be used to create temporary symbols.
|
/// Returns the Control that must be used to create temporary symbols.
|
||||||
/// \internal
|
/// \internal
|
||||||
QSharedPointer<Control> control() const;
|
QSharedPointer<Control> control() const
|
||||||
|
{ return _control; }
|
||||||
|
|
||||||
bool expandTemplates() const
|
bool expandTemplates() const
|
||||||
{ return _expandTemplates; }
|
{ return _expandTemplates; }
|
||||||
@@ -292,8 +293,6 @@ public:
|
|||||||
/// \internal
|
/// \internal
|
||||||
void setBindings(QSharedPointer<CreateBindings> bindings);
|
void setBindings(QSharedPointer<CreateBindings> bindings);
|
||||||
|
|
||||||
QSharedPointer<Control> control() const; // ### deprecate
|
|
||||||
|
|
||||||
static QList<const Name *> fullyQualifiedName(Symbol *symbol);
|
static QList<const Name *> fullyQualifiedName(Symbol *symbol);
|
||||||
static QList<const Name *> path(Symbol *symbol);
|
static QList<const Name *> path(Symbol *symbol);
|
||||||
|
|
||||||
@@ -319,8 +318,6 @@ private:
|
|||||||
// Bindings
|
// Bindings
|
||||||
mutable QSharedPointer<CreateBindings> _bindings;
|
mutable QSharedPointer<CreateBindings> _bindings;
|
||||||
|
|
||||||
QSharedPointer<Control> _control;
|
|
||||||
|
|
||||||
bool m_expandTemplates;
|
bool m_expandTemplates;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -621,7 +621,7 @@ Utils::ChangeSet FunctionDeclDefLink::changes(const Snapshot &snapshot, int targ
|
|||||||
targetCoN = targetContext.globalNamespace();
|
targetCoN = targetContext.globalNamespace();
|
||||||
UseMinimalNames q(targetCoN);
|
UseMinimalNames q(targetCoN);
|
||||||
env.enter(&q);
|
env.enter(&q);
|
||||||
Control *control = sourceContext.control().data();
|
Control *control = sourceContext.bindings()->control().data();
|
||||||
|
|
||||||
// get return type start position and declarator info from declaration
|
// get return type start position and declarator info from declaration
|
||||||
DeclaratorAST *declarator = 0;
|
DeclaratorAST *declarator = 0;
|
||||||
@@ -667,7 +667,7 @@ Utils::ChangeSet FunctionDeclDefLink::changes(const Snapshot &snapshot, int targ
|
|||||||
targetCoN = targetContext.globalNamespace();
|
targetCoN = targetContext.globalNamespace();
|
||||||
UseMinimalNames q(targetCoN);
|
UseMinimalNames q(targetCoN);
|
||||||
env.enter(&q);
|
env.enter(&q);
|
||||||
Control *control = sourceContext.control().data();
|
Control *control = sourceContext.bindings()->control().data();
|
||||||
Overview overview = overviewFromCurrentProjectStyle;
|
Overview overview = overviewFromCurrentProjectStyle;
|
||||||
|
|
||||||
// make a easy to access list of the target parameter declarations
|
// make a easy to access list of the target parameter declarations
|
||||||
|
|||||||
@@ -259,7 +259,7 @@ public:
|
|||||||
env.switchScope(m_decl->enclosingScope());
|
env.switchScope(m_decl->enclosingScope());
|
||||||
UseMinimalNames q(targetCoN);
|
UseMinimalNames q(targetCoN);
|
||||||
env.enter(&q);
|
env.enter(&q);
|
||||||
Control *control = assistInterface()->context().control().data();
|
Control *control = assistInterface()->context().bindings()->control().data();
|
||||||
|
|
||||||
// rewrite the function type
|
// rewrite the function type
|
||||||
FullySpecifiedType tn = rewriteType(m_decl->type(), &env, control);
|
FullySpecifiedType tn = rewriteType(m_decl->type(), &env, control);
|
||||||
@@ -651,7 +651,7 @@ public:
|
|||||||
env.enter(&subs);
|
env.enter(&subs);
|
||||||
|
|
||||||
Overview printer = CppCodeStyleSettings::currentProjectCodeStyleOverview();
|
Overview printer = CppCodeStyleSettings::currentProjectCodeStyleOverview();
|
||||||
Control *control = assistInterface()->context().control().data();
|
Control *control = assistInterface()->context().bindings()->control().data();
|
||||||
QString funcDef;
|
QString funcDef;
|
||||||
QString funcDecl; // We generate a declaration only in the case of a member function.
|
QString funcDecl; // We generate a declaration only in the case of a member function.
|
||||||
QString funcCall;
|
QString funcCall;
|
||||||
|
|||||||
@@ -1069,7 +1069,7 @@ void TranslateStringLiteral::match(const CppQuickFixInterface &interface,
|
|||||||
|
|
||||||
QString trContext;
|
QString trContext;
|
||||||
|
|
||||||
QSharedPointer<Control> control = interface->context().control();
|
QSharedPointer<Control> control = interface->context().bindings()->control();
|
||||||
const Name *trName = control->identifier("tr");
|
const Name *trName = control->identifier("tr");
|
||||||
|
|
||||||
// Check whether we are in a method:
|
// Check whether we are in a method:
|
||||||
@@ -1471,7 +1471,7 @@ public:
|
|||||||
UseMinimalNames q(con);
|
UseMinimalNames q(con);
|
||||||
env.enter(&q);
|
env.enter(&q);
|
||||||
|
|
||||||
Control *control = assistInterface()->context().control().data();
|
Control *control = assistInterface()->context().bindings()->control().data();
|
||||||
FullySpecifiedType tn = rewriteType(result.first().type(), &env, control);
|
FullySpecifiedType tn = rewriteType(result.first().type(), &env, control);
|
||||||
|
|
||||||
Overview oo = CppCodeStyleSettings::currentProjectCodeStyleOverview();
|
Overview oo = CppCodeStyleSettings::currentProjectCodeStyleOverview();
|
||||||
|
|||||||
@@ -1778,7 +1778,7 @@ bool CppCompletionAssistProcessor::completeConstructorOrFunction(const QList<CPl
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (functions.isEmpty()) {
|
if (functions.isEmpty()) {
|
||||||
const Name *functionCallOp = context.control()->operatorNameId(OperatorNameId::FunctionCallOp);
|
const Name *functionCallOp = context.bindings()->control()->operatorNameId(OperatorNameId::FunctionCallOp);
|
||||||
|
|
||||||
foreach (const LookupItem &result, results) {
|
foreach (const LookupItem &result, results) {
|
||||||
FullySpecifiedType ty = result.type().simplified();
|
FullySpecifiedType ty = result.type().simplified();
|
||||||
@@ -1873,7 +1873,7 @@ bool CppCompletionAssistProcessor::completeConstructorOrFunction(const QList<CPl
|
|||||||
targetCoN = context.globalNamespace();
|
targetCoN = context.globalNamespace();
|
||||||
UseMinimalNames q(targetCoN);
|
UseMinimalNames q(targetCoN);
|
||||||
env.enter(&q);
|
env.enter(&q);
|
||||||
Control *control = context.control().data();
|
Control *control = context.bindings()->control().data();
|
||||||
|
|
||||||
// set up signature autocompletion
|
// set up signature autocompletion
|
||||||
foreach (Function *f, functions) {
|
foreach (Function *f, functions) {
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ void tst_cxx11::inlineNamespaceLookup()
|
|||||||
snapshot.insert(doc);
|
snapshot.insert(doc);
|
||||||
|
|
||||||
LookupContext context(doc, snapshot);
|
LookupContext context(doc, snapshot);
|
||||||
QSharedPointer<Control> control = context.control();
|
QSharedPointer<Control> control = context.bindings()->control();
|
||||||
|
|
||||||
QList<LookupItem> results = context.lookup(control->identifier("foo"), doc->globalNamespace());
|
QList<LookupItem> results = context.lookup(control->identifier("foo"), doc->globalNamespace());
|
||||||
QCOMPARE(results.size(), 1); // the symbol is visible from the global scope
|
QCOMPARE(results.size(), 1); // the symbol is visible from the global scope
|
||||||
|
|||||||
Reference in New Issue
Block a user