Commit 8f0be66d authored by Nikolai Kosjar's avatar Nikolai Kosjar

CppEditor: Fix crash on virtual function override lookup

...involving templates.

Task-number: QTCREATORBUG-10496

Change-Id: I485d691043f27b03e120353f0dfd6a2fb0aa07ec
Reviewed-by: Orgad Shaneh's avatarOrgad Shaneh <orgads@gmail.com>
Reviewed-by: default avatarErik Verbruggen <erik.verbruggen@digia.com>
parent 1113097c
......@@ -140,6 +140,7 @@ private slots:
void test_FollowSymbolUnderCursor_virtualFunctionCall_possibleOverrides2();
void test_FollowSymbolUnderCursor_virtualFunctionCall_fallbackToDeclaration();
void test_FollowSymbolUnderCursor_virtualFunctionCall_itemOrder();
void test_FollowSymbolUnderCursor_virtualFunctionCall_instantiatedSymbols();
void test_FollowSymbolUnderCursor_virtualFunctionCall_onDotMemberAccessOfReferenceTypes();
void test_FollowSymbolUnderCursor_virtualFunctionCall_notOnDotMemberAccessOfNonReferenceType();
void test_FollowSymbolUnderCursor_virtualFunctionCall_notOnQualified();
......
......@@ -512,12 +512,12 @@ BaseTextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &
break;
}
TypeOfExpression typeOfExpression;
typeOfExpression.init(doc, snapshot);
const QSharedPointer<TypeOfExpression> typeOfExpression(new TypeOfExpression);
typeOfExpression->init(doc, snapshot);
// make possible to instantiate templates
typeOfExpression.setExpandTemplates(true);
typeOfExpression->setExpandTemplates(true);
const QList<LookupItem> resolvedSymbols =
typeOfExpression.reference(expression.toUtf8(), scope, TypeOfExpression::Preprocess);
typeOfExpression->reference(expression.toUtf8(), scope, TypeOfExpression::Preprocess);
if (!resolvedSymbols.isEmpty()) {
LookupItem result = skipForwardDeclarations(resolvedSymbols);
......@@ -552,13 +552,15 @@ BaseTextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &
// Consider to show a pop-up displaying overrides for the function
Function *function = symbol->type()->asFunctionType();
if (lookupVirtualFunctionOverrides(typeOfExpression, doc, function, scope, snapshot)) {
if (lookupVirtualFunctionOverrides(*typeOfExpression, doc, function, scope, snapshot)) {
Class *klass = symbolFinder->findMatchingClassDeclaration(function, snapshot);
QTC_CHECK(klass);
VirtualFunctionAssistProvider::Parameters params;
params.startClass = klass;
params.function = function;
params.typeOfExpression = typeOfExpression;
params.snapshot = snapshot;
params.cursorPosition = cursor.position();
params.openInNextSplit = inNextSplit;
......@@ -566,6 +568,7 @@ BaseTextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &
if (m_virtualFunctionAssistProvider->configure(params)) {
m_widget->invokeAssist(TextEditor::FollowSymbol,
m_virtualFunctionAssistProvider);
m_virtualFunctionAssistProvider->clearParams();
}
// Ensure a valid link text, so the symbol name will be underlined on Ctrl+Hover.
......
......@@ -34,7 +34,9 @@
#include <cplusplus/CppDocument.h>
#include <cplusplus/Symbols.h>
#include <cplusplus/TypeOfExpression.h>
#include <QSharedPointer>
#include <QTextCursor>
namespace CppEditor {
......@@ -50,6 +52,7 @@ public:
CPlusPlus::Class *startClass;
CPlusPlus::Function *function;
QSharedPointer<CPlusPlus::TypeOfExpression> typeOfExpression; // Keeps instantiated symbols.
CPlusPlus::Snapshot snapshot;
int cursorPosition;
bool openInNextSplit;
......@@ -57,6 +60,7 @@ public:
virtual bool configure(const Parameters &parameters);
Parameters params() const { return m_params; }
void clearParams() { m_params = Parameters(); }
bool isAsynchronous() const;
bool supportsEditor(const Core::Id &editorId) const;
......
......@@ -112,6 +112,8 @@ public:
IAssistProposal *immediateProposal = processor->immediateProposal(assistInterface);
IAssistProposal *finalProposal = processor->perform(assistInterface);
VirtualFunctionAssistProvider::clearParams();
m_immediateItems = itemList(immediateProposal->model());
m_finalItems = itemList(finalProposal->model());
......@@ -1399,6 +1401,25 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_itemOrder
test.run();
}
/// Check: If class templates are involved, the class and function symbols might be generated.
/// In that case, make sure that the symbols are not deleted before we reference them.
void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_instantiatedSymbols()
{
const QByteArray source =
"template <class T> struct A { virtual void virt() {} };\n"
"void f(A<int> *l) { l->$@virt(); }\n"
;
const OverrideItemList immediateResults = OverrideItemList()
<< OverrideItem(QLatin1String("A::virt"), 1)
<< OverrideItem(QLatin1String("...searching overrides"));
const OverrideItemList finalResults = OverrideItemList()
<< OverrideItem(QLatin1String("A::virt"), 1);
TestCase test(TestCase::FollowSymbolUnderCursorAction, source, immediateResults, finalResults);
test.run();
}
/// Check: Trigger on a.virt() if a is of type &A.
void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_onDotMemberAccessOfReferenceTypes()
{
......
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