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:
parent
dc15641954
commit
f4cdf57955
|
@ -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;
|
||||||
|
|
103
lib/tokenize.cpp
103
lib/tokenize.cpp
|
@ -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;
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
Loading…
Reference in New Issue