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:
Erik Verbruggen
2013-03-20 13:48:20 +01:00
committed by Erik Verbruggen
parent 6999e3c339
commit 8e18adc70f
7 changed files with 33 additions and 49 deletions

View File

@@ -151,47 +151,42 @@ uint qHash(const FullyQualifiedName &fullyQualifiedName)
// LookupContext
/////////////////////////////////////////////////////////////////////
LookupContext::LookupContext()
: _control(new Control())
, m_expandTemplates(false)
: m_expandTemplates(false)
{ }
LookupContext::LookupContext(Document::Ptr thisDocument,
const Snapshot &snapshot)
: _expressionDocument(Document::create(QLatin1String("<LookupContext>"))),
_thisDocument(thisDocument),
_snapshot(snapshot),
_control(new Control()),
m_expandTemplates(false)
: _expressionDocument(Document::create(QLatin1String("<LookupContext>")))
, _thisDocument(thisDocument)
, _snapshot(snapshot)
, m_expandTemplates(false)
{
}
LookupContext::LookupContext(Document::Ptr expressionDocument,
Document::Ptr thisDocument,
const Snapshot &snapshot)
: _expressionDocument(expressionDocument),
_thisDocument(thisDocument),
_snapshot(snapshot),
_control(new Control()),
m_expandTemplates(false)
: _expressionDocument(expressionDocument)
, _thisDocument(thisDocument)
, _snapshot(snapshot)
, m_expandTemplates(false)
{
}
LookupContext::LookupContext(const LookupContext &other)
: _expressionDocument(other._expressionDocument),
_thisDocument(other._thisDocument),
_snapshot(other._snapshot),
_bindings(other._bindings),
_control(other._control),
m_expandTemplates(other.m_expandTemplates)
: _expressionDocument(other._expressionDocument)
, _thisDocument(other._thisDocument)
, _snapshot(other._snapshot)
, _bindings(other._bindings)
, m_expandTemplates(other.m_expandTemplates)
{ }
LookupContext &LookupContext::operator = (const LookupContext &other)
LookupContext &LookupContext::operator=(const LookupContext &other)
{
_expressionDocument = other._expressionDocument;
_thisDocument = other._thisDocument;
_snapshot = other._snapshot;
_bindings = other._bindings;
_control = other._control;
m_expandTemplates = other.m_expandTemplates;
return *this;
}
@@ -250,7 +245,7 @@ const Name *LookupContext::minimalName(Symbol *symbol, ClassOrNamespace *target,
QSharedPointer<CreateBindings> LookupContext::bindings() const
{
if (! _bindings) {
_bindings = QSharedPointer<CreateBindings>(new CreateBindings(_thisDocument, _snapshot, control()));
_bindings = QSharedPointer<CreateBindings>(new CreateBindings(_thisDocument, _snapshot));
_bindings->setExpandTemplates(m_expandTemplates);
}
@@ -262,11 +257,6 @@ void LookupContext::setBindings(QSharedPointer<CreateBindings> bindings)
_bindings = bindings;
}
QSharedPointer<Control> LookupContext::control() const
{
return _control;
}
Document::Ptr LookupContext::expressionDocument() const
{ return _expressionDocument; }
@@ -649,7 +639,7 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope,
}
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.
}
@@ -1215,8 +1205,10 @@ ClassOrNamespace *ClassOrNamespace::findOrCreateType(const Name *name, ClassOrNa
return 0;
}
CreateBindings::CreateBindings(Document::Ptr thisDocument, const Snapshot &snapshot, QSharedPointer<Control> control)
: _snapshot(snapshot), _control(control), _expandTemplates(false)
CreateBindings::CreateBindings(Document::Ptr thisDocument, const Snapshot &snapshot)
: _snapshot(snapshot)
, _control(QSharedPointer<Control>(new Control))
, _expandTemplates(false)
{
_globalNamespace = allocClassOrNamespace(/*parent = */ 0);
_currentClassOrNamespace = _globalNamespace;
@@ -1277,11 +1269,6 @@ void CreateBindings::process(Symbol *symbol)
_currentClassOrNamespace->addTodo(symbol);
}
QSharedPointer<Control> CreateBindings::control() const
{
return _control;
}
ClassOrNamespace *CreateBindings::allocClassOrNamespace(ClassOrNamespace *parent)
{
ClassOrNamespace *e = new ClassOrNamespace(this, parent);

View File

@@ -173,7 +173,7 @@ class CPLUSPLUS_EXPORT CreateBindings: protected SymbolVisitor
Q_DISABLE_COPY(CreateBindings)
public:
CreateBindings(Document::Ptr thisDocument, const Snapshot &snapshot, QSharedPointer<Control> control);
CreateBindings(Document::Ptr thisDocument, const Snapshot &snapshot);
virtual ~CreateBindings();
/// Returns the binding for the global namespace.
@@ -187,7 +187,8 @@ public:
/// Returns the Control that must be used to create temporary symbols.
/// \internal
QSharedPointer<Control> control() const;
QSharedPointer<Control> control() const
{ return _control; }
bool expandTemplates() const
{ return _expandTemplates; }
@@ -292,8 +293,6 @@ public:
/// \internal
void setBindings(QSharedPointer<CreateBindings> bindings);
QSharedPointer<Control> control() const; // ### deprecate
static QList<const Name *> fullyQualifiedName(Symbol *symbol);
static QList<const Name *> path(Symbol *symbol);
@@ -319,8 +318,6 @@ private:
// Bindings
mutable QSharedPointer<CreateBindings> _bindings;
QSharedPointer<Control> _control;
bool m_expandTemplates;
};

