]> granicus.if.org Git - clang/commitdiff
Parser: Don't manage TemplateAnnotationIds in a delayed cleanup pool.
authorBenjamin Kramer <benny.kra@googlemail.com>
Sat, 14 Apr 2012 12:14:03 +0000 (12:14 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Sat, 14 Apr 2012 12:14:03 +0000 (12:14 +0000)
Instead, make it the allocation function's responsibility to add them
to a list and clear it when a top-level decl is finished.

This plugs leakage of TemplateAnnotationIds. DelayedCleanupPool is
ugly and unused, remove it.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154743 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DelayedCleanupPool.h [deleted file]
include/clang/Parse/Parser.h
include/clang/Sema/ParsedTemplate.h
lib/Parse/ParseExprCXX.cpp
lib/Parse/ParseTemplate.cpp
lib/Parse/Parser.cpp

diff --git a/include/clang/Basic/DelayedCleanupPool.h b/include/clang/Basic/DelayedCleanupPool.h
deleted file mode 100644 (file)
index 8575bc2..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-//=== DelayedCleanupPool.h - Delayed Clean-up Pool Implementation *- C++ -*===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines a facility to delay calling cleanup methods until specific
-// points.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_BASIC_DELAYEDCLEANUPPOOL_H
-#define LLVM_CLANG_BASIC_DELAYEDCLEANUPPOOL_H
-
-#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallVector.h"
-
-namespace clang {
-
-/// \brief Gathers pairs of pointer-to-object/pointer-to-cleanup-function
-/// allowing the cleanup functions to get called (with the pointer as parameter)
-/// at specific points.
-///
-/// The use case is to simplify clean-up of certain resources that, while their
-/// lifetime is well-known and restricted, cleaning them up manually is easy to
-/// miss and cause a leak.
-///
-/// The same pointer can be added multiple times; its clean-up function will
-/// only be called once.
-class DelayedCleanupPool {
-public:
-  typedef void (*CleanupFn)(void *ptr);
-
-  /// \brief Adds a pointer and its associated cleanup function to be called
-  /// at a later point.
-  ///
-  /// \returns false if the pointer is already added, true otherwise.
-  bool delayCleanup(void *ptr, CleanupFn fn) {
-    assert(ptr && "Expected valid pointer to object");
-    assert(fn && "Expected valid pointer to function");
-
-    CleanupFn &mapFn = Ptrs[ptr];
-    assert((!mapFn || mapFn == fn) &&
-           "Adding a pointer with different cleanup function!");
-
-    if (!mapFn) {
-      mapFn = fn;
-      Cleanups.push_back(std::make_pair(ptr, fn));
-      return true;
-    }
-
-    return false;
-  }
-
-  template <typename T>
-  bool delayDelete(T *ptr) {
-    return delayCleanup(ptr, cleanupWithDelete<T>);
-  }
-
-  template <typename T, void (T::*Fn)()>
-  bool delayMemberFunc(T *ptr) {
-    return delayCleanup(ptr, cleanupWithMemberFunc<T, Fn>);
-  }
-
-  void doCleanup() {
-    for (SmallVector<std::pair<void *, CleanupFn>, 8>::reverse_iterator
-           I = Cleanups.rbegin(), E = Cleanups.rend(); I != E; ++I)
-      I->second(I->first);
-    Cleanups.clear();
-    Ptrs.clear();
-  }
-
-  ~DelayedCleanupPool() {
-    doCleanup();
-  }
-
-private:
-  llvm::DenseMap<void *, CleanupFn> Ptrs;
-  SmallVector<std::pair<void *, CleanupFn>, 8> Cleanups;
-
-  template <typename T>
-  static void cleanupWithDelete(void *ptr) {
-    delete static_cast<T *>(ptr);
-  }
-
-  template <typename T, void (T::*Fn)()>
-  static void cleanupWithMemberFunc(void *ptr) {
-    (static_cast<T *>(ptr)->*Fn)();
-  }
-};
-
-/// \brief RAII object for triggering a cleanup of a DelayedCleanupPool.
-class DelayedCleanupPoint {
-  DelayedCleanupPool &Pool;
-
-public:
-  DelayedCleanupPoint(DelayedCleanupPool &pool) : Pool(pool) { }
-
-  ~DelayedCleanupPoint() {
-    Pool.doCleanup();
-  }
-};
-
-} // end namespace clang
-
-#endif
index a9e7a74d69acd6f8fa97c3fc00c4174bbe5ad1b4..3b2318365b53679d305d6c6e0ce8c2cb09dab0c5 100644 (file)
@@ -15,7 +15,6 @@
 #define LLVM_CLANG_PARSE_PARSER_H
 
 #include "clang/Basic/Specifiers.h"
-#include "clang/Basic/DelayedCleanupPool.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Lex/CodeCompletionHandler.h"
 #include "clang/Sema/Sema.h"
@@ -192,9 +191,9 @@ class Parser : public CodeCompletionHandler {
   /// Factory object for creating AttributeList objects.
   AttributeFactory AttrFactory;
 
-  /// \brief Gathers and cleans up objects when parsing of a top-level
-  /// declaration is finished.
-  DelayedCleanupPool TopLevelDeclCleanupPool;
+  /// \brief Gathers and cleans up TemplateIdAnnotations when parsing of a
+  /// top-level declaration is finished.
+  SmallVector<TemplateIdAnnotation *, 16> TemplateIds;
 
   IdentifierInfo *getSEHExceptKeyword();
 
@@ -568,9 +567,7 @@ private:
                                 const char *&PrevSpec, unsigned &DiagID,
                                 bool &isInvalid);
 
-  /// \brief Get the TemplateIdAnnotation from the token and put it in the
-  /// cleanup pool so that it gets destroyed when parsing the current top level
-  /// declaration is finished.
+  /// \brief Get the TemplateIdAnnotation from the token.
   TemplateIdAnnotation *takeTemplateIdAnnotation(const Token &tok);
 
   /// TentativeParsingAction - An object that is used as a kind of "tentative
index 3ff045954be702ab1a0b1adb9e8b3936a0c225f3..c1b471014b73ebba4cbc99c1863f1492c8686eea 100644 (file)
@@ -178,8 +178,11 @@ namespace clang {
     ParsedTemplateArgument *getTemplateArgs() { 
       return reinterpret_cast<ParsedTemplateArgument *>(this + 1); 
     }
-    
-    static TemplateIdAnnotation* Allocate(unsigned NumArgs) {
+
+    /// \brief Creates a new TemplateIdAnnotation with NumArgs arguments and
+    /// appends it to List.
+    static TemplateIdAnnotation *
+    Allocate(unsigned NumArgs, SmallVectorImpl<TemplateIdAnnotation*> &List) {
       TemplateIdAnnotation *TemplateId
         = (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) +
                                       sizeof(ParsedTemplateArgument) * NumArgs);
@@ -193,6 +196,7 @@ namespace clang {
       for (unsigned I = 0; I != NumArgs; ++I)
         new (TemplateArgs + I) ParsedTemplateArgument();
       
+      List.push_back(TemplateId);
       return TemplateId;
     }
     
index 2af74824ebcf610a4af9b74387c2482adf09a382..491b4a1381ec805a6f43052f3d17c33c7fa46852 100644 (file)
@@ -1711,7 +1711,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
     // Form a parsed representation of the template-id to be stored in the
     // UnqualifiedId.
     TemplateIdAnnotation *TemplateId
-      = TemplateIdAnnotation::Allocate(TemplateArgs.size());
+      = TemplateIdAnnotation::Allocate(TemplateArgs.size(), TemplateIds);
 
     if (Id.getKind() == UnqualifiedId::IK_Identifier) {
       TemplateId->Name = Id.Identifier;
index 61cd9f2119a6565a3ee8cd3116f8d355651b9c18..f8204d9cda5ec5ecc73dfbcc40daa34dc8f082ac 100644 (file)
@@ -838,7 +838,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
     // later.
     Tok.setKind(tok::annot_template_id);
     TemplateIdAnnotation *TemplateId
-      = TemplateIdAnnotation::Allocate(TemplateArgs.size());
+      = TemplateIdAnnotation::Allocate(TemplateArgs.size(), TemplateIds);
     TemplateId->TemplateNameLoc = TemplateNameLoc;
     if (TemplateName.getKind() == UnqualifiedId::IK_Identifier) {
       TemplateId->Name = TemplateName.Identifier;
index 054a8fd6a55fcc46ad8c69f8e0ff5c1a0c4eec19..f1b99fb0a129fdc9449e1fa1596b776557059ad8 100644 (file)
@@ -397,6 +397,8 @@ Parser::~Parser() {
   PP.RemovePragmaHandler("STDC", FPContractHandler.get());
   FPContractHandler.reset();
   PP.clearCodeCompletionHandler();
+
+  assert(TemplateIds.empty() && "Still alive TemplateIdAnnotations around?");
 }
 
 /// Initialize - Warm up the parser.
@@ -470,10 +472,30 @@ void Parser::Initialize() {
   }
 }
 
+namespace {
+  /// \brief RAIIObject to destroy the contents of a SmallVector of
+  /// TemplateIdAnnotation pointers and clear the vector.
+  class DestroyTemplateIdAnnotationsRAIIObj {
+    SmallVectorImpl<TemplateIdAnnotation *> &Container;
+  public:
+    DestroyTemplateIdAnnotationsRAIIObj(SmallVectorImpl<TemplateIdAnnotation *>
+                                       &Container)
+      : Container(Container) {}
+
+    ~DestroyTemplateIdAnnotationsRAIIObj() {
+      for (SmallVectorImpl<TemplateIdAnnotation *>::iterator I =
+           Container.begin(), E = Container.end();
+           I != E; ++I)
+        (*I)->Destroy();
+      Container.clear();
+    }
+  };
+}
+
 /// ParseTopLevelDecl - Parse one top-level declaration, return whatever the
 /// action tells us to.  This returns true if the EOF was encountered.
 bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
-  DelayedCleanupPoint CleanupRAII(TopLevelDeclCleanupPool);
+  DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(TemplateIds);
 
   // Skip over the EOF token, flagging end of previous input for incremental 
   // processing
@@ -543,7 +565,7 @@ void Parser::ParseTranslationUnit() {
 Parser::DeclGroupPtrTy
 Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
                                  ParsingDeclSpec *DS) {
-  DelayedCleanupPoint CleanupRAII(TopLevelDeclCleanupPool);
+  DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(TemplateIds);
   ParenBraceBracketBalancer BalancerRAIIObj(*this);
 
   if (PP.isCodeCompletionReached()) {
@@ -1201,8 +1223,6 @@ TemplateIdAnnotation *Parser::takeTemplateIdAnnotation(const Token &tok) {
   assert(tok.is(tok::annot_template_id) && "Expected template-id token");
   TemplateIdAnnotation *
       Id = static_cast<TemplateIdAnnotation *>(tok.getAnnotationValue());
-  TopLevelDeclCleanupPool.delayMemberFunc< TemplateIdAnnotation,
-                                          &TemplateIdAnnotation::Destroy>(Id);
   return Id;
 }