From 5782bb960e17b060fc4b39bf242b4d4cb305a912 Mon Sep 17 00:00:00 2001 From: Oleksandr Labetskyi Date: Fri, 24 Jan 2025 20:36:06 +0200 Subject: [PATCH 1/2] Fix #13559: Tokenizer: remove simplification that converts \'int x(0)\' to \'int x; x = 0;\' --- lib/token.h | 8 +++++++ lib/tokenize.cpp | 11 +++++++--- test/testsimplifytokens.cpp | 6 +++--- test/testtokenize.cpp | 42 ++++++++++++++++++------------------- test/testunusedvar.cpp | 20 ++++-------------- test/testvarid.cpp | 8 +++---- 6 files changed, 48 insertions(+), 47 deletions(-) diff --git a/lib/token.h b/lib/token.h index eb2434d1a84..a2cd97cf278 100644 --- a/lib/token.h +++ b/lib/token.h @@ -725,6 +725,13 @@ class CPPCHECKLIB Token { setFlag(fIsInitComma, b); } + bool isInitBracket() const { + return getFlag(fIsInitBracket); + } + void isInitBracket(bool b) { + setFlag(fIsInitBracket, b); + } + // cppcheck-suppress unusedFunction bool isBitfield() const { return mImpl->mBits > 0; @@ -1401,6 +1408,7 @@ class CPPCHECKLIB Token { fIsSimplifiedTypedef = (1ULL << 40), fIsFinalType = (1ULL << 41), // Is this a type with final specifier fIsInitComma = (1ULL << 42), // Is this comma located inside some {..}. i.e: {1,2,3,4} + fIsInitBracket = (1ULL << 43), // Is this bracket used as a part of variable initialization i.e: int a{5}, b(2); }; enum : std::uint8_t { diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 5c85a23e3cc..128b4e05f27 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -6072,6 +6072,8 @@ void Tokenizer::dump(std::ostream &out) const outs += " isAttributeMaybeUnused=\"true\""; if (tok->isAttributeUnused()) outs += " isAttributeUnused=\"true\""; + if (tok->isInitBracket()) + outs += " isInitBracket=\"true\""; if (tok->hasAttributeAlignas()) { const std::vector& a = tok->getAttributeAlignas(); outs += " alignas=\"" + ErrorLogger::toxml(a[0]) + "\""; @@ -7687,8 +7689,11 @@ void Tokenizer::simplifyInitVar() if (tok->str() == "return") continue; - if (Token::Match(tok, "class|struct|union| %type% *| %name% (|{ &| %any% )|} ;")) { - tok = initVar(tok); + if (Token::Match(tok, "%type% *|&| %name% (|{")) { + while(tok && !Token::Match(tok, "(|{")) + tok = tok->next(); + tok->isInitBracket(true); + /* tok = initVar(tok); } else if (Token::Match(tok, "%type% *| %name% ( %type% (")) { const Token* tok2 = tok->tokAt(2); if (!tok2->link()) @@ -7703,7 +7708,7 @@ void Tokenizer::simplifyInitVar() const int numTokens = (Token::Match(tok, "class|struct|union")) ? 2 : 1; TokenList::insertTokens(tok1, tok, numTokens); - tok = initVar(tok); + tok = initVar(tok); */ } } } diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index f34891af85d..97bfb914cca 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -1041,7 +1041,7 @@ class TestSimplifyTokens : public TestFixture { // ticket #980 { const char code[] = "void f() { int A(1),B(2),C=3,D,E(5),F=6; }"; - const char expected[] = "void f ( ) { int A ; A = 1 ; int B ; B = 2 ; int C ; C = 3 ; int D ; int E ; E = 5 ; int F ; F = 6 ; }"; + const char expected[] = "void f ( ) { int A ( 1 ) ; int B ( 2 ) ; int C ; C = 3 ; int D ; int E ( 5 ) ; int F ; F = 6 ; }"; ASSERT_EQUALS(expected, tok(code)); } @@ -2540,10 +2540,10 @@ class TestSimplifyTokens : public TestFixture { "3: namespace M { const int m@2 = 0 ; }\n" "4: }\n" "5: using namespace N ;\n" - "6: int i ; i = n@1 ;\n" + "6: int i ( n@1 ) ;\n" "7: int j ( M :: m@2 ) ;\n" "8: using namespace N :: M ;\n" - "9: int k ; k = m@2 ;\n" + "9: int k ( m@2 ) ;\n" "10: int l ( N :: M :: m@2 ) ;\n"; ASSERT_EQUALS(exp, tokenizeDebugListing(code)); } diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 80d8706e446..414692ba592 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -585,7 +585,7 @@ class TestTokenizer : public TestFixture { " int x1 = 1;\n" " int x2(x1);\n" "}\n"; - ASSERT_EQUALS("void f ( ) {\nint x1 ; x1 = 1 ;\nint x2 ; x2 = x1 ;\n}", + ASSERT_EQUALS("void f ( ) {\nint x1 ; x1 = 1 ;\nint x2 ( x1 ) ;\n}", tokenizeAndStringify(code)); } @@ -595,8 +595,8 @@ class TestTokenizer : public TestFixture { " int x2(x1);\n" "}\n"; ASSERT_EQUALS("1: void f ( ) {\n" - "2: int x1@1 ; x1@1 = g ( ) ;\n" - "3: int x2@2 ; x2@2 = x1@1 ;\n" + "2: int x1@1 ( g ( ) ) ;\n" + "3: int x2@2 ( x1@1 ) ;\n" "4: }\n", tokenizeDebugListing(code)); } @@ -4292,79 +4292,79 @@ class TestTokenizer : public TestFixture { void simplifyInitVar() { { const char code[] = "int i ; int p(0);"; - ASSERT_EQUALS("int i ; int p ; p = 0 ;", tokenizeAndStringify(code)); + ASSERT_EQUALS("int i ; int p ( 0 ) ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout_str()); } { const char code[] = "int i; int *p(0);"; - ASSERT_EQUALS("int i ; int * p ; p = 0 ;", tokenizeAndStringify(code)); + ASSERT_EQUALS("int i ; int * p ( 0 ) ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout_str()); } { const char code[] = "int p(0);"; - ASSERT_EQUALS("int p ; p = 0 ;", tokenizeAndStringify(code)); + ASSERT_EQUALS("int p ( 0 ) ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout_str()); } { const char code[] = "int *p(0);"; - ASSERT_EQUALS("int * p ; p = 0 ;", tokenizeAndStringify(code)); + ASSERT_EQUALS("int * p ( 0 ) ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout_str()); } { const char code[] = "int i ; int p(i);"; - ASSERT_EQUALS("int i ; int p ; p = i ;", tokenizeAndStringify(code)); + ASSERT_EQUALS("int i ; int p ( i ) ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout_str()); } { const char code[] = "int i; int *p(&i);"; - ASSERT_EQUALS("int i ; int * p ; p = & i ;", tokenizeAndStringify(code)); + ASSERT_EQUALS("int i ; int * p ( & i ) ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout_str()); } { const char code[] = "int i; void *p(&i);"; - ASSERT_EQUALS("int i ; void * p ; p = & i ;", tokenizeAndStringify(code)); + ASSERT_EQUALS("int i ; void * p ( & i ) ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout_str()); } { const char code[] = "struct S { }; struct S s; struct S *p(&s);"; - ASSERT_EQUALS("struct S { } ; struct S s ; struct S * p ; p = & s ;", tokenizeAndStringify(code)); + ASSERT_EQUALS("struct S { } ; struct S s ; struct S * p ( & s ) ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout_str()); } { const char code[] = "struct S { }; S s; S *p(&s);"; - ASSERT_EQUALS("struct S { } ; S s ; S * p ; p = & s ;", tokenizeAndStringify(code)); + ASSERT_EQUALS("struct S { } ; S s ; S * p ( & s ) ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout_str()); } { const char code[] = "union S { int i; float f; }; union S s; union S *p(&s);"; - ASSERT_EQUALS("union S { int i ; float f ; } ; union S s ; union S * p ; p = & s ;", tokenizeAndStringify(code)); + ASSERT_EQUALS("union S { int i ; float f ; } ; union S s ; union S * p ( & s ) ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout_str()); } { const char code[] = "union S { int i; float f; }; S s; S *p(&s);"; - ASSERT_EQUALS("union S { int i ; float f ; } ; S s ; S * p ; p = & s ;", tokenizeAndStringify(code)); + ASSERT_EQUALS("union S { int i ; float f ; } ; S s ; S * p ( & s ) ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout_str()); } { const char code[] = "class C { }; class C c; class C *p(&c);"; - ASSERT_EQUALS("class C { } ; class C c ; class C * p ; p = & c ;", tokenizeAndStringify(code)); + ASSERT_EQUALS("class C { } ; class C c ; class C * p ( & c ) ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout_str()); } { const char code[] = "class C { }; C c; C *p(&c);"; - ASSERT_EQUALS("class C { } ; C c ; C * p ; p = & c ;", tokenizeAndStringify(code)); + ASSERT_EQUALS("class C { } ; C c ; C * p ( & c ) ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout_str()); } @@ -4456,13 +4456,13 @@ class TestTokenizer : public TestFixture { { const char code[] = "class A { } ; A a; int foo(a);"; - ASSERT_EQUALS("class A { } ; A a ; int foo ; foo = a ;", tokenizeAndStringify(code)); + ASSERT_EQUALS("class A { } ; A a ; int foo ( a ) ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout_str()); } { const char code[] = "int x(f());"; - ASSERT_EQUALS("int x ; x = f ( ) ;", tokenizeAndStringify(code)); + ASSERT_EQUALS("int x ( f ( ) ) ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout_str()); } @@ -4479,7 +4479,7 @@ class TestTokenizer : public TestFixture { " unsigned int a(0),b(0);\n" "}"; ASSERT_EQUALS("void f ( ) {\n" - "unsigned int a ; a = 0 ; unsigned int b ; b = 0 ;\n" + "unsigned int a ( 0 ) ; unsigned int b ( 0 ) ;\n" "}", tokenizeAndStringify(code)); } @@ -4488,7 +4488,7 @@ class TestTokenizer : public TestFixture { " int *a(0),b(0);\n" "}"; ASSERT_EQUALS("void f ( ) {\n" - "int * a ; a = 0 ; int b ; b = 0 ;\n" + "int * a ( 0 ) ; int b ( 0 ) ;\n" "}", tokenizeAndStringify(code)); } @@ -4497,7 +4497,7 @@ class TestTokenizer : public TestFixture { " uint32_t x{0};\n" "}"; ASSERT_EQUALS("void f ( ) {\n" - "uint32_t x ; x = 0 ;\n" + "uint32_t x { 0 } ;\n" "}", tokenizeAndStringify(code)); } diff --git a/test/testunusedvar.cpp b/test/testunusedvar.cpp index c9ac956b816..875052f858e 100644 --- a/test/testunusedvar.cpp +++ b/test/testunusedvar.cpp @@ -2096,10 +2096,7 @@ class TestUnusedVar : public TestFixture { "{\n" " int i(0);\n" "}"); - ASSERT_EQUALS( - "[test.cpp:3]: (style) Variable 'i' is assigned a value that is never used.\n" - "[test.cpp:3]: (style) Variable 'i' is assigned a value that is never used.\n", // duplicate - errout_str()); + ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'i' is assigned a value that is never used.\n", errout_str()); // if a is undefined then Cppcheck can't determine if "int i(a)" is a // * variable declaration @@ -2115,10 +2112,7 @@ class TestUnusedVar : public TestFixture { " int j = 0;\n" " int i(j);\n" "}"); - ASSERT_EQUALS( - "[test.cpp:4]: (style) Variable 'i' is assigned a value that is never used.\n" - "[test.cpp:4]: (style) Variable 'i' is assigned a value that is never used.\n", // duplicate - errout_str()); + ASSERT_EQUALS("[test.cpp:4]: (style) Variable 'i' is assigned a value that is never used.\n", errout_str()); functionVariableUsage("void foo()\n" "{\n" @@ -2157,10 +2151,7 @@ class TestUnusedVar : public TestFixture { " int * j = Data;\n" " int * i(j);\n" "}"); - ASSERT_EQUALS( - "[test.cpp:4]: (style) Variable 'i' is assigned a value that is never used.\n" - "[test.cpp:4]: (style) Variable 'i' is assigned a value that is never used.\n", // duplicate - errout_str()); + ASSERT_EQUALS("[test.cpp:4]: (style) Variable 'i' is assigned a value that is never used.\n", errout_str()); functionVariableUsage("void foo()\n" "{\n" @@ -6863,10 +6854,7 @@ class TestUnusedVar : public TestFixture { functionVariableUsage("void f(int* p) {\n" " int* q{ p };\n" "}\n"); - ASSERT_EQUALS( - "[test.cpp:2]: (style) Variable 'q' is assigned a value that is never used.\n" - "[test.cpp:2]: (style) Variable 'q' is assigned a value that is never used.\n", // duplicate - errout_str()); + ASSERT_EQUALS("[test.cpp:2]: (style) Variable 'q' is assigned a value that is never used.\n", errout_str()); } void localvarRangeBasedFor() { diff --git a/test/testvarid.cpp b/test/testvarid.cpp index 990faa58718..610a77de59a 100644 --- a/test/testvarid.cpp +++ b/test/testvarid.cpp @@ -2924,11 +2924,11 @@ class TestVarID : public TestFixture { } void varid_cpp11initialization() { - ASSERT_EQUALS("1: int i@1 ; i@1 = 1 ;\n" + ASSERT_EQUALS("1: int i@1 { 1 } ;\n" "2: std :: vector < int > vec@2 { 1 , 2 , 3 } ;\n" "3: namespace n { int z@3 ; } ;\n" "4: int & j@4 { i@1 } ;\n" - "5: int k@5 ; k@5 = 1 ; int l@6 ; l@6 = 2 ;\n", + "5: int k@5 { 1 } ; int l@6 { 2 } ;\n", tokenize("int i{1};\n" "std::vector vec{1, 2, 3};\n" "namespace n { int z; };\n" @@ -2947,7 +2947,7 @@ class TestVarID : public TestFixture { ASSERT_EQUALS("1: class A : public B , public C :: D , public E < F > :: G < H > {\n" "2: int i@1 ;\n" "3: A ( int i@2 ) : B { i@2 } , C :: D { i@2 } , E < F > :: G < H > { i@2 } , i@1 { i@2 } {\n" - "4: int j@3 ; j@3 = i@2 ;\n" + "4: int j@3 { i@2 } ;\n" "5: }\n" "6: } ;\n", tokenize("class A: public B, public C::D, public E::G {\n" @@ -3818,7 +3818,7 @@ class TestVarID : public TestFixture { const char expected[] = "1: class A : public B , public C :: D {\n" "2: int i@1 ;\n" "3: A ( int i@2 ) : B ( i@2 ) , C :: D ( i@2 ) , i@1 ( i@2 ) {\n" - "4: int j@3 ; j@3 = i@2 ;\n" + "4: int j@3 ( i@2 ) ;\n" "5: }\n" "6: } ;\n"; ASSERT_EQUALS(expected, tokenize(code)); From 0686b6429966c8e9ee548e490d3174787ddb7fc0 Mon Sep 17 00:00:00 2001 From: Oleksandr Labetskyi Date: Fri, 24 Jan 2025 20:46:33 +0200 Subject: [PATCH 2/2] Format --- lib/tokenize.cpp | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 128b4e05f27..394956bf2b1 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -7690,25 +7690,26 @@ void Tokenizer::simplifyInitVar() continue; if (Token::Match(tok, "%type% *|&| %name% (|{")) { - while(tok && !Token::Match(tok, "(|{")) + while (tok && !Token::Match(tok, "(|{")) tok = tok->next(); - tok->isInitBracket(true); + if (tok) + tok->isInitBracket(true); /* tok = initVar(tok); - } else if (Token::Match(tok, "%type% *| %name% ( %type% (")) { - const Token* tok2 = tok->tokAt(2); - if (!tok2->link()) + } else if (Token::Match(tok, "%type% *| %name% ( %type% (")) { + const Token* tok2 = tok->tokAt(2); + if (!tok2->link()) tok2 = tok2->next(); - if (!tok2->link() || (tok2->link()->strAt(1) == ";" && !Token::simpleMatch(tok2->linkAt(2), ") ("))) + if (!tok2->link() || (tok2->link()->strAt(1) == ";" && !Token::simpleMatch(tok2->linkAt(2), ") ("))) tok = initVar(tok); - } else if (Token::Match(tok, "class|struct|union| %type% *| %name% ( &| %any% ) ,") && tok->str() != "new") { - Token *tok1 = tok->tokAt(5); - while (tok1->str() != ",") + } else if (Token::Match(tok, "class|struct|union| %type% *| %name% ( &| %any% ) ,") && tok->str() != "new") { + Token *tok1 = tok->tokAt(5); + while (tok1->str() != ",") tok1 = tok1->next(); - tok1->str(";"); + tok1->str(";"); - const int numTokens = (Token::Match(tok, "class|struct|union")) ? 2 : 1; - TokenList::insertTokens(tok1, tok, numTokens); - tok = initVar(tok); */ + const int numTokens = (Token::Match(tok, "class|struct|union")) ? 2 : 1; + TokenList::insertTokens(tok1, tok, numTokens); + tok = initVar(tok); */ } } }