From da27159d7c704a13790795226803ca764c441d79 Mon Sep 17 00:00:00 2001 From: dummyunit Date: Sun, 2 May 2021 10:05:12 +0300 Subject: [PATCH] Fixed #9728 (Support function level try blocks) --- lib/tokenize.cpp | 35 +++++++++++++++++++++++++++++++++++ lib/tokenize.h | 6 ++++++ test/testtokenize.cpp | 35 ++++++++++++++++++++++++++++++++++- 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 3b04feeb7..63159ed61 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -4802,6 +4802,8 @@ bool Tokenizer::simplifyTokenList1(const char FileName[]) reportUnknownMacros(); + simplifyFunctionTryCatch(); + simplifyHeadersAndUnusedTemplates(); // Remove __asm.. @@ -10513,6 +10515,39 @@ void Tokenizer::simplifyWhile0() } } +void Tokenizer::simplifyFunctionTryCatch() +{ + if (!isCPP()) + return; + + for (Token * tok = list.front(); tok; tok = tok->next()) { + if (!Token::simpleMatch(tok, "try {")) + continue; + if (!isFunctionHead(tok->previous(), "try")) + continue; + + // find the end of the last catch block + Token * const tryEndToken = tok->linkAt(1); + Token * endToken = tryEndToken; + while (Token::simpleMatch(endToken, "} catch (")) { + endToken = endToken->linkAt(2)->next(); + if (!endToken) + break; + if (endToken->str() != "{") { + endToken = nullptr; + break; + } + endToken = endToken->link(); + } + if (!endToken || endToken == tryEndToken) + continue; + + tok->previous()->insertToken("{"); + endToken->insertToken("}"); + Token::createMutualLinks(tok->previous(), endToken->next()); + } +} + void Tokenizer::simplifyErrNoInWhile() { for (Token *tok = list.front(); tok; tok = tok->next()) { diff --git a/lib/tokenize.h b/lib/tokenize.h index da4861b1b..c17f4b829 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -511,6 +511,12 @@ public: */ void simplifyFunctionParameters(); + /** Simplify function level try blocks: + * Convert "void f() try {} catch (int) {}" + * to "void f() { try {} catch (int) {} }" + */ + void simplifyFunctionTryCatch(); + /** * Simplify templates */ diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index bf505bf5a..24eadcca9 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -147,6 +147,8 @@ private: TEST_CASE(simplifyFunctionParametersMultiTemplate); TEST_CASE(simplifyFunctionParametersErrors); + TEST_CASE(simplifyFunctionTryCatch); + TEST_CASE(removeParentheses1); // Ticket #61 TEST_CASE(removeParentheses3); TEST_CASE(removeParentheses4); // Ticket #390 @@ -1454,6 +1456,36 @@ private: ASSERT_EQUALS("", errout.str()); } + void simplifyFunctionTryCatch() { + ASSERT_EQUALS("void foo ( ) { try {\n" + "} catch ( int ) {\n" + "} catch ( char ) {\n" + "} }", + tokenizeAndStringify("void foo() try {\n" + "} catch (int) {\n" + "} catch (char) {\n" + "}")); + + ASSERT_EQUALS("void foo ( ) { try {\n" + "struct S {\n" + "void bar ( ) { try {\n" + "} catch ( int ) {\n" + "} catch ( char ) {\n" + "} }\n" + "} ;\n" + "} catch ( long ) {\n" + "} }", + tokenizeAndStringify("void foo() try {\n" + " struct S {\n" + " void bar() try {\n" + " } catch (int) {\n" + " } catch (char) {\n" + " }\n" + " };\n" + "} catch (long) {\n" + "}")); + } + // Simplify "((..))" into "(..)" void removeParentheses1() { const char code[] = "void foo()" @@ -6100,7 +6132,8 @@ private: void findGarbageCode() { // Test Tokenizer::findGarbageCode() // C++ try/catch in global scope - ASSERT_THROW_EQUALS(tokenizeAndStringify("void f() try { }"), InternalError, "syntax error: keyword 'try' is not allowed in global scope"); + ASSERT_THROW_EQUALS(tokenizeAndStringify("try { }"), InternalError, "syntax error: keyword 'try' is not allowed in global scope"); + ASSERT_NO_THROW(tokenizeAndStringify("void f() try { } catch (int) { }")); // before if|for|while|switch ASSERT_NO_THROW(tokenizeAndStringify("void f() { do switch (a) {} while (1); }"));