Fixed ticket #3148 (Analysis failed on "Modules/mathmodule.c")
Fix: Do not handle code when 'return' is inside a macro. This is valid also for 'switch' code inside a macro.
This commit is contained in:
parent
7436dd02ba
commit
8e90ad106c
|
@ -4908,11 +4908,21 @@ void Tokenizer::removeRedundantCodeAfterReturn()
|
||||||
{
|
{
|
||||||
unsigned int indentlevel = 0;
|
unsigned int indentlevel = 0;
|
||||||
unsigned int indentcase = 0;
|
unsigned int indentcase = 0;
|
||||||
unsigned int indentret = 0; //this is the indentation level when 'return ;' token is found;
|
unsigned int indentret = 0;
|
||||||
unsigned int indentswitch = 0;
|
unsigned int indentswitch = 0;
|
||||||
unsigned int indentlabel = 0;
|
unsigned int indentlabel = 0;
|
||||||
|
unsigned int roundbraces = 0;
|
||||||
for (Token *tok = _tokens; tok; tok = tok->next())
|
for (Token *tok = _tokens; tok; tok = tok->next())
|
||||||
{
|
{
|
||||||
|
if (tok->str() == "(")
|
||||||
|
++roundbraces;
|
||||||
|
else if (tok->str() == ")")
|
||||||
|
{
|
||||||
|
if (!roundbraces)
|
||||||
|
break; //too many ending round parenthesis
|
||||||
|
--roundbraces;
|
||||||
|
}
|
||||||
|
|
||||||
if (tok->str() == "{")
|
if (tok->str() == "{")
|
||||||
{
|
{
|
||||||
++indentlevel;
|
++indentlevel;
|
||||||
|
@ -4929,8 +4939,7 @@ void Tokenizer::removeRedundantCodeAfterReturn()
|
||||||
break;
|
break;
|
||||||
--indentlevel1;
|
--indentlevel1;
|
||||||
}
|
}
|
||||||
else if (Token::Match(tok2, "%var% : ;")
|
else if (Token::Match(tok2, "%var% : ;") && !Token::Match(tok2, "case!default"))
|
||||||
&& tok2->str()!="case" && tok2->str()!="default")
|
|
||||||
{
|
{
|
||||||
indentlabel = indentlevel1;
|
indentlabel = indentlevel1;
|
||||||
break;
|
break;
|
||||||
|
@ -4943,12 +4952,10 @@ void Tokenizer::removeRedundantCodeAfterReturn()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (tok->str() == "}")
|
else if (tok->str() == "}")
|
||||||
{
|
{
|
||||||
if (indentlevel == 0)
|
if (!indentlevel)
|
||||||
break; // break out - it seems the code is wrong
|
break; //too many closing parenthesis
|
||||||
//there's already a 'return ;' and more indentation!
|
|
||||||
if (indentret)
|
if (indentret)
|
||||||
{
|
{
|
||||||
if (!indentswitch || indentlevel > indentcase)
|
if (!indentswitch || indentlevel > indentcase)
|
||||||
|
@ -4990,26 +4997,44 @@ void Tokenizer::removeRedundantCodeAfterReturn()
|
||||||
{
|
{
|
||||||
if (tok->str() == "switch")
|
if (tok->str() == "switch")
|
||||||
{
|
{
|
||||||
if (indentlevel == 0)
|
if (!indentlevel)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Don't care about unpreprocessed macros part of code
|
||||||
|
if (roundbraces)
|
||||||
|
break;
|
||||||
|
|
||||||
|
unsigned int switchroundbraces = 0;
|
||||||
for (Token *tok2 = tok->next(); tok2; tok2 = tok2->next())
|
for (Token *tok2 = tok->next(); tok2; tok2 = tok2->next())
|
||||||
{
|
{
|
||||||
|
if (tok2->str() == "(")
|
||||||
|
++switchroundbraces;
|
||||||
|
else if (tok2->str() == ")")
|
||||||
|
{
|
||||||
|
if (!switchroundbraces)
|
||||||
|
break; //too many closing parenthesis
|
||||||
|
--switchroundbraces;
|
||||||
|
}
|
||||||
if (tok2->str() == "{")
|
if (tok2->str() == "{")
|
||||||
{
|
{
|
||||||
|
if (switchroundbraces)
|
||||||
|
{
|
||||||
|
tok = tok2->previous();
|
||||||
|
break; //too many opening parenthesis
|
||||||
|
}
|
||||||
tok = tok2;
|
tok = tok2;
|
||||||
++indentswitch;
|
++indentswitch;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (tok2->str() == "}")
|
else if (tok2->str() == "}")
|
||||||
break; //bad code
|
break; //it's not expected, hence it's bad code
|
||||||
}
|
}
|
||||||
if (!indentswitch)
|
if (!indentswitch)
|
||||||
break;
|
break;
|
||||||
++indentlevel;
|
++indentlevel;
|
||||||
indentcase = indentlevel;
|
indentcase = indentlevel;
|
||||||
}
|
}
|
||||||
else if (indentswitch
|
else if (indentswitch && Token::Match(tok, "case|default"))
|
||||||
&& (tok->str() == "case" || tok->str() == "default"))
|
|
||||||
{
|
{
|
||||||
if (indentlevel > indentcase)
|
if (indentlevel > indentcase)
|
||||||
{
|
{
|
||||||
|
@ -5017,7 +5042,7 @@ void Tokenizer::removeRedundantCodeAfterReturn()
|
||||||
}
|
}
|
||||||
for (Token *tok2 = tok->next(); tok2; tok2 = tok2->next())
|
for (Token *tok2 = tok->next(); tok2; tok2 = tok2->next())
|
||||||
{
|
{
|
||||||
if (tok2->str() == ":" || Token::Match(tok2, ": ;"))
|
if (Token::Match(tok2, ": ;| "))
|
||||||
{
|
{
|
||||||
if (indentlevel == indentcase)
|
if (indentlevel == indentcase)
|
||||||
{
|
{
|
||||||
|
@ -5026,25 +5051,40 @@ void Tokenizer::removeRedundantCodeAfterReturn()
|
||||||
tok = tok2;
|
tok = tok2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (tok2->str() == "}" || tok2->str() == "{")
|
else if (Token::Match(tok2, "[{}]"))
|
||||||
break; //bad code
|
break; //bad code
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (tok->str() == "return")
|
else if (tok->str()=="return")
|
||||||
{
|
{
|
||||||
if (indentlevel == 0)
|
if (!indentlevel)
|
||||||
break; // break out - never seen a 'return' not inside a scope;
|
break;
|
||||||
|
|
||||||
|
// Don't care about unpreprocessed macros part of code
|
||||||
|
if (roundbraces)
|
||||||
|
continue;
|
||||||
|
|
||||||
//catch the first ';' after the return
|
//catch the first ';' after the return
|
||||||
|
unsigned int returnroundbraces = 0;
|
||||||
for (Token *tok2 = tok->next(); tok2; tok2 = tok2->next())
|
for (Token *tok2 = tok->next(); tok2; tok2 = tok2->next())
|
||||||
{
|
{
|
||||||
if (tok2->str() == ";")
|
if (tok2->str() == "(")
|
||||||
|
++returnroundbraces;
|
||||||
|
else if (tok2->str() == ")")
|
||||||
{
|
{
|
||||||
|
if (!returnroundbraces)
|
||||||
|
break; //excessive closing parenthesis
|
||||||
|
--returnroundbraces;
|
||||||
|
}
|
||||||
|
else if (tok2->str() == ";")
|
||||||
|
{
|
||||||
|
if (returnroundbraces)
|
||||||
|
break; //excessive opening parenthesis
|
||||||
indentret = indentlevel;
|
indentret = indentlevel;
|
||||||
tok = tok2;
|
tok = tok2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (tok2->str() == "{" || tok2->str() == "}")
|
else if (Token::Match(tok2, "[{}]"))
|
||||||
break; //I think this is an error code...
|
break; //I think this is an error code...
|
||||||
}
|
}
|
||||||
if (!indentret)
|
if (!indentret)
|
||||||
|
@ -5055,7 +5095,7 @@ void Tokenizer::removeRedundantCodeAfterReturn()
|
||||||
{
|
{
|
||||||
if (!indentswitch || indentlevel > indentcase+1)
|
if (!indentswitch || indentlevel > indentcase+1)
|
||||||
{
|
{
|
||||||
if (indentlevel >= indentret && (!(Token::Match(tok, "%var% : ;")) || tok->str()=="case" || tok->str()=="default"))
|
if (indentlevel >= indentret && (!Token::Match(tok, "%var% : ;") || Token::Match(tok, "case|default")))
|
||||||
{
|
{
|
||||||
tok = tok->previous();
|
tok = tok->previous();
|
||||||
tok->deleteNext();
|
tok->deleteNext();
|
||||||
|
@ -5067,7 +5107,7 @@ void Tokenizer::removeRedundantCodeAfterReturn()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!(Token::Match(tok, "%var% : ;")) && tok -> str() != "case" && tok->str() != "default")
|
if (!Token::Match(tok, "%var% : ;") && !Token::Match(tok, "case|default"))
|
||||||
{
|
{
|
||||||
tok = tok->previous();
|
tok = tok->previous();
|
||||||
tok->deleteNext();
|
tok->deleteNext();
|
||||||
|
|
|
@ -358,7 +358,11 @@ private:
|
||||||
TEST_CASE(simplifyIfAddBraces); // ticket # 2739 (segmentation fault)
|
TEST_CASE(simplifyIfAddBraces); // ticket # 2739 (segmentation fault)
|
||||||
|
|
||||||
//remove redundant code after the 'return ;' statement
|
//remove redundant code after the 'return ;' statement
|
||||||
TEST_CASE(removeRedundantCodeAfterReturn);
|
TEST_CASE(removeRedundantCodeAfterReturn1);
|
||||||
|
TEST_CASE(removeRedundantCodeAfterReturn2);
|
||||||
|
TEST_CASE(removeRedundantCodeAfterReturn3);
|
||||||
|
TEST_CASE(removeRedundantCodeAfterReturn4);
|
||||||
|
TEST_CASE(removeRedundantCodeAfterReturn5);
|
||||||
|
|
||||||
TEST_CASE(platformWin32);
|
TEST_CASE(platformWin32);
|
||||||
TEST_CASE(platformWin32A);
|
TEST_CASE(platformWin32A);
|
||||||
|
@ -5922,7 +5926,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeRedundantCodeAfterReturn()
|
void removeRedundantCodeAfterReturn1()
|
||||||
{
|
{
|
||||||
ASSERT_EQUALS("void f ( ) { return ; }", tokenizeAndStringify("void f() { return; foo();}"));
|
ASSERT_EQUALS("void f ( ) { return ; }", tokenizeAndStringify("void f() { return; foo();}"));
|
||||||
ASSERT_EQUALS("void f ( int n ) { if ( n ) { return ; } foo ( ) ; }",tokenizeAndStringify("void f(int n) { if (n) return; foo();}"));
|
ASSERT_EQUALS("void f ( int n ) { if ( n ) { return ; } foo ( ) ; }",tokenizeAndStringify("void f(int n) { if (n) return; foo();}"));
|
||||||
|
@ -5931,58 +5935,67 @@ private:
|
||||||
tokenizeAndStringify("int f(int n) { switch (n) {case 0: return 0; n*=2; default: return n; n*=6;} return -1; foo();}"));
|
tokenizeAndStringify("int f(int n) { switch (n) {case 0: return 0; n*=2; default: return n; n*=6;} return -1; foo();}"));
|
||||||
//ticket #3132
|
//ticket #3132
|
||||||
ASSERT_EQUALS("void f ( int i ) { goto label ; switch ( i ) { label : ; return ; } }",tokenizeAndStringify("void f (int i) { goto label; switch(i) { label: return; } }"));
|
ASSERT_EQUALS("void f ( int i ) { goto label ; switch ( i ) { label : ; return ; } }",tokenizeAndStringify("void f (int i) { goto label; switch(i) { label: return; } }"));
|
||||||
|
//ticket #3148
|
||||||
|
ASSERT_EQUALS("void f ( ) { MACRO ( return 0 ) }",tokenizeAndStringify("void f() { MACRO(return NULL) }"));
|
||||||
|
ASSERT_EQUALS("void f ( ) { MACRO ( return ; , 0 ) }",tokenizeAndStringify("void f() { MACRO(return;, NULL) }"));
|
||||||
|
ASSERT_EQUALS("void f ( ) { MACRO ( bar1 , return 0 ) }",tokenizeAndStringify("void f() { MACRO(bar1, return NULL) }"));
|
||||||
|
ASSERT_EQUALS("void f ( ) { MACRO ( return ; bar2 , foo ) }",tokenizeAndStringify("void f() { MACRO(return; bar2, foo) }"));
|
||||||
|
}
|
||||||
|
|
||||||
{
|
void removeRedundantCodeAfterReturn2()
|
||||||
const char code[] = "void f(){ "
|
{
|
||||||
"if (k>0) goto label; "
|
const char code[] = "void f(){ "
|
||||||
"return; "
|
"if (k>0) goto label; "
|
||||||
"if (tnt) "
|
"return; "
|
||||||
" { "
|
"if (tnt) "
|
||||||
" { "
|
" { "
|
||||||
" check(); "
|
" { "
|
||||||
" k=0; "
|
" check(); "
|
||||||
" } "
|
" k=0; "
|
||||||
" label: "
|
" } "
|
||||||
" bar(); "
|
" label: "
|
||||||
" } "
|
" bar(); "
|
||||||
"}";
|
" } "
|
||||||
ASSERT_EQUALS("void f ( ) { if ( 0 < k ) { goto label ; } return ; { label : ; bar ( ) ; } }",simplifyKnownVariables(code));
|
"}";
|
||||||
}
|
ASSERT_EQUALS("void f ( ) { if ( 0 < k ) { goto label ; } return ; { label : ; bar ( ) ; } }",simplifyKnownVariables(code));
|
||||||
|
}
|
||||||
|
|
||||||
{
|
void removeRedundantCodeAfterReturn3()
|
||||||
const char code[] = "int f() { "
|
{
|
||||||
"switch (x) { case 1: return 1; bar(); tack; { ticak(); return; } return; "
|
const char code[] = "int f() { "
|
||||||
"case 2: return 2; { reere(); } tack(); "
|
"switch (x) { case 1: return 1; bar(); tack; { ticak(); return; } return; "
|
||||||
"switch(y) { case 1: return 0; case 2: return 7; } "
|
"case 2: return 2; { random(); } tack(); "
|
||||||
"return 2; } return 3; }";
|
"switch(y) { case 1: return 0; case 2: return 7; } "
|
||||||
ASSERT_EQUALS("int f ( ) { switch ( x ) { case 1 : return 1 ; case 2 : return 2 ; } return 3 ; }",simplifyKnownVariables(code));
|
"return 2; } return 3; }";
|
||||||
}
|
ASSERT_EQUALS("int f ( ) { switch ( x ) { case 1 : return 1 ; case 2 : return 2 ; } return 3 ; }",simplifyKnownVariables(code));
|
||||||
|
}
|
||||||
|
|
||||||
{
|
void removeRedundantCodeAfterReturn4()
|
||||||
const char code[] = "int f() {"
|
{
|
||||||
"switch (x) { case 1: return 1; bar(); tack; { ticak(); return; } return;"
|
const char code[] = "int f() {"
|
||||||
"case 2: switch(y) { case 1: return 0; bar2(); foo(); case 2: return 7; }"
|
"switch (x) { case 1: return 1; bar(); tack; { ticak(); return; } return;"
|
||||||
"return 2; } return 3; }";
|
"case 2: switch(y) { case 1: return 0; bar2(); foo(); case 2: return 7; }"
|
||||||
const char expected[] = "int f ( ) {"
|
"return 2; } return 3; }";
|
||||||
" switch ( x ) { case 1 : return 1 ;"
|
const char expected[] = "int f ( ) {"
|
||||||
" case 2 : switch ( y ) { case 1 : return 0 ; case 2 : return 7 ; }"
|
" switch ( x ) { case 1 : return 1 ;"
|
||||||
" return 2 ; } return 3 ; }";
|
" case 2 : switch ( y ) { case 1 : return 0 ; case 2 : return 7 ; }"
|
||||||
ASSERT_EQUALS(expected,simplifyKnownVariables(code));
|
" return 2 ; } return 3 ; }";
|
||||||
}
|
ASSERT_EQUALS(expected,simplifyKnownVariables(code));
|
||||||
//ticket #3146
|
}
|
||||||
{
|
|
||||||
const char code[] = "void foo () {"
|
void removeRedundantCodeAfterReturn5()
|
||||||
" switch (i) { case 0: switch (j) { case 0: return -1; }"
|
{
|
||||||
" case 1: switch (j) { case -1: return -1; }"
|
const char code[] = "void foo () {"
|
||||||
" case 2: switch (j) { case -2: return -1; }"
|
" switch (i) { case 0: switch (j) { case 0: return -1; }"
|
||||||
" case 3: if (blah6) return -1; break; } }";
|
" case 1: switch (j) { case -1: return -1; }"
|
||||||
const char expected[] = "void foo ( ) {"
|
" case 2: switch (j) { case -2: return -1; }"
|
||||||
" switch ( i ) { case 0 : switch ( j ) { case 0 : return -1 ; }"
|
" case 3: if (blah6) return -1; break; } }";
|
||||||
" case 1 : switch ( j ) { case -1 : return -1 ; }"
|
const char expected[] = "void foo ( ) {"
|
||||||
" case 2 : switch ( j ) { case -2 : return -1 ; }"
|
" switch ( i ) { case 0 : switch ( j ) { case 0 : return -1 ; }"
|
||||||
" case 3 : if ( blah6 ) { return -1 ; } break ; } }";
|
" case 1 : switch ( j ) { case -1 : return -1 ; }"
|
||||||
ASSERT_EQUALS(expected, simplifyKnownVariables(code));
|
" case 2 : switch ( j ) { case -2 : return -1 ; }"
|
||||||
}
|
" case 3 : if ( blah6 ) { return -1 ; } break ; } }";
|
||||||
|
ASSERT_EQUALS(expected, simplifyKnownVariables(code));
|
||||||
}
|
}
|
||||||
|
|
||||||
void platformWin32()
|
void platformWin32()
|
||||||
|
|
Loading…
Reference in New Issue