From 8c327f82b3b75ee4e2955e1b1c9f1f9b8f51f707 Mon Sep 17 00:00:00 2001 From: Slava Semushin Date: Mon, 15 Jun 2009 00:32:34 +0700 Subject: [PATCH] Fixed ticket #346 (adding a "const" token prevents detection of memory leak) http://sourceforge.net/apps/trac/cppcheck/ticket/346 --- src/checkmemoryleak.cpp | 14 ++++++++++---- src/tokenize.cpp | 14 +++++++++++++- test/testmemleak.cpp | 9 +++++++++ test/testtokenize.cpp | 22 ++++++++++++++++++++++ 4 files changed, 54 insertions(+), 5 deletions(-) diff --git a/src/checkmemoryleak.cpp b/src/checkmemoryleak.cpp index c251fa3ab..c5726905c 100644 --- a/src/checkmemoryleak.cpp +++ b/src/checkmemoryleak.cpp @@ -1544,11 +1544,17 @@ void CheckMemoryLeakInFunction::check() if (sz < 1) sz = 1; - if (Token::Match(tok, "[{};] %type% * %var% [;=]")) - checkScope(tok->next(), tok->strAt(3), classmember, sz); + if (Token::Match(tok, "[{};] %type% * const| %var% [;=]")) + { + const int varname_tok = (tok->tokAt(3)->str() != "const" ? 3 : 4); + checkScope(tok->next(), tok->strAt(varname_tok), classmember, sz); + } - else if (Token::Match(tok, "[{};] %type% %type% * %var% [;=]")) - checkScope(tok->next(), tok->strAt(4), classmember, sz); + else if (Token::Match(tok, "[{};] %type% %type% * const| %var% [;=]")) + { + const int varname_tok = (tok->tokAt(4)->str() != "const" ? 4 : 5); + checkScope(tok->next(), tok->strAt(varname_tok), classmember, sz); + } } } } diff --git a/src/tokenize.cpp b/src/tokenize.cpp index a844f5510..3456ea4bb 100644 --- a/src/tokenize.cpp +++ b/src/tokenize.cpp @@ -2165,6 +2165,18 @@ bool Tokenizer::simplifyVarDecl() tok2 = NULL; } + else if (Token::Match(tok2, "%type% * const %var% ,|=")) + { + if (tok2->tokAt(3)->str() != "operator") + { + tok2 = tok2->tokAt(4); // The ',' token + } + else + { + tok2 = NULL; + } + } + else if (Token::Match(tok2, "%type% %var% [ %num% ] ,")) { tok2 = tok2->tokAt(5); // The ',' token @@ -2215,7 +2227,7 @@ bool Tokenizer::simplifyVarDecl() { // "type var =" => "type var; var =" Token *VarTok = type0->tokAt(typelen); - if (VarTok->str()[0] == '*') + while (Token::Match(VarTok, "*|const")) VarTok = VarTok->next(); InsertTokens(eq, VarTok, 2); eq->str(";"); diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index a4ed8f0c4..57335d48a 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -227,6 +227,15 @@ private: " int *a = new int[10];\n" "}\n"); ASSERT_EQUALS("[test.cpp:4]: (error) Memory leak: a\n", errout.str()); + + // ticket #346 + check("void f()\n" + "{\n" + " int * const a = new int[10];\n" + " const int * const b = new int[10];\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:5]: (error) Memory leak: a\n[test.cpp:5]: (error) Memory leak: b\n", + errout.str()); } void simple2() diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 16711bd8d..fb7fcd6dd 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -144,6 +144,7 @@ private: TEST_CASE(vardecl1); TEST_CASE(vardecl2); TEST_CASE(vardecl3); + TEST_CASE(vardecl4); TEST_CASE(volatile_variables); TEST_CASE(syntax_error); @@ -2043,6 +2044,27 @@ private: ASSERT_EQUALS("void f ( ) { char * p ; p = foo < 10 , char > ( ) ; }", actual); } + void vardecl4() + { + // ticket #346 + + const char code1[] = "void *p = NULL;"; + const char res1[] = "void * p ; p = NULL ;"; + ASSERT_EQUALS(res1, tokenizeAndStringify(code1)); + + const char code2[] = "const void *p = NULL;"; + const char res2[] = "const void * p ; p = NULL ;"; + ASSERT_EQUALS(res2, tokenizeAndStringify(code2)); + + const char code3[] = "void * const p = NULL;"; + const char res3[] = "void * const p ; p = NULL ;"; + ASSERT_EQUALS(res3, tokenizeAndStringify(code3)); + + const char code4[] = "const void * const p = NULL;"; + const char res4[] = "const void * const p ; p = NULL ;"; + ASSERT_EQUALS(res4, tokenizeAndStringify(code4)); + } + void volatile_variables() { const char code[] = "volatile int a=0;\n"