From 2a7fa04101bf487f4fd6dd04297573f62157d41a Mon Sep 17 00:00:00 2001
From: Roberto Raggi <roberto.raggi@nokia.com>
Date: Thu, 22 Oct 2009 16:46:26 +0200
Subject: [PATCH] Released the memory allocated in the memory pool when
 backtracking from Parser::parseTemplateId().

---
 src/shared/cplusplus/MemoryPool.cpp | 13 ++++++++++++
 src/shared/cplusplus/MemoryPool.h   | 16 +++++++++++++++
 src/shared/cplusplus/Parser.cpp     | 32 +++++++++++++++++++++++++++++
 src/shared/cplusplus/Parser.h       |  3 +++
 4 files changed, 64 insertions(+)

diff --git a/src/shared/cplusplus/MemoryPool.cpp b/src/shared/cplusplus/MemoryPool.cpp
index 2002a654350..1453c62cd69 100644
--- a/src/shared/cplusplus/MemoryPool.cpp
+++ b/src/shared/cplusplus/MemoryPool.cpp
@@ -110,6 +110,19 @@ void *MemoryPool::allocate_helper(size_t size)
     return addr;
 }
 
+MemoryPool::State MemoryPool::state() const
+{ return State(ptr, _blockCount); }
+
+void MemoryPool::rewind(const State &state)
+{
+    if (_blockCount == state.blockCount && state.ptr < ptr) {
+        if (_initializeAllocatedMemory)
+            memset(state.ptr, '\0', ptr - state.ptr);
+
+        ptr = state.ptr;
+    }
+}
+
 Managed::Managed()
 { }
 
diff --git a/src/shared/cplusplus/MemoryPool.h b/src/shared/cplusplus/MemoryPool.h
index e0f1ff87017..5b6fae925ff 100644
--- a/src/shared/cplusplus/MemoryPool.h
+++ b/src/shared/cplusplus/MemoryPool.h
@@ -79,6 +79,22 @@ public:
         return allocate_helper(size);
     }
 
+    struct State
+    {
+        char *ptr;
+        char *end;
+        int blockCount;
+
+        inline bool isValid() const
+        { return ptr != 0; }
+
+        inline State(char *ptr = 0, int blockCount = 0)
+            : ptr(ptr), blockCount(blockCount) {}
+    };
+
+    State state() const;
+    void rewind(const State &state);
+
 private:
     void *allocate_helper(size_t size);
 
diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp
index 8f3bd549ce4..24851c991da 100644
--- a/src/shared/cplusplus/Parser.cpp
+++ b/src/shared/cplusplus/Parser.cpp
@@ -88,6 +88,30 @@ int DebugRule::depth = 0;
 #  define DEBUG_THIS_RULE() do {} while (0)
 #endif
 
+class Parser::Rewind
+{
+    Parser *_parser;
+    MemoryPool::State _state;
+
+public:
+    inline Rewind(Parser *parser)
+        : _parser(parser) {}
+
+    inline void operator()(unsigned tokenIndex)
+    { rewind(tokenIndex); }
+
+    inline void mark()
+    { _state = _parser->_pool->state(); }
+
+    inline void rewind(unsigned tokenIndex)
+    {
+        _parser->rewind(tokenIndex);
+
+        if (_state.isValid())
+            _parser->_pool->rewind(_state);
+    }
+};
+
 Parser::Parser(TranslationUnit *unit)
     : _translationUnit(unit),
       _control(_translationUnit->control()),
@@ -302,6 +326,11 @@ bool Parser::parseClassOrNamespaceName(NameAST *&node)
 bool Parser::parseTemplateId(NameAST *&node)
 {
     DEBUG_THIS_RULE();
+
+    const unsigned start = cursor();
+    Rewind rewind(this);
+    rewind.mark();
+
     if (LA() == T_IDENTIFIER && LA(2) == T_LESS) {
         TemplateIdAST *ast = new (_pool) TemplateIdAST;
         ast->identifier_token = consumeToken();
@@ -315,6 +344,9 @@ bool Parser::parseTemplateId(NameAST *&node)
             }
         }
     }
+
+    rewind(start);
+
     return false;
 }
 
diff --git a/src/shared/cplusplus/Parser.h b/src/shared/cplusplus/Parser.h
index 3ca3371d815..2a7c15dfa3e 100644
--- a/src/shared/cplusplus/Parser.h
+++ b/src/shared/cplusplus/Parser.h
@@ -298,6 +298,9 @@ private:
     bool _inFunctionBody: 1;
     bool _inObjCImplementationContext: 1;
 
+    class Rewind;
+    friend class Rewind;
+
 private:
     Parser(const Parser& source);
     void operator =(const Parser& source);
-- 
GitLab