Parser; simplify (break out) init expression from if/switch/range-for
This commit is contained in:
parent
dcc90c6dfa
commit
28a7bb63ec
|
@ -5143,6 +5143,8 @@ bool Tokenizer::simplifyTokenList1(const char FileName[])
|
|||
|
||||
elseif();
|
||||
|
||||
simplifyIfSwitchForInit();
|
||||
|
||||
simplifyOverloadedOperators();
|
||||
|
||||
validate();
|
||||
|
@ -8593,6 +8595,66 @@ void Tokenizer::elseif()
|
|||
}
|
||||
|
||||
|
||||
void Tokenizer::simplifyIfSwitchForInit()
|
||||
{
|
||||
if (!isCPP() || mSettings->standards.cpp < Standards::CPP17)
|
||||
return;
|
||||
|
||||
const bool forInit = (mSettings->standards.cpp >= Standards::CPP20);
|
||||
|
||||
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
||||
if (!Token::Match(tok, "if|switch|for ("))
|
||||
continue;
|
||||
|
||||
Token *semicolon = tok->tokAt(2);
|
||||
while (!Token::Match(semicolon, "[;)]")) {
|
||||
if (semicolon->str() == "(")
|
||||
semicolon = semicolon->link();
|
||||
semicolon = semicolon->next();
|
||||
}
|
||||
if (semicolon->str() != ";")
|
||||
continue;
|
||||
|
||||
if (tok->str() == "for") {
|
||||
if (!forInit)
|
||||
continue;
|
||||
|
||||
// Is it a for range..
|
||||
const Token *tok2 = semicolon->next();
|
||||
bool rangeFor = false;
|
||||
while (!Token::Match(tok2, "[;)]")) {
|
||||
if (tok2->str() == "(")
|
||||
tok2 = tok2->link();
|
||||
else if (!rangeFor && tok2->str() == "?")
|
||||
break;
|
||||
else if (tok2->str() == ":")
|
||||
rangeFor = true;
|
||||
tok2 = tok2->next();
|
||||
}
|
||||
if (!rangeFor || tok2->str() != ")")
|
||||
continue;
|
||||
}
|
||||
|
||||
Token *endpar = tok->linkAt(1);
|
||||
if (!Token::simpleMatch(endpar, ") {"))
|
||||
continue;
|
||||
|
||||
Token *endscope = endpar->linkAt(1);
|
||||
if (Token::simpleMatch(endscope, "} else {"))
|
||||
endscope = endscope->linkAt(2);
|
||||
|
||||
// Simplify, the initialization expression is broken out..
|
||||
semicolon->insertToken(tok->str());
|
||||
semicolon->next()->insertToken("(");
|
||||
Token::createMutualLinks(semicolon->next()->next(), endpar);
|
||||
tok->deleteNext();
|
||||
tok->str("{");
|
||||
endscope->insertToken("}");
|
||||
Token::createMutualLinks(tok, endscope->next());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Tokenizer::simplifyRedundantParentheses()
|
||||
{
|
||||
bool ret = false;
|
||||
|
|
|
@ -449,6 +449,9 @@ public:
|
|||
/** Simplify "if else" */
|
||||
void elseif();
|
||||
|
||||
/** Simplify C++17/C++20 if/switch/for initialization expression */
|
||||
void simplifyIfSwitchForInit();
|
||||
|
||||
/** Simplify conditions
|
||||
* @return true if something is modified
|
||||
* false if nothing is done.
|
||||
|
|
|
@ -281,7 +281,6 @@ private:
|
|||
TEST_CASE(bitfields14); // ticket #4561 (segfault for 'class a { signals: };')
|
||||
TEST_CASE(bitfields15); // ticket #7747 (enum Foo {A,B}:4;)
|
||||
TEST_CASE(bitfields16); // Save bitfield bit count
|
||||
TEST_CASE(bitfields17); // for (A; b:c);
|
||||
|
||||
TEST_CASE(simplifyNamespaceStd);
|
||||
|
||||
|
@ -422,6 +421,11 @@ private:
|
|||
TEST_CASE(simplifyCoroutines);
|
||||
|
||||
TEST_CASE(simplifySpaceshipOperator);
|
||||
|
||||
TEST_CASE(simplifyIfSwitchForInit1);
|
||||
TEST_CASE(simplifyIfSwitchForInit2);
|
||||
TEST_CASE(simplifyIfSwitchForInit3);
|
||||
TEST_CASE(simplifyIfSwitchForInit4);
|
||||
}
|
||||
|
||||
std::string tokenizeAndStringify(const char code[], bool expand = true, Settings::PlatformType platform = Settings::Native, const char* filename = "test.cpp", bool cpp11 = true) {
|
||||
|
@ -3953,13 +3957,6 @@ private:
|
|||
ASSERT_EQUALS(1, x->bits());
|
||||
}
|
||||
|
||||
void bitfields17() {
|
||||
Settings settings;
|
||||
settings.standards.cpp = Standards::CPP20;
|
||||
const char code[] = "void f() { for (a;b:c) {} }";
|
||||
ASSERT_EQUALS("void f ( ) { for ( a ; b : c ) { } }", tokenizeAndStringify(code, settings));
|
||||
}
|
||||
|
||||
void simplifyNamespaceStd() {
|
||||
const char *code, *expected;
|
||||
|
||||
|
@ -6556,6 +6553,34 @@ private:
|
|||
|
||||
ASSERT_EQUALS("; x <=> y ;", tokenizeAndStringify(";x<=>y;", settings));
|
||||
}
|
||||
|
||||
void simplifyIfSwitchForInit1() {
|
||||
Settings settings;
|
||||
settings.standards.cpp = Standards::CPP17;
|
||||
const char code[] = "void f() { if (a;b) {} }";
|
||||
ASSERT_EQUALS("void f ( ) { { a ; if ( b ) { } } }", tokenizeAndStringify(code, settings));
|
||||
}
|
||||
|
||||
void simplifyIfSwitchForInit2() {
|
||||
Settings settings;
|
||||
settings.standards.cpp = Standards::CPP20;
|
||||
const char code[] = "void f() { if (a;b) {} else {} }";
|
||||
ASSERT_EQUALS("void f ( ) { { a ; if ( b ) { } else { } } }", tokenizeAndStringify(code, settings));
|
||||
}
|
||||
|
||||
void simplifyIfSwitchForInit3() {
|
||||
Settings settings;
|
||||
settings.standards.cpp = Standards::CPP20;
|
||||
const char code[] = "void f() { switch (a;b) {} }";
|
||||
ASSERT_EQUALS("void f ( ) { { a ; switch ( b ) { } } }", tokenizeAndStringify(code, settings));
|
||||
}
|
||||
|
||||
void simplifyIfSwitchForInit4() {
|
||||
Settings settings;
|
||||
settings.standards.cpp = Standards::CPP20;
|
||||
const char code[] = "void f() { for (a;b:c) {} }";
|
||||
ASSERT_EQUALS("void f ( ) { { a ; for ( b : c ) { } } }", tokenizeAndStringify(code, settings));
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST(TestTokenizer)
|
||||
|
|
Loading…
Reference in New Issue