Merge pull request #866 from simartin/ticket_7440

Ticket #7440: Function calls should not abort pointer alias analysis for local variables.
This commit is contained in:
amai2012 2017-01-28 01:32:52 +01:00 committed by GitHub
commit 7ae0b2b336
3 changed files with 31 additions and 5 deletions

View File

@ -6413,6 +6413,7 @@ bool Tokenizer::simplifyKnownVariablesGetData(unsigned int varid, Token **_tok2,
bool Tokenizer::simplifyKnownVariablesSimplify(Token **tok2, Token *tok3, unsigned int varid, const std::string &structname, std::string &value, unsigned int valueVarId, bool valueIsPointer, const Token * const valueToken, int indentlevel) const bool Tokenizer::simplifyKnownVariablesSimplify(Token **tok2, Token *tok3, unsigned int varid, const std::string &structname, std::string &value, unsigned int valueVarId, bool valueIsPointer, const Token * const valueToken, int indentlevel) const
{ {
const bool pointeralias(valueToken->isName() || Token::Match(valueToken, "& %name% [")); const bool pointeralias(valueToken->isName() || Token::Match(valueToken, "& %name% ["));
const bool varIsGlobal = (indentlevel == 0);
const bool printDebug = _settings->debugwarnings; const bool printDebug = _settings->debugwarnings;
if (_errorLogger && !list.getFiles().empty()) if (_errorLogger && !list.getFiles().empty())
@ -6491,12 +6492,9 @@ bool Tokenizer::simplifyKnownVariablesSimplify(Token **tok2, Token *tok3, unsign
if (pointeralias && Token::Match(tok3, "do|for|while")) if (pointeralias && Token::Match(tok3, "do|for|while"))
break; break;
// Stop if unknown function call is seen // Stop if unknown function call is seen and the variable is global: it might be
// If the variable is a global or a member variable it might be
// changed by the function call // changed by the function call
// TODO: don't bail out if the variable is a local variable, if (varIsGlobal && tok3->str() == ")" && tok3->link() &&
// then it can't be changed by the function call.
if (tok3->str() == ")" && tok3->link() &&
Token::Match(tok3->link()->tokAt(-2), "[;{}] %name% (") && Token::Match(tok3->link()->tokAt(-2), "[;{}] %name% (") &&
!Token::Match(tok3->link()->previous(), "if|for|while|switch|BOOST_FOREACH")) !Token::Match(tok3->link()->previous(), "if|for|while|switch|BOOST_FOREACH"))
break; break;

View File

@ -369,6 +369,7 @@ private:
TEST_CASE(trac3991); TEST_CASE(trac3991);
TEST_CASE(crash); TEST_CASE(crash);
TEST_CASE(trac7680); TEST_CASE(trac7680);
TEST_CASE(trac7440);
} }
std::string getcode(const char code[], const char varname[], bool classfunc=false) { std::string getcode(const char code[], const char varname[], bool classfunc=false) {
@ -4032,6 +4033,16 @@ private:
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void trac7440() {
check("int main(void) {\n"
" char* data = new char[100];\n"
" char** dataPtr = &data;\n"
" printf(\"test\");\n"
" delete [] *dataPtr;\n"
"}");
ASSERT_EQUALS("", errout.str());
}
}; };
REGISTER_TEST(TestMemleakInFunction) REGISTER_TEST(TestMemleakInFunction)

View File

@ -193,6 +193,7 @@ private:
TEST_CASE(simplifyKnownVariablesClassMember); // #2815 - value of class member may be changed by function call TEST_CASE(simplifyKnownVariablesClassMember); // #2815 - value of class member may be changed by function call
TEST_CASE(simplifyKnownVariablesFunctionCalls); // Function calls (don't assume pass by reference) TEST_CASE(simplifyKnownVariablesFunctionCalls); // Function calls (don't assume pass by reference)
TEST_CASE(simplifyKnownVariablesReturn); // 3500 - return TEST_CASE(simplifyKnownVariablesReturn); // 3500 - return
TEST_CASE(simplifyKnownVariablesPointerAliasFunctionCall); // #7440
TEST_CASE(simplifyExternC); TEST_CASE(simplifyExternC);
TEST_CASE(simplifyKeyword); // #5842 - remove C99 static keyword between [] TEST_CASE(simplifyKeyword); // #5842 - remove C99 static keyword between []
@ -2879,6 +2880,22 @@ private:
ASSERT_EQUALS("int a ( ) { return 123 ; }", tokenizeAndStringify(code,true)); ASSERT_EQUALS("int a ( ) { return 123 ; }", tokenizeAndStringify(code,true));
} }
void simplifyKnownVariablesPointerAliasFunctionCall() { // #7440
const char code[] = "int main() {\n"
" char* data = new char[100];\n"
" char** dataPtr = &data;\n"
" printf(\"test\");\n"
" delete [] *dataPtr;\n"
"}";
const char exp[] = "int main ( ) {\n"
"char * data ; data = new char [ 100 ] ;\n"
"char * * dataPtr ; dataPtr = & data ;\n"
"printf ( \"test\" ) ;\n"
"delete [ ] data ;\n"
"}";
ASSERT_EQUALS(exp, tokenizeAndStringify(code, /*simplify=*/true));
}
void simplifyKnownVariablesClassMember() { void simplifyKnownVariablesClassMember() {
// Ticket #2815 // Ticket #2815
{ {