diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 02a2ec1dc..c4160c00e 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -2380,6 +2380,27 @@ void Tokenizer::simplifyLabelsCaseDefault() } +void Tokenizer::simplifyCaseRange() +{ + for (Token* tok = list.front(); tok; tok = tok->next()) { + if (Token::Match(tok, "case %num% . . . %num% :")) { + MathLib::bigint start = MathLib::toLongNumber(tok->strAt(1)); + MathLib::bigint end = MathLib::toLongNumber(tok->strAt(5)); + if (start < end) { + tok = tok->tokAt(2); + tok->str(":"); + tok->deleteNext(); + tok->next()->str("case"); + for (MathLib::bigint i = end-1; i > start; i--) { + tok->insertToken(":"); + tok->insertToken(MathLib::toString(i)); + tok->insertToken("case"); + } + } + } + } +} + void Tokenizer::simplifyTemplates() @@ -3373,6 +3394,9 @@ bool Tokenizer::simplifyTokenList1(const char FileName[]) simplifyVarDecl(true); simplifyFunctionParameters(); + // simplify case ranges (gcc extension) + simplifyCaseRange(); + // simplify labels and 'case|default'-like syntaxes simplifyLabelsCaseDefault(); diff --git a/lib/tokenize.h b/lib/tokenize.h index c5c092e51..7849e689f 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -209,6 +209,10 @@ public: */ void simplifyLabelsCaseDefault(); + /** simplify case ranges (gcc extension) + */ + void simplifyCaseRange(); + /** Remove macros in global scope */ void removeMacrosInGlobalScope(); diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 0d4c2c126..4d9df9751 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -443,6 +443,8 @@ private: TEST_CASE(simplifyDeprecated); + TEST_CASE(simplifyCaseRange); + TEST_CASE(compileLimits); // #5592 crash: gcc: testsuit: gcc.c-torture/compile/limits-declparen.c TEST_CASE(prepareTernaryOpForAST); @@ -7991,6 +7993,11 @@ private: tokenizeAndStringify("[[deprecated]] int f();", false, true, Settings::Unspecified, "test.c", true)); } + void simplifyCaseRange() { + ASSERT_EQUALS("void f ( ) { case 1 : ; case 2 : ; case 3 : ; case 4 : ; }", tokenizeAndStringify("void f() { case 1 ... 4: }")); + ASSERT_EQUALS("void f ( ) { case 4 . . . 1 : ; }", tokenizeAndStringify("void f() { case 4 ... 1: }")); + } + void prepareTernaryOpForAST() { ASSERT_EQUALS("a ? b : c ;", tokenizeAndStringify("a ? b : c;"));