From 932ba10ddaf323d9d67cc4a45f1da65011cc713f Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Sat, 13 Dec 2025 12:34:46 +0100 Subject: [PATCH 1/3] Reject invalid code after if/switch/loop (also fixes #14326) --- lib/tokenize.cpp | 3 +++ test/testcondition.cpp | 2 +- test/testgarbage.cpp | 6 ++---- test/testsymboldatabase.cpp | 3 +-- test/testtokenize.cpp | 9 +++++++-- 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index c69e73d03be..3b21746cdfc 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -8664,6 +8664,9 @@ void Tokenizer::findGarbageCode() const } if (!Token::Match(tok->next(), "( !!)")) syntaxError(tok); + if (Token::simpleMatch(tok->linkAt(1), ") }")) { + syntaxError(tok->linkAt(1)->next()); + } if (tok->str() != "for") { if (isGarbageExpr(tok->next(), tok->linkAt(1), cpp && (mSettings.standards.cpp>=Standards::cppstd_t::CPP17))) syntaxError(tok); diff --git a/test/testcondition.cpp b/test/testcondition.cpp index dd4d52848ea..60e423a0d73 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -771,7 +771,7 @@ class TestCondition : public TestFixture { check("void f(size_t x) {\n" " if (x == sizeof(int)) {}\n" - " else { if (x == sizeof(long))} {}\n" + " else { if (x == sizeof(long)) {} }\n" "}\n"); ASSERT_EQUALS("", errout_str()); diff --git a/test/testgarbage.cpp b/test/testgarbage.cpp index c3f0d25ca56..2bfb1283587 100644 --- a/test/testgarbage.cpp +++ b/test/testgarbage.cpp @@ -883,8 +883,7 @@ class TestGarbage : public TestFixture { } void garbageCode102() { // #6846 (segmentation fault) - (void)checkCode("struct Object { ( ) ; Object & operator= ( Object ) { ( ) { } if ( this != & b ) } }"); - ignore_errout(); // we do not care about the output + ASSERT_THROW_INTERNAL(checkCode("struct Object { ( ) ; Object & operator= ( Object ) { ( ) { } if ( this != & b ) } }"), SYNTAX); } void garbageCode103() { // #6824 @@ -1251,8 +1250,7 @@ class TestGarbage : public TestFixture { const char code[] = "template \n" "static std::string foo(char *Bla) {\n" " while (Bla[1] && Bla[1] != ',') }\n"; - (void)checkCode(code); - ignore_errout(); // we are not interested in the output + ASSERT_THROW_INTERNAL(checkCode(code), SYNTAX); } void garbageCode153() { diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 7d146551d25..aaf67303517 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -3672,8 +3672,7 @@ class TestSymbolDatabase : public TestFixture { } void symboldatabase36() { // ticket #4892 - check("void struct ( ) { if ( 1 ) } int main ( ) { }"); - ASSERT_EQUALS("", errout_str()); + ASSERT_THROW_INTERNAL(check("void struct ( ) { if ( 1 ) } int main ( ) { }"), SYNTAX); } void symboldatabase37() { diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 45df39a4557..239ac526187 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -5345,8 +5345,8 @@ class TestTokenizer : public TestFixture { ASSERT_EQUALS("; x = 123 ;", tokenizeAndStringify(";x=({123;});")); ASSERT_EQUALS("; x = y ;", tokenizeAndStringify(";x=({y;});")); // #13419: Do not simplify compound statements in for loop - ASSERT_EQUALS("void foo ( int x ) { for ( ; ( { { } ; x < 1 ; } ) ; ) }", - tokenizeAndStringify("void foo(int x) { for (;({ {}; x<1; });) }")); + ASSERT_EQUALS("void foo ( int x ) { for ( ; ( { { } ; x < 1 ; } ) { ; } ) }", + tokenizeAndStringify("void foo(int x) { for (;({ {}; x<1; });); }")); } void simplifyOperatorName1() { @@ -7627,6 +7627,11 @@ class TestTokenizer : public TestFixture { ASSERT_THROW_INTERNAL(tokenizeAndStringify("{ for (()()) }"), SYNTAX); // #11643 + ASSERT_THROW_INTERNAL(tokenizeAndStringify("void f(const std::vector& v) {\n" // #14326 + " for (const std::string&s : v)\n" + "}"), + SYNTAX); + ASSERT_NO_THROW(tokenizeAndStringify("S* g = ::new(ptr) S();")); // #12552 ASSERT_NO_THROW(tokenizeAndStringify("void f(int* p) { return ::delete p; }")); From a79a84738479a3531ebbf298ddd3154591c6a5ee Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Sat, 13 Dec 2025 12:40:37 +0100 Subject: [PATCH 2/3] Fix --- test/testcondition.cpp | 2 +- test/testtokenize.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/testcondition.cpp b/test/testcondition.cpp index 60e423a0d73..ffeca5c5be7 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -777,7 +777,7 @@ class TestCondition : public TestFixture { check("void f(size_t x) {\n" " if (x == sizeof(long)) {}\n" - " else { if (x == sizeof(long long))} {}\n" + " else { if (x == sizeof(long long)) {} }\n" "}\n"); ASSERT_EQUALS("", errout_str()); } diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 239ac526187..ad119901e44 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -5345,7 +5345,7 @@ class TestTokenizer : public TestFixture { ASSERT_EQUALS("; x = 123 ;", tokenizeAndStringify(";x=({123;});")); ASSERT_EQUALS("; x = y ;", tokenizeAndStringify(";x=({y;});")); // #13419: Do not simplify compound statements in for loop - ASSERT_EQUALS("void foo ( int x ) { for ( ; ( { { } ; x < 1 ; } ) { ; } ) }", + ASSERT_EQUALS("void foo ( int x ) { for ( ; ( { { } ; x < 1 ; } ) ; ) { ; } }", tokenizeAndStringify("void foo(int x) { for (;({ {}; x<1; });); }")); } From 8f8845a2cd0642c0294802a4c9ad787e583be05e Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Sat, 13 Dec 2025 12:46:07 +0100 Subject: [PATCH 3/3] Format --- test/testtokenize.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index ad119901e44..b9056f8cb80 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -7630,7 +7630,7 @@ class TestTokenizer : public TestFixture { ASSERT_THROW_INTERNAL(tokenizeAndStringify("void f(const std::vector& v) {\n" // #14326 " for (const std::string&s : v)\n" "}"), - SYNTAX); + SYNTAX); ASSERT_NO_THROW(tokenizeAndStringify("S* g = ::new(ptr) S();")); // #12552 ASSERT_NO_THROW(tokenizeAndStringify("void f(int* p) { return ::delete p; }"));