From 01343100eb014f299f84db3d86beb417af874f3f Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Mon, 31 Oct 2022 20:08:56 +0100 Subject: [PATCH 01/10] Update tokenlist.cpp --- lib/tokenlist.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index 342decd7fcb..a1cf0b8ddbc 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -504,7 +504,8 @@ static Token* skipDecl(Token* tok, std::vector* inner = nullptr) return tok; } else if (Token::Match(vartok, "%var% [:=(]")) { return vartok; - } else if (Token::Match(vartok, "decltype|typeof (") && !Token::Match(tok->linkAt(1), ") [,)]")) { + } else if (Token::Match(vartok, "decltype|typeof (") && + (!Token::Match(tok->linkAt(1), ") ,|)|%name%") || Token::Match(tok->linkAt(1), ") %name% [:=]"))) { if (inner) inner->push_back(vartok->tokAt(2)); return vartok->linkAt(1)->next(); From 08961e7173e0a2526aac8e97b1686cac57fc46ca Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Mon, 31 Oct 2022 21:23:47 +0100 Subject: [PATCH 02/10] Update testincompletestatement.cpp --- test/testincompletestatement.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/testincompletestatement.cpp b/test/testincompletestatement.cpp index 7106fb7f39a..ddf136bf12b 100644 --- a/test/testincompletestatement.cpp +++ b/test/testincompletestatement.cpp @@ -709,6 +709,12 @@ class TestIncompleteStatement : public TestFixture { " (*s).i;\n" "}\n"); ASSERT_EQUALS("[test.cpp:3]: (warning) Redundant code: Found unused member access.\n", errout.str()); + + check("int a[2];\n" // #11370 + "void f() {\n" + " auto g = [](decltype(a[0]) i) {};\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); } void vardecl() { From 4871c0e1b2c340f8bb95fa96b3c872f0b5fd172b Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Mon, 31 Oct 2022 23:35:20 +0100 Subject: [PATCH 03/10] Fix #11370 FP constStatement with lambda --- lib/tokenlist.cpp | 14 ++++++++++++-- test/testtokenize.cpp | 4 ++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index a1cf0b8ddbc..d4217b23276 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -493,6 +493,17 @@ static Token * createAstAtToken(Token *tok, bool cpp); static Token* skipDecl(Token* tok, std::vector* inner = nullptr) { + auto isDecltypeFuncParam = [](const Token* tok) -> bool { + if (!Token::simpleMatch(tok, ")")) + return false; + tok = tok->next(); + while (Token::Match(tok, "*|&|&&|const")) + tok = tok->next(); + if (Token::simpleMatch(tok, "(")) + tok = tok->link()->next(); + return Token::Match(tok, "%name%| ,|)"); + }; + if (!Token::Match(tok->previous(), "( %name%")) return tok; Token *vartok = tok; @@ -504,8 +515,7 @@ static Token* skipDecl(Token* tok, std::vector* inner = nullptr) return tok; } else if (Token::Match(vartok, "%var% [:=(]")) { return vartok; - } else if (Token::Match(vartok, "decltype|typeof (") && - (!Token::Match(tok->linkAt(1), ") ,|)|%name%") || Token::Match(tok->linkAt(1), ") %name% [:=]"))) { + } else if (Token::Match(vartok, "decltype|typeof (") && !isDecltypeFuncParam(tok->linkAt(1))) { if (inner) inner->push_back(vartok->tokAt(2)); return vartok->linkAt(1)->next(); diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 714dda10649..165fbb28807 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -6243,6 +6243,10 @@ class TestTokenizer : public TestFixture { ASSERT_EQUALS("decltypexy+(yx+{", testAst("decltype(x+y){y+x};")); ASSERT_EQUALS("adecltypeac::(,decltypead::(,", testAst("template void b(a &, decltype(a::c), decltype(a::d));")); + ASSERT_EQUALS("g{([= decltypea0[(", + testAst("auto g = [](decltype(a[0]) i) {};")); + ASSERT_EQUALS("g{([= decltypea0[(i&", + testAst("auto g = [](decltype(a[0])& i) {};")); ASSERT_NO_THROW(tokenizeAndStringify("struct A;\n" // #10839 "struct B { A* hash; };\n" From 19d8e5ebcba457ba4af171120c519aa725b822da Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Mon, 31 Oct 2022 23:37:51 +0100 Subject: [PATCH 04/10] Format --- test/testincompletestatement.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/testincompletestatement.cpp b/test/testincompletestatement.cpp index ddf136bf12b..a5a340e9773 100644 --- a/test/testincompletestatement.cpp +++ b/test/testincompletestatement.cpp @@ -712,7 +712,7 @@ class TestIncompleteStatement : public TestFixture { check("int a[2];\n" // #11370 "void f() {\n" - " auto g = [](decltype(a[0]) i) {};\n" + " auto g = [](decltype(a[0]) i) {};\n" "}\n"); ASSERT_EQUALS("", errout.str()); } From 85736c12f0546f157d1f614275eef723169ebaf9 Mon Sep 17 00:00:00 2001 From: chrchr Date: Wed, 2 Nov 2022 12:44:14 +0100 Subject: [PATCH 05/10] Fix crash on nullptr --- lib/tokenlist.cpp | 2 +- test/testtokenize.cpp | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index d4217b23276..c921cab009a 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -656,7 +656,7 @@ static bool iscpp11init_impl(const Token * const tok) if (!Token::Match(colonTok->tokAt(-1), "%name%|%num% :")) return false; const Token* caseTok = colonTok->tokAt(-2); - while (Token::Match(caseTok->tokAt(-1), "::|%name%")) + while (caseTok && Token::Match(caseTok->tokAt(-1), "::|%name%")) caseTok = caseTok->tokAt(-1); return Token::simpleMatch(caseTok, "case"); }; diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 165fbb28807..15509d13eac 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -433,6 +433,7 @@ class TestTokenizer : public TestFixture { TEST_CASE(noCrash4); TEST_CASE(noCrash5); // #10603 TEST_CASE(noCrash6); // #10212 + TEST_CASE(noCrash7); // --check-config TEST_CASE(checkConfiguration); @@ -7237,6 +7238,11 @@ class TestTokenizer : public TestFixture { "struct c, true> {};\n")); } + void noCrash7() { + ASSERT_NO_THROW(tokenizeAndStringify("enum : { };\n" + "enum : 3 { };\n")); + } + void checkConfig(const char code[]) { errout.str(""); From 9455db224c97b06aadaaeb494ef9f70939291f09 Mon Sep 17 00:00:00 2001 From: chrchr Date: Mon, 7 Nov 2022 12:47:51 +0100 Subject: [PATCH 06/10] Emit syntax error --- lib/tokenize.cpp | 2 ++ test/testtokenize.cpp | 9 +++------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 101e375e149..20d36168759 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -7634,6 +7634,8 @@ void Tokenizer::findGarbageCode() const syntaxError(tok2, "Unexpected token '" + tok2->str() + "'"); } } + if (Token::Match(tok, "enum : %num%| {")) + syntaxError(tok->next(), "Unexpected token '" + tok->next()->str() + "'"); } // Keywords in global scope diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 15509d13eac..2902e42acdc 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -433,7 +433,6 @@ class TestTokenizer : public TestFixture { TEST_CASE(noCrash4); TEST_CASE(noCrash5); // #10603 TEST_CASE(noCrash6); // #10212 - TEST_CASE(noCrash7); // --check-config TEST_CASE(checkConfiguration); @@ -6760,6 +6759,9 @@ class TestTokenizer : public TestFixture { // #9445 - typeof is not a keyword in C ASSERT_NO_THROW(tokenizeAndStringify("void foo() { char *typeof, *value; }", false, Settings::Native, "test.c")); + + ASSERT_THROW_EQUALS(tokenizeAndStringify("enum : { };"), InternalError, "syntax error: Unexpected token ':'"); + ASSERT_THROW_EQUALS(tokenizeAndStringify("enum : 3 { };"), InternalError, "syntax error: Unexpected token ':'"); } @@ -7238,11 +7240,6 @@ class TestTokenizer : public TestFixture { "struct c, true> {};\n")); } - void noCrash7() { - ASSERT_NO_THROW(tokenizeAndStringify("enum : { };\n" - "enum : 3 { };\n")); - } - void checkConfig(const char code[]) { errout.str(""); From 0a0bf45bc515b5167ee576b4e6651141bcc75df6 Mon Sep 17 00:00:00 2001 From: chrchr Date: Mon, 7 Nov 2022 12:49:42 +0100 Subject: [PATCH 07/10] Fix test --- lib/tokenize.cpp | 2 +- test/testtokenize.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 20d36168759..38857a8caab 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -7635,7 +7635,7 @@ void Tokenizer::findGarbageCode() const } } if (Token::Match(tok, "enum : %num%| {")) - syntaxError(tok->next(), "Unexpected token '" + tok->next()->str() + "'"); + syntaxError(tok->tokAt(2), "Unexpected token '" + tok->tokAt(2)->str() + "'"); } // Keywords in global scope diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 2902e42acdc..b1243aa3505 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -6760,8 +6760,8 @@ class TestTokenizer : public TestFixture { // #9445 - typeof is not a keyword in C ASSERT_NO_THROW(tokenizeAndStringify("void foo() { char *typeof, *value; }", false, Settings::Native, "test.c")); - ASSERT_THROW_EQUALS(tokenizeAndStringify("enum : { };"), InternalError, "syntax error: Unexpected token ':'"); - ASSERT_THROW_EQUALS(tokenizeAndStringify("enum : 3 { };"), InternalError, "syntax error: Unexpected token ':'"); + ASSERT_THROW_EQUALS(tokenizeAndStringify("enum : { };"), InternalError, "syntax error: Unexpected token '{'"); + ASSERT_THROW_EQUALS(tokenizeAndStringify("enum : 3 { };"), InternalError, "syntax error: Unexpected token '3'"); } From 6e95121d6c811e44e24054a609aa28ed74c05146 Mon Sep 17 00:00:00 2001 From: chrchr Date: Mon, 7 Nov 2022 13:42:15 +0100 Subject: [PATCH 08/10] Use strAt() --- lib/tokenize.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 38857a8caab..0fcb1588b03 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -7635,7 +7635,7 @@ void Tokenizer::findGarbageCode() const } } if (Token::Match(tok, "enum : %num%| {")) - syntaxError(tok->tokAt(2), "Unexpected token '" + tok->tokAt(2)->str() + "'"); + syntaxError(tok->tokAt(2), "Unexpected token '" + tok->strAt(2) + "'"); } // Keywords in global scope From 9d9932d9acba42d1c5badee2879359ac4feac48e Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Mon, 7 Nov 2022 22:17:07 +0100 Subject: [PATCH 09/10] Fix another crash on nullptr --- lib/checkclass.cpp | 16 ++++++++++++++++ test/testconstructors.cpp | 8 ++++++++ 2 files changed, 24 insertions(+) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 18cbf3b79b8..bc568a232d1 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -686,6 +686,22 @@ void CheckClass::assignAllVar(std::vector &usageList) i.assign = true; } +void CheckClass::assignAllVarsVisibleFromScope(std::vector& usageList, const Scope* scope) +{ + for (Usage& usage : usageList) { + if (usage.var->scope() == scope) + usage.assign = true; + } + + // Iterate through each base class... + for (const Type::BaseInfo& i : scope->definedType->derivedFrom) { + const Type *derivedFrom = i.type; + + if (derivedFrom) + assignAllVarsVisibleFromScope(usageList, derivedFrom->classScope); + } +} + void CheckClass::clearAllVar(std::vector &usageList) { for (Usage & i : usageList) { diff --git a/test/testconstructors.cpp b/test/testconstructors.cpp index 7b0af6b7849..a01ba97904d 100644 --- a/test/testconstructors.cpp +++ b/test/testconstructors.cpp @@ -1415,6 +1415,14 @@ class TestConstructors : public TestFixture { "[test.cpp:9]: (warning) Member variable 'B::ca' is not assigned a value in 'B::operator='.\n", errout.str()); + check("class C : B {\n" + " virtual C& operator=(C& c);\n" + "};\n" + "class D : public D {\n" + " virtual C& operator=(C& c) { return C::operator=(c); };\n" + "};\n"); + ASSERT_EQUALS("", errout.str()); + } void initvar_derived_pod_struct_with_union() { From ef16eda1f659ebd42fa3dfb7231ef5084ad1f389 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Tue, 8 Nov 2022 15:13:40 +0100 Subject: [PATCH 10/10] Update testconstructors.cpp --- test/testconstructors.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/testconstructors.cpp b/test/testconstructors.cpp index 1cd6006d49c..e49a66ce2d1 100644 --- a/test/testconstructors.cpp +++ b/test/testconstructors.cpp @@ -1443,7 +1443,7 @@ class TestConstructors : public TestFixture { check("class C : B {\n" " virtual C& operator=(C& c);\n" "};\n" - "class D : public D {\n" + "class D : public C {\n" " virtual C& operator=(C& c) { return C::operator=(c); };\n" "};\n"); ASSERT_EQUALS("", errout.str());