Fixed #1975 (segmentation fault of cppcheck)
This commit is contained in:
parent
190a0040b7
commit
427c0f4bfd
|
@ -919,7 +919,7 @@ std::list<std::string> Preprocessor::getcfgs(const std::string &filedata, const
|
||||||
{
|
{
|
||||||
Tokenizer tokenizer(_settings, _errorLogger);
|
Tokenizer tokenizer(_settings, _errorLogger);
|
||||||
std::istringstream tempIstr(s.c_str());
|
std::istringstream tempIstr(s.c_str());
|
||||||
if (!tokenizer.tokenize(tempIstr, filename.c_str()))
|
if (!tokenizer.tokenize(tempIstr, filename.c_str(), "", true))
|
||||||
{
|
{
|
||||||
std::ostringstream lineStream;
|
std::ostringstream lineStream;
|
||||||
lineStream << __LINE__;
|
lineStream << __LINE__;
|
||||||
|
@ -1053,7 +1053,7 @@ void Preprocessor::simplifyCondition(const std::map<std::string, std::string> &v
|
||||||
{
|
{
|
||||||
Tokenizer tokenizer;
|
Tokenizer tokenizer;
|
||||||
std::istringstream istr(("(" + condition + ")").c_str());
|
std::istringstream istr(("(" + condition + ")").c_str());
|
||||||
tokenizer.tokenize(istr, "");
|
tokenizer.tokenize(istr, "", "", true);
|
||||||
|
|
||||||
if (Token::Match(tokenizer.tokens(), "( %var% )"))
|
if (Token::Match(tokenizer.tokens(), "( %var% )"))
|
||||||
{
|
{
|
||||||
|
|
184
lib/tokenize.cpp
184
lib/tokenize.cpp
|
@ -1695,7 +1695,10 @@ void Tokenizer::simplifyTypedef()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Tokenizer::tokenize(std::istream &code, const char FileName[], const std::string &configuration)
|
bool Tokenizer::tokenize(std::istream &code,
|
||||||
|
const char FileName[],
|
||||||
|
const std::string &configuration,
|
||||||
|
const bool preprocessorCondition)
|
||||||
{
|
{
|
||||||
_configuration = configuration;
|
_configuration = configuration;
|
||||||
|
|
||||||
|
@ -1704,7 +1707,6 @@ bool Tokenizer::tokenize(std::istream &code, const char FileName[], const std::s
|
||||||
|
|
||||||
createTokens(code);
|
createTokens(code);
|
||||||
|
|
||||||
|
|
||||||
// remove inline SQL (Oracle PRO*C). Ticket: #1959
|
// remove inline SQL (Oracle PRO*C). Ticket: #1959
|
||||||
for (Token *tok = _tokens; tok; tok = tok->next())
|
for (Token *tok = _tokens; tok; tok = tok->next())
|
||||||
{
|
{
|
||||||
|
@ -1816,105 +1818,108 @@ bool Tokenizer::tokenize(std::istream &code, const char FileName[], const std::s
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for more complicated syntax errors when using templates..
|
// check for more complicated syntax errors when using templates..
|
||||||
for (const Token *tok = _tokens; tok; tok = tok->next())
|
if (!preprocessorCondition)
|
||||||
{
|
{
|
||||||
// skip executing scopes..
|
for (const Token *tok = _tokens; tok; tok = tok->next())
|
||||||
if (Token::Match(tok, ") const| {"))
|
|
||||||
{
|
{
|
||||||
while (tok->str() != "{")
|
// skip executing scopes..
|
||||||
|
if (Token::Match(tok, ") const| {"))
|
||||||
|
{
|
||||||
|
while (tok->str() != "{")
|
||||||
|
tok = tok->next();
|
||||||
|
tok = tok->link();
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip executing scopes (ticket #1984)..
|
||||||
|
if (Token::simpleMatch(tok, "; {"))
|
||||||
|
{
|
||||||
|
tok = tok->next()->link();
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip executing scopes (ticket #1985)..
|
||||||
|
if (Token::simpleMatch(tok, "try {"))
|
||||||
|
{
|
||||||
|
tok = tok->next()->link();
|
||||||
|
while (Token::simpleMatch(tok, "} catch ("))
|
||||||
|
{
|
||||||
|
tok = tok->tokAt(2)->link();
|
||||||
|
if (Token::simpleMatch(tok, ") {"))
|
||||||
|
tok = tok->next()->link();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// not start of statement?
|
||||||
|
if (tok->previous() && !Token::Match(tok, "[;{}]"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// skip starting tokens.. ;;; typedef typename foo::bar::..
|
||||||
|
while (Token::Match(tok, "[;{}]"))
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
tok = tok->link();
|
while (Token::Match(tok, "typedef|typename"))
|
||||||
}
|
tok = tok->next();
|
||||||
|
while (Token::Match(tok, "%type% ::"))
|
||||||
|
tok = tok->tokAt(2);
|
||||||
|
if (!tok)
|
||||||
|
break;
|
||||||
|
|
||||||
// skip executing scopes (ticket #1984)..
|
// template variable or type..
|
||||||
if (Token::simpleMatch(tok, "; {"))
|
if (Token::Match(tok, "%type% <"))
|
||||||
{
|
|
||||||
tok = tok->next()->link();
|
|
||||||
}
|
|
||||||
|
|
||||||
// skip executing scopes (ticket #1985)..
|
|
||||||
if (Token::simpleMatch(tok, "try {"))
|
|
||||||
{
|
|
||||||
tok = tok->next()->link();
|
|
||||||
while (Token::simpleMatch(tok, "} catch ("))
|
|
||||||
{
|
{
|
||||||
tok = tok->tokAt(2)->link();
|
// these are used types..
|
||||||
if (Token::simpleMatch(tok, ") {"))
|
std::set<std::string> usedtypes;
|
||||||
tok = tok->next()->link();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// not start of statement?
|
// parse this statement and see if the '<' and '>' are matching
|
||||||
if (tok->previous() && !Token::Match(tok, "[;{}]"))
|
unsigned int level = 0;
|
||||||
continue;
|
for (const Token *tok2 = tok; tok2 && !Token::Match(tok2, "[;{}]"); tok2 = tok2->next())
|
||||||
|
|
||||||
// skip starting tokens.. ;;; typedef typename foo::bar::..
|
|
||||||
while (Token::Match(tok, "[;{}]"))
|
|
||||||
tok = tok->next();
|
|
||||||
while (Token::Match(tok, "typedef|typename"))
|
|
||||||
tok = tok->next();
|
|
||||||
while (Token::Match(tok, "%type% ::"))
|
|
||||||
tok = tok->tokAt(2);
|
|
||||||
if (!tok)
|
|
||||||
break;
|
|
||||||
|
|
||||||
// template variable or type..
|
|
||||||
if (Token::Match(tok, "%type% <"))
|
|
||||||
{
|
|
||||||
// these are used types..
|
|
||||||
std::set<std::string> usedtypes;
|
|
||||||
|
|
||||||
// parse this statement and see if the '<' and '>' are matching
|
|
||||||
unsigned int level = 0;
|
|
||||||
for (const Token *tok2 = tok; tok2 && !Token::Match(tok2, "[;{}]"); tok2 = tok2->next())
|
|
||||||
{
|
|
||||||
if (tok2->str() == "(")
|
|
||||||
tok2 = tok2->link();
|
|
||||||
else if (tok2->str() == "<")
|
|
||||||
{
|
{
|
||||||
bool inclevel = false;
|
if (tok2->str() == "(")
|
||||||
if (Token::simpleMatch(tok2->previous(), "operator <"))
|
tok2 = tok2->link();
|
||||||
;
|
else if (tok2->str() == "<")
|
||||||
else if (level == 0)
|
|
||||||
inclevel = true;
|
|
||||||
else if (tok2->next()->isStandardType())
|
|
||||||
inclevel = true;
|
|
||||||
else if (Token::simpleMatch(tok2, "< typename"))
|
|
||||||
inclevel = true;
|
|
||||||
else if (Token::Match(tok2->tokAt(-2), "<|, %type% <") && usedtypes.find(tok2->strAt(-1)) != usedtypes.end())
|
|
||||||
inclevel = true;
|
|
||||||
else if (Token::Match(tok2, "< %type%") && usedtypes.find(tok2->strAt(1)) != usedtypes.end())
|
|
||||||
inclevel = true;
|
|
||||||
else if (Token::Match(tok2, "< %type%"))
|
|
||||||
{
|
{
|
||||||
// is the next token a type and not a variable/constant?
|
bool inclevel = false;
|
||||||
// assume it's a type if there comes another "<"
|
if (Token::simpleMatch(tok2->previous(), "operator <"))
|
||||||
const Token *tok3 = tok2->next();
|
;
|
||||||
while (Token::Match(tok3, "%type% ::"))
|
else if (level == 0)
|
||||||
tok3 = tok3->tokAt(2);
|
|
||||||
if (Token::Match(tok3, "%type% <"))
|
|
||||||
inclevel = true;
|
inclevel = true;
|
||||||
}
|
else if (tok2->next()->isStandardType())
|
||||||
|
inclevel = true;
|
||||||
|
else if (Token::simpleMatch(tok2, "< typename"))
|
||||||
|
inclevel = true;
|
||||||
|
else if (Token::Match(tok2->tokAt(-2), "<|, %type% <") && usedtypes.find(tok2->strAt(-1)) != usedtypes.end())
|
||||||
|
inclevel = true;
|
||||||
|
else if (Token::Match(tok2, "< %type%") && usedtypes.find(tok2->strAt(1)) != usedtypes.end())
|
||||||
|
inclevel = true;
|
||||||
|
else if (Token::Match(tok2, "< %type%"))
|
||||||
|
{
|
||||||
|
// is the next token a type and not a variable/constant?
|
||||||
|
// assume it's a type if there comes another "<"
|
||||||
|
const Token *tok3 = tok2->next();
|
||||||
|
while (Token::Match(tok3, "%type% ::"))
|
||||||
|
tok3 = tok3->tokAt(2);
|
||||||
|
if (Token::Match(tok3, "%type% <"))
|
||||||
|
inclevel = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (inclevel)
|
if (inclevel)
|
||||||
|
{
|
||||||
|
++level;
|
||||||
|
if (Token::Match(tok2->tokAt(-2), "<|, %type% <"))
|
||||||
|
usedtypes.insert(tok2->strAt(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (tok2->str() == ">")
|
||||||
{
|
{
|
||||||
++level;
|
if (level > 0)
|
||||||
if (Token::Match(tok2->tokAt(-2), "<|, %type% <"))
|
--level;
|
||||||
usedtypes.insert(tok2->strAt(-1));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (tok2->str() == ">")
|
if (level > 0)
|
||||||
{
|
{
|
||||||
if (level > 0)
|
syntaxError(tok);
|
||||||
--level;
|
deallocateTokens();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (level > 0)
|
|
||||||
{
|
|
||||||
syntaxError(tok);
|
|
||||||
deallocateTokens();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2050,10 +2055,13 @@ bool Tokenizer::tokenize(std::istream &code, const char FileName[], const std::s
|
||||||
// Change initialisation of variable to assignment
|
// Change initialisation of variable to assignment
|
||||||
simplifyInitVar();
|
simplifyInitVar();
|
||||||
|
|
||||||
setVarId();
|
if (!preprocessorCondition)
|
||||||
|
{
|
||||||
|
setVarId();
|
||||||
|
|
||||||
// Change initialisation of variable to assignment
|
// Change initialisation of variable to assignment
|
||||||
simplifyInitVar();
|
simplifyInitVar();
|
||||||
|
}
|
||||||
|
|
||||||
_tokens->assignProgressValues();
|
_tokens->assignProgressValues();
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,10 @@ public:
|
||||||
* @param configuration E.g. "A" for code where "#ifdef A" is true
|
* @param configuration E.g. "A" for code where "#ifdef A" is true
|
||||||
* @return false if Source code contains syntax errors
|
* @return false if Source code contains syntax errors
|
||||||
*/
|
*/
|
||||||
bool tokenize(std::istream &code, const char FileName[], const std::string &configuration = "");
|
bool tokenize(std::istream &code,
|
||||||
|
const char FileName[],
|
||||||
|
const std::string &configuration = "",
|
||||||
|
const bool preprocessorCondition = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create tokens from code.
|
* Create tokens from code.
|
||||||
|
|
|
@ -110,6 +110,7 @@ private:
|
||||||
TEST_CASE(if_cond8);
|
TEST_CASE(if_cond8);
|
||||||
TEST_CASE(if_cond9);
|
TEST_CASE(if_cond9);
|
||||||
TEST_CASE(if_cond10);
|
TEST_CASE(if_cond10);
|
||||||
|
TEST_CASE(if_cond11);
|
||||||
|
|
||||||
TEST_CASE(if_or_1);
|
TEST_CASE(if_or_1);
|
||||||
TEST_CASE(if_or_2);
|
TEST_CASE(if_or_2);
|
||||||
|
@ -1067,6 +1068,22 @@ private:
|
||||||
preprocessor.preprocess(istr, actual, "file.c");
|
preprocessor.preprocess(istr, actual, "file.c");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void if_cond11()
|
||||||
|
{
|
||||||
|
errout.str("");
|
||||||
|
const char filedata[] = "#if defined(L_fixunssfdi) && LIBGCC2_HAS_SF_MODE\n"
|
||||||
|
"#if LIBGCC2_HAS_DF_MODE\n"
|
||||||
|
"#elif FLT_MANT_DIG < W_TYPE_SIZE\n"
|
||||||
|
"#endif\n"
|
||||||
|
"#endif\n";
|
||||||
|
std::istringstream istr(filedata);
|
||||||
|
std::map<std::string, std::string> actual;
|
||||||
|
Settings settings;
|
||||||
|
Preprocessor preprocessor(&settings, this);
|
||||||
|
preprocessor.preprocess(istr, actual, "file.c");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void if_or_1()
|
void if_or_1()
|
||||||
|
|
Loading…
Reference in New Issue