]> granicus.if.org Git - clang/commitdiff
Don't leak MacroArgs when using code completion, PR19688.
authorNico Weber <nicolasweber@gmx.de>
Fri, 9 May 2014 18:09:42 +0000 (18:09 +0000)
committerNico Weber <nicolasweber@gmx.de>
Fri, 9 May 2014 18:09:42 +0000 (18:09 +0000)
MacroArgs are owned by TokenLexer, and when a TokenLexer is destroyed, it'll
call its MacroArgs's destroy() method.  destroy() only appends the MacroArg to
Preprocessor's MacroArgCache list, and Preprocessor's destructor then calls
deallocate() on all MacroArgs in that list.  This method then ends up freeing
the MacroArgs's memory.

In a code completion context, Parser::cutOffParsing() gets called when a code
completion token is hit, which changes the type of the current token to
tok::eof.  eof tokens aren't always ConsumeToken()ed, so
Preprocessor::HandleEndOfFile() isn't always called, and that function is
responsible for popping the macro stack.

Due to this, Preprocessor::CurTokenLexer can be non-NULL when
~Preprocessor runs.  It's a unique_ptr, so it ended up being destructed after
~Preprocessor completed, and its MacroArgs thus got added to the freelist after
the code freeing things on the freelist had already completed.  The fix is to
explicitly call reset() before the freelist processing happens.  (See the bug
for more notes.)

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

lib/Lex/Preprocessor.cpp

index 56eabf41ffe121e6f105e7b4d978c5696fc46bbc..d263e7d2a09f984996d85c4cd00816f4557032c9 100644 (file)
@@ -143,14 +143,17 @@ Preprocessor::~Preprocessor() {
     I->MI.Destroy();
 
   // Free any cached macro expanders.
+  // This populates MacroArgCache, so all TokenLexers need to be destroyed
+  // before the code below that frees up the MacroArgCache list.
   for (unsigned i = 0, e = NumCachedTokenLexers; i != e; ++i)
     delete TokenLexerCache[i];
+  CurTokenLexer.reset();
 
   for (DeserializedMacroInfoChain *I = DeserialMIChainHead ; I ; I = I->Next)
     I->MI.Destroy();
 
   // Free any cached MacroArgs.
-  for (MacroArgs *ArgList = MacroArgCache; ArgList; )
+  for (MacroArgs *ArgList = MacroArgCache; ArgList;)
     ArgList = ArgList->deallocate();
 
   // Release pragma information.