aboutsummaryrefslogtreecommitdiffstats
path: root/sources
diff options
context:
space:
mode:
Diffstat (limited to 'sources')
-rw-r--r--sources/shiboken6/tests/libsample/spaceship.cpp15
-rw-r--r--sources/shiboken6/tests/libsample/spaceship.h14
-rw-r--r--sources/shiboken6/tests/samplebinding/CMakeLists.txt1
-rw-r--r--sources/shiboken6/tests/samplebinding/spaceship_test.py12
-rw-r--r--sources/shiboken6/tests/samplebinding/typesystem_sample.xml1
-rw-r--r--sources/shiboken6_generator/ApiExtractor/abstractmetabuilder.cpp37
-rw-r--r--sources/shiboken6_generator/ApiExtractor/abstractmetabuilder_p.h2
-rw-r--r--sources/shiboken6_generator/ApiExtractor/parser/codemodel.cpp30
-rw-r--r--sources/shiboken6_generator/ApiExtractor/parser/codemodel.h6
9 files changed, 112 insertions, 6 deletions
diff --git a/sources/shiboken6/tests/libsample/spaceship.cpp b/sources/shiboken6/tests/libsample/spaceship.cpp
index 294ad58f8..c883f7c2f 100644
--- a/sources/shiboken6/tests/libsample/spaceship.cpp
+++ b/sources/shiboken6/tests/libsample/spaceship.cpp
@@ -32,3 +32,18 @@ std::strong_ordering operator<=>(FreeSpaceshipComparisonTester lhs,
return lhs.value() <=> rhs.value();
}
#endif // C++ 20
+
+NonEqualityComparisonTester::NonEqualityComparisonTester(int v) noexcept
+ : m_value(v)
+{
+}
+
+int NonEqualityComparisonTester::value() const
+{
+ return m_value;
+}
+
+bool NonEqualityComparisonTester::operator==(NonEqualityComparisonTester rhs) const
+{
+ return m_value == rhs.m_value;
+}
diff --git a/sources/shiboken6/tests/libsample/spaceship.h b/sources/shiboken6/tests/libsample/spaceship.h
index 1bdd1a3e5..26f636009 100644
--- a/sources/shiboken6/tests/libsample/spaceship.h
+++ b/sources/shiboken6/tests/libsample/spaceship.h
@@ -45,4 +45,18 @@ LIBSAMPLE_API std::strong_ordering operator<=>(FreeSpaceshipComparisonTester lhs
FreeSpaceshipComparisonTester rhs);
#endif // C++ 20
+
+class LIBSAMPLE_API NonEqualityComparisonTester
+{
+public:
+ explicit NonEqualityComparisonTester(int v) noexcept;
+
+ int value() const;
+
+ bool operator==(NonEqualityComparisonTester rhs) const;
+
+private:
+ int m_value;
+};
+
#endif // SPACESHIP_H
diff --git a/sources/shiboken6/tests/samplebinding/CMakeLists.txt b/sources/shiboken6/tests/samplebinding/CMakeLists.txt
index c9e4f601f..01f51fc2d 100644
--- a/sources/shiboken6/tests/samplebinding/CMakeLists.txt
+++ b/sources/shiboken6/tests/samplebinding/CMakeLists.txt
@@ -64,6 +64,7 @@ ${CMAKE_CURRENT_BINARY_DIR}/sample/moveonly_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/moveonlyhandler_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/noimplicitconversion_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/nondefaultctor_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/sample/nonequalitycomparisontester_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/objectmodel_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/objecttype_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/objecttypebyvalue_wrapper.cpp
diff --git a/sources/shiboken6/tests/samplebinding/spaceship_test.py b/sources/shiboken6/tests/samplebinding/spaceship_test.py
index 1b07511f8..95d2506ce 100644
--- a/sources/shiboken6/tests/samplebinding/spaceship_test.py
+++ b/sources/shiboken6/tests/samplebinding/spaceship_test.py
@@ -14,7 +14,8 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from sample import FreeSpaceshipComparisonTester, SpaceshipComparisonTester
+from sample import (FreeSpaceshipComparisonTester, SpaceshipComparisonTester,
+ NonEqualityComparisonTester)
class SpaceshipTest(unittest.TestCase):
@@ -45,6 +46,15 @@ class SpaceshipTest(unittest.TestCase):
self.assertTrue(t1 < t2)
self.assertFalse(t1 > t2)
+ @unittest.skipUnless(SpaceshipComparisonTester.Enabled.HasSpaceshipOperator, "< C++ 20")
+ def testNonEqualSynthetization(self):
+ ne_a = NonEqualityComparisonTester(1)
+ ne_b = NonEqualityComparisonTester(1)
+ self.assertTrue(ne_a == ne_b)
+ # Verify that different instances with same value are not reported as "not equal",
+ # (fooling the FallbackRichCompare() function which is generated for missing operators).
+ self.assertFalse(ne_a != ne_b)
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/typesystem_sample.xml b/sources/shiboken6/tests/samplebinding/typesystem_sample.xml
index fed84ba0d..05798a6ce 100644
--- a/sources/shiboken6/tests/samplebinding/typesystem_sample.xml
+++ b/sources/shiboken6/tests/samplebinding/typesystem_sample.xml
@@ -160,6 +160,7 @@
<enum-type name="Enabled"/>
</value-type>
<value-type name="FreeSpaceshipComparisonTester"/>
+ <value-type name="NonEqualityComparisonTester"/>
<primitive-type name="PStr">
<include file-name="str.h" location="global"/>
diff --git a/sources/shiboken6_generator/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken6_generator/ApiExtractor/abstractmetabuilder.cpp
index 7c5d34315..bf8d3246c 100644
--- a/sources/shiboken6_generator/ApiExtractor/abstractmetabuilder.cpp
+++ b/sources/shiboken6_generator/ApiExtractor/abstractmetabuilder.cpp
@@ -278,6 +278,15 @@ void AbstractMetaBuilderPrivate::registerToStringCapability(const FunctionModelI
}
}
+// Find "operator!=" matching an "operator==" in a scope.
+static bool hasOperatorNotEqual(const ScopeModelItem &scopeItem, const FunctionModelItem &operatorEqual)
+{
+ auto pred = [&operatorEqual](const FunctionModelItem &f) {
+ return f->isOperatorNotEqual() && operatorEqual->hasEquivalentArguments(*f);
+ };
+ return std::any_of(scopeItem->functions().cbegin(), scopeItem->functions().cend(), pred);
+}
+
static ComparisonOperators synthesizedSpaceshipComparison(const AbstractMetaClassCPtr &currentClass,
const FunctionModelItem &item)
{
@@ -297,6 +306,7 @@ static ComparisonOperators synthesizedSpaceshipComparison(const AbstractMetaClas
// Traverse free operator functions (global/namespace)
void AbstractMetaBuilderPrivate::traverseFreeOperatorFunction(const FunctionModelItem &item,
+ const ScopeModelItem &scope,
const AbstractMetaClassPtr &currentClass)
{
Q_ASSERT(!currentClass || currentClass->isNamespace());
@@ -380,6 +390,17 @@ void AbstractMetaBuilderPrivate::traverseFreeOperatorFunction(const FunctionMode
ops, flags);
return;
}
+
+ // C++20: Synthesize "!=" from "=="
+ if (clang::emulatedCompilerLanguageLevel() >= LanguageLevel::Cpp20
+ && item->isOperatorEqual()
+ && !item->hasPointerArguments() && !hasOperatorNotEqual(scope, item)) {
+ AbstractMetaClass::addSynthesizedComparisonOperators(
+ baseoperandClass, metaFunction->arguments(),
+ ComparisonOperatorType::OperatorNotEqual,
+ flags | InternalFunctionFlag::OperatorCpp20NonEquality);
+ }
+
AbstractMetaClass::addFunction(baseoperandClass, metaFunction);
ReportHandler::addGeneralMessage(msgSynthesizedFunction(metaFunction, item));
if (!metaFunction->arguments().isEmpty()) {
@@ -697,11 +718,11 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom,
case CodeModel::ArithmeticOperator:
case CodeModel::BitwiseOperator:
case CodeModel::LogicalOperator:
- traverseFreeOperatorFunction(func, {});
+ traverseFreeOperatorFunction(func, dom, {});
break;
case CodeModel::ShiftOperator:
if (!traverseStreamOperator(func, {}))
- traverseFreeOperatorFunction(func, {});
+ traverseFreeOperatorFunction(func, dom, {});
default:
break;
}
@@ -1486,7 +1507,7 @@ void AbstractMetaBuilderPrivate::traverseNameSpaceFunctions(const ScopeModelItem
functions.reserve(scopeFunctionList.size());
for (const FunctionModelItem &function : scopeFunctionList) {
if (function->isOperator()) {
- traverseFreeOperatorFunction(function, currentClass);
+ traverseFreeOperatorFunction(function, scopeItem, currentClass);
} else if (auto metaFunction = traverseFunction(function, currentClass)) {
metaFunction->setCppAttribute(FunctionAttribute::Static);
functions.append(metaFunction);
@@ -1569,7 +1590,6 @@ void AbstractMetaBuilderPrivate::traverseClassFunction(const ScopeModelItem& sco
const AbstractMetaFunctionPtr &metaFunction,
const AbstractMetaClassPtr &metaClass) const
{
- Q_UNUSED(scopeItem)
if (function->isSpaceshipOperator()) {
// For spaceship, the traverse mechanism is only used to handle rejections
// and get the argument type.
@@ -1582,6 +1602,15 @@ void AbstractMetaBuilderPrivate::traverseClassFunction(const ScopeModelItem& sco
return;
}
+ // C++20: Synthesize "!=" from "=="
+ if (clang::emulatedCompilerLanguageLevel() >= LanguageLevel::Cpp20
+ && function->isOperatorEqual() && !hasOperatorNotEqual(scopeItem, function)) {
+ AbstractMetaClass::addSynthesizedComparisonOperators(
+ metaClass, metaFunction->arguments(),
+ ComparisonOperatorType::OperatorNotEqual,
+ InternalFunctionFlag::OperatorCpp20NonEquality);
+ }
+
traverseClassFunction(metaFunction, metaClass);
}
diff --git a/sources/shiboken6_generator/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken6_generator/ApiExtractor/abstractmetabuilder_p.h
index b503f4b33..0890eb752 100644
--- a/sources/shiboken6_generator/ApiExtractor/abstractmetabuilder_p.h
+++ b/sources/shiboken6_generator/ApiExtractor/abstractmetabuilder_p.h
@@ -116,7 +116,7 @@ public:
void traverseFields(const ScopeModelItem &item, const AbstractMetaClassPtr &parent);
bool traverseStreamOperator(const FunctionModelItem &functionItem,
const AbstractMetaClassPtr &currentClass);
- void traverseFreeOperatorFunction(const FunctionModelItem &item,
+ void traverseFreeOperatorFunction(const FunctionModelItem &item, const ScopeModelItem &scope,
const AbstractMetaClassPtr &currentClass);
AbstractMetaFunctionPtr
traverseAddedFunctionHelper(const AddedFunctionPtr &addedFunc,
diff --git a/sources/shiboken6_generator/ApiExtractor/parser/codemodel.cpp b/sources/shiboken6_generator/ApiExtractor/parser/codemodel.cpp
index 8cbca7bc9..bfccacbac 100644
--- a/sources/shiboken6_generator/ApiExtractor/parser/codemodel.cpp
+++ b/sources/shiboken6_generator/ApiExtractor/parser/codemodel.cpp
@@ -846,6 +846,13 @@ void _ArgumentModelItem::setScopeResolution(bool v)
m_scopeResolution = v;
}
+bool _ArgumentModelItem::isEquivalent(const _ArgumentModelItem &rhs) const
+{
+ return m_scopeResolution == rhs.m_scopeResolution && m_defaultValue == rhs.m_defaultValue
+ && m_defaultValueExpression == rhs.m_defaultValueExpression
+ && m_type == rhs.m_type;
+}
+
#ifndef QT_NO_DEBUG_STREAM
void _ArgumentModelItem::formatDebug(QDebug &d) const
{
@@ -991,6 +998,16 @@ bool _FunctionModelItem::isOperator() const
return result;
}
+static bool isPointerArgument(const ArgumentModelItem &a)
+{
+ return !a->type().indirectionsV().isEmpty();
+}
+
+bool _FunctionModelItem::hasPointerArguments() const
+{
+ return std::any_of(m_arguments.cbegin(), m_arguments.cend(), isPointerArgument);
+}
+
ExceptionSpecification _FunctionModelItem::exceptionSpecification() const
{
return m_exceptionSpecification;
@@ -1075,6 +1092,19 @@ QString _FunctionModelItem::typeSystemSignature() const // For dumping out type
return result;
}
+static inline bool equivalentArguments(const ArgumentModelItem &lhs,
+ const ArgumentModelItem &rhs)
+{
+ return lhs->isEquivalent(*rhs);
+}
+
+bool _FunctionModelItem::hasEquivalentArguments(const _FunctionModelItem &rhs) const
+{
+ return m_arguments.size() == rhs.m_arguments.size()
+ && std::equal(m_arguments.cbegin(), m_arguments.cend(), rhs.m_arguments.cbegin(), rhs.m_arguments.cend(),
+ equivalentArguments);
+}
+
using NameFunctionTypeHash = QHash<QStringView, CodeModel::FunctionType>;
static const NameFunctionTypeHash &nameToOperatorFunction()
diff --git a/sources/shiboken6_generator/ApiExtractor/parser/codemodel.h b/sources/shiboken6_generator/ApiExtractor/parser/codemodel.h
index 8d757e635..7ff0a88e2 100644
--- a/sources/shiboken6_generator/ApiExtractor/parser/codemodel.h
+++ b/sources/shiboken6_generator/ApiExtractor/parser/codemodel.h
@@ -380,6 +380,8 @@ public:
bool scopeResolution() const;
void setScopeResolution(bool v);
+ bool isEquivalent(const _ArgumentModelItem &rhs) const; // Compare all except name
+
#ifndef QT_NO_DEBUG_STREAM
void formatDebug(QDebug &d) const override;
#endif
@@ -502,6 +504,7 @@ public:
bool isSpaceshipOperator() const;
bool isOperatorEqual() const;
bool isOperatorNotEqual() const;
+ bool hasPointerArguments() const;
bool isSimilar(const FunctionModelItem &other) const;
@@ -515,6 +518,9 @@ public:
QString classQualifiedSignature() const;
QString typeSystemSignature() const; // For dumping out type system files
+ // Compare all except names
+ bool hasEquivalentArguments(const _FunctionModelItem &rhs) const;
+
// Private, for usage by the clang builder.
void _determineType();