diff options
author | Christian Kandeler <christian.kandeler@qt.io> | 2020-08-17 12:02:47 +0200 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@qt.io> | 2020-08-20 10:34:53 +0000 |
commit | 86728b84f1bb44d0f0d02f0eb167aa907d2fd8fc (patch) | |
tree | c20f6b4fb216c4c00a0616c6090f6653fd6370ba /src/plugins/cpptools/functionutils.cpp | |
parent | 919dc86c37ceac9808a1997ab8c5db153dba5e3b (diff) | |
download | qt-creator-86728b84f1bb44d0f0d02f0eb167aa907d2fd8fc.tar.gz |
CppEditor: Properly handle multiple inheritance
... in "Insert Virtual Functions" quickfix.
Fixes: QTCREATORBUG-12223
Change-Id: I7dad7c219017a8c7b10b08190e35d1899ca5dfe6
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Diffstat (limited to 'src/plugins/cpptools/functionutils.cpp')
-rw-r--r-- | src/plugins/cpptools/functionutils.cpp | 76 |
1 files changed, 59 insertions, 17 deletions
diff --git a/src/plugins/cpptools/functionutils.cpp b/src/plugins/cpptools/functionutils.cpp index fa82fece8a..b19fe43958 100644 --- a/src/plugins/cpptools/functionutils.cpp +++ b/src/plugins/cpptools/functionutils.cpp @@ -33,6 +33,11 @@ #include <utils/qtcassert.h> #include <QList> +#include <QPair> + +#include <limits> + +#include <cplusplus/TypePrettyPrinter.h> using namespace CPlusPlus; using namespace CppTools; @@ -42,12 +47,12 @@ enum VirtualType { Virtual, PureVirtual }; static bool isVirtualFunction_helper(const Function *function, const LookupContext &context, VirtualType virtualType, - const Function **firstVirtual) + QList<const Function *> *firstVirtuals) { enum { Unknown, False, True } res = Unknown; - if (firstVirtual) - *firstVirtual = nullptr; + if (firstVirtuals) + firstVirtuals->clear(); if (!function) return false; @@ -55,14 +60,51 @@ static bool isVirtualFunction_helper(const Function *function, if (virtualType == PureVirtual) res = function->isPureVirtual() ? True : False; + const Class * const klass = function->enclosingScope() + ? function->enclosingScope()->asClass() : nullptr; + if (!klass) + return false; + + int hierarchyDepthOfFirstVirtuals = -1; + const auto updateFirstVirtualsList + = [&hierarchyDepthOfFirstVirtuals, &context, firstVirtuals, klass](Function *candidate) { + const Class * const candidateClass = candidate->enclosingScope() + ? candidate->enclosingScope()->asClass() : nullptr; + if (!candidateClass) + return; + QList<QPair<const Class *, int>> classes{{klass, 0}}; + while (!classes.isEmpty()) { + const auto c = classes.takeFirst(); + if (c.first == candidateClass) { + QTC_ASSERT(c.second != 0, return); + if (c.second >= hierarchyDepthOfFirstVirtuals) { + if (c.second > hierarchyDepthOfFirstVirtuals) { + firstVirtuals->clear(); + hierarchyDepthOfFirstVirtuals = c.second; + } + firstVirtuals->append(candidate); + } + return; + } + for (int i = 0; i < c.first->baseClassCount(); ++i) { + const ClassOrNamespace * const base = context.lookupType( + c.first->baseClassAt(i)->name(), c.first->enclosingScope()); + if (base && base->rootClass()) + classes.append({base->rootClass(), c.second + 1}); + } + } + }; + if (function->isVirtual()) { - if (firstVirtual) - *firstVirtual = function; + if (firstVirtuals) { + hierarchyDepthOfFirstVirtuals = 0; + firstVirtuals->append(function); + } if (res == Unknown) res = True; } - if (!firstVirtual && res != Unknown) + if (!firstVirtuals && res != Unknown) return res == True; QList<LookupItem> results = context.lookup(function->name(), function->enclosingScope()); @@ -80,11 +122,11 @@ static bool isVirtualFunction_helper(const Function *function, if (functionType->isFinal()) return res == True; if (functionType->isVirtual()) { - if (!firstVirtual) + if (!firstVirtuals) return true; if (res == Unknown) res = True; - *firstVirtual = functionType; + updateFirstVirtualsList(functionType); } } } @@ -96,16 +138,16 @@ static bool isVirtualFunction_helper(const Function *function, bool FunctionUtils::isVirtualFunction(const Function *function, const LookupContext &context, - const Function **firstVirtual) + QList<const Function *> *firstVirtuals) { - return isVirtualFunction_helper(function, context, Virtual, firstVirtual); + return isVirtualFunction_helper(function, context, Virtual, firstVirtuals); } bool FunctionUtils::isPureVirtualFunction(const Function *function, const LookupContext &context, - const Function **firstVirtual) + QList<const Function *> *firstVirtuals) { - return isVirtualFunction_helper(function, context, PureVirtual, firstVirtual); + return isVirtualFunction_helper(function, context, PureVirtual, firstVirtuals); } QList<Function *> FunctionUtils::overrides(Function *function, Class *functionsClass, @@ -191,7 +233,7 @@ void CppToolsPlugin::test_functionutils_virtualFunctions() QCOMPARE(document->diagnosticMessages().size(), 0); QVERIFY(document->translationUnit()->ast()); QList<const Function *> allFunctions; - const Function *firstVirtual = nullptr; + QList<const Function *> firstVirtuals; // Iterate through Function symbols Snapshot snapshot; @@ -206,9 +248,9 @@ void CppToolsPlugin::test_functionutils_virtualFunctions() Virtuality virtuality = virtualityList.takeFirst(); QTC_ASSERT(!firstVirtualList.isEmpty(), return); int firstVirtualIndex = firstVirtualList.takeFirst(); - bool isVirtual = FunctionUtils::isVirtualFunction(function, context, &firstVirtual); + bool isVirtual = FunctionUtils::isVirtualFunction(function, context, &firstVirtuals); bool isPureVirtual = FunctionUtils::isPureVirtualFunction(function, context, - &firstVirtual); + &firstVirtuals); // Test for regressions introduced by firstVirtual QCOMPARE(FunctionUtils::isVirtualFunction(function, context), isVirtual); @@ -225,9 +267,9 @@ void CppToolsPlugin::test_functionutils_virtualFunctions() QCOMPARE(virtuality, NotVirtual); } if (firstVirtualIndex == -1) - QVERIFY(!firstVirtual); + QVERIFY(firstVirtuals.isEmpty()); else - QCOMPARE(firstVirtual, allFunctions.at(firstVirtualIndex)); + QCOMPARE(firstVirtuals, {allFunctions.at(firstVirtualIndex)}); } } QVERIFY(virtualityList.isEmpty()); |