summaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/cppeditor/cppeditorplugin.h3
-rw-r--r--src/plugins/cppeditor/cppfollowsymbolundercursor.cpp5
-rw-r--r--src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp284
-rw-r--r--src/plugins/cppeditor/cppvirtualfunctionassistprovider.h17
-rw-r--r--src/plugins/cpptools/cpptools.pro6
-rw-r--r--src/plugins/cpptools/cpptools.qbs2
-rw-r--r--src/plugins/cpptools/cpptoolsplugin.h3
-rw-r--r--src/plugins/cpptools/functionutils.cpp321
-rw-r--r--src/plugins/cpptools/functionutils.h68
9 files changed, 404 insertions, 305 deletions
diff --git a/src/plugins/cppeditor/cppeditorplugin.h b/src/plugins/cppeditor/cppeditorplugin.h
index e06355949b..6ef87cf793 100644
--- a/src/plugins/cppeditor/cppeditorplugin.h
+++ b/src/plugins/cppeditor/cppeditorplugin.h
@@ -206,9 +206,6 @@ private slots:
void test_quickfix_InsertVirtualMethods_implementationFile();
void test_quickfix_InsertVirtualMethods_BaseClassInNamespace();
- void test_functionhelper_virtualFunctions();
- void test_functionhelper_virtualFunctions_data();
-
// tests for "Include Hiererchy"
void test_includeHierarchyModel_simpleIncludes();
void test_includeHierarchyModel_simpleIncludedBy();
diff --git a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp b/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp
index 6b566f9f41..1b678ba33c 100644
--- a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp
+++ b/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp
@@ -39,6 +39,7 @@
#include <cplusplus/SimpleLexer.h>
#include <cplusplus/TypeOfExpression.h>
#include <cpptools/cppmodelmanagerinterface.h>
+#include <cpptools/functionutils.h>
#include <cpptools/symbolfinder.h>
#include <texteditor/basetextdocumentlayout.h>
#include <utils/qtcassert.h>
@@ -128,12 +129,12 @@ bool VirtualFunctionHelper::canLookupVirtualFunctionOverrides(Function *function
if (IdExpressionAST *idExpressionAST = m_baseExpressionAST->asIdExpression()) {
NameAST *name = idExpressionAST->name;
const bool nameIsQualified = name && name->asQualifiedName();
- result = !nameIsQualified && FunctionHelper::isVirtualFunction(
+ result = !nameIsQualified && FunctionUtils::isVirtualFunction(
function, LookupContext(m_document, m_snapshot));
} else if (MemberAccessAST *memberAccessAST = m_baseExpressionAST->asMemberAccess()) {
NameAST *name = memberAccessAST->member_name;
const bool nameIsQualified = name && name->asQualifiedName();
- if (!nameIsQualified && FunctionHelper::isVirtualFunction(
+ if (!nameIsQualified && FunctionUtils::isVirtualFunction(
function, LookupContext(m_document, m_snapshot))) {
TranslationUnit *unit = m_expressionDocument->translationUnit();
QTC_ASSERT(unit, return false);
diff --git a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp
index aff4973e05..a3f7048909 100644
--- a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp
+++ b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp
@@ -40,6 +40,7 @@
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
+#include <cpptools/functionutils.h>
#include <cpptools/symbolfinder.h>
#include <cpptools/typehierarchybuilder.h>
@@ -55,6 +56,7 @@
using namespace CPlusPlus;
using namespace CppEditor::Internal;
+using namespace CppTools;
using namespace TextEditor;
/// Activate current item with the same shortcut that is configured for Follow Symbol Under Cursor.
@@ -143,7 +145,7 @@ public:
if (!functionsClass)
return 0;
- const QList<Symbol *> overrides = FunctionHelper::overrides(
+ const QList<Symbol *> overrides = FunctionUtils::overrides(
m_params.function, functionsClass, m_params.staticClass, m_params.snapshot);
if (overrides.isEmpty())
return 0;
@@ -208,283 +210,3 @@ IAssistProcessor *VirtualFunctionAssistProvider::createProcessor() const
{
return new VirtualFunctionsAssistProcessor(m_params);
}
-
-enum VirtualType { Virtual, PureVirtual };
-
-static bool isVirtualFunction_helper(const Function *function,
- const LookupContext &context,
- VirtualType virtualType,
- const Function **firstVirtual)
-{
- enum { Unknown, False, True } res = Unknown;
-
- if (firstVirtual)
- *firstVirtual = 0;
-
- if (!function)
- return false;
-
- if (virtualType == PureVirtual)
- res = function->isPureVirtual() ? True : False;
-
- if (function->isVirtual()) {
- if (firstVirtual)
- *firstVirtual = function;
- if (res == Unknown)
- res = True;
- }
-
- if (!firstVirtual && res != Unknown)
- return res == True;
-
- QList<LookupItem> results = context.lookup(function->name(), function->enclosingScope());
- if (!results.isEmpty()) {
- const bool isDestructor = function->name()->isDestructorNameId();
- foreach (const LookupItem &item, results) {
- if (Symbol *symbol = item.declaration()) {
- if (Function *functionType = symbol->type()->asFunctionType()) {
- if (functionType->name()->isDestructorNameId() != isDestructor)
- continue;
- if (functionType == function) // already tested
- continue;
- if (functionType->isFinal())
- return res == True;
- if (functionType->isVirtual()) {
- if (!firstVirtual)
- return true;
- if (res == Unknown)
- res = True;
- *firstVirtual = functionType;
- }
- }
- }
- }
- }
-
- return res == True;
-}
-
-bool FunctionHelper::isVirtualFunction(const Function *function,
- const LookupContext &context,
- const Function **firstVirtual)
-{
- return isVirtualFunction_helper(function, context, Virtual, firstVirtual);
-}
-
-bool FunctionHelper::isPureVirtualFunction(const Function *function,
- const LookupContext &context,
- const Function **firstVirtual)
-{
- return isVirtualFunction_helper(function, context, PureVirtual, firstVirtual);
-}
-
-QList<Symbol *> FunctionHelper::overrides(Function *function, Class *functionsClass,
- Class *staticClass, const Snapshot &snapshot)
-{
- QList<Symbol *> result;
- QTC_ASSERT(function && functionsClass && staticClass, return result);
-
- FullySpecifiedType referenceType = function->type();
- const Name *referenceName = function->name();
- QTC_ASSERT(referenceName && referenceType.isValid(), return result);
-
- // Find overrides
- CppTools::TypeHierarchyBuilder builder(staticClass, snapshot);
- const CppTools::TypeHierarchy &staticClassHierarchy = builder.buildDerivedTypeHierarchy();
-
- QList<CppTools::TypeHierarchy> l;
- l.append(CppTools::TypeHierarchy(functionsClass));
- l.append(staticClassHierarchy);
-
- while (!l.isEmpty()) {
- // Add derived
- const CppTools::TypeHierarchy hierarchy = l.takeFirst();
- QTC_ASSERT(hierarchy.symbol(), continue);
- Class *c = hierarchy.symbol()->asClass();
- QTC_ASSERT(c, continue);
-
- foreach (const CppTools::TypeHierarchy &t, hierarchy.hierarchy()) {
- if (!l.contains(t))
- l << t;
- }
-
- // Check member functions
- for (int i = 0, total = c->memberCount(); i < total; ++i) {
- Symbol *candidate = c->memberAt(i);
- const Name *candidateName = candidate->name();
- const FullySpecifiedType candidateType = candidate->type();
- if (!candidateName || !candidateType.isValid())
- continue;
- if (candidateName->isEqualTo(referenceName) && candidateType.isEqualTo(referenceType))
- result << candidate;
- }
- }
-
- return result;
-}
-
-#ifdef WITH_TESTS
-#include "cppeditorplugin.h"
-
-#include <QList>
-#include <QTest>
-
-namespace CppEditor {
-namespace Internal {
-
-enum Virtuality
-{
- NotVirtual,
- Virtual,
- PureVirtual
-};
-typedef QList<Virtuality> VirtualityList;
-} // Internal namespace
-} // CppEditor namespace
-
-Q_DECLARE_METATYPE(CppEditor::Internal::Virtuality)
-Q_DECLARE_METATYPE(CppEditor::Internal::VirtualityList)
-Q_DECLARE_METATYPE(QList<int>)
-
-namespace CppEditor {
-namespace Internal {
-
-void CppEditorPlugin::test_functionhelper_virtualFunctions()
-{
- // Create and parse document
- QFETCH(QByteArray, source);
- QFETCH(VirtualityList, virtualityList);
- QFETCH(QList<int>, firstVirtualList);
- Document::Ptr document = Document::create(QLatin1String("virtuals"));
- document->setUtf8Source(source);
- document->check(); // calls parse();
- QCOMPARE(document->diagnosticMessages().size(), 0);
- QVERIFY(document->translationUnit()->ast());
- QList<const Function *> allFunctions;
- const Function *firstVirtual = 0;
-
- // Iterate through Function symbols
- Snapshot snapshot;
- snapshot.insert(document);
- const LookupContext context(document, snapshot);
- Control *control = document->translationUnit()->control();
- Symbol **end = control->lastSymbol();
- for (Symbol **it = control->firstSymbol(); it != end; ++it) {
- if (const Function *function = (*it)->asFunction()) {
- allFunctions.append(function);
- QTC_ASSERT(!virtualityList.isEmpty(), return);
- Virtuality virtuality = virtualityList.takeFirst();
- QTC_ASSERT(!firstVirtualList.isEmpty(), return);
- int firstVirtualIndex = firstVirtualList.takeFirst();
- bool isVirtual = FunctionHelper::isVirtualFunction(function, context, &firstVirtual);
- bool isPureVirtual = FunctionHelper::isPureVirtualFunction(function, context,
- &firstVirtual);
-
- // Test for regressions introduced by firstVirtual
- QCOMPARE(FunctionHelper::isVirtualFunction(function, context), isVirtual);
- QCOMPARE(FunctionHelper::isPureVirtualFunction(function, context), isPureVirtual);
- if (isVirtual) {
- if (isPureVirtual)
- QCOMPARE(virtuality, PureVirtual);
- else
- QCOMPARE(virtuality, Virtual);
- } else {
- QEXPECT_FAIL("virtual-dtor-dtor", "Not implemented", Abort);
- if (allFunctions.size() == 3)
- QEXPECT_FAIL("dtor-virtual-dtor-dtor", "Not implemented", Abort);
- QCOMPARE(virtuality, NotVirtual);
- }
- if (firstVirtualIndex == -1)
- QVERIFY(!firstVirtual);
- else
- QCOMPARE(firstVirtual, allFunctions.at(firstVirtualIndex));
- }
- }
- QVERIFY(virtualityList.isEmpty());
- QVERIFY(firstVirtualList.isEmpty());
-}
-
-void CppEditorPlugin::test_functionhelper_virtualFunctions_data()
-{
- typedef QByteArray _;
- QTest::addColumn<QByteArray>("source");
- QTest::addColumn<VirtualityList>("virtualityList");
- QTest::addColumn<QList<int> >("firstVirtualList");
-
- QTest::newRow("none")
- << _("struct None { void foo() {} };\n")
- << (VirtualityList() << NotVirtual)
- << (QList<int>() << -1);
-
- QTest::newRow("single-virtual")
- << _("struct V { virtual void foo() {} };\n")
- << (VirtualityList() << Virtual)
- << (QList<int>() << 0);
-
- QTest::newRow("single-pure-virtual")
- << _("struct PV { virtual void foo() = 0; };\n")
- << (VirtualityList() << PureVirtual)
- << (QList<int>() << 0);
-
- QTest::newRow("virtual-derived-with-specifier")
- << _("struct Base { virtual void foo() {} };\n"
- "struct Derived : Base { virtual void foo() {} };\n")
- << (VirtualityList() << Virtual << Virtual)
- << (QList<int>() << 0 << 0);
-
- QTest::newRow("virtual-derived-implicit")
- << _("struct Base { virtual void foo() {} };\n"
- "struct Derived : Base { void foo() {} };\n")
- << (VirtualityList() << Virtual << Virtual)
- << (QList<int>() << 0 << 0);
-
- QTest::newRow("not-virtual-then-virtual")
- << _("struct Base { void foo() {} };\n"
- "struct Derived : Base { virtual void foo() {} };\n")
- << (VirtualityList() << NotVirtual << Virtual)
- << (QList<int>() << -1 << 1);
-
- QTest::newRow("virtual-final-not-virtual")
- << _("struct Base { virtual void foo() {} };\n"
- "struct Derived : Base { void foo() final {} };\n"
- "struct Derived2 : Derived { void foo() {} };")
- << (VirtualityList() << Virtual << Virtual << NotVirtual)
- << (QList<int>() << 0 << 0 << -1);
-
- QTest::newRow("virtual-then-pure")
- << _("struct Base { virtual void foo() {} };\n"
- "struct Derived : Base { virtual void foo() = 0; };\n"
- "struct Derived2 : Derived { void foo() {} };")
- << (VirtualityList() << Virtual << PureVirtual << Virtual)
- << (QList<int>() << 0 << 0 << 0);
-
- QTest::newRow("virtual-virtual-final-not-virtual")
- << _("struct Base { virtual void foo() {} };\n"
- "struct Derived : Base { virtual void foo() final {} };\n"
- "struct Derived2 : Derived { void foo() {} };")
- << (VirtualityList() << Virtual << Virtual << NotVirtual)
- << (QList<int>() << 0 << 0 << -1);
-
- QTest::newRow("ctor-virtual-dtor")
- << _("struct Base { Base() {} virtual ~Base() {} };\n")
- << (VirtualityList() << NotVirtual << Virtual)
- << (QList<int>() << -1 << 1);
-
- QTest::newRow("virtual-dtor-dtor")
- << _("struct Base { virtual ~Base() {} };\n"
- "struct Derived : Base { ~Derived() {} };\n")
- << (VirtualityList() << Virtual << Virtual)
- << (QList<int>() << 0 << 0);
-
- QTest::newRow("dtor-virtual-dtor-dtor")
- << _("struct Base { ~Base() {} };\n"
- "struct Derived : Base { virtual ~Derived() {} };\n"
- "struct Derived2 : Derived { ~Derived2() {} };\n")
- << (VirtualityList() << NotVirtual << Virtual << Virtual)
- << (QList<int>() << -1 << 1 << 1);
-}
-
-} // namespace Internal
-} // namespace CppEditor
-
-#endif
diff --git a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.h b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.h
index 933fa3be4e..731f1efc5a 100644
--- a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.h
+++ b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.h
@@ -70,23 +70,6 @@ private:
Parameters m_params;
};
-class FunctionHelper
-{
-public:
- static bool isVirtualFunction(const CPlusPlus::Function *function,
- const CPlusPlus::LookupContext &context,
- const CPlusPlus::Function **firstVirtual = 0);
-
- static bool isPureVirtualFunction(const CPlusPlus::Function *function,
- const CPlusPlus::LookupContext &context,
- const CPlusPlus::Function **firstVirtual = 0);
-
- static QList<CPlusPlus::Symbol *> overrides(CPlusPlus::Function *function,
- CPlusPlus::Class *functionsClass,
- CPlusPlus::Class *staticClass,
- const CPlusPlus::Snapshot &snapshot);
-};
-
} // namespace Internal
} // namespace CppEditor
diff --git a/src/plugins/cpptools/cpptools.pro b/src/plugins/cpptools/cpptools.pro
index 9700ea853a..c75af62eb9 100644
--- a/src/plugins/cpptools/cpptools.pro
+++ b/src/plugins/cpptools/cpptools.pro
@@ -51,7 +51,8 @@ HEADERS += completionsettingspage.h \
cpplocatordata.h \
cppmodelmanagersupportinternal.h \
cppcodemodelsettings.h \
- cppcodemodelsettingspage.h
+ cppcodemodelsettingspage.h \
+ functionutils.h
SOURCES += completionsettingspage.cpp \
cppclassesfilter.cpp \
@@ -100,7 +101,8 @@ SOURCES += completionsettingspage.cpp \
cpplocatordata.cpp \
cppmodelmanagersupportinternal.cpp \
cppcodemodelsettings.cpp \
- cppcodemodelsettingspage.cpp
+ cppcodemodelsettingspage.cpp \
+ functionutils.cpp
FORMS += completionsettingspage.ui \
cppfilesettingspage.ui \
diff --git a/src/plugins/cpptools/cpptools.qbs b/src/plugins/cpptools/cpptools.qbs
index e955c80e3a..14dc119d61 100644
--- a/src/plugins/cpptools/cpptools.qbs
+++ b/src/plugins/cpptools/cpptools.qbs
@@ -101,6 +101,8 @@ QtcPlugin {
"cpptoolssettings.h",
"doxygengenerator.cpp",
"doxygengenerator.h",
+ "functionutils.cpp",
+ "functionutils.h",
"insertionpointlocator.cpp",
"insertionpointlocator.h",
"searchsymbols.cpp",
diff --git a/src/plugins/cpptools/cpptoolsplugin.h b/src/plugins/cpptools/cpptoolsplugin.h
index 94b30bf9e5..bb5cd9b3c6 100644
--- a/src/plugins/cpptools/cpptoolsplugin.h
+++ b/src/plugins/cpptools/cpptoolsplugin.h
@@ -204,6 +204,9 @@ private slots:
void test_cpppreprocessor_includes();
+ void test_functionutils_virtualFunctions();
+ void test_functionutils_virtualFunctions_data();
+
void test_modelmanager_paths_are_clean();
void test_modelmanager_framework_headers();
void test_modelmanager_refresh_also_includes_of_project_files();
diff --git a/src/plugins/cpptools/functionutils.cpp b/src/plugins/cpptools/functionutils.cpp
new file mode 100644
index 0000000000..fd7ae1d89c
--- /dev/null
+++ b/src/plugins/cpptools/functionutils.cpp
@@ -0,0 +1,321 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "functionutils.h"
+
+#include "typehierarchybuilder.h"
+
+#include <cplusplus/CppDocument.h>
+#include <cplusplus/LookupContext.h>
+#include <cplusplus/Symbols.h>
+#include <utils/qtcassert.h>
+
+#include <QList>
+
+using namespace CPlusPlus;
+using namespace CppTools;
+
+enum VirtualType { Virtual, PureVirtual };
+
+static bool isVirtualFunction_helper(const Function *function,
+ const LookupContext &context,
+ VirtualType virtualType,
+ const Function **firstVirtual)
+{
+ enum { Unknown, False, True } res = Unknown;
+
+ if (firstVirtual)
+ *firstVirtual = 0;
+
+ if (!function)
+ return false;
+
+ if (virtualType == PureVirtual)
+ res = function->isPureVirtual() ? True : False;
+
+ if (function->isVirtual()) {
+ if (firstVirtual)
+ *firstVirtual = function;
+ if (res == Unknown)
+ res = True;
+ }
+
+ if (!firstVirtual && res != Unknown)
+ return res == True;
+
+ QList<LookupItem> results = context.lookup(function->name(), function->enclosingScope());
+ if (!results.isEmpty()) {
+ const bool isDestructor = function->name()->isDestructorNameId();
+ foreach (const LookupItem &item, results) {
+ if (Symbol *symbol = item.declaration()) {
+ if (Function *functionType = symbol->type()->asFunctionType()) {
+ if (functionType->name()->isDestructorNameId() != isDestructor)
+ continue;
+ if (functionType == function) // already tested
+ continue;
+ if (functionType->isFinal())
+ return res == True;
+ if (functionType->isVirtual()) {
+ if (!firstVirtual)
+ return true;
+ if (res == Unknown)
+ res = True;
+ *firstVirtual = functionType;
+ }
+ }
+ }
+ }
+ }
+
+ return res == True;
+}
+
+bool FunctionUtils::isVirtualFunction(const Function *function,
+ const LookupContext &context,
+ const Function **firstVirtual)
+{
+ return isVirtualFunction_helper(function, context, Virtual, firstVirtual);
+}
+
+bool FunctionUtils::isPureVirtualFunction(const Function *function,
+ const LookupContext &context,
+ const Function **firstVirtual)
+{
+ return isVirtualFunction_helper(function, context, PureVirtual, firstVirtual);
+}
+
+QList<Symbol *> FunctionUtils::overrides(Function *function, Class *functionsClass,
+ Class *staticClass, const Snapshot &snapshot)
+{
+ QList<Symbol *> result;
+ QTC_ASSERT(function && functionsClass && staticClass, return result);
+
+ FullySpecifiedType referenceType = function->type();
+ const Name *referenceName = function->name();
+ QTC_ASSERT(referenceName && referenceType.isValid(), return result);
+
+ // Find overrides
+ TypeHierarchyBuilder builder(staticClass, snapshot);
+ const TypeHierarchy &staticClassHierarchy = builder.buildDerivedTypeHierarchy();
+
+ QList<TypeHierarchy> l;
+ l.append(TypeHierarchy(functionsClass));
+ l.append(staticClassHierarchy);
+
+ while (!l.isEmpty()) {
+ // Add derived
+ const TypeHierarchy hierarchy = l.takeFirst();
+ QTC_ASSERT(hierarchy.symbol(), continue);
+ Class *c = hierarchy.symbol()->asClass();
+ QTC_ASSERT(c, continue);
+
+ foreach (const TypeHierarchy &t, hierarchy.hierarchy()) {
+ if (!l.contains(t))
+ l << t;
+ }
+
+ // Check member functions
+ for (int i = 0, total = c->memberCount(); i < total; ++i) {
+ Symbol *candidate = c->memberAt(i);
+ const Name *candidateName = candidate->name();
+ const FullySpecifiedType candidateType = candidate->type();
+ if (!candidateName || !candidateType.isValid())
+ continue;
+ if (candidateName->isEqualTo(referenceName) && candidateType.isEqualTo(referenceType))
+ result << candidate;
+ }
+ }
+
+ return result;
+}
+
+#ifdef WITH_TESTS
+#include "cpptoolsplugin.h"
+
+#include <QTest>
+
+namespace CppTools {
+namespace Internal {
+
+enum Virtuality
+{
+ NotVirtual,
+ Virtual,
+ PureVirtual
+};
+typedef QList<Virtuality> VirtualityList;
+} // Internal namespace
+} // CppTools namespace
+
+Q_DECLARE_METATYPE(CppTools::Internal::Virtuality)
+Q_DECLARE_METATYPE(CppTools::Internal::VirtualityList)
+Q_DECLARE_METATYPE(QList<int>)
+
+namespace CppTools {
+namespace Internal {
+
+void CppToolsPlugin::test_functionutils_virtualFunctions()
+{
+ // Create and parse document
+ QFETCH(QByteArray, source);
+ QFETCH(VirtualityList, virtualityList);
+ QFETCH(QList<int>, firstVirtualList);
+ Document::Ptr document = Document::create(QLatin1String("virtuals"));
+ document->setUtf8Source(source);
+ document->check(); // calls parse();
+ QCOMPARE(document->diagnosticMessages().size(), 0);
+ QVERIFY(document->translationUnit()->ast());
+ QList<const Function *> allFunctions;
+ const Function *firstVirtual = 0;
+
+ // Iterate through Function symbols
+ Snapshot snapshot;
+ snapshot.insert(document);
+ const LookupContext context(document, snapshot);
+ Control *control = document->translationUnit()->control();
+ Symbol **end = control->lastSymbol();
+ for (Symbol **it = control->firstSymbol(); it != end; ++it) {
+ if (const Function *function = (*it)->asFunction()) {
+ allFunctions.append(function);
+ QTC_ASSERT(!virtualityList.isEmpty(), return);
+ Virtuality virtuality = virtualityList.takeFirst();
+ QTC_ASSERT(!firstVirtualList.isEmpty(), return);
+ int firstVirtualIndex = firstVirtualList.takeFirst();
+ bool isVirtual = FunctionUtils::isVirtualFunction(function, context, &firstVirtual);
+ bool isPureVirtual = FunctionUtils::isPureVirtualFunction(function, context,
+ &firstVirtual);
+
+ // Test for regressions introduced by firstVirtual
+ QCOMPARE(FunctionUtils::isVirtualFunction(function, context), isVirtual);
+ QCOMPARE(FunctionUtils::isPureVirtualFunction(function, context), isPureVirtual);
+ if (isVirtual) {
+ if (isPureVirtual)
+ QCOMPARE(virtuality, PureVirtual);
+ else
+ QCOMPARE(virtuality, Virtual);
+ } else {
+ QEXPECT_FAIL("virtual-dtor-dtor", "Not implemented", Abort);
+ if (allFunctions.size() == 3)
+ QEXPECT_FAIL("dtor-virtual-dtor-dtor", "Not implemented", Abort);
+ QCOMPARE(virtuality, NotVirtual);
+ }
+ if (firstVirtualIndex == -1)
+ QVERIFY(!firstVirtual);
+ else
+ QCOMPARE(firstVirtual, allFunctions.at(firstVirtualIndex));
+ }
+ }
+ QVERIFY(virtualityList.isEmpty());
+ QVERIFY(firstVirtualList.isEmpty());
+}
+
+void CppToolsPlugin::test_functionutils_virtualFunctions_data()
+{
+ typedef QByteArray _;
+ QTest::addColumn<QByteArray>("source");
+ QTest::addColumn<VirtualityList>("virtualityList");
+ QTest::addColumn<QList<int> >("firstVirtualList");
+
+ QTest::newRow("none")
+ << _("struct None { void foo() {} };\n")
+ << (VirtualityList() << NotVirtual)
+ << (QList<int>() << -1);
+
+ QTest::newRow("single-virtual")
+ << _("struct V { virtual void foo() {} };\n")
+ << (VirtualityList() << Virtual)
+ << (QList<int>() << 0);
+
+ QTest::newRow("single-pure-virtual")
+ << _("struct PV { virtual void foo() = 0; };\n")
+ << (VirtualityList() << PureVirtual)
+ << (QList<int>() << 0);
+
+ QTest::newRow("virtual-derived-with-specifier")
+ << _("struct Base { virtual void foo() {} };\n"
+ "struct Derived : Base { virtual void foo() {} };\n")
+ << (VirtualityList() << Virtual << Virtual)
+ << (QList<int>() << 0 << 0);
+
+ QTest::newRow("virtual-derived-implicit")
+ << _("struct Base { virtual void foo() {} };\n"
+ "struct Derived : Base { void foo() {} };\n")
+ << (VirtualityList() << Virtual << Virtual)
+ << (QList<int>() << 0 << 0);
+
+ QTest::newRow("not-virtual-then-virtual")
+ << _("struct Base { void foo() {} };\n"
+ "struct Derived : Base { virtual void foo() {} };\n")
+ << (VirtualityList() << NotVirtual << Virtual)
+ << (QList<int>() << -1 << 1);
+
+ QTest::newRow("virtual-final-not-virtual")
+ << _("struct Base { virtual void foo() {} };\n"
+ "struct Derived : Base { void foo() final {} };\n"
+ "struct Derived2 : Derived { void foo() {} };")
+ << (VirtualityList() << Virtual << Virtual << NotVirtual)
+ << (QList<int>() << 0 << 0 << -1);
+
+ QTest::newRow("virtual-then-pure")
+ << _("struct Base { virtual void foo() {} };\n"
+ "struct Derived : Base { virtual void foo() = 0; };\n"
+ "struct Derived2 : Derived { void foo() {} };")
+ << (VirtualityList() << Virtual << PureVirtual << Virtual)
+ << (QList<int>() << 0 << 0 << 0);
+
+ QTest::newRow("virtual-virtual-final-not-virtual")
+ << _("struct Base { virtual void foo() {} };\n"
+ "struct Derived : Base { virtual void foo() final {} };\n"
+ "struct Derived2 : Derived { void foo() {} };")
+ << (VirtualityList() << Virtual << Virtual << NotVirtual)
+ << (QList<int>() << 0 << 0 << -1);
+
+ QTest::newRow("ctor-virtual-dtor")
+ << _("struct Base { Base() {} virtual ~Base() {} };\n")
+ << (VirtualityList() << NotVirtual << Virtual)
+ << (QList<int>() << -1 << 1);
+
+ QTest::newRow("virtual-dtor-dtor")
+ << _("struct Base { virtual ~Base() {} };\n"
+ "struct Derived : Base { ~Derived() {} };\n")
+ << (VirtualityList() << Virtual << Virtual)
+ << (QList<int>() << 0 << 0);
+
+ QTest::newRow("dtor-virtual-dtor-dtor")
+ << _("struct Base { ~Base() {} };\n"
+ "struct Derived : Base { virtual ~Derived() {} };\n"
+ "struct Derived2 : Derived { ~Derived2() {} };\n")
+ << (VirtualityList() << NotVirtual << Virtual << Virtual)
+ << (QList<int>() << -1 << 1 << 1);
+}
+
+} // namespace Internal
+} // namespace CppTools
+
+#endif
diff --git a/src/plugins/cpptools/functionutils.h b/src/plugins/cpptools/functionutils.h
new file mode 100644
index 0000000000..d44231cc19
--- /dev/null
+++ b/src/plugins/cpptools/functionutils.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef FUNCTIONUTILS_H
+#define FUNCTIONUTILS_H
+
+#include "cpptools_global.h"
+
+QT_BEGIN_NAMESPACE
+template <class> class QList;
+QT_END_NAMESPACE
+
+namespace CPlusPlus {
+class Class;
+class Function;
+class LookupContext;
+class Snapshot;
+class Symbol;
+} // namespace CPlusPlus
+
+namespace CppTools {
+
+class CPPTOOLS_EXPORT FunctionUtils
+{
+public:
+ static bool isVirtualFunction(const CPlusPlus::Function *function,
+ const CPlusPlus::LookupContext &context,
+ const CPlusPlus::Function **firstVirtual = 0);
+
+ static bool isPureVirtualFunction(const CPlusPlus::Function *function,
+ const CPlusPlus::LookupContext &context,
+ const CPlusPlus::Function **firstVirtual = 0);
+
+ static QList<CPlusPlus::Symbol *> overrides(CPlusPlus::Function *function,
+ CPlusPlus::Class *functionsClass,
+ CPlusPlus::Class *staticClass,
+ const CPlusPlus::Snapshot &snapshot);
+};
+
+} // namespace CppTools
+
+#endif // FUNCTIONUTILS_H