xref: /llvm-project/mlir/lib/TableGen/Class.cpp (revision 971b852546a7d96bc8887ced913724b884cf40df)
12696a952SMogball //===- Class.cpp - Helper classes for Op C++ code emission --------------===//
22696a952SMogball //
32696a952SMogball // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42696a952SMogball // See https://llvm.org/LICENSE.txt for license information.
52696a952SMogball // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62696a952SMogball //
72696a952SMogball //===----------------------------------------------------------------------===//
82696a952SMogball 
92696a952SMogball #include "mlir/TableGen/Class.h"
102696a952SMogball #include "mlir/TableGen/Format.h"
112696a952SMogball #include "llvm/ADT/Sequence.h"
122696a952SMogball #include "llvm/ADT/Twine.h"
132696a952SMogball #include "llvm/Support/Debug.h"
142696a952SMogball 
152696a952SMogball using namespace mlir;
162696a952SMogball using namespace mlir::tblgen;
172696a952SMogball 
18ca6bd9cdSMogball /// Returns space to be emitted after the given C++ `type`. return "" if the
19ca6bd9cdSMogball /// ends with '&' or '*', or is empty, else returns " ".
getSpaceAfterType(StringRef type)202696a952SMogball static StringRef getSpaceAfterType(StringRef type) {
2188d319a2SKazu Hirata   return (type.empty() || type.ends_with("&") || type.ends_with("*")) ? ""
2288d319a2SKazu Hirata                                                                       : " ";
232696a952SMogball }
242696a952SMogball 
252696a952SMogball //===----------------------------------------------------------------------===//
262696a952SMogball // MethodParameter definitions
272696a952SMogball //===----------------------------------------------------------------------===//
282696a952SMogball 
writeDeclTo(raw_indented_ostream & os) const29ca6bd9cdSMogball void MethodParameter::writeDeclTo(raw_indented_ostream &os) const {
302696a952SMogball   if (optional)
312696a952SMogball     os << "/*optional*/";
322696a952SMogball   os << type << getSpaceAfterType(type) << name;
33ca6bd9cdSMogball   if (hasDefaultValue())
342696a952SMogball     os << " = " << defaultValue;
352696a952SMogball }
362696a952SMogball 
writeDefTo(raw_indented_ostream & os) const37ca6bd9cdSMogball void MethodParameter::writeDefTo(raw_indented_ostream &os) const {
38ca6bd9cdSMogball   if (optional)
39ca6bd9cdSMogball     os << "/*optional*/";
40ca6bd9cdSMogball   os << type << getSpaceAfterType(type) << name;
41ca6bd9cdSMogball }
42ca6bd9cdSMogball 
432696a952SMogball //===----------------------------------------------------------------------===//
442696a952SMogball // MethodParameters definitions
452696a952SMogball //===----------------------------------------------------------------------===//
462696a952SMogball 
writeDeclTo(raw_indented_ostream & os) const47ca6bd9cdSMogball void MethodParameters::writeDeclTo(raw_indented_ostream &os) const {
482696a952SMogball   llvm::interleaveComma(parameters, os,
492696a952SMogball                         [&os](auto &param) { param.writeDeclTo(os); });
502696a952SMogball }
writeDefTo(raw_indented_ostream & os) const51ca6bd9cdSMogball void MethodParameters::writeDefTo(raw_indented_ostream &os) const {
522696a952SMogball   llvm::interleaveComma(parameters, os,
532696a952SMogball                         [&os](auto &param) { param.writeDefTo(os); });
542696a952SMogball }
552696a952SMogball 
subsumes(const MethodParameters & other) const562696a952SMogball bool MethodParameters::subsumes(const MethodParameters &other) const {
572696a952SMogball   // These parameters do not subsume the others if there are fewer parameters
582696a952SMogball   // or their types do not match.
592696a952SMogball   if (parameters.size() < other.parameters.size())
602696a952SMogball     return false;
612696a952SMogball   if (!std::equal(
622696a952SMogball           other.parameters.begin(), other.parameters.end(), parameters.begin(),
632696a952SMogball           [](auto &lhs, auto &rhs) { return lhs.getType() == rhs.getType(); }))
642696a952SMogball     return false;
652696a952SMogball 
662696a952SMogball   // If all the common parameters have the same type, we can elide the other
672696a952SMogball   // method if this method has the same number of parameters as other or if the
682696a952SMogball   // first paramater after the common parameters has a default value (and, as
692696a952SMogball   // required by C++, subsequent parameters will have default values too).
702696a952SMogball   return parameters.size() == other.parameters.size() ||
712696a952SMogball          parameters[other.parameters.size()].hasDefaultValue();
722696a952SMogball }
732696a952SMogball 
742696a952SMogball //===----------------------------------------------------------------------===//
752696a952SMogball // MethodSignature definitions
762696a952SMogball //===----------------------------------------------------------------------===//
772696a952SMogball 
makesRedundant(const MethodSignature & other) const782696a952SMogball bool MethodSignature::makesRedundant(const MethodSignature &other) const {
792696a952SMogball   return methodName == other.methodName &&
802696a952SMogball          parameters.subsumes(other.parameters);
812696a952SMogball }
822696a952SMogball 
writeDeclTo(raw_indented_ostream & os) const83ca6bd9cdSMogball void MethodSignature::writeDeclTo(raw_indented_ostream &os) const {
842696a952SMogball   os << returnType << getSpaceAfterType(returnType) << methodName << "(";
852696a952SMogball   parameters.writeDeclTo(os);
862696a952SMogball   os << ")";
872696a952SMogball }
882696a952SMogball 
writeDefTo(raw_indented_ostream & os,StringRef namePrefix) const89ca6bd9cdSMogball void MethodSignature::writeDefTo(raw_indented_ostream &os,
90ca6bd9cdSMogball                                  StringRef namePrefix) const {
912696a952SMogball   os << returnType << getSpaceAfterType(returnType) << namePrefix
922696a952SMogball      << (namePrefix.empty() ? "" : "::") << methodName << "(";
932696a952SMogball   parameters.writeDefTo(os);
942696a952SMogball   os << ")";
952696a952SMogball }
962696a952SMogball 
writeTemplateParamsTo(mlir::raw_indented_ostream & os) const97f3b1361fSMarkus Böck void MethodSignature::writeTemplateParamsTo(
98f3b1361fSMarkus Böck     mlir::raw_indented_ostream &os) const {
99f3b1361fSMarkus Böck   if (templateParams.empty())
100f3b1361fSMarkus Böck     return;
101f3b1361fSMarkus Böck 
102f3b1361fSMarkus Böck   os << "template <";
103f3b1361fSMarkus Böck   llvm::interleaveComma(templateParams, os,
104f3b1361fSMarkus Böck                         [&](StringRef param) { os << "typename " << param; });
105f3b1361fSMarkus Böck   os << ">\n";
106f3b1361fSMarkus Böck }
107f3b1361fSMarkus Böck 
1082696a952SMogball //===----------------------------------------------------------------------===//
1092696a952SMogball // MethodBody definitions
1102696a952SMogball //===----------------------------------------------------------------------===//
1112696a952SMogball 
MethodBody(bool declOnly)112ca6bd9cdSMogball MethodBody::MethodBody(bool declOnly)
113ca6bd9cdSMogball     : declOnly(declOnly), stringOs(body), os(stringOs) {}
1142696a952SMogball 
writeTo(raw_indented_ostream & os) const115ca6bd9cdSMogball void MethodBody::writeTo(raw_indented_ostream &os) const {
116abaa79b2SKazu Hirata   auto bodyRef = StringRef(body).ltrim('\n');
1172696a952SMogball   os << bodyRef;
118ca6bd9cdSMogball   if (bodyRef.empty())
119ca6bd9cdSMogball     return;
120ca6bd9cdSMogball   if (bodyRef.back() != '\n')
1212696a952SMogball     os << "\n";
1222696a952SMogball }
1232696a952SMogball 
1242696a952SMogball //===----------------------------------------------------------------------===//
1252696a952SMogball // Method definitions
1262696a952SMogball //===----------------------------------------------------------------------===//
1272696a952SMogball 
writeDeclTo(raw_indented_ostream & os) const128ca6bd9cdSMogball void Method::writeDeclTo(raw_indented_ostream &os) const {
129f3b1361fSMarkus Böck   methodSignature.writeTemplateParamsTo(os);
1300f827ee0SMarkus Böck   if (deprecationMessage) {
1310f827ee0SMarkus Böck     os << "[[deprecated(\"";
1320f827ee0SMarkus Böck     os.write_escaped(*deprecationMessage);
1330f827ee0SMarkus Böck     os << "\")]]\n";
1340f827ee0SMarkus Böck   }
1352696a952SMogball   if (isStatic())
1362696a952SMogball     os << "static ";
137ca6bd9cdSMogball   if (properties & ConstexprValue)
1382696a952SMogball     os << "constexpr ";
1392696a952SMogball   methodSignature.writeDeclTo(os);
140ca6bd9cdSMogball   if (isConst())
141ca6bd9cdSMogball     os << " const";
1422696a952SMogball   if (!isInline()) {
143ca6bd9cdSMogball     os << ";\n";
1442696a952SMogball     return;
145ca6bd9cdSMogball   }
1462696a952SMogball   os << " {\n";
1472696a952SMogball   methodBody.writeTo(os);
148ca6bd9cdSMogball   os << "}\n\n";
149ca6bd9cdSMogball }
150ca6bd9cdSMogball 
writeDefTo(raw_indented_ostream & os,StringRef namePrefix) const151ca6bd9cdSMogball void Method::writeDefTo(raw_indented_ostream &os, StringRef namePrefix) const {
152ca6bd9cdSMogball   // The method has no definition to write if it is declaration only or inline.
153ca6bd9cdSMogball   if (properties & Declaration || isInline())
154ca6bd9cdSMogball     return;
155ca6bd9cdSMogball 
156ca6bd9cdSMogball   methodSignature.writeDefTo(os, namePrefix);
157ca6bd9cdSMogball   if (isConst())
158ca6bd9cdSMogball     os << " const";
159ca6bd9cdSMogball   os << " {\n";
160ca6bd9cdSMogball   methodBody.writeTo(os);
161ca6bd9cdSMogball   os << "}\n\n";
1622696a952SMogball }
1632696a952SMogball 
1642696a952SMogball //===----------------------------------------------------------------------===//
1652696a952SMogball // Constructor definitions
1662696a952SMogball //===----------------------------------------------------------------------===//
1672696a952SMogball 
writeDeclTo(raw_indented_ostream & os) const168ca6bd9cdSMogball void Constructor::writeDeclTo(raw_indented_ostream &os) const {
169f3b1361fSMarkus Böck   methodSignature.writeTemplateParamsTo(os);
170ca6bd9cdSMogball   if (properties & ConstexprValue)
171ca6bd9cdSMogball     os << "constexpr ";
172ca6bd9cdSMogball   methodSignature.writeDeclTo(os);
173ca6bd9cdSMogball   if (!isInline()) {
174ca6bd9cdSMogball     os << ";\n\n";
175ca6bd9cdSMogball     return;
176ca6bd9cdSMogball   }
177ca6bd9cdSMogball   os << ' ';
178ca6bd9cdSMogball   if (!initializers.empty())
179ca6bd9cdSMogball     os << ": ";
180ca6bd9cdSMogball   llvm::interleaveComma(initializers, os,
181ca6bd9cdSMogball                         [&](auto &initializer) { initializer.writeTo(os); });
182ca6bd9cdSMogball   if (!initializers.empty())
183ca6bd9cdSMogball     os << ' ';
184ca6bd9cdSMogball   os << "{";
185ca6bd9cdSMogball   methodBody.writeTo(os);
186ca6bd9cdSMogball   os << "}\n\n";
1872696a952SMogball }
1882696a952SMogball 
writeDefTo(raw_indented_ostream & os,StringRef namePrefix) const189ca6bd9cdSMogball void Constructor::writeDefTo(raw_indented_ostream &os,
190ca6bd9cdSMogball                              StringRef namePrefix) const {
191ca6bd9cdSMogball   // The method has no definition to write if it is declaration only or inline.
192ca6bd9cdSMogball   if (properties & Declaration || isInline())
1932696a952SMogball     return;
1942696a952SMogball 
1952696a952SMogball   methodSignature.writeDefTo(os, namePrefix);
196ca6bd9cdSMogball   os << ' ';
197ca6bd9cdSMogball   if (!initializers.empty())
198ca6bd9cdSMogball     os << ": ";
199ca6bd9cdSMogball   llvm::interleaveComma(initializers, os,
200ca6bd9cdSMogball                         [&](auto &initializer) { initializer.writeTo(os); });
201ca6bd9cdSMogball   if (!initializers.empty())
202ca6bd9cdSMogball     os << ' ';
203ca6bd9cdSMogball   os << "{";
2042696a952SMogball   methodBody.writeTo(os);
205ca6bd9cdSMogball   os << "}\n\n";
206ca6bd9cdSMogball }
207ca6bd9cdSMogball 
writeTo(raw_indented_ostream & os) const208ca6bd9cdSMogball void Constructor::MemberInitializer::writeTo(raw_indented_ostream &os) const {
209ca6bd9cdSMogball   os << name << '(' << value << ')';
210ca6bd9cdSMogball }
211ca6bd9cdSMogball 
212ca6bd9cdSMogball //===----------------------------------------------------------------------===//
213ca6bd9cdSMogball // Visibility definitions
214ca6bd9cdSMogball //===----------------------------------------------------------------------===//
215ca6bd9cdSMogball 
216ca6bd9cdSMogball namespace mlir {
217ca6bd9cdSMogball namespace tblgen {
operator <<(raw_ostream & os,Visibility visibility)218ca6bd9cdSMogball raw_ostream &operator<<(raw_ostream &os, Visibility visibility) {
219ca6bd9cdSMogball   switch (visibility) {
220ca6bd9cdSMogball   case Visibility::Public:
221ca6bd9cdSMogball     return os << "public";
222ca6bd9cdSMogball   case Visibility::Protected:
223ca6bd9cdSMogball     return os << "protected";
224ca6bd9cdSMogball   case Visibility::Private:
225ca6bd9cdSMogball     return os << "private";
226ca6bd9cdSMogball   }
227ca6bd9cdSMogball   return os;
228ca6bd9cdSMogball }
229be0a7e9fSMehdi Amini } // namespace tblgen
230be0a7e9fSMehdi Amini } // namespace mlir
231ca6bd9cdSMogball 
232ca6bd9cdSMogball //===----------------------------------------------------------------------===//
233ca6bd9cdSMogball // ParentClass definitions
234ca6bd9cdSMogball //===----------------------------------------------------------------------===//
235ca6bd9cdSMogball 
writeTo(raw_indented_ostream & os) const236ca6bd9cdSMogball void ParentClass::writeTo(raw_indented_ostream &os) const {
237ca6bd9cdSMogball   os << visibility << ' ' << name;
238ca6bd9cdSMogball   if (!templateParams.empty()) {
239ca6bd9cdSMogball     auto scope = os.scope("<", ">", /*indent=*/false);
240ca6bd9cdSMogball     llvm::interleaveComma(templateParams, os,
241ca6bd9cdSMogball                           [&](auto &param) { os << param; });
242ca6bd9cdSMogball   }
243ca6bd9cdSMogball }
244ca6bd9cdSMogball 
245ca6bd9cdSMogball //===----------------------------------------------------------------------===//
246ca6bd9cdSMogball // UsingDeclaration definitions
247ca6bd9cdSMogball //===----------------------------------------------------------------------===//
248ca6bd9cdSMogball 
writeDeclTo(raw_indented_ostream & os) const249ca6bd9cdSMogball void UsingDeclaration::writeDeclTo(raw_indented_ostream &os) const {
250cf6f2175SMarkus Böck   if (!templateParams.empty()) {
251cf6f2175SMarkus Böck     os << "template <";
252cf6f2175SMarkus Böck     llvm::interleaveComma(templateParams, os, [&](StringRef paramName) {
253cf6f2175SMarkus Böck       os << "typename " << paramName;
254cf6f2175SMarkus Böck     });
255cf6f2175SMarkus Böck     os << ">\n";
256cf6f2175SMarkus Böck   }
257ca6bd9cdSMogball   os << "using " << name;
258ca6bd9cdSMogball   if (!value.empty())
259ca6bd9cdSMogball     os << " = " << value;
260ca6bd9cdSMogball   os << ";\n";
261ca6bd9cdSMogball }
262ca6bd9cdSMogball 
263ca6bd9cdSMogball //===----------------------------------------------------------------------===//
264ca6bd9cdSMogball // Field definitions
265ca6bd9cdSMogball //===----------------------------------------------------------------------===//
266ca6bd9cdSMogball 
writeDeclTo(raw_indented_ostream & os) const267ca6bd9cdSMogball void Field::writeDeclTo(raw_indented_ostream &os) const {
268ca6bd9cdSMogball   os << type << ' ' << name << ";\n";
269ca6bd9cdSMogball }
270ca6bd9cdSMogball 
271ca6bd9cdSMogball //===----------------------------------------------------------------------===//
272ca6bd9cdSMogball // VisibilityDeclaration definitions
273ca6bd9cdSMogball //===----------------------------------------------------------------------===//
274ca6bd9cdSMogball 
writeDeclTo(raw_indented_ostream & os) const275ca6bd9cdSMogball void VisibilityDeclaration::writeDeclTo(raw_indented_ostream &os) const {
276ca6bd9cdSMogball   os.unindent();
277ca6bd9cdSMogball   os << visibility << ":\n";
278ca6bd9cdSMogball   os.indent();
279ca6bd9cdSMogball }
280ca6bd9cdSMogball 
281ca6bd9cdSMogball //===----------------------------------------------------------------------===//
282ca6bd9cdSMogball // ExtraClassDeclaration definitions
283ca6bd9cdSMogball //===----------------------------------------------------------------------===//
284ca6bd9cdSMogball 
writeDeclTo(raw_indented_ostream & os) const285ca6bd9cdSMogball void ExtraClassDeclaration::writeDeclTo(raw_indented_ostream &os) const {
286ca6bd9cdSMogball   os.printReindented(extraClassDeclaration);
2872696a952SMogball }
2882696a952SMogball 
writeDefTo(raw_indented_ostream & os,StringRef namePrefix) const289b0774e5fSMogball void ExtraClassDeclaration::writeDefTo(raw_indented_ostream &os,
290b0774e5fSMogball                                        StringRef namePrefix) const {
291b0774e5fSMogball   os.printReindented(extraClassDefinition);
292b0774e5fSMogball }
293b0774e5fSMogball 
2942696a952SMogball //===----------------------------------------------------------------------===//
2952696a952SMogball // Class definitions
2962696a952SMogball //===----------------------------------------------------------------------===//
2972696a952SMogball 
addParent(ParentClass parent)298ca6bd9cdSMogball ParentClass &Class::addParent(ParentClass parent) {
299ca6bd9cdSMogball   parents.push_back(std::move(parent));
300ca6bd9cdSMogball   return parents.back();
3012696a952SMogball }
3022696a952SMogball 
writeDeclTo(raw_indented_ostream & os) const303ca6bd9cdSMogball void Class::writeDeclTo(raw_indented_ostream &os) const {
304cf6f2175SMarkus Böck   if (!templateParams.empty()) {
305cf6f2175SMarkus Böck     os << "template <";
306cf6f2175SMarkus Böck     llvm::interleaveComma(templateParams, os,
307cf6f2175SMarkus Böck                           [&](StringRef param) { os << "typename " << param; });
308cf6f2175SMarkus Böck     os << ">\n";
309cf6f2175SMarkus Böck   }
310cf6f2175SMarkus Böck 
311ca6bd9cdSMogball   // Declare the class.
312ca6bd9cdSMogball   os << (isStruct ? "struct" : "class") << ' ' << className << ' ';
3132696a952SMogball 
314ca6bd9cdSMogball   // Declare the parent classes, if any.
315ca6bd9cdSMogball   if (!parents.empty()) {
316ca6bd9cdSMogball     os << ": ";
317ca6bd9cdSMogball     llvm::interleaveComma(parents, os,
318ca6bd9cdSMogball                           [&](auto &parent) { parent.writeTo(os); });
319ca6bd9cdSMogball     os << ' ';
3202696a952SMogball   }
321ca6bd9cdSMogball   auto classScope = os.scope("{\n", "};\n", /*indent=*/true);
322ca6bd9cdSMogball 
323ca6bd9cdSMogball   // Print all the class declarations.
324ca6bd9cdSMogball   for (auto &decl : declarations)
325ca6bd9cdSMogball     decl->writeDeclTo(os);
326ca6bd9cdSMogball }
327ca6bd9cdSMogball 
writeDefTo(raw_indented_ostream & os) const328ca6bd9cdSMogball void Class::writeDefTo(raw_indented_ostream &os) const {
329ca6bd9cdSMogball   // Print all the definitions.
330ca6bd9cdSMogball   for (auto &decl : declarations)
331ca6bd9cdSMogball     decl->writeDefTo(os, className);
332ca6bd9cdSMogball }
333ca6bd9cdSMogball 
finalize()334ca6bd9cdSMogball void Class::finalize() {
335ca6bd9cdSMogball   // Sort the methods by public and private. Remove them from the pending list
336ca6bd9cdSMogball   // of methods.
337ca6bd9cdSMogball   SmallVector<std::unique_ptr<Method>> publicMethods, privateMethods;
338ca6bd9cdSMogball   for (auto &method : methods) {
339ca6bd9cdSMogball     if (method->isPrivate())
340ca6bd9cdSMogball       privateMethods.push_back(std::move(method));
341ca6bd9cdSMogball     else
342ca6bd9cdSMogball       publicMethods.push_back(std::move(method));
343ca6bd9cdSMogball   }
344ca6bd9cdSMogball   methods.clear();
345ca6bd9cdSMogball 
346ca6bd9cdSMogball   // If the last visibility declaration wasn't `public`, add one that is. Then,
347ca6bd9cdSMogball   // declare the public methods.
348ca6bd9cdSMogball   if (!publicMethods.empty() && getLastVisibilityDecl() != Visibility::Public)
349ca6bd9cdSMogball     declare<VisibilityDeclaration>(Visibility::Public);
350ca6bd9cdSMogball   for (auto &method : publicMethods)
351ca6bd9cdSMogball     declarations.push_back(std::move(method));
352ca6bd9cdSMogball 
353ca6bd9cdSMogball   // If the last visibility declaration wasn't `private`, add one that is. Then,
354ca6bd9cdSMogball   // declare the private methods.
355ca6bd9cdSMogball   if (!privateMethods.empty() && getLastVisibilityDecl() != Visibility::Private)
356ca6bd9cdSMogball     declare<VisibilityDeclaration>(Visibility::Private);
357ca6bd9cdSMogball   for (auto &method : privateMethods)
358ca6bd9cdSMogball     declarations.push_back(std::move(method));
359ca6bd9cdSMogball 
360ca6bd9cdSMogball   // All fields added to the pending list are private and declared at the bottom
361ca6bd9cdSMogball   // of the class. If the last visibility declaration wasn't `private`, add one
362ca6bd9cdSMogball   // that is, then declare the fields.
363ca6bd9cdSMogball   if (!fields.empty() && getLastVisibilityDecl() != Visibility::Private)
364ca6bd9cdSMogball     declare<VisibilityDeclaration>(Visibility::Private);
365ca6bd9cdSMogball   for (auto &field : fields)
366ca6bd9cdSMogball     declare<Field>(std::move(field));
367ca6bd9cdSMogball   fields.clear();
368ca6bd9cdSMogball }
369ca6bd9cdSMogball 
getLastVisibilityDecl() const370ca6bd9cdSMogball Visibility Class::getLastVisibilityDecl() const {
371ca6bd9cdSMogball   auto reverseDecls = llvm::reverse(declarations);
372*971b8525SJakub Kuderski   auto it = llvm::find_if(reverseDecls, llvm::IsaPred<VisibilityDeclaration>);
373ca6bd9cdSMogball   return it == reverseDecls.end()
374ca6bd9cdSMogball              ? (isStruct ? Visibility::Public : Visibility::Private)
375cf6f2175SMarkus Böck              : cast<VisibilityDeclaration>(**it).getVisibility();
3762696a952SMogball }
3772696a952SMogball 
insertAndPruneMethods(std::vector<std::unique_ptr<Method>> & methods,std::unique_ptr<Method> newMethod)378ca6bd9cdSMogball Method *insertAndPruneMethods(std::vector<std::unique_ptr<Method>> &methods,
379ca6bd9cdSMogball                               std::unique_ptr<Method> newMethod) {
3802696a952SMogball   if (llvm::any_of(methods, [&](auto &method) {
381ca6bd9cdSMogball         return method->makesRedundant(*newMethod);
3822696a952SMogball       }))
3832696a952SMogball     return nullptr;
3842696a952SMogball 
385ca6bd9cdSMogball   llvm::erase_if(methods, [&](auto &method) {
386ca6bd9cdSMogball     return newMethod->makesRedundant(*method);
387ca6bd9cdSMogball   });
3882696a952SMogball   methods.push_back(std::move(newMethod));
389ca6bd9cdSMogball   return methods.back().get();
3902696a952SMogball }
3912696a952SMogball 
addMethodAndPrune(Method && newMethod)3922696a952SMogball Method *Class::addMethodAndPrune(Method &&newMethod) {
393ca6bd9cdSMogball   return insertAndPruneMethods(methods,
394ca6bd9cdSMogball                                std::make_unique<Method>(std::move(newMethod)));
3952696a952SMogball }
3962696a952SMogball 
addConstructorAndPrune(Constructor && newCtor)3972696a952SMogball Constructor *Class::addConstructorAndPrune(Constructor &&newCtor) {
398ca6bd9cdSMogball   return dyn_cast_or_null<Constructor>(insertAndPruneMethods(
399ca6bd9cdSMogball       methods, std::make_unique<Constructor>(std::move(newCtor))));
4002696a952SMogball }
401