View File

@@ -621,7 +621,7 @@ Utils::ChangeSet FunctionDeclDefLink::changes(const Snapshot &snapshot, int targ
targetCoN = targetContext.globalNamespace();
UseMinimalNames q(targetCoN);
env.enter(&q);
Control *control = sourceContext.control().data();
Control *control = sourceContext.bindings()->control().data();
// get return type start position and declarator info from declaration
DeclaratorAST *declarator = 0;
@@ -667,7 +667,7 @@ Utils::ChangeSet FunctionDeclDefLink::changes(const Snapshot &snapshot, int targ
targetCoN = targetContext.globalNamespace();
UseMinimalNames q(targetCoN);
env.enter(&q);
Control *control = sourceContext.control().data();
Control *control = sourceContext.bindings()->control().data();
Overview overview = overviewFromCurrentProjectStyle;
// make a easy to access list of the target parameter declarations

View File

@@ -259,7 +259,7 @@ public:
env.switchScope(m_decl->enclosingScope());
UseMinimalNames q(targetCoN);
env.enter(&q);
Control *control = assistInterface()->context().control().data();
Control *control = assistInterface()->context().bindings()->control().data();
// rewrite the function type
FullySpecifiedType tn = rewriteType(m_decl->type(), &env, control);
@@ -651,7 +651,7 @@ public:
env.enter(&subs);
Overview printer = CppCodeStyleSettings::currentProjectCodeStyleOverview();
Control *control = assistInterface()->context().control().data();
Control *control = assistInterface()->context().bindings()->control().data();
QString funcDef;
QString funcDecl; // We generate a declaration only in the case of a member function.
QString funcCall;

View File

@@ -1069,7 +1069,7 @@ void TranslateStringLiteral::match(const CppQuickFixInterface &interface,
QString trContext;
QSharedPointer<Control> control = interface->context().control();
QSharedPointer<Control> control = interface->context().bindings()->control();
const Name *trName = control->identifier("tr");
// Check whether we are in a method:
@@ -1471,7 +1471,7 @@ public:
UseMinimalNames q(con);
env.enter(&q);
Control *control = assistInterface()->context().control().data();
Control *control = assistInterface()->context().bindings()->control().data();
FullySpecifiedType tn = rewriteType(result.first().type(), &env, control);
Overview oo = CppCodeStyleSettings::currentProjectCodeStyleOverview();

View File

@@ -1778,7 +1778,7 @@ bool CppCompletionAssistProcessor::completeConstructorOrFunction(const QList<CPl
}
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) {
FullySpecifiedType ty = result.type().simplified();
@@ -1873,7 +1873,7 @@ bool CppCompletionAssistProcessor::completeConstructorOrFunction(const QList<CPl
targetCoN = context.globalNamespace();
UseMinimalNames q(targetCoN);
env.enter(&q);
Control *control = context.control().data();
Control *control = context.bindings()->control().data();
// set up signature autocompletion
foreach (Function *f, functions) {

View File

@@ -174,7 +174,7 @@ void tst_cxx11::inlineNamespaceLookup()
snapshot.insert(doc);
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());
QCOMPARE(results.size(), 1); // the symbol is visible from the global scope