<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div>IIRC TableGen has <i>plenty</i> of leaks, but I agree on the principle of the thing.</div><br><div><div>On Mar 5, 2014, at 8:49 , Aaron Ballman <<a href="mailto:aaron@aaronballman.com">aaron@aaronballman.com</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite">Author: aaronballman<br>Date: Wed Mar 5 10:49:55 2014<br>New Revision: 202989<br><br>URL: <a href="http://llvm.org/viewvc/llvm-project?rev=202989&view=rev">http://llvm.org/viewvc/llvm-project?rev=202989&view=rev</a><br>Log:<br>[C++11] Using std::unique_ptr to ensure that Argument objects do not leak (since clang-tblgen isn't long-lived, the old leak is probably acceptable, but it offended my senses nonetheless).<br><br>Modified:<br> cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp<br><br>Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=202989&r1=202988&r2=202989&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=202989&r1=202988&r2=202989&view=diff</a><br>==============================================================================<br>--- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original)<br>+++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Wed Mar 5 10:49:55 2014<br>@@ -21,6 +21,7 @@<br> #include "llvm/TableGen/TableGenBackend.h"<br> #include <algorithm><br> #include <cctype><br>+#include <memory><br> #include <set><br> #include <sstream><br><br>@@ -967,8 +968,8 @@ namespace {<br> };<br> }<br><br>-static Argument *createArgument(Record &Arg, StringRef Attr,<br>- Record *Search = 0) {<br>+static std::unique_ptr<Argument> createArgument(Record &Arg, StringRef Attr,<br>+ Record *Search = 0) {<br> if (!Search)<br> Search = &Arg;<br><br>@@ -1008,7 +1009,7 @@ static Argument *createArgument(Record &<br> // Search in reverse order so that the most-derived type is handled first.<br> std::vector<Record*> Bases = Search->getSuperClasses();<br> for (auto i = Bases.rbegin(), e = Bases.rend(); i != e; ++i) {<br>- Ptr = createArgument(Arg, Attr, *i);<br>+ Ptr = createArgument(Arg, Attr, *i).release();<br> if (Ptr)<br> break;<br> }<br>@@ -1017,7 +1018,7 @@ static Argument *createArgument(Record &<br> if (Ptr && Arg.getValueAsBit("Optional"))<br> Ptr->setOptional(true);<br><br>- return Ptr;<br>+ return std::unique_ptr<Argument>(Ptr);<br> }<br><br> static void writeAvailabilityValue(raw_ostream &OS) {<br>@@ -1052,8 +1053,10 @@ static void writeGetSpellingFunction(Rec<br> OS << "}\n\n";<br> }<br><br>-static void writePrettyPrintFunction(Record &R, std::vector<Argument*> &Args,<br>- raw_ostream &OS) {<br>+static void<br>+writePrettyPrintFunction(Record &R,<br>+ const std::vector<std::unique_ptr<Argument>> &Args,<br>+ raw_ostream &OS) {<br> std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);<br><br> OS << "void " << R.getName() << "Attr::printPretty("<br>@@ -1106,7 +1109,8 @@ static void writePrettyPrintFunction(Rec<br> " case " << I << " : {\n"<br> " OS << \"" + Prefix.str() + Spelling.str();<br><br>- if (Args.size()) OS << "(";<br>+ if (!Args.empty())<br>+ OS << "(";<br> if (Spelling == "availability") {<br> writeAvailabilityValue(OS);<br> } else {<br>@@ -1116,7 +1120,8 @@ static void writePrettyPrintFunction(Rec<br> }<br> }<br><br>- if (Args.size()) OS << ")";<br>+ if (!Args.empty())<br>+ OS << ")";<br> OS << Suffix.str() + "\";\n";<br><br> OS <<<br>@@ -1379,15 +1384,12 @@ void EmitClangAttrClass(RecordKeeper &Re<br> OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n";<br><br> std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");<br>- std::vector<Argument*> Args;<br>+ std::vector<std::unique_ptr<Argument>> Args;<br> Args.reserve(ArgRecords.size());<br><br> for (auto ArgRecord : ArgRecords) {<br>- Argument *Arg = createArgument(*ArgRecord, R.getName());<br>- assert(Arg);<br>- Args.push_back(Arg);<br>-<br>- Arg->writeDeclarations(OS);<br>+ Args.emplace_back(createArgument(*ArgRecord, R.getName()));<br>+ Args.back()->writeDeclarations(OS);<br> OS << "\n\n";<br> }<br><br>@@ -1411,7 +1413,7 @@ void EmitClangAttrClass(RecordKeeper &Re<br> OS << "ASTContext &Ctx";<br> if (!ElideSpelling)<br> OS << ", Spelling S";<br>- for (auto ai : Args) {<br>+ for (auto const &ai : Args) {<br> OS << ", ";<br> ai->writeCtorParameters(OS);<br> }<br>@@ -1419,7 +1421,7 @@ void EmitClangAttrClass(RecordKeeper &Re<br> OS << ") {\n";<br> OS << " " << R.getName() << "Attr *A = new (Ctx) " << R.getName();<br> OS << "Attr(Loc, Ctx, ";<br>- for (auto ai : Args) {<br>+ for (auto const &ai : Args) {<br> ai->writeImplicitCtorArgs(OS);<br> OS << ", ";<br> }<br>@@ -1430,7 +1432,7 @@ void EmitClangAttrClass(RecordKeeper &Re<br> OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";<br><br> bool HasOpt = false;<br>- for (auto ai : Args) {<br>+ for (auto const &ai : Args) {<br> OS << " , ";<br> ai->writeCtorParameters(OS);<br> OS << "\n";<br>@@ -1444,7 +1446,7 @@ void EmitClangAttrClass(RecordKeeper &Re<br> OS << " )\n";<br> OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n";<br><br>- for (auto ai : Args) {<br>+ for (auto const &ai : Args) {<br> OS << " , ";<br> ai->writeCtorInitializers(OS);<br> OS << "\n";<br>@@ -1452,7 +1454,7 @@ void EmitClangAttrClass(RecordKeeper &Re<br><br> OS << " {\n";<br><br>- for (auto ai : Args) {<br>+ for (auto const &ai : Args) {<br> ai->writeCtorBody(OS);<br> OS << "\n";<br> }<br>@@ -1462,7 +1464,7 @@ void EmitClangAttrClass(RecordKeeper &Re<br> // optional arguments as well.<br> if (HasOpt) {<br> OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";<br>- for (auto ai : Args) {<br>+ for (auto const &ai : Args) {<br> if (!ai->isOptional()) {<br> OS << " , ";<br> ai->writeCtorParameters(OS);<br>@@ -1476,7 +1478,7 @@ void EmitClangAttrClass(RecordKeeper &Re<br> OS << " )\n";<br> OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n";<br><br>- for (auto ai : Args) {<br>+ for (auto const &ai : Args) {<br> OS << " , ";<br> ai->writeCtorDefaultInitializers(OS);<br> OS << "\n";<br>@@ -1484,7 +1486,7 @@ void EmitClangAttrClass(RecordKeeper &Re<br><br> OS << " {\n";<br><br>- for (auto ai : Args) {<br>+ for (auto const &ai : Args) {<br> if (!ai->isOptional()) {<br> ai->writeCtorBody(OS);<br> OS << "\n";<br>@@ -1508,14 +1510,15 @@ void EmitClangAttrClass(RecordKeeper &Re<br><br> writeAttrAccessorDefinition(R, OS);<br><br>- for (auto ai : Args) {<br>+ for (auto const &ai : Args) {<br> ai->writeAccessors(OS);<br> OS << "\n\n";<br><br> if (ai->isEnumArg())<br>- static_cast<EnumArgument *>(ai)->writeConversion(OS);<br>+ static_cast<const EnumArgument *>(ai.get())->writeConversion(OS);<br> else if (ai->isVariadicEnumArg())<br>- static_cast<VariadicEnumArgument *>(ai)->writeConversion(OS);<br>+ static_cast<const VariadicEnumArgument *>(ai.get())<br>+ ->writeConversion(OS);<br> }<br><br> OS << R.getValueAsString("AdditionalMembers");<br>@@ -1548,19 +1551,19 @@ void EmitClangAttrImpl(RecordKeeper &Rec<br><br> if (!R.getValueAsBit("ASTNode"))<br> continue;<br>- <br>+<br> std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");<br>- std::vector<Argument*> Args;<br>+ std::vector<std::unique_ptr<Argument>> Args;<br> for (auto ri : ArgRecords)<br>- Args.push_back(createArgument(*ri, R.getName()));<br>+ Args.emplace_back(createArgument(*ri, R.getName()));<br><br>- for (auto ai : Args)<br>+ for (auto const &ai : Args)<br> ai->writeAccessorDefinitions(OS);<br><br> OS << R.getName() << "Attr *" << R.getName()<br> << "Attr::clone(ASTContext &C) const {\n";<br> OS << " return new (C) " << R.getName() << "Attr(getLocation(), C";<br>- for (auto ai : Args) {<br>+ for (auto const &ai : Args) {<br> OS << ", ";<br> ai->writeCloneArgs(OS);<br> }<br>@@ -1651,7 +1654,7 @@ void EmitClangAttrPCHRead(RecordKeeper &<br> Record *InhClass = Records.getClass("InheritableAttr");<br> std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),<br> ArgRecords;<br>- std::vector<Argument*> Args;<br>+ std::vector<std::unique_ptr<Argument>> Args;<br><br> OS << " switch (Kind) {\n";<br> OS << " default:\n";<br>@@ -1670,12 +1673,11 @@ void EmitClangAttrPCHRead(RecordKeeper &<br> ArgRecords = R.getValueAsListOfDefs("Args");<br> Args.clear();<br> for (auto ai : ArgRecords) {<br>- Argument *A = createArgument(*ai, R.getName());<br>- Args.push_back(A);<br>- A->writePCHReadDecls(OS);<br>+ Args.emplace_back(createArgument(*ai, R.getName()));<br>+ Args.back()->writePCHReadDecls(OS);<br> }<br> OS << " New = new (Context) " << R.getName() << "Attr(Range, Context";<br>- for (auto ri : Args) {<br>+ for (auto const &ri : Args) {<br> OS << ", ";<br> ri->writePCHReadArgs(OS);<br> }<br>@@ -1846,12 +1848,8 @@ void EmitClangAttrASTVisitor(RecordKeepe<br> << " return false;\n";<br><br> std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");<br>- for (auto ri : ArgRecords) {<br>- Record &ArgRecord = *ri;<br>- Argument *Arg = createArgument(ArgRecord, R.getName());<br>- assert(Arg);<br>- Arg->writeASTVisitorTraversal(OS);<br>- }<br>+ for (auto ri : ArgRecords)<br>+ createArgument(*ri, R.getName())->writeASTVisitorTraversal(OS);<br><br> OS << " return true;\n";<br> OS << "}\n\n";<br>@@ -1921,20 +1919,17 @@ void EmitClangAttrTemplateInstantiate(Re<br> }<br><br> std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");<br>- std::vector<Argument*> Args;<br>+ std::vector<std::unique_ptr<Argument>> Args;<br> Args.reserve(ArgRecords.size());<br><br>- for (auto ArgRecord : ArgRecords) {<br>- Argument *Arg = createArgument(*ArgRecord, R.getName());<br>- assert(Arg);<br>- Args.push_back(Arg);<br>- }<br>+ for (auto ArgRecord : ArgRecords)<br>+ Args.emplace_back(createArgument(*ArgRecord, R.getName()));<br><br>- for (auto ai : Args) {<br>+ for (auto const &ai : Args)<br> ai->writeTemplateInstantiation(OS);<br>- }<br>+<br> OS << " return new (C) " << R.getName() << "Attr(A->getLocation(), C";<br>- for (auto ai : Args) {<br>+ for (auto const &ai : Args) {<br> OS << ", ";<br> ai->writeTemplateInstantiationArgs(OS);<br> }<br><br><br>_______________________________________________<br>cfe-commits mailing list<br><a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits<br></blockquote></div><br></body></html>