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 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 indentlabel = 0;
|
||||
unsigned int roundbraces = 0;
|
||||
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() == "{")
|
||||
{
|
||||
++indentlevel;
|
||||
|
@ -4929,8 +4939,7 @@ void Tokenizer::removeRedundantCodeAfterReturn()
|
|||
break;
|
||||
--indentlevel1;
|
||||
}
|
||||
else if (Token::Match(tok2, "%var% : ;")
|
||||
&& tok2->str()!="case" && tok2->str()!="default")
|
||||
else if (Token::Match(tok2, "%var% : ;") && !Token::Match(tok2, "case!default"))
|
||||
{
|
||||
indentlabel = indentlevel1;
|
||||
break;
|
||||
|
@ -4943,12 +4952,10 @@ void Tokenizer::removeRedundantCodeAfterReturn()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (tok->str() == "}")
|
||||
{
|
||||
if (indentlevel == 0)
|
||||
break; // break out - it seems the code is wrong
|
||||
//there's already a 'return ;' and more indentation!
|
||||
if (!indentlevel)
|
||||
break; //too many closing parenthesis
|
||||
if (indentret)
|
||||
{
|
||||
if (!indentswitch || indentlevel > indentcase)
|
||||
|
@ -4990,26 +4997,44 @@ void Tokenizer::removeRedundantCodeAfterReturn()
|
|||
{
|
||||
if (tok->str() == "switch")
|
||||
{
|
||||
if (indentlevel == 0)
|
||||
if (!indentlevel)
|
||||
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())
|
||||
{
|
||||
if (tok2->str() == "(")
|
||||
++switchroundbraces;
|
||||
else if (tok2->str() == ")")
|
||||
{
|
||||
if (!switchroundbraces)
|
||||
break; //too many closing parenthesis
|
||||
--switchroundbraces;
|
||||
}
|
||||
if (tok2->str() == "{")
|
||||
{
|
||||
if (switchroundbraces)
|
||||
{
|
||||
tok = tok2->previous();
|
||||
break; //too many opening parenthesis
|
||||
}
|
||||
tok = tok2;
|
||||
++indentswitch;
|
||||
break;
|
||||
}
|
||||
else if (tok2->str() == "}")
|
||||
break; //bad code
|
||||
break; //it's not expected, hence it's bad code
|
||||
}
|
||||
if (!indentswitch)
|
||||
break;
|
||||
++indentlevel;
|
||||
indentcase = indentlevel;
|
||||
}
|
||||
else if (indentswitch
|
||||
&& (tok->str() == "case" || tok->str() == "default"))
|
||||
else if (indentswitch && Token::Match(tok, "case|default"))
|
||||
{
|
||||
if (indentlevel > indentcase)
|
||||
{
|
||||
|
@ -5017,7 +5042,7 @@ void Tokenizer::removeRedundantCodeAfterReturn()
|
|||
}
|
||||
for (Token *tok2 = tok->next(); tok2; tok2 = tok2->next())
|
||||
{
|
||||
if (tok2->str() == ":" || Token::Match(tok2, ": ;"))
|
||||
if (Token::Match(tok2, ": ;| "))
|
||||
{
|
||||
if (indentlevel == indentcase)
|
||||
{
|
||||
|
@ -5026,25 +5051,40 @@ void Tokenizer::removeRedundantCodeAfterReturn()
|
|||
tok = tok2;
|
||||
break;
|
||||
}
|
||||
else if (tok2->str() == "}" || tok2->str() == "{")
|
||||
else if (Token::Match(tok2, "[{}]"))
|
||||
break; //bad code
|
||||
}
|
||||
}
|
||||
else if (tok->str() == "return")
|
||||
else if (tok->str()=="return")
|
||||
{
|
||||
if (indentlevel == 0)
|
||||
break; // break out - never seen a 'return' not inside a scope;
|
||||
if (!indentlevel)
|
||||
break;
|
||||
|
||||
// Don't care about unpreprocessed macros part of code
|
||||
if (roundbraces)
|
||||
continue;
|
||||
|
||||
//catch the first ';' after the return
|
||||
unsigned int returnroundbraces = 0;
|
||||
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;
|
||||
tok = tok2;
|
||||
break;
|
||||
}
|
||||
else if (tok2->str() == "{" || tok2->str() == "}")
|
||||
else if (Token::Match(tok2, "[{}]"))
|
||||
break; //I think this is an error code...
|
||||
}
|
||||
if (!indentret)
|
||||
|
@ -5055,7 +5095,7 @@ void Tokenizer::removeRedundantCodeAfterReturn()
|
|||
{
|
||||
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->deleteNext();
|
||||
|
@ -5067,7 +5107,7 @@ void Tokenizer::removeRedundantCodeAfterReturn()
|
|||
}
|
||||
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->deleteNext();
|
||||
|
|
|
@ -358,7 +358,11 @@ private:
|
|||
TEST_CASE(simplifyIfAddBraces); // ticket # 2739 (segmentation fault)
|
||||
|
||||
//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(platformWin32A);
|
||||
|
@ -5922,7 +5926,7 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
void removeRedundantCodeAfterReturn()
|
||||
void removeRedundantCodeAfterReturn1()
|
||||
{
|
||||
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();}"));
|
||||
|
@ -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();}"));
|
||||
//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; } }"));
|
||||
//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) }"));
|
||||
}
|
||||
|
||||
{
|
||||
const char code[] = "void f(){ "
|
||||
"if (k>0) goto label; "
|
||||
"return; "
|
||||
"if (tnt) "
|
||||
" { "
|
||||
" { "
|
||||
" check(); "
|
||||
" k=0; "
|
||||
" } "
|
||||
" label: "
|
||||
" bar(); "
|
||||
" } "
|
||||
"}";
|
||||
ASSERT_EQUALS("void f ( ) { if ( 0 < k ) { goto label ; } return ; { label : ; bar ( ) ; } }",simplifyKnownVariables(code));
|
||||
}
|
||||
void removeRedundantCodeAfterReturn2()
|
||||
{
|
||||
const char code[] = "void f(){ "
|
||||
"if (k>0) goto label; "
|
||||
"return; "
|
||||
"if (tnt) "
|
||||
" { "
|
||||
" { "
|
||||
" check(); "
|
||||
" k=0; "
|
||||
" } "
|
||||
" label: "
|
||||
" bar(); "
|
||||
" } "
|
||||
"}";
|
||||
ASSERT_EQUALS("void f ( ) { if ( 0 < k ) { goto label ; } return ; { label : ; bar ( ) ; } }",simplifyKnownVariables(code));
|
||||
}
|
||||
|
||||
{
|
||||
const char code[] = "int f() { "
|
||||
"switch (x) { case 1: return 1; bar(); tack; { ticak(); return; } return; "
|
||||
"case 2: return 2; { reere(); } tack(); "
|
||||
"switch(y) { case 1: return 0; case 2: return 7; } "
|
||||
"return 2; } return 3; }";
|
||||
ASSERT_EQUALS("int f ( ) { switch ( x ) { case 1 : return 1 ; case 2 : return 2 ; } return 3 ; }",simplifyKnownVariables(code));
|
||||
}
|
||||
void removeRedundantCodeAfterReturn3()
|
||||
{
|
||||
const char code[] = "int f() { "
|
||||
"switch (x) { case 1: return 1; bar(); tack; { ticak(); return; } return; "
|
||||
"case 2: return 2; { random(); } tack(); "
|
||||
"switch(y) { case 1: return 0; case 2: return 7; } "
|
||||
"return 2; } return 3; }";
|
||||
ASSERT_EQUALS("int f ( ) { switch ( x ) { case 1 : return 1 ; case 2 : return 2 ; } return 3 ; }",simplifyKnownVariables(code));
|
||||
}
|
||||
|
||||
{
|
||||
const char code[] = "int f() {"
|
||||
"switch (x) { case 1: return 1; bar(); tack; { ticak(); return; } return;"
|
||||
"case 2: switch(y) { case 1: return 0; bar2(); foo(); case 2: return 7; }"
|
||||
"return 2; } return 3; }";
|
||||
const char expected[] = "int f ( ) {"
|
||||
" switch ( x ) { case 1 : return 1 ;"
|
||||
" case 2 : switch ( y ) { case 1 : return 0 ; case 2 : return 7 ; }"
|
||||
" return 2 ; } return 3 ; }";
|
||||
ASSERT_EQUALS(expected,simplifyKnownVariables(code));
|
||||
}
|
||||
//ticket #3146
|
||||
{
|
||||
const char code[] = "void foo () {"
|
||||
" switch (i) { case 0: switch (j) { case 0: return -1; }"
|
||||
" case 1: switch (j) { case -1: return -1; }"
|
||||
" case 2: switch (j) { case -2: return -1; }"
|
||||
" case 3: if (blah6) return -1; break; } }";
|
||||
const char expected[] = "void foo ( ) {"
|
||||
" switch ( i ) { case 0 : switch ( j ) { case 0 : return -1 ; }"
|
||||
" case 1 : switch ( j ) { case -1 : return -1 ; }"
|
||||
" case 2 : switch ( j ) { case -2 : return -1 ; }"
|
||||
" case 3 : if ( blah6 ) { return -1 ; } break ; } }";
|
||||
ASSERT_EQUALS(expected, simplifyKnownVariables(code));
|
||||
}
|
||||
void removeRedundantCodeAfterReturn4()
|
||||
{
|
||||
const char code[] = "int f() {"
|
||||
"switch (x) { case 1: return 1; bar(); tack; { ticak(); return; } return;"
|
||||
"case 2: switch(y) { case 1: return 0; bar2(); foo(); case 2: return 7; }"
|
||||
"return 2; } return 3; }";
|
||||
const char expected[] = "int f ( ) {"
|
||||
" switch ( x ) { case 1 : return 1 ;"
|
||||
" case 2 : switch ( y ) { case 1 : return 0 ; case 2 : return 7 ; }"
|
||||
" return 2 ; } return 3 ; }";
|
||||
ASSERT_EQUALS(expected,simplifyKnownVariables(code));
|
||||
}
|
||||
|
||||
void removeRedundantCodeAfterReturn5()
|
||||
{
|
||||
const char code[] = "void foo () {"
|
||||
" switch (i) { case 0: switch (j) { case 0: return -1; }"
|
||||
" case 1: switch (j) { case -1: return -1; }"
|
||||
" case 2: switch (j) { case -2: return -1; }"
|
||||
" case 3: if (blah6) return -1; break; } }";
|
||||
const char expected[] = "void foo ( ) {"
|
||||
" switch ( i ) { case 0 : switch ( j ) { case 0 : return -1 ; }"
|
||||
" case 1 : switch ( j ) { case -1 : return -1 ; }"
|
||||
" case 2 : switch ( j ) { case -2 : return -1 ; }"
|
||||
" case 3 : if ( blah6 ) { return -1 ; } break ; } }";
|
||||
ASSERT_EQUALS(expected, simplifyKnownVariables(code));
|
||||
}
|
||||
|
||||
void platformWin32()
|
||||
|
|
Loading…
Reference in New Issue