From 6acf826b4b2eab32237845f98228171bb8be213c Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Tue, 30 Mar 2010 19:30:25 -0300 Subject: Adds reverse operator functions to the proper classes. AbstractMetaBuilder::traverseOperatorFunction does additional checks to avoid mistaken a class' reverse operator as a direct operator of another class. An unit test was added to check for this case. Reviewed by Anderson Lizardo Reviewed by Hugo Parente --- abstractmetabuilder.cpp | 13 +++++++++++ tests/testreverseoperators.cpp | 49 +++++++++++++++++++++++++++++++++++++++++- tests/testreverseoperators.h | 1 + 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/abstractmetabuilder.cpp b/abstractmetabuilder.cpp index 211c82a41..ac1dcd029 100644 --- a/abstractmetabuilder.cpp +++ b/abstractmetabuilder.cpp @@ -168,12 +168,25 @@ void AbstractMetaBuilder::traverseOperatorFunction(FunctionModelItem item) bool unaryOperator = false; baseoperandClass = argumentToClass(arguments.at(0)); + if (arguments.size() == 1) { unaryOperator = true; } else if (!baseoperandClass || !(baseoperandClass->typeEntry()->codeGeneration() & TypeEntry::GenerateTargetLang)) { baseoperandClass = argumentToClass(arguments.at(1)); firstArgumentIsSelf = false; + } else { + bool ok; + AbstractMetaType* type = translateType(item->type(), &ok); + const TypeEntry* retType = ok ? type->typeEntry() : 0; + AbstractMetaClass* otherArgClass = argumentToClass(arguments.at(1)); + if (otherArgClass && retType + && (retType->isValue() || retType->isObject()) + && retType != baseoperandClass->typeEntry() + && retType == otherArgClass->typeEntry()) { + baseoperandClass = m_metaClasses.findClass(retType); + firstArgumentIsSelf = false; + } } if (baseoperandClass) { diff --git a/tests/testreverseoperators.cpp b/tests/testreverseoperators.cpp index 5c7f66671..a13e0036e 100644 --- a/tests/testreverseoperators.cpp +++ b/tests/testreverseoperators.cpp @@ -25,7 +25,6 @@ #include #include "testutil.h" - void TestReverseOperators::testReverseSum() { const char cppCode[] = "struct A {\ @@ -63,6 +62,54 @@ void TestReverseOperators::testReverseSum() QCOMPARE(reverseOp->arguments().count(), 1); } +void TestReverseOperators::testReverseSumWithAmbiguity() +{ + const char cppCode[] = "\ + struct A { A operator+(int); };\ + A operator+(int, const A&);\ + struct B {};\ + B operator+(const A&, const B&);\ + B operator+(const B&, const A&);\ + "; + const char xmlCode[] = "\ + \ + \ + \ + \ + "; + + TestUtil t(cppCode, xmlCode, false); + AbstractMetaClassList classes = t.builder()->classes(); + AbstractMetaClass* classA = classes.findClass("A"); + QVERIFY(classA); + QCOMPARE(classA->functions().count(), 4); + + AbstractMetaClass* classB = classes.findClass("B"); + QVERIFY(classB); + QCOMPARE(classB->functions().count(), 4); + + const AbstractMetaFunction* reverseOp = 0; + const AbstractMetaFunction* normalOp = 0; + foreach(const AbstractMetaFunction* func, classB->functions()) { + if (func->name() == "operator+") { + if (func->isReverseOperator()) + reverseOp = func; + else + normalOp = func; + } + } + QVERIFY(normalOp); + QVERIFY(!normalOp->isReverseOperator()); + QCOMPARE(normalOp->arguments().count(), 1); + QCOMPARE(normalOp->minimalSignature(), QString("operator+(B,A)")); + QVERIFY(reverseOp); + QVERIFY(reverseOp->isReverseOperator()); + QCOMPARE(reverseOp->arguments().count(), 1); + QCOMPARE(reverseOp->minimalSignature(), QString("operator+(A,B)")); +} + + + QTEST_APPLESS_MAIN(TestReverseOperators) #include "testreverseoperators.moc" diff --git a/tests/testreverseoperators.h b/tests/testreverseoperators.h index 470e576cc..d5bdd9a1c 100644 --- a/tests/testreverseoperators.h +++ b/tests/testreverseoperators.h @@ -30,6 +30,7 @@ class TestReverseOperators : public QObject Q_OBJECT private slots: void testReverseSum(); + void testReverseSumWithAmbiguity(); }; #endif -- cgit v1.2.3