Tokenizer: Report unknown macro when argument list contains if/for/while/switch

This commit is contained in:
Daniel Marjamäki 2019-10-30 19:36:19 +01:00
parent 33d43808f7
commit b96a347914
3 changed files with 17 additions and 38 deletions

View File

@ -9270,12 +9270,20 @@ void Tokenizer::findGarbageCode() const
for (const Token *tok = tokens(); tok; tok = tok->next()) {
if (Token::Match(tok, "if|while|for|switch")) { // if|while|for|switch (EXPR) { ... }
if (tok->previous() && !Token::Match(tok->previous(), "%name%|:|;|{|}|(|)|,")) {
if (tok->previous() && !Token::Match(tok->previous(), "%name%|:|;|{|}|)")) {
if (Token::Match(tok->previous(), "[,(]")) {
const Token *prev = tok->previous();
while (prev && prev->str() != "(") {
if (prev->str() == ")")
prev = prev->link();
prev = prev->previous();
}
if (prev && Token::Match(prev->previous(), "%name% ("))
unknownMacroError(prev->previous());
}
if (!Token::simpleMatch(tok->tokAt(-2), "operator \"\" if"))
syntaxError(tok);
}
if (Token::Match(tok->previous(), "[(,]"))
continue;
if (!Token::Match(tok->next(), "( !!)"))
syntaxError(tok);
if (tok->str() != "for") {

View File

@ -66,7 +66,6 @@ private:
TEST_CASE(garbageCode10); // #6127
TEST_CASE(garbageCode12);
TEST_CASE(garbageCode13); // #2607
TEST_CASE(garbageCode14); // #5595
TEST_CASE(garbageCode15); // #5203
TEST_CASE(garbageCode16);
TEST_CASE(garbageCode17);
@ -486,10 +485,6 @@ private:
checkCode("struct C {} {} x");
}
void garbageCode14() {
checkCode("static f() { int i; int source[1] = { 1 }; for (i = 0; i < 4; i++) (u, if (y u.x e)) }"); // Garbage code
}
void garbageCode15() { // Ticket #5203
ASSERT_THROW(checkCode("int f ( int* r ) { { int s[2] ; f ( s ) ; if ( ) } }"), InternalError);
}
@ -1275,10 +1270,6 @@ private:
"}\n";
ASSERT_THROW(checkCode(code), InternalError);
// #6106
code = " f { int i ; b2 , [ ] ( for ( i = 0 ; ; ) ) }";
checkCode(code);
// 6122 survive garbage code
code = "; { int i ; for ( i = 0 ; = 123 ; ) - ; }";
ASSERT_THROW(checkCode(code), InternalError);

View File

@ -49,7 +49,6 @@ private:
TEST_CASE(tokenize1);
TEST_CASE(tokenize2);
TEST_CASE(tokenize3);
TEST_CASE(tokenize4);
TEST_CASE(tokenize5);
TEST_CASE(tokenize6); // array access. replace "*(p+1)" => "p[1]"
@ -123,7 +122,6 @@ private:
TEST_CASE(ifAddBraces5);
TEST_CASE(ifAddBraces7);
TEST_CASE(ifAddBraces9);
TEST_CASE(ifAddBraces10);
TEST_CASE(ifAddBraces11);
TEST_CASE(ifAddBraces12);
TEST_CASE(ifAddBraces13);
@ -573,20 +571,6 @@ private:
ASSERT_EQUALS("{ sizeof ( a ) , sizeof ( b ) }", tokenizeAndStringify(code));
}
void tokenize3() {
const char code[] = "void foo()\n"
"{\n"
" int i;\n"
" ABC(for(i=0;i<10;i++) x());\n"
"}";
ASSERT_EQUALS("void foo ( )\n"
"{\n"
"int i ;\n"
"ABC ( for ( i = 0 ; i < 10 ; i ++ ) x ( ) ) ;\n"
"}", tokenizeAndStringify(code));
ASSERT_EQUALS("", errout.str());
}
void tokenize4() {
const char code[] = "class foo\n"
"{\n"
@ -1267,13 +1251,6 @@ private:
ASSERT_EQUALS(expected, tokenizeAndStringify(code, true));
}
void ifAddBraces10() {
// ticket #1361
const char code[] = "{ DEBUG(if (x) y; else z); }";
const char expected[] = "{ DEBUG ( if ( x ) { y ; } else z ) ; }";
ASSERT_EQUALS(expected, tokenizeAndStringify(code, true));
}
void ifAddBraces11() {
const char code[] = "{ if (x) if (y) ; else ; }";
const char expected[] = "{ if ( x ) { if ( y ) { ; } else { ; } } }";
@ -7708,15 +7685,18 @@ private:
ASSERT_EQUALS("sizeof ( a ) > sizeof ( & main ) ;", tokenizeAndStringify("sizeof a > sizeof &main;"));
}
void findGarbageCode() { // Make sure the Tokenizer::findGarbageCode() does not have FPs
void findGarbageCode() { // Test Tokenizer::findGarbageCode()
// before if|for|while|switch
ASSERT_NO_THROW(tokenizeAndStringify("void f() { do switch (a) {} while (1); }"))
ASSERT_NO_THROW(tokenizeAndStringify("void f() { label: switch (a) {} }"));
ASSERT_NO_THROW(tokenizeAndStringify("void f() { UNKNOWN_MACRO if (a) {} }"))
ASSERT_NO_THROW(tokenizeAndStringify("void f() { []() -> int * {}; }"));
ASSERT_NO_THROW(tokenizeAndStringify("void f() { const char* var = \"1\" \"2\"; }"));
// TODO ASSERT_NO_THROW(tokenizeAndStringify("void f() { MACRO(switch); }"));
// TODO ASSERT_NO_THROW(tokenizeAndStringify("void f() { MACRO(x,switch); }"));
ASSERT_THROW(tokenizeAndStringify("void f() { MACRO(switch); }"), InternalError);
ASSERT_THROW(tokenizeAndStringify("void f() { MACRO(x,switch); }"), InternalError);
ASSERT_THROW(tokenizeAndStringify("void foo() { for_chain( if (!done) done = 1); }"), InternalError);
ASSERT_THROW(tokenizeAndStringify("void foo() { for_chain( a, b, if (!done) done = 1); }"), InternalError);
// after (expr)
ASSERT_NO_THROW(tokenizeAndStringify("void f() { switch (a) int b; }"));