From bcf95eb0d0826fc2fb0b02c621431c85a7f92daf Mon Sep 17 00:00:00 2001 From: Austin Henriksen Date: Mon, 6 Jan 2025 17:29:01 -0500 Subject: [PATCH 1/7] Removing sorting/unique-ifying of exception specifications in generated code. --- cpp/src/slice2cpp/Gen.cpp | 8 +------- cpp/src/slice2cs/Gen.cpp | 27 +++------------------------ cpp/src/slice2java/Gen.cpp | 9 +-------- cpp/src/slice2js/Gen.cpp | 9 +++++---- cpp/src/slice2matlab/Main.cpp | 6 +----- cpp/src/slice2swift/SwiftUtil.cpp | 8 ++++++-- 6 files changed, 17 insertions(+), 50 deletions(-) diff --git a/cpp/src/slice2cpp/Gen.cpp b/cpp/src/slice2cpp/Gen.cpp index d1a14acdccf..8988e6c629e 100644 --- a/cpp/src/slice2cpp/Gen.cpp +++ b/cpp/src/slice2cpp/Gen.cpp @@ -216,15 +216,10 @@ namespace } else { - throws.sort(); - throws.unique(); - - // // Arrange exceptions into most-derived to least-derived order. If we don't // do this, a base exception handler can appear before a derived exception // handler, causing compiler warnings and resulting in the base exception // being marshaled instead of the derived exception. - // throws.sort(Slice::DerivedToBaseCompare()); C << "[](const " << getUnqualified("::Ice::UserException&", scope) << " ex)"; @@ -233,9 +228,8 @@ namespace C << sb; C << nl << "ex.ice_throw();"; C << eb; - // + // Generate a catch block for each legal user exception. - // for (const auto& ex : throws) { C << nl << "catch(const " << getUnqualified(fixKwd(ex->scoped()), scope) << "&)"; diff --git a/cpp/src/slice2cs/Gen.cpp b/cpp/src/slice2cs/Gen.cpp index 9f5c8eb221d..5cca67555ab 100644 --- a/cpp/src/slice2cs/Gen.cpp +++ b/cpp/src/slice2cs/Gen.cpp @@ -2698,18 +2698,6 @@ Slice::Gen::HelperVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p) ParameterList outParams = op->outParameters(); - ExceptionList throws = op->throws(); - throws.sort(); - throws.unique(); - - // - // Arrange exceptions into most-derived to least-derived order. If we don't - // do this, a base exception handler can appear before a derived exception - // handler, causing compiler warnings and resulting in the base exception - // being marshaled instead of the derived exception. - // - throws.sort(Slice::DerivedToBaseCompare()); - string context = getEscapedParamName(op, "context"); _out << sp; @@ -2789,21 +2777,14 @@ Slice::Gen::HelperVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p) string returnTypeS = resultType(op, ns); - ExceptionList throws = op->throws(); - throws.sort(); - throws.unique(); - - // // Arrange exceptions into most-derived to least-derived order. If we don't // do this, a base exception handler can appear before a derived exception // handler, causing compiler warnings and resulting in the base exception // being marshaled instead of the derived exception. - // + ExceptionList throws = op->throws(); throws.sort(Slice::DerivedToBaseCompare()); - // // Write the public Async method. - // _out << sp; _out << nl << "public global::System.Threading.Tasks.Task"; if (!returnTypeS.empty()) @@ -2910,12 +2891,10 @@ Slice::Gen::HelperVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p) _out << nl << "throw ex;"; _out << eb; - // // Generate a catch block for each legal user exception. - // - for (ExceptionList::const_iterator i = throws.begin(); i != throws.end(); ++i) + for (const auto& thrown : throws) { - _out << nl << "catch(" << getUnqualified(*i, ns) << ")"; + _out << nl << "catch(" << getUnqualified(thrown, ns) << ")"; _out << sb; _out << nl << "throw;"; _out << eb; diff --git a/cpp/src/slice2java/Gen.cpp b/cpp/src/slice2java/Gen.cpp index 1e24ad8f800..d8ecb77793b 100644 --- a/cpp/src/slice2java/Gen.cpp +++ b/cpp/src/slice2java/Gen.cpp @@ -1302,8 +1302,6 @@ Slice::JavaVisitor::writeDispatch(Output& out, const InterfaceDefPtr& p) const bool amd = p->hasMetadata("amd") || op->hasMetadata("amd"); ExceptionList throws = op->throws(); - throws.sort(); - throws.unique(); out << sp; writeServantDocComment(out, op, package, dc, amd); @@ -4209,16 +4207,11 @@ Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p) } const vector args = getInArgs(p); - ExceptionList throws = p->throws(); - throws.sort(); - throws.unique(); - - // // Arrange exceptions into most-derived to least-derived order. If we don't // do this, a base exception handler can appear before a derived exception // handler, causing compiler warnings and resulting in the base exception // being marshaled instead of the derived exception. - // + ExceptionList throws = p->throws(); throws.sort(Slice::DerivedToBaseCompare()); const string contextParamName = getEscapedParamName(p, "context"); diff --git a/cpp/src/slice2js/Gen.cpp b/cpp/src/slice2js/Gen.cpp index 05b415fa374..305c571c940 100644 --- a/cpp/src/slice2js/Gen.cpp +++ b/cpp/src/slice2js/Gen.cpp @@ -1456,13 +1456,14 @@ Slice::Gen::TypesVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p) } _out << ","; - // // User exceptions. - // + // Arrange exceptions into most-derived to least-derived order. If we don't + // do this, a base exception handler can appear before a derived exception + // handler, causing compiler warnings and resulting in the base exception + // being marshaled instead of the derived exception. ExceptionList throws = op->throws(); - throws.sort(); - throws.unique(); throws.sort(Slice::DerivedToBaseCompare()); + if (throws.empty()) { _out << " "; diff --git a/cpp/src/slice2matlab/Main.cpp b/cpp/src/slice2matlab/Main.cpp index fae0b6e2232..92062b25cd9 100644 --- a/cpp/src/slice2matlab/Main.cpp +++ b/cpp/src/slice2matlab/Main.cpp @@ -2198,16 +2198,12 @@ CodeVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p) for (OperationList::const_iterator q = ops.begin(); q != ops.end(); ++q) { OperationPtr op = *q; - ExceptionList exceptions = op->throws(); - exceptions.sort(); - exceptions.unique(); - // // Arrange exceptions into most-derived to least-derived order. If we don't // do this, a base exception handler can appear before a derived exception // handler, causing compiler warnings and resulting in the base exception // being marshaled instead of the derived exception. - // + ExceptionList exceptions = op->throws(); exceptions.sort(Slice::DerivedToBaseCompare()); if (!exceptions.empty()) diff --git a/cpp/src/slice2swift/SwiftUtil.cpp b/cpp/src/slice2swift/SwiftUtil.cpp index 410dc4f1ea2..2493da33741 100644 --- a/cpp/src/slice2swift/SwiftUtil.cpp +++ b/cpp/src/slice2swift/SwiftUtil.cpp @@ -1820,9 +1820,13 @@ void SwiftGenerator::writeUnmarshalUserException(::IceInternal::Output& out, const OperationPtr& op) { const string swiftModule = getSwiftModule(getTopLevelModule(dynamic_pointer_cast(op))); + + // Arrange exceptions into most-derived to least-derived order. If we don't + // do this, a base exception handler can appear before a derived exception + // handler, causing compiler warnings and resulting in the base exception + // being marshaled instead of the derived exception. ExceptionList throws = op->throws(); - throws.sort(); - throws.unique(); + throws.sort(Slice::DerivedToBaseCompare()); out << "{ ex in"; out.inc(); From 9ade3bdb298e763e197f9be1a6c3ff9455174ae7 Mon Sep 17 00:00:00 2001 From: Austin Henriksen Date: Tue, 7 Jan 2025 11:34:26 -0500 Subject: [PATCH 2/7] Removed sorting of operation name lists (except in C++). --- cpp/src/Slice/Parser.cpp | 1 - cpp/src/ice2slice/Gen.cpp | 2 -- cpp/src/slice2cs/Gen.cpp | 31 +++++++++++++------------------ cpp/src/slice2java/Gen.cpp | 2 -- cpp/src/slice2js/Gen.cpp | 1 - cpp/src/slice2matlab/Main.cpp | 1 - cpp/src/slice2swift/Gen.cpp | 2 -- 7 files changed, 13 insertions(+), 27 deletions(-) diff --git a/cpp/src/Slice/Parser.cpp b/cpp/src/Slice/Parser.cpp index 9236bdac22f..117b51ac454 100644 --- a/cpp/src/Slice/Parser.cpp +++ b/cpp/src/Slice/Parser.cpp @@ -3053,7 +3053,6 @@ Slice::InterfaceDef::allBases() const { InterfaceList result = _bases; result.sort(containedCompare); - result.unique(containedEqual); for (const auto& p : _bases) { result.merge(p->allBases(), containedCompare); diff --git a/cpp/src/ice2slice/Gen.cpp b/cpp/src/ice2slice/Gen.cpp index 9d76f7e5aa0..98608b7e950 100644 --- a/cpp/src/ice2slice/Gen.cpp +++ b/cpp/src/ice2slice/Gen.cpp @@ -561,8 +561,6 @@ Gen::TypesVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p) } ExceptionList throws = op->throws(); - throws.sort(); - throws.unique(); if (throws.size() == 1) { out << " throws " << getUnqualified(throws.front(), scope); diff --git a/cpp/src/slice2cs/Gen.cpp b/cpp/src/slice2cs/Gen.cpp index 5cca67555ab..ed24682429c 100644 --- a/cpp/src/slice2cs/Gen.cpp +++ b/cpp/src/slice2cs/Gen.cpp @@ -317,25 +317,20 @@ Slice::CsVisitor::writeUnmarshalDataMember( void Slice::CsVisitor::writeInheritedOperations(const InterfaceDefPtr& p) { - InterfaceList bases = p->bases(); - if (!bases.empty()) + OperationList allBaseOps; + for (const auto& base : p->bases()) { - OperationList allOps; - for (InterfaceList::const_iterator q = bases.begin(); q != bases.end(); ++q) - { - OperationList tmp = (*q)->allOperations(); - allOps.splice(allOps.end(), tmp); - } - allOps.sort(); - allOps.unique(); - for (OperationList::const_iterator i = allOps.begin(); i != allOps.end(); ++i) - { - string retS; - vector params, args; - string ns = getNamespace(p); - string name = getDispatchParams(*i, retS, params, args, ns); - _out << sp << nl << "public abstract " << retS << " " << name << spar << params << epar << ';'; - } + OperationList tmp = base->allOperations(); + allBaseOps.splice(allBaseOps.end(), tmp); + } + + for (const auto& op : allBaseOps) + { + string retS; + vector params, args; + string ns = getNamespace(p); + string name = getDispatchParams(op, retS, params, args, ns); + _out << sp << nl << "public abstract " << retS << " " << name << spar << params << epar << ';'; } } diff --git a/cpp/src/slice2java/Gen.cpp b/cpp/src/slice2java/Gen.cpp index d8ecb77793b..9b7d235794a 100644 --- a/cpp/src/slice2java/Gen.cpp +++ b/cpp/src/slice2java/Gen.cpp @@ -3954,8 +3954,6 @@ Slice::Gen::ProxyVisitor::ProxyVisitor(const string& dir) : JavaVisitor(dir) {} bool Slice::Gen::ProxyVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p) { - const OperationList ops = p->allOperations(); - string name = p->name(); InterfaceList bases = p->bases(); string package = getPackage(p); diff --git a/cpp/src/slice2js/Gen.cpp b/cpp/src/slice2js/Gen.cpp index 305c571c940..733746cd106 100644 --- a/cpp/src/slice2js/Gen.cpp +++ b/cpp/src/slice2js/Gen.cpp @@ -2036,7 +2036,6 @@ Slice::Gen::TypeScriptImportVisitor::visitInterfaceDefStart(const InterfaceDefPt } // Add imports required for operation parameters and return types. - const OperationList operationList = p->allOperations(); for (const auto& op : p->allOperations()) { auto ret = dynamic_pointer_cast(op->returnType()); diff --git a/cpp/src/slice2matlab/Main.cpp b/cpp/src/slice2matlab/Main.cpp index 92062b25cd9..ea21a2c9776 100644 --- a/cpp/src/slice2matlab/Main.cpp +++ b/cpp/src/slice2matlab/Main.cpp @@ -1713,7 +1713,6 @@ CodeVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p) const string scoped = p->scoped(); const string abs = getAbsolute(p); InterfaceList bases = p->bases(); - const OperationList allOps = p->allOperations(); // // Generate proxy class. diff --git a/cpp/src/slice2swift/Gen.cpp b/cpp/src/slice2swift/Gen.cpp index 3606f64183c..77220939752 100644 --- a/cpp/src/slice2swift/Gen.cpp +++ b/cpp/src/slice2swift/Gen.cpp @@ -1391,8 +1391,6 @@ Gen::ObjectVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p) allOpNames.push_back("ice_ids"); allOpNames.push_back("ice_isA"); allOpNames.push_back("ice_ping"); - allOpNames.sort(); - allOpNames.unique(); out << sp; out << nl; From 8f0a440d63a8080685458adaa2c4d089014b06ea Mon Sep 17 00:00:00 2001 From: Austin Henriksen Date: Tue, 7 Jan 2025 11:38:41 -0500 Subject: [PATCH 3/7] Another dead variable... --- cpp/src/Slice/Parser.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/cpp/src/Slice/Parser.cpp b/cpp/src/Slice/Parser.cpp index 117b51ac454..2559c21ad42 100644 --- a/cpp/src/Slice/Parser.cpp +++ b/cpp/src/Slice/Parser.cpp @@ -3583,7 +3583,6 @@ Slice::Exception::createDataMember( checkIdentifier(name); // Don't return here -- we create the data member anyway. // Check whether any bases have defined a member with the same name already. - ExceptionList bl = allBases(); for (const auto& q : allBases()) { ContainedList contents; From 91faa631d44d90ed60e111a5db5e1dd6b082f2d1 Mon Sep 17 00:00:00 2001 From: Austin Henriksen Date: Tue, 7 Jan 2025 14:40:07 -0500 Subject: [PATCH 4/7] Fixes. --- cpp/src/slice2cs/Gen.cpp | 15 ++++++++++++--- cpp/src/slice2php/Main.cpp | 1 + cpp/src/slice2swift/Gen.cpp | 1 - 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/cpp/src/slice2cs/Gen.cpp b/cpp/src/slice2cs/Gen.cpp index ed24682429c..24205145dc6 100644 --- a/cpp/src/slice2cs/Gen.cpp +++ b/cpp/src/slice2cs/Gen.cpp @@ -320,8 +320,18 @@ Slice::CsVisitor::writeInheritedOperations(const InterfaceDefPtr& p) OperationList allBaseOps; for (const auto& base : p->bases()) { - OperationList tmp = base->allOperations(); - allBaseOps.splice(allBaseOps.end(), tmp); + for (const auto& baseOp : base->allOperations()) + { + // It's possible to get the same operation name through diamond inheritance. + // But we only want one 'copy' of each operation in our list, to avoid generating duplicate methods. + if (find_if( + allBaseOps.begin(), + allBaseOps.end(), + [name = baseOp->name()](const auto& other) { return other->name() == name; }) == allBaseOps.end()) + { + allBaseOps.push_back(baseOp); + } + } } for (const auto& op : allBaseOps) @@ -3231,7 +3241,6 @@ Slice::Gen::DispatcherVisitor::writeDispatch(const InterfaceDefPtr& p) string scoped = p->scoped(); string ns = getNamespace(p); - OperationList ops = p->operations(); OperationList allOps = p->allOperations(); if (!allOps.empty()) { diff --git a/cpp/src/slice2php/Main.cpp b/cpp/src/slice2php/Main.cpp index 9a6bf074457..b2b869635dd 100644 --- a/cpp/src/slice2php/Main.cpp +++ b/cpp/src/slice2php/Main.cpp @@ -558,6 +558,7 @@ CodeVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p) _out << "null"; } _out << ", "; + ExceptionList exceptions = (*oli)->throws(); if (!exceptions.empty()) { diff --git a/cpp/src/slice2swift/Gen.cpp b/cpp/src/slice2swift/Gen.cpp index 77220939752..d539ebada5c 100644 --- a/cpp/src/slice2swift/Gen.cpp +++ b/cpp/src/slice2swift/Gen.cpp @@ -1479,7 +1479,6 @@ Gen::ObjectVisitor::visitOperation(const OperationPtr& op) const string opName = fixIdent(op->name()); const ParamInfoList allInParams = getAllInParams(op); const ParamInfoList allOutParams = getAllOutParams(op); - const ExceptionList allExceptions = op->throws(); out << sp; writeOpDocSummary(out, op, true); From 156b3feabe7abf8765de13219d0c423fd8519f2b Mon Sep 17 00:00:00 2001 From: Austin Henriksen Date: Tue, 7 Jan 2025 14:43:32 -0500 Subject: [PATCH 5/7] Clang-format... --- cpp/src/slice2cs/Gen.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/src/slice2cs/Gen.cpp b/cpp/src/slice2cs/Gen.cpp index 24205145dc6..5234bb515b2 100644 --- a/cpp/src/slice2cs/Gen.cpp +++ b/cpp/src/slice2cs/Gen.cpp @@ -325,9 +325,9 @@ Slice::CsVisitor::writeInheritedOperations(const InterfaceDefPtr& p) // It's possible to get the same operation name through diamond inheritance. // But we only want one 'copy' of each operation in our list, to avoid generating duplicate methods. if (find_if( - allBaseOps.begin(), - allBaseOps.end(), - [name = baseOp->name()](const auto& other) { return other->name() == name; }) == allBaseOps.end()) + allBaseOps.begin(), + allBaseOps.end(), + [name = baseOp->name()](const auto& other) { return other->name() == name; }) == allBaseOps.end()) { allBaseOps.push_back(baseOp); } From 9af91c3697a3607a1c5ebcd9a55a26a2d6e3506b Mon Sep 17 00:00:00 2001 From: Austin Henriksen Date: Tue, 7 Jan 2025 16:29:37 -0500 Subject: [PATCH 6/7] Fixed review comments. --- cpp/src/slice2cpp/Gen.cpp | 1 - cpp/src/slice2cs/Gen.cpp | 50 +++++++++++++-------------------------- cpp/src/slice2cs/Gen.h | 1 - 3 files changed, 17 insertions(+), 35 deletions(-) diff --git a/cpp/src/slice2cpp/Gen.cpp b/cpp/src/slice2cpp/Gen.cpp index 8988e6c629e..2fb7662b2d7 100644 --- a/cpp/src/slice2cpp/Gen.cpp +++ b/cpp/src/slice2cpp/Gen.cpp @@ -2651,7 +2651,6 @@ Slice::Gen::InterfaceVisitor::visitInterfaceDefEnd(const InterfaceDefPtr& p) allOpNames.push_back("ice_isA"); allOpNames.push_back("ice_ping"); allOpNames.sort(); - allOpNames.unique(); H << sp; H << nl << "/// \\cond INTERNAL"; diff --git a/cpp/src/slice2cs/Gen.cpp b/cpp/src/slice2cs/Gen.cpp index 5234bb515b2..c02799b42fd 100644 --- a/cpp/src/slice2cs/Gen.cpp +++ b/cpp/src/slice2cs/Gen.cpp @@ -314,36 +314,6 @@ Slice::CsVisitor::writeUnmarshalDataMember( } } -void -Slice::CsVisitor::writeInheritedOperations(const InterfaceDefPtr& p) -{ - OperationList allBaseOps; - for (const auto& base : p->bases()) - { - for (const auto& baseOp : base->allOperations()) - { - // It's possible to get the same operation name through diamond inheritance. - // But we only want one 'copy' of each operation in our list, to avoid generating duplicate methods. - if (find_if( - allBaseOps.begin(), - allBaseOps.end(), - [name = baseOp->name()](const auto& other) { return other->name() == name; }) == allBaseOps.end()) - { - allBaseOps.push_back(baseOp); - } - } - } - - for (const auto& op : allBaseOps) - { - string retS; - vector params, args; - string ns = getNamespace(p); - string name = getDispatchParams(op, retS, params, args, ns); - _out << sp << nl << "public abstract " << retS << " " << name << spar << params << epar << ';'; - } -} - void Slice::CsVisitor::writeMarshaling(const ClassDefPtr& p) { @@ -3208,7 +3178,23 @@ Slice::Gen::DispatcherVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p) _out << sb; - for (const auto& op : p->operations()) + OperationList allOps = p->operations(); + for (const auto& base : bases) + { + for (const auto& baseOp : base->allOperations()) + { + // It's possible to get the same operation name through diamond inheritance. + // But we only want one 'copy' of each operation in our list, to avoid generating duplicate methods. + if (find_if( + allOps.begin(), + allOps.end(), + [name = baseOp->name()](const auto& other) { return other->name() == name; }) == allOps.end()) + { + allOps.push_back(baseOp); + } + } + } + for (const auto& op : allOps) { string retS; vector params, args; @@ -3216,8 +3202,6 @@ Slice::Gen::DispatcherVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p) _out << sp << nl << "public abstract " << retS << " " << opName << spar << params << epar << ';'; } - writeInheritedOperations(p); - _out << sp; _out << nl << "public override string ice_id(Ice.Current current) => ice_staticId();"; diff --git a/cpp/src/slice2cs/Gen.h b/cpp/src/slice2cs/Gen.h index b909a13677e..abd24effb17 100644 --- a/cpp/src/slice2cs/Gen.h +++ b/cpp/src/slice2cs/Gen.h @@ -27,7 +27,6 @@ namespace Slice void writeMarshalDataMember(const DataMemberPtr&, const std::string&, const std::string&, bool = false); void writeUnmarshalDataMember(const DataMemberPtr&, const std::string&, const std::string&, bool = false); - void writeInheritedOperations(const InterfaceDefPtr&); void writeMarshaling(const ClassDefPtr&); static std::vector getParams(const OperationPtr&, const std::string&); From cbc0efcd7761a57eef36c943ea437332b7ee775b Mon Sep 17 00:00:00 2001 From: Austin Henriksen Date: Tue, 7 Jan 2025 17:42:41 -0500 Subject: [PATCH 7/7] After looking at it more, Bernard is right, 'allOperations' is safe here. --- cpp/src/Slice/Parser.cpp | 4 ++-- cpp/src/slice2cs/Gen.cpp | 19 +------------------ 2 files changed, 3 insertions(+), 20 deletions(-) diff --git a/cpp/src/Slice/Parser.cpp b/cpp/src/Slice/Parser.cpp index 2559c21ad42..50157996ee9 100644 --- a/cpp/src/Slice/Parser.cpp +++ b/cpp/src/Slice/Parser.cpp @@ -3087,7 +3087,7 @@ Slice::InterfaceDef::allOperations() const if (find_if( result.begin(), result.end(), - [scoped = q->scoped()](const auto& other) { return other->scoped() == scoped; }) == result.end()) + [name = q->name()](const auto& other) { return other->name() == name; }) == result.end()) { result.push_back(q); } @@ -3099,7 +3099,7 @@ Slice::InterfaceDef::allOperations() const if (find_if( result.begin(), result.end(), - [scoped = q->scoped()](const auto& other) { return other->scoped() == scoped; }) == result.end()) + [name = q->name()](const auto& other) { return other->name() == name; }) == result.end()) { result.push_back(q); } diff --git a/cpp/src/slice2cs/Gen.cpp b/cpp/src/slice2cs/Gen.cpp index c02799b42fd..22b8cac022e 100644 --- a/cpp/src/slice2cs/Gen.cpp +++ b/cpp/src/slice2cs/Gen.cpp @@ -3177,24 +3177,7 @@ Slice::Gen::DispatcherVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p) _out << fixId(name); _out << sb; - - OperationList allOps = p->operations(); - for (const auto& base : bases) - { - for (const auto& baseOp : base->allOperations()) - { - // It's possible to get the same operation name through diamond inheritance. - // But we only want one 'copy' of each operation in our list, to avoid generating duplicate methods. - if (find_if( - allOps.begin(), - allOps.end(), - [name = baseOp->name()](const auto& other) { return other->name() == name; }) == allOps.end()) - { - allOps.push_back(baseOp); - } - } - } - for (const auto& op : allOps) + for (const auto& op : p->allOperations()) { string retS; vector params, args;