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 ¶m) { 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 ¶m) { 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 ¶m) { 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