CheckUninitVar: Assertion for '} while (' after 'do {..' in debug builds. Bail out in release builds to avoid segfaults.
This commit is contained in:
parent
09f4d3732a
commit
2a1af1acda
|
@ -1349,8 +1349,20 @@ bool CheckUninitVar::checkScopeForVariable(const Scope* scope, const Token *tok,
|
||||||
tok = tok2->link();
|
tok = tok2->link();
|
||||||
|
|
||||||
// do-while => goto ")"
|
// do-while => goto ")"
|
||||||
if (!forwhile)
|
if (!forwhile) {
|
||||||
|
// Assert that the tokens are '} while ('
|
||||||
|
if (testrunner && !Token::simpleMatch(tok, "} while ("))
|
||||||
|
reportError(tok,Severity::debug,"","assertion failed '} while ('");
|
||||||
|
else
|
||||||
|
assert(Token::simpleMatch(tok, "} while ("));
|
||||||
|
|
||||||
|
// Goto ')'
|
||||||
tok = tok->linkAt(2);
|
tok = tok->linkAt(2);
|
||||||
|
|
||||||
|
if (!tok)
|
||||||
|
// bailout : invalid code / bad tokenizer
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,12 +39,12 @@ class Variable;
|
||||||
class CPPCHECKLIB CheckUninitVar : public Check {
|
class CPPCHECKLIB CheckUninitVar : public Check {
|
||||||
public:
|
public:
|
||||||
/** @brief This constructor is used when registering the CheckUninitVar */
|
/** @brief This constructor is used when registering the CheckUninitVar */
|
||||||
CheckUninitVar() : Check(myName())
|
CheckUninitVar() : Check(myName()), testrunner(false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
/** @brief This constructor is used when running checks. */
|
/** @brief This constructor is used when running checks. */
|
||||||
CheckUninitVar(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
CheckUninitVar(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
||||||
: Check(myName(), tokenizer, settings, errorLogger)
|
: Check(myName(), tokenizer, settings, errorLogger), testrunner(false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
/** @brief Run checks against the simplified token list */
|
/** @brief Run checks against the simplified token list */
|
||||||
|
@ -83,6 +83,9 @@ public:
|
||||||
void uninitvarError(const Token *tok, const std::string &varname);
|
void uninitvarError(const Token *tok, const std::string &varname);
|
||||||
void uninitStructMemberError(const Token *tok, const std::string &membername);
|
void uninitStructMemberError(const Token *tok, const std::string &membername);
|
||||||
|
|
||||||
|
/** testrunner: (don't abort() when assertion fails, just write error message) */
|
||||||
|
bool testrunner;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
|
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
|
||||||
CheckUninitVar c(0, settings, errorLogger);
|
CheckUninitVar c(0, settings, errorLogger);
|
||||||
|
|
|
@ -1970,6 +1970,7 @@ private:
|
||||||
|
|
||||||
// Check for redundant code..
|
// Check for redundant code..
|
||||||
CheckUninitVar checkuninitvar(&tokenizer, &settings, this);
|
CheckUninitVar checkuninitvar(&tokenizer, &settings, this);
|
||||||
|
checkuninitvar.testrunner = true;
|
||||||
checkuninitvar.check();
|
checkuninitvar.check();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2873,6 +2874,13 @@ private:
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: x\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: x\n", errout.str());
|
||||||
|
|
||||||
|
checkUninitVar2("void f() {\n" // #4911 - bad simplification => don't crash
|
||||||
|
" int a;\n"
|
||||||
|
" do { } a=do_something(); while (a);\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n"
|
||||||
|
"[test.cpp:3]: (debug) assertion failed '} while ('\n", errout.str());
|
||||||
|
|
||||||
checkUninitVar2("void f() {\n"
|
checkUninitVar2("void f() {\n"
|
||||||
" int x;\n"
|
" int x;\n"
|
||||||
" while (a) {\n"
|
" while (a) {\n"
|
||||||
|
|
Loading…
Reference in New Issue