<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>