diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-06-22 06:09:49 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-06-22 06:09:49 +0000 |
commit | 25a767651d14db87aa03dd5fe3e011d877dd4100 (patch) | |
tree | a4be9c9ef892b9807686250089b35afb71863238 /lib/Parse/Parser.cpp | |
parent | fc0f40acc6877c2d1fa7e50decd8ec330a3569a4 (diff) |
Introduce DelayedCleanupPool useful for simplifying 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.
Use it to plug the leaking of TemplateIdAnnotation objects. rdar://9634138.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133610 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/Parser.cpp')
-rw-r--r-- | lib/Parse/Parser.cpp | 21 |
1 files changed, 16 insertions, 5 deletions
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index f19472ccdc..1089d2309a 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -486,6 +486,7 @@ void Parser::Initialize() { /// 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); while (Tok.is(tok::annot_pragma_unused)) HandlePragmaUnused(); @@ -548,6 +549,7 @@ void Parser::ParseTranslationUnit() { Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, ParsingDeclSpec *DS) { + DelayedCleanupPoint CleanupRAII(TopLevelDeclCleanupPool); ParenBraceBracketBalancer BalancerRAIIObj(*this); Decl *SingleDecl = 0; @@ -1155,6 +1157,18 @@ Parser::ExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) { return move(Result); } +/// \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. +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; +} + /// TryAnnotateTypeOrScopeToken - If the current token position is on a /// typename (possibly qualified in C++) or a C++ scope specifier not followed /// by a typename, TryAnnotateTypeOrScopeToken will replace one or more tokens @@ -1209,8 +1223,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) { *Tok.getIdentifierInfo(), Tok.getLocation()); } else if (Tok.is(tok::annot_template_id)) { - TemplateIdAnnotation *TemplateId - = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue()); + TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); if (TemplateId->Kind == TNK_Function_template) { Diag(Tok, diag::err_typename_refers_to_non_type_template) << Tok.getAnnotationRange(); @@ -1228,7 +1241,6 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) { TemplateId->LAngleLoc, TemplateArgsPtr, TemplateId->RAngleLoc); - TemplateId->Destroy(); } else { Diag(Tok, diag::err_expected_type_name_after_typename) << SS.getRange(); @@ -1311,8 +1323,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) { } if (Tok.is(tok::annot_template_id)) { - TemplateIdAnnotation *TemplateId - = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue()); + TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); if (TemplateId->Kind == TNK_Type_template) { // A template-id that refers to a type was parsed into a // template-id annotation in a context where we weren't allowed |