diff options
-rw-r--r-- | clang/include/clang/Basic/DelayedCleanupPool.h | 110 | ||||
-rw-r--r-- | clang/include/clang/Parse/Parser.h | 11 | ||||
-rw-r--r-- | clang/include/clang/Sema/ParsedTemplate.h | 8 | ||||
-rw-r--r-- | clang/lib/Parse/ParseExprCXX.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Parse/ParseTemplate.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Parse/Parser.cpp | 28 |
6 files changed, 36 insertions, 125 deletions
diff --git a/clang/include/clang/Basic/DelayedCleanupPool.h b/clang/include/clang/Basic/DelayedCleanupPool.h deleted file mode 100644 index 8575bc21113..00000000000 --- a/clang/include/clang/Basic/DelayedCleanupPool.h +++ /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 diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index a9e7a74d69a..3b2318365b5 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -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 diff --git a/clang/include/clang/Sema/ParsedTemplate.h b/clang/include/clang/Sema/ParsedTemplate.h index 3ff045954be..c1b471014b7 100644 --- a/clang/include/clang/Sema/ParsedTemplate.h +++ b/clang/include/clang/Sema/ParsedTemplate.h @@ -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; } diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 2af74824ebc..491b4a1381e 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -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; diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index 61cd9f2119a..f8204d9cda5 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -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; diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 054a8fd6a55..f1b99fb0a12 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -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; } |