Ticket #7440: Function calls should not abort pointer alias analysis for local variables.
This commit is contained in:
parent
a012e5b5fb
commit
5262ed018e
|
@ -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
|
||||
{
|
||||
const bool pointeralias(valueToken->isName() || Token::Match(valueToken, "& %name% ["));
|
||||
const bool varIsGlobal = (indentlevel == 0);
|
||||
const bool printDebug = _settings->debugwarnings;
|
||||
|
||||
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"))
|
||||
break;
|
||||
|
||||
// Stop if unknown function call is seen
|
||||
// If the variable is a global or a member variable it might be
|
||||
// Stop if unknown function call is seen and the variable is global: it might be
|
||||
// changed by the function call
|
||||
// TODO: don't bail out if the variable is a local variable,
|
||||
// then it can't be changed by the function call.
|
||||
if (tok3->str() == ")" && tok3->link() &&
|
||||
if (varIsGlobal && tok3->str() == ")" && tok3->link() &&
|
||||
Token::Match(tok3->link()->tokAt(-2), "[;{}] %name% (") &&
|
||||
!Token::Match(tok3->link()->previous(), "if|for|while|switch|BOOST_FOREACH"))
|
||||
break;
|
||||
|
|
|
@ -369,6 +369,7 @@ private:
|
|||
TEST_CASE(trac3991);
|
||||
TEST_CASE(crash);
|
||||
TEST_CASE(trac7680);
|
||||
TEST_CASE(trac7440);
|
||||
}
|
||||
|
||||
std::string getcode(const char code[], const char varname[], bool classfunc=false) {
|
||||
|
@ -4032,6 +4033,16 @@ private:
|
|||
"}");
|
||||
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)
|
||||
|
|
|
@ -193,6 +193,7 @@ private:
|
|||
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(simplifyKnownVariablesReturn); // 3500 - return
|
||||
TEST_CASE(simplifyKnownVariablesPointerAliasFunctionCall); // #7440
|
||||
TEST_CASE(simplifyExternC);
|
||||
TEST_CASE(simplifyKeyword); // #5842 - remove C99 static keyword between []
|
||||
|
||||
|
@ -2879,6 +2880,22 @@ private:
|
|||
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() {
|
||||
// Ticket #2815
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue