Fix namespaced types for auto_ptr new[] errors

This fixes false negatives for code such as:

    std::auto_ptr<foo::bar> p(new foo::bar[10]);

The idea is to find a "new", search for the end token ";", then see if
the declaration ends in a closing square bracket. Also fixes other cases
that checked for "new %type% [" so that they work with namespaces.
This commit is contained in:
Richard Quirk 2011-11-06 15:32:28 +01:00
parent 7ef1107a55
commit 7f88b66842
2 changed files with 44 additions and 4 deletions

View File

@ -1081,6 +1081,18 @@ void CheckStl::string_c_strError(const Token* tok, bool is_inconlusive)
reportError(tok, Severity::error, "stlcstr", "Dangerous usage of c_str()");
}
static bool hasArrayEnd(const Token *tok1)
{
const Token *end = Token::findsimplematch(tok1, ";");
return (end && Token::simpleMatch(end->previous(), "] ;"));
}
static bool hasArrayEndParen(const Token *tok1)
{
const Token *end = Token::findsimplematch(tok1, ";");
return (end && end->previous() &&
Token::simpleMatch(end->previous()->previous(), "] ) ;"));
}
//---------------------------------------------------------------------------
//
@ -1101,7 +1113,7 @@ void CheckStl::checkAutoPointer()
while (tok2) {
if (Token::Match(tok2, "> %var%")) {
const Token *tok3 = tok2->next()->next();
if (Token::Match(tok3, "( new %type% [")) {
if (Token::Match(tok3, "( new %type%") && hasArrayEndParen(tok3)) {
autoPointerArrayError(tok2->next());
break;
}
@ -1113,8 +1125,8 @@ void CheckStl::checkAutoPointer()
if (Token::simpleMatch(tok3->previous(), "[ ] )")) {
autoPointerArrayError(tok2->next());
} else if (tok3->varId()) {
const Token *decltok = Token::findmatch(_tokenizer->tokens(), "%varid% = new %type% [", tok3->varId());
if (decltok) {
const Token *decltok = Token::findmatch(_tokenizer->tokens(), "%varid% = new %type%", tok3->varId());
if (decltok && hasArrayEnd(decltok)) {
autoPointerArrayError(tok2->next());
}
}
@ -1135,7 +1147,8 @@ void CheckStl::checkAutoPointer()
autoPointerError(tok->next()->next());
}
}
} else if (Token::Match(tok, "%var% = new %type% [") || Token::Match(tok, "%var% . reset ( new %type% [")) {
} else if ((Token::Match(tok, "%var% = new %type% ") && hasArrayEnd(tok)) ||
(Token::Match(tok, "%var% . reset ( new %type% ") && hasArrayEndParen(tok))) {
iter = autoPtrVarId.find(tok->varId());
if (iter != autoPtrVarId.end()) {
autoPointerArrayError(tok);

View File

@ -1427,6 +1427,13 @@ private:
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with operator 'new[]'.\n", errout.str());
check("void f() \n"
"{\n"
" foo::bar::baz* var = new foo::bar::baz[10];\n"
" auto_ptr<foo::bar::baz> p2( var );\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with operator 'new[]'.\n", errout.str());
check("void f() \n"
"{\n"
" auto_ptr<T> p2( new T[] );\n"
@ -1439,6 +1446,12 @@ private:
"}\n");
ASSERT_EQUALS("[test.cpp:3]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with operator 'new[]'.\n", errout.str());
check("void f() \n"
"{\n"
" auto_ptr<foo::bar> p(new foo::bar[10]);\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with operator 'new[]'.\n", errout.str());
check("void f() \n"
"{\n"
" auto_ptr<T> p2;\n"
@ -1460,6 +1473,13 @@ private:
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with operator 'new[]'.\n", errout.str());
check("void f() \n"
"{\n"
" auto_ptr<T::B> p2;\n"
" p2 = new T::B[10];\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with operator 'new[]'.\n", errout.str());
check("void f() \n"
"{\n"
" auto_ptr<T> p2;\n"
@ -1467,6 +1487,13 @@ private:
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with operator 'new[]'.\n", errout.str());
check("void f() \n"
"{\n"
" auto_ptr<T::B> p2;\n"
" p2.reset( new T::B[10] );\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with operator 'new[]'.\n", errout.str());
// ticket #2887 (infinite loop)
check("A::A(std::auto_ptr<X> e){}\n");
ASSERT_EQUALS("", errout.str());