Tokenizer: Improve syntax checking of switch,if,while
This commit is contained in:
parent
224e55780e
commit
ed4a47de45
|
@ -3469,6 +3469,20 @@ bool Tokenizer::simplifyTokenList1(const char FileName[])
|
|||
Token::simpleMatch(tok->linkAt(2), "} ;")) {
|
||||
syntaxError(tok);
|
||||
}
|
||||
|
||||
if (tok->str() == "switch") { // switch (EXPR) { ... }
|
||||
if (!Token::Match(tok->next(), "( !!)"))
|
||||
syntaxError(tok->next());
|
||||
if (!Token::simpleMatch(tok->linkAt(1),") {"))
|
||||
syntaxError(tok->linkAt(1));
|
||||
validateExpr(tok->next(), tok->linkAt(1));
|
||||
}
|
||||
|
||||
if (Token::Match(tok, "if|while")) {
|
||||
if (!Token::Match(tok->next(), "( !!)"))
|
||||
syntaxError(tok->next());
|
||||
validateExpr(tok->next(), tok->linkAt(1));
|
||||
}
|
||||
}
|
||||
|
||||
if (!simplifyAddBraces())
|
||||
|
@ -8175,6 +8189,29 @@ void Tokenizer::validate() const
|
|||
cppcheckError(lastTok);
|
||||
}
|
||||
|
||||
void Tokenizer::validateExpr(const Token *start, const Token *end)
|
||||
{
|
||||
std::set<std::string> controlFlowKeywords;
|
||||
controlFlowKeywords.insert("goto");
|
||||
controlFlowKeywords.insert("do");
|
||||
controlFlowKeywords.insert("if");
|
||||
controlFlowKeywords.insert("else");
|
||||
controlFlowKeywords.insert("for");
|
||||
controlFlowKeywords.insert("while");
|
||||
controlFlowKeywords.insert("switch");
|
||||
controlFlowKeywords.insert("break");
|
||||
controlFlowKeywords.insert("continue");
|
||||
controlFlowKeywords.insert("return");
|
||||
for (const Token *tok = start; tok != end; tok = tok->next()) {
|
||||
if (controlFlowKeywords.find(tok->str()) != controlFlowKeywords.end())
|
||||
syntaxError(tok);
|
||||
if (tok->str() == ";")
|
||||
syntaxError(tok);
|
||||
if (tok->str() == "{")
|
||||
tok = tok->link();
|
||||
}
|
||||
}
|
||||
|
||||
std::string Tokenizer::simplifyString(const std::string &source)
|
||||
{
|
||||
std::string str = source;
|
||||
|
|
|
@ -592,6 +592,9 @@ private:
|
|||
*/
|
||||
void validate() const;
|
||||
|
||||
/** Validate that expression is valid. If it's invalid a syntax error is reported. */
|
||||
void validateExpr(const Token *start, const Token *end);
|
||||
|
||||
/**
|
||||
* Remove __declspec()
|
||||
*/
|
||||
|
|
|
@ -246,7 +246,7 @@ private:
|
|||
// run alternate check first. It should only ensure stability - so we catch exceptions here.
|
||||
try {
|
||||
checkCodeInternal(code, alternatefilename);
|
||||
} catch (InternalError&) {
|
||||
} catch (const InternalError&) {
|
||||
}
|
||||
|
||||
return checkCodeInternal(code, filename);
|
||||
|
@ -451,7 +451,7 @@ private:
|
|||
}
|
||||
|
||||
void garbageCode15() { // Ticket #5203
|
||||
checkCode("int f ( int* r ) { { int s[2] ; f ( s ) ; if ( ) } }");
|
||||
ASSERT_THROW(checkCode("int f ( int* r ) { { int s[2] ; f ( s ) ; if ( ) } }"), InternalError);
|
||||
}
|
||||
|
||||
void garbageCode16() {
|
||||
|
@ -480,13 +480,13 @@ private:
|
|||
|
||||
void garbageCode21() {
|
||||
// Ticket #3486 - Don't crash garbage code
|
||||
checkCode("void f()\n"
|
||||
"{\n"
|
||||
" (\n"
|
||||
" x;\n"
|
||||
" int a, a2, a2*x; if () ;\n"
|
||||
" )\n"
|
||||
"}");
|
||||
ASSERT_THROW(checkCode("void f()\n"
|
||||
"{\n"
|
||||
" (\n"
|
||||
" x;\n"
|
||||
" int a, a2, a2*x; if () ;\n"
|
||||
" )\n"
|
||||
"}"), InternalError);
|
||||
}
|
||||
|
||||
void garbageCode22() {
|
||||
|
@ -765,7 +765,7 @@ private:
|
|||
}
|
||||
|
||||
void garbageCode76() { // #6754
|
||||
checkCode(" ( ) ( ) { ( ) [ ] } TEST ( ) { ( _broadcast_f32x4 ) ( ) ( ) ( ) ( ) if ( ) ( ) ; } E mask = ( ) [ ] ( ) res1.x =");
|
||||
ASSERT_THROW(checkCode(" ( ) ( ) { ( ) [ ] } TEST ( ) { ( _broadcast_f32x4 ) ( ) ( ) ( ) ( ) if ( ) ( ) ; } E mask = ( ) [ ] ( ) res1.x ="), InternalError);
|
||||
}
|
||||
|
||||
void garbageCode77() { // #6755
|
||||
|
|
|
@ -1538,9 +1538,6 @@ private:
|
|||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
// #2582 - segmentation fault
|
||||
check("if()");
|
||||
|
||||
// #2674 - different functions
|
||||
check("class Fred {\n"
|
||||
"public:\n"
|
||||
|
|
|
@ -3410,7 +3410,7 @@ private:
|
|||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
// make sure there are not "same expression" fp when there are different ({}) expressions
|
||||
check("void f(long x) { if (({ 1+2; }) == ({3+4};)) {} }");
|
||||
check("void f(long x) { if (({ 1+2; }) == ({3+4;})) {} }");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
// #5535: Reference named like its type
|
||||
|
|
|
@ -102,16 +102,14 @@ private:
|
|||
TEST_CASE(ifAddBraces3);
|
||||
TEST_CASE(ifAddBraces4);
|
||||
TEST_CASE(ifAddBraces5);
|
||||
TEST_CASE(ifAddBraces6);
|
||||
TEST_CASE(ifAddBraces7);
|
||||
TEST_CASE(ifAddBraces9);
|
||||
TEST_CASE(ifAddBraces10);
|
||||
TEST_CASE(ifAddBraces11);
|
||||
TEST_CASE(ifAddBraces12);
|
||||
TEST_CASE(ifAddBraces13);
|
||||
TEST_CASE(ifAddBraces14); // #2610 - segfault: if()<{}
|
||||
TEST_CASE(ifAddBraces15); // #2616 - unknown macro before if
|
||||
TEST_CASE(ifAddBraces16); // ticket # 2739 (segmentation fault)
|
||||
TEST_CASE(ifAddBraces16);
|
||||
TEST_CASE(ifAddBraces17); // '} else' should be in the same line
|
||||
TEST_CASE(ifAddBraces18); // #3424 - if if { } else else
|
||||
TEST_CASE(ifAddBraces19); // #3928 - if for if else
|
||||
|
@ -1096,11 +1094,6 @@ private:
|
|||
"}", tokenizeAndStringify(code, true));
|
||||
}
|
||||
|
||||
void ifAddBraces6() {
|
||||
const char code[] = "if()";
|
||||
ASSERT_EQUALS("if ( )", tokenizeAndStringify(code, true));
|
||||
}
|
||||
|
||||
void ifAddBraces7() {
|
||||
const char code[] = "void f()\n"
|
||||
"{\n"
|
||||
|
@ -1163,20 +1156,12 @@ private:
|
|||
ASSERT_EQUALS(expected2, tokenizeAndStringify(code2, true));
|
||||
}
|
||||
|
||||
void ifAddBraces14() {
|
||||
// ticket #2610 (segfault)
|
||||
tokenizeAndStringify("if()<{}", false);
|
||||
}
|
||||
|
||||
void ifAddBraces15() {
|
||||
// ticket #2616 - unknown macro before if
|
||||
ASSERT_EQUALS("{ A if ( x ) { y ( ) ; } }", tokenizeAndStringify("{A if(x)y();}", false));
|
||||
}
|
||||
|
||||
void ifAddBraces16() { // ticket # 2739 (segmentation fault)
|
||||
tokenizeAndStringify("if()x");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
void ifAddBraces16() {
|
||||
// ticket #2873 - the fix is not needed anymore.
|
||||
{
|
||||
const char code[] = "void f() { "
|
||||
|
|
|
@ -60,7 +60,6 @@ private:
|
|||
TEST_CASE(uninitvar2_while);
|
||||
TEST_CASE(uninitvar2_4494); // #4494
|
||||
TEST_CASE(uninitvar2_malloc); // malloc returns uninitialized data
|
||||
TEST_CASE(uninitvar7); // ticket #5971
|
||||
TEST_CASE(uninitvar8); // ticket #6230
|
||||
TEST_CASE(uninitvar9); // ticket #6424
|
||||
TEST_CASE(uninitvar_unconditionalTry);
|
||||
|
@ -2576,18 +2575,6 @@ private:
|
|||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void uninitvar7() {
|
||||
const char code[] = "void eDBauth_user() {\n"
|
||||
" char *blid_cert;\n"
|
||||
" if( ) {\n"
|
||||
" blid_cert = ;\n"
|
||||
" } \n"
|
||||
"}\n";
|
||||
|
||||
// Assume dfs is a non POD type if file is C++
|
||||
checkUninitVar(code, "test.cpp");
|
||||
}
|
||||
|
||||
void uninitvar8() {
|
||||
const char code[] = "struct Fred {\n"
|
||||
" void Sync(dsmp_t& type, int& len, int limit = 123);\n"
|
||||
|
|
Loading…
Reference in New Issue