aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse/Parser.cpp
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-06-22 06:09:49 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-06-22 06:09:49 +0000
commit25a767651d14db87aa03dd5fe3e011d877dd4100 (patch)
treea4be9c9ef892b9807686250089b35afb71863238 /lib/Parse/Parser.cpp
parentfc0f40acc6877c2d1fa7e50decd8ec330a3569a4 (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.cpp21
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