Fixed ticket #3229 (Segfault with goto):

Don't handle labels, gotos, returns and indentations inside the round braces. This is applied not only for simplifyGoto, but also to simplifyFlowControl.
Rewrite enum badly handled by astyle inside mathlib.cpp and move simplifyFlowControl at the end of the simplifyTokenList in order to catch more dead code, not related to the ticket.
This commit is contained in:
Edoardo Prezioso 2011-10-18 23:56:35 +02:00
parent dc15641954
commit f4cdf57955
3 changed files with 73 additions and 41 deletions

View File

@ -115,10 +115,10 @@ bool MathLib::isInt(const std::string & s)
// prechecking has nothing found,...
// gather information
enum Representation {
eScientific = 0 // NumberE+Number or NumberENumber
, eOctal // starts with 0
, eHex // starts with 0x
, eDefault // Numbers with a (possible) trailing u or U or l or L for unsigned or long datatypes
eScientific = 0, // NumberE+Number or NumberENumber
eOctal, // starts with 0
eHex, // starts with 0x
eDefault // Numbers with a (possible) trailing u or U or l or L for unsigned or long datatypes
};
// create an instance
Representation Mode = eDefault;

View File

@ -3969,8 +3969,6 @@ bool Tokenizer::simplifyTokenList()
simplifyGoto();
simplifyFlowControl();
// Combine wide strings
for (Token *tok = _tokens; tok; tok = tok->next()) {
while (tok->str() == "L" && tok->next() && tok->next()->str()[0] == '"') {
@ -4191,6 +4189,8 @@ bool Tokenizer::simplifyTokenList()
removeRedundantSemicolons();
simplifyFlowControl();
if (!validate())
return false;
@ -4285,15 +4285,25 @@ void Tokenizer::simplifyFlowControl()
unsigned int indentlabel = 0;
unsigned int roundbraces = 0;
for (Token *tok = _tokens; tok; tok = tok->next()) {
if (tok->str() == "(")
if (tok->str() == "(") {
++roundbraces;
else if (tok->str() == ")") {
if (indentflow) {
tok = tok->previous();
tok->deleteNext();
continue;
}
} else if (tok->str() == ")") {
if (!roundbraces)
break; //too many ending round parenthesis
--roundbraces;
if (indentflow) {
tok = tok->previous();
tok->deleteNext();
continue;
}
}
if (tok->str() == "{") {
if (!roundbraces && tok->str() == "{") {
++indentlevel;
if (indentflow) {
indentlabel = 0;
@ -4315,7 +4325,7 @@ void Tokenizer::simplifyFlowControl()
tok->deleteNext();
}
}
} else if (tok->str() == "}") {
} else if (!roundbraces && tok->str() == "}") {
if (!indentlevel)
break; //too many closing parenthesis
if (indentflow) {
@ -4344,14 +4354,10 @@ void Tokenizer::simplifyFlowControl()
}
}
} else if (!indentflow) {
if (tok->str() == "switch") {
if (!roundbraces && tok->str() == "switch") {
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() == "(")
@ -4376,7 +4382,7 @@ void Tokenizer::simplifyFlowControl()
break;
++indentlevel;
indentcase = indentlevel;
} else if (indentswitch && Token::Match(tok, "case|default")) {
} else if (!roundbraces && indentswitch && Token::Match(tok, "case|default")) {
if (indentlevel > indentcase) {
--indentlevel;
}
@ -4390,14 +4396,10 @@ void Tokenizer::simplifyFlowControl()
} else if (Token::Match(tok2, "[{}]"))
break; //bad code
}
} else if (Token::Match(tok,"return|goto|continue|break")) {
} else if (!roundbraces && Token::Match(tok,"return|goto|continue|break")) {
if (!indentlevel)
break;
// Don't care about unpreprocessed macros part of code
if (roundbraces)
continue;
if (Token::Match(tok,"continue|break ;")) {
indentflow = indentlevel;
if (Token::Match(tok->tokAt(2),"continue|break ;")) {
@ -4407,16 +4409,16 @@ void Tokenizer::simplifyFlowControl()
}
//catch the first ';' after the return
unsigned int returnroundbraces = 0;
unsigned int flowroundbraces = 0;
for (Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) {
if (tok2->str() == "(")
++returnroundbraces;
++flowroundbraces;
else if (tok2->str() == ")") {
if (!returnroundbraces)
if (!flowroundbraces)
break; //excessive closing parenthesis
--returnroundbraces;
--flowroundbraces;
} else if (tok2->str() == ";") {
if (returnroundbraces)
if (flowroundbraces)
break; //excessive opening parenthesis
indentflow = indentlevel;
tok = tok2;
@ -4429,14 +4431,14 @@ void Tokenizer::simplifyFlowControl()
}
} else if (indentflow) { //there's already a "return;" declaration
if (!indentswitch || indentlevel > indentcase+1) {
if (indentlevel >= indentflow && (!Token::Match(tok, "%var% : ;") || Token::Match(tok, "case|default"))) {
if (indentlevel >= indentflow && (!Token::Match(tok, "%var% : ;") || Token::Match(tok, "case|default") || roundbraces)) {
tok = tok->previous();
tok->deleteNext();
} else {
indentflow = 0;
}
} else {
if (!Token::Match(tok, "%var% : ;") && !Token::Match(tok, "case|default")) {
if (roundbraces || (!Token::Match(tok, "%var% : ;") && !Token::Match(tok, "case|default"))) {
tok = tok->previous();
tok->deleteNext();
} else {
@ -7357,8 +7359,20 @@ void Tokenizer::simplifyGoto()
std::list<Token *> gotos;
unsigned int indentlevel = 0;
unsigned int indentspecial = 0;
unsigned int roundbraces = 0;
Token *beginfunction = 0;
for (Token *tok = _tokens; tok; tok = tok->next()) {
if (tok->str() == ")") {
if (!roundbraces)
break;
--roundbraces;
}
if (tok->str() == "(")
++roundbraces;
if (roundbraces)
continue;
if (tok->str() == "{") {
if ((tok->tokAt(-2) && Token::Match(tok->tokAt(-2),"namespace|struct|class|union %var% {")) ||
(tok->previous() && Token::Match(tok->previous(),"namespace {")))
@ -7384,10 +7398,6 @@ void Tokenizer::simplifyGoto()
}
}
else if (indentlevel && tok->str() == "(") {
tok = tok->link();
}
else if (!indentlevel && Token::Match(tok, ") const| {")) {
gotos.clear();
beginfunction = tok;
@ -7399,14 +7409,25 @@ void Tokenizer::simplifyGoto()
else if (indentlevel == 1 && Token::Match(tok->previous(), "[};] %var% :")) {
// Is this label at the end..
bool end = false;
int level = 0;
unsigned int level = 0;
for (const Token *tok2 = tok->tokAt(2); tok2; tok2 = tok2->next()) {
if (tok2->str() == ")") {
if (!roundbraces)
break;
--roundbraces;
}
if (tok2->str() == "(")
++roundbraces;
if (roundbraces)
continue;
if (tok2->str() == "}") {
--level;
if (level < 0) {
if (!level) {
end = true;
break;
}
--level;
} else if (tok2->str() == "{") {
++level;
}
@ -7441,16 +7462,24 @@ void Tokenizer::simplifyGoto()
std::list<Token*> links;
std::list<Token*> links2;
std::list<Token*> links3;
int lev = 0;
unsigned int lev = 0;
for (const Token *tok2 = tok; tok2; tok2 = tok2->next()) {
if (tok2->str() == "}") {
--lev;
if (lev < 0)
if (tok2->str() == ")") {
if (!roundbraces)
break;
--roundbraces;
}
if (tok2->str() == "{") {
if (tok2->str() == "(")
++roundbraces;
if (!roundbraces && tok2->str() == "}") {
if (!lev)
break;
--lev;
}
if (!roundbraces && tok2->str() == "{") {
++lev;
} else if (tok2->str() == "return") {
} else if (!roundbraces && tok2->str() == "return") {
ret = true;
if (indentlevel == 1 && lev == 0)
ret2 = true;

View File

@ -2896,6 +2896,9 @@ private:
// Don't simplify goto inside function call (macro)
const char code[] = "void f ( ) { slist_iter ( if ( a ) { goto dont_write ; } dont_write : ; x ( ) ; ) ; }";
ASSERT_EQUALS(code, tok(code));
//ticket #3229 (segmentation fault)
ASSERT_EQUALS("void f ( ) { MACRO ( return ; ) return ; }",tok("void f ( ) {goto label; label: MACRO(return;)}"));
}
void goto3() {