Fixed #9728 (Support function level try blocks)

This commit is contained in:
dummyunit 2021-05-02 10:05:12 +03:00 committed by GitHub
parent d553df75c6
commit da27159d7c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 75 additions and 1 deletions

View File

@ -4802,6 +4802,8 @@ bool Tokenizer::simplifyTokenList1(const char FileName[])
reportUnknownMacros(); reportUnknownMacros();
simplifyFunctionTryCatch();
simplifyHeadersAndUnusedTemplates(); simplifyHeadersAndUnusedTemplates();
// Remove __asm.. // 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() void Tokenizer::simplifyErrNoInWhile()
{ {
for (Token *tok = list.front(); tok; tok = tok->next()) { for (Token *tok = list.front(); tok; tok = tok->next()) {

View File

@ -511,6 +511,12 @@ public:
*/ */
void simplifyFunctionParameters(); void simplifyFunctionParameters();
/** Simplify function level try blocks:
* Convert "void f() try {} catch (int) {}"
* to "void f() { try {} catch (int) {} }"
*/
void simplifyFunctionTryCatch();
/** /**
* Simplify templates * Simplify templates
*/ */

View File

@ -147,6 +147,8 @@ private:
TEST_CASE(simplifyFunctionParametersMultiTemplate); TEST_CASE(simplifyFunctionParametersMultiTemplate);
TEST_CASE(simplifyFunctionParametersErrors); TEST_CASE(simplifyFunctionParametersErrors);
TEST_CASE(simplifyFunctionTryCatch);
TEST_CASE(removeParentheses1); // Ticket #61 TEST_CASE(removeParentheses1); // Ticket #61
TEST_CASE(removeParentheses3); TEST_CASE(removeParentheses3);
TEST_CASE(removeParentheses4); // Ticket #390 TEST_CASE(removeParentheses4); // Ticket #390
@ -1454,6 +1456,36 @@ private:
ASSERT_EQUALS("", errout.str()); 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 "(..)" // Simplify "((..))" into "(..)"
void removeParentheses1() { void removeParentheses1() {
const char code[] = "void foo()" const char code[] = "void foo()"
@ -6100,7 +6132,8 @@ private:
void findGarbageCode() { // Test Tokenizer::findGarbageCode() void findGarbageCode() { // Test Tokenizer::findGarbageCode()
// C++ try/catch in global scope // 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 // before if|for|while|switch
ASSERT_NO_THROW(tokenizeAndStringify("void f() { do switch (a) {} while (1); }")); ASSERT_NO_THROW(tokenizeAndStringify("void f() { do switch (a) {} while (1); }"));