Fixed #1725 (segfault in ExecutionPath::bailOutVar (probably caused by #1721 fix))

This commit is contained in:
Daniel Marjamäki 2010-06-05 09:45:35 +02:00
parent 4ac7da7d51
commit 07e00d57d9
2 changed files with 86 additions and 93 deletions

View File

@ -25,6 +25,9 @@
#include <iostream> #include <iostream>
static void checkExecutionPaths_(const Token *tok, std::list<ExecutionPath *> &checks);
// default : bail out if the condition is has variable handling // default : bail out if the condition is has variable handling
bool ExecutionPath::parseCondition(const Token &tok, std::list<ExecutionPath *> & checks) bool ExecutionPath::parseCondition(const Token &tok, std::list<ExecutionPath *> & checks)
{ {
@ -80,6 +83,61 @@ static void printchecks(const std::list<ExecutionPath *> &checks)
#endif #endif
/**
* @brief Parse If/Switch body recursively.
* @param tok First token in body.
* @param checks The current checks
* @param newchecks new checks
* @param countif The countif set - count number of if for each execution path
*/
static void parseIfSwitchBody(const Token * const tok,
const std::list<ExecutionPath *> &checks,
std::list<ExecutionPath *> &newchecks,
std::set<unsigned int> &countif)
{
std::set<unsigned int> countif2;
std::list<ExecutionPath *> c;
if (!checks.empty())
{
std::list<ExecutionPath *>::const_iterator it;
for (it = checks.begin(); it != checks.end(); ++it)
{
c.push_back((*it)->copy());
if ((*it)->varId != 0)
countif2.insert((*it)->varId);
}
}
checkExecutionPaths_(tok, c);
while (!c.empty())
{
if (c.back()->varId == 0)
{
c.pop_back();
continue;
}
bool duplicate = false;
std::list<ExecutionPath *>::const_iterator it;
for (it = checks.begin(); it != checks.end(); ++it)
{
if (*(*it) == *c.back())
{
duplicate = true;
countif2.erase((*it)->varId);
break;
}
}
if (!duplicate)
newchecks.push_back(c.back());
c.pop_back();
}
// Add countif2 ids to countif.. countif.
countif.insert(countif2.begin(), countif2.end());
}
static void checkExecutionPaths_(const Token *tok, std::list<ExecutionPath *> &checks) static void checkExecutionPaths_(const Token *tok, std::list<ExecutionPath *> &checks)
{ {
if (!tok || tok->str() == "}" || checks.empty()) if (!tok || tok->str() == "}" || checks.empty())
@ -138,51 +196,12 @@ static void checkExecutionPaths_(const Token *tok, std::list<ExecutionPath *> &c
tok2 = tok2->link(); tok2 = tok2->link();
else if (tok2->str() == "}") else if (tok2->str() == "}")
break; break;
else if (tok2->str() == "case") else if (tok2->str() == "case" &&
!Token::Match(tok2, "case %num% : ; case"))
{ {
if (Token::Match(tok2, "case %num% : ; case")) parseIfSwitchBody(tok2, checks, newchecks, countif);
continue;
std::set<unsigned int> countif2;
std::list<ExecutionPath *> c;
if (!checks.empty())
{
std::list<ExecutionPath *>::const_iterator it;
for (it = checks.begin(); it != checks.end(); ++it)
{
c.push_back((*it)->copy());
if ((*it)->varId != 0)
countif2.insert((*it)->varId);
} }
} }
checkExecutionPaths_(tok2, c);
while (!c.empty())
{
if (c.back()->varId == 0)
{
c.pop_back();
continue;
}
bool duplicate = false;
std::list<ExecutionPath *>::const_iterator it;
for (it = checks.begin(); it != checks.end(); ++it)
{
if (*(*it) == *c.back())
{
duplicate = true;
countif2.erase((*it)->varId);
break;
}
}
if (!duplicate)
newchecks.push_back(c.back());
c.pop_back();
}
// Add countif2 ids to countif.. countif.
countif.insert(countif2.begin(), countif2.end());
}
// Add newchecks to checks.. // Add newchecks to checks..
std::copy(newchecks.begin(), newchecks.end(), std::back_inserter(checks)); std::copy(newchecks.begin(), newchecks.end(), std::back_inserter(checks));
@ -196,7 +215,6 @@ static void checkExecutionPaths_(const Token *tok, std::list<ExecutionPath *> &c
} }
} }
} }
}
// for/while/switch/do .. bail out // for/while/switch/do .. bail out
if (Token::Match(tok, "for|while|switch|do")) if (Token::Match(tok, "for|while|switch|do"))
@ -336,47 +354,7 @@ static void checkExecutionPaths_(const Token *tok, std::list<ExecutionPath *> &c
} }
// Recursively check into the if .. // Recursively check into the if ..
{ parseIfSwitchBody(tok->next(), checks, newchecks, countif);
std::set<unsigned int> countif2;
std::list<ExecutionPath *> c;
if (!checks.empty())
{
std::list<ExecutionPath *>::const_iterator it;
for (it = checks.begin(); it != checks.end(); ++it)
{
c.push_back((*it)->copy());
if ((*it)->varId != 0)
countif2.insert((*it)->varId);
}
}
checkExecutionPaths_(tok->next(), c);
while (!c.empty())
{
if (c.back()->varId == 0)
{
c.pop_back();
continue;
}
bool duplicate = false;
std::list<ExecutionPath *>::const_iterator it;
for (it = checks.begin(); it != checks.end(); ++it)
{
if (*(*it) == *c.back())
{
duplicate = true;
countif2.erase((*it)->varId);
break;
}
}
if (!duplicate)
newchecks.push_back(c.back());
c.pop_back();
}
// Add countif2 ids to countif..
countif.insert(countif2.begin(), countif2.end());
}
// goto "}" // goto "}"
tok = tok->link(); tok = tok->link();

View File

@ -1754,6 +1754,21 @@ private:
" return i;\n" " return i;\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
// No segmentation fault
checkUninitVar("void a() try\n"
"{\n"
" {\n"
" while (1) {\n"
" switch (1) {\n"
" case 1: {\n"
" int i;\n"
" }\n"
" }\n"
" }\n"
" } catch (...) {\n"
" }\n"
"}\n");
} }
// arrays.. // arrays..