Tokenizer: Improve syntax checking of switch,if,while

This commit is contained in:
Daniel Marjamäki 2016-07-22 16:54:24 +02:00
parent 224e55780e
commit ed4a47de45
7 changed files with 53 additions and 44 deletions

View File

@ -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;

View File

@ -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()
*/

View File

@ -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

View File

@ -1538,9 +1538,6 @@ private:
"}");
ASSERT_EQUALS("", errout.str());
// #2582 - segmentation fault
check("if()");
// #2674 - different functions
check("class Fred {\n"
"public:\n"

View File

@ -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

View File

@ -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() { "

View File

@ -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"