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,... // prechecking has nothing found,...
// gather information // gather information
enum Representation { enum Representation {
eScientific = 0 // NumberE+Number or NumberENumber eScientific = 0, // NumberE+Number or NumberENumber
, eOctal // starts with 0 eOctal, // starts with 0
, eHex // starts with 0x eHex, // starts with 0x
, eDefault // Numbers with a (possible) trailing u or U or l or L for unsigned or long datatypes eDefault // Numbers with a (possible) trailing u or U or l or L for unsigned or long datatypes
}; };
// create an instance // create an instance
Representation Mode = eDefault; Representation Mode = eDefault;

View File

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

View File

@ -2896,6 +2896,9 @@ private:
// Don't simplify goto inside function call (macro) // Don't simplify goto inside function call (macro)
const char code[] = "void f ( ) { slist_iter ( if ( a ) { goto dont_write ; } dont_write : ; x ( ) ; ) ; }"; const char code[] = "void f ( ) { slist_iter ( if ( a ) { goto dont_write ; } dont_write : ; x ( ) ; ) ; }";
ASSERT_EQUALS(code, tok(code)); 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() { void goto3() {