From 7696fa90b29878cb195c1d7af1d66f5af4377616 Mon Sep 17 00:00:00 2001 From: chrchr Date: Mon, 2 Jan 2023 20:39:54 +0100 Subject: [PATCH 1/4] Fix #11473 FP constVariable with range-based for / #11448 FP constParameter with unused non-const range loop variable --- lib/checkother.cpp | 7 +++++++ test/testother.cpp | 16 ++++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 6485ee4ccc5..32d07b1e1ec 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1473,6 +1473,13 @@ void CheckOther::checkConstVariable() break; } } + if (astIsRangeBasedForDecl(tok) && Token::Match(tok->astParent()->astOperand2(), "%varid%", var->declarationId())) { + const Variable* refvar = tok->astParent()->astOperand1()->variable(); + if (refvar && refvar->isReference() && !refvar->isConst()) { + usedInAssignment = true; + break; + } + } } if (usedInAssignment) continue; diff --git a/test/testother.cpp b/test/testother.cpp index b19e3b5bcfe..880c756bbfa 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -2349,8 +2349,7 @@ class TestOther : public TestFixture { check("void f(std::vector& v) {\n" " for(auto& x:v) {}\n" "}"); - ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'v' can be declared as reference to const\n" - "[test.cpp:2]: (style) Variable 'x' can be declared as reference to const\n", + ASSERT_EQUALS("[test.cpp:2]: (style) Variable 'x' can be declared as reference to const\n", errout.str()); check("void f(std::vector& v) {\n" // #10980 @@ -3019,6 +3018,16 @@ class TestOther : public TestFixture { " std::cout << m[0] << std::endl;\n" "};\n"); ASSERT_EQUALS("", errout.str()); + + check("struct S { int i; };\n" // #11473 + "void f(std::vector>&m, int*& p) {\n" + " auto& a = m[0];\n" + " for (auto& s : a) {\n" + " p = &s.i;\n" + " return;\n" + " }\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); } void constParameterCallback() { @@ -3230,8 +3239,7 @@ class TestOther : public TestFixture { " for (const int* p : v)\n" " if (p == nullptr) {}\n" "}\n"); - ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'v' can be declared as reference to const\n" - "[test.cpp:2]: (style) Variable 'p' can be declared as pointer to const\n", + ASSERT_EQUALS("[test.cpp:2]: (style) Variable 'p' can be declared as pointer to const\n", errout.str()); check("void f(std::vector& v) {\n" From bed7dd928dcb33b3e856d5710c1f338c10f8e6ee Mon Sep 17 00:00:00 2001 From: chrchr Date: Tue, 3 Jan 2023 19:24:57 +0100 Subject: [PATCH 2/4] Fix ValueType / #11188 FP danglingTempReference with auto --- lib/symboldatabase.cpp | 8 ++++++-- test/testautovariables.cpp | 7 +++++++ test/testsymboldatabase.cpp | 37 +++++++++++++++++++++++++++++++++---- 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 4d01d35b194..19ad6fd44f3 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -6131,8 +6131,12 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, Source vt.constness &= ~(1 << vt.pointer); if (autoTok->strAt(1) == "*" && vt.pointer) vt.pointer--; - if (Token::Match(autoTok->tokAt(-1), "const|constexpr")) - vt.constness |= 1; + if (Token::Match(autoTok->tokAt(-1), "const|constexpr")) { + if (vt.pointer) + vt.constness |= (1 << vt.pointer); + else + vt.constness |= 1; + } setValueType(autoTok, vt); setAutoTokenProperties(autoTok); if (vt2->pointer > vt.pointer) diff --git a/test/testautovariables.cpp b/test/testautovariables.cpp index 3ddc8325b73..64a41cc1cd9 100644 --- a/test/testautovariables.cpp +++ b/test/testautovariables.cpp @@ -1995,6 +1995,13 @@ class TestAutoVariables : public TestFixture { ASSERT_EQUALS( "[test.cpp:11] -> [test.cpp:2] -> [test.cpp:11] -> [test.cpp:12]: (error) Using reference to dangling temporary.\n", errout.str()); + + check("int* g();\n" // #11188 + "void f() {\n" + " const auto& p = g();\n" + " if (p != nullptr) {}\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); } void testglobalnamespace() { diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 4521085356f..2baee022197 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -500,6 +500,7 @@ class TestSymbolDatabase : public TestFixture { TEST_CASE(auto15); // C++17 auto deduction from braced-init-list TEST_CASE(auto16); TEST_CASE(auto17); // #11163 + TEST_CASE(auto18); TEST_CASE(unionWithConstructor); @@ -8469,14 +8470,14 @@ class TestSymbolDatabase : public TestFixture { autotok = Token::findsimplematch(autotok, "auto v4"); ASSERT(autotok); ASSERT(autotok->valueType()); - TODO_ASSERT_EQUALS(0, 1, autotok->valueType()->constness); + ASSERT_EQUALS(3, autotok->valueType()->constness); ASSERT_EQUALS(1, autotok->valueType()->pointer); ASSERT_EQUALS(ValueType::SIGNED, autotok->valueType()->sign); ASSERT_EQUALS(ValueType::INT, autotok->valueType()->type); vartok = Token::findsimplematch(autotok, "v4 ="); ASSERT(autotok); ASSERT(autotok->valueType()); - ASSERT_EQUALS(1, vartok->valueType()->constness); + ASSERT_EQUALS(3, vartok->valueType()->constness); ASSERT_EQUALS(1, vartok->valueType()->pointer); ASSERT_EQUALS(ValueType::SIGNED, vartok->valueType()->sign); ASSERT_EQUALS(ValueType::INT, vartok->valueType()->type); @@ -8549,14 +8550,14 @@ class TestSymbolDatabase : public TestFixture { autotok = Token::findsimplematch(autotok, "auto v9"); ASSERT(autotok); ASSERT(autotok->valueType()); - TODO_ASSERT_EQUALS(0, 1, autotok->valueType()->constness); + ASSERT_EQUALS(3, autotok->valueType()->constness); ASSERT_EQUALS(1, autotok->valueType()->pointer); ASSERT_EQUALS(ValueType::SIGNED, autotok->valueType()->sign); ASSERT_EQUALS(ValueType::INT, autotok->valueType()->type); vartok = Token::findsimplematch(autotok, "v9 ="); ASSERT(autotok); ASSERT(autotok->valueType()); - ASSERT_EQUALS(1, vartok->valueType()->constness); + ASSERT_EQUALS(3, vartok->valueType()->constness); ASSERT_EQUALS(1, vartok->valueType()->pointer); ASSERT_EQUALS(ValueType::SIGNED, vartok->valueType()->sign); ASSERT_EQUALS(ValueType::INT, vartok->valueType()->type); @@ -8750,6 +8751,34 @@ class TestSymbolDatabase : public TestFixture { ASSERT_EQUALS(5, db->variableList().size()); } + void auto18() { + GET_SYMBOL_DB("void f(const int* p) {\n" + " const int* const& r = p;\n" + " const auto& s = p;\n" + "}\n"); + ASSERT_EQUALS(4, db->variableList().size()); + + const Variable* r = db->variableList()[2]; + ASSERT(r->isReference()); + ASSERT(r->isConst()); + ASSERT(r->isPointer()); + const Token* varTok = Token::findsimplematch(tokenizer.tokens(), "r"); + ASSERT(varTok && varTok->valueType()); + ASSERT_EQUALS(varTok->valueType()->constness, 3); + ASSERT_EQUALS(varTok->valueType()->pointer, 1); + ASSERT(varTok->valueType()->reference == Reference::LValue); + + const Variable* s = db->variableList()[3]; + ASSERT(s->isReference()); + ASSERT(s->isConst()); + ASSERT(s->isPointer()); + const Token* autoTok = Token::findsimplematch(tokenizer.tokens(), "auto"); + ASSERT(autoTok && autoTok->valueType()); + ASSERT_EQUALS(autoTok->valueType()->constness, 3); + ASSERT_EQUALS(autoTok->valueType()->pointer, 1); + TODO_ASSERT(autoTok->valueType()->reference == Reference::LValue); + } + void unionWithConstructor() { GET_SYMBOL_DB("union Fred {\n" " Fred(int x) : i(x) { }\n" From 1d44925f7a4671e249611dc3bf442058ab9cbe16 Mon Sep 17 00:00:00 2001 From: chrchr Date: Tue, 3 Jan 2023 20:10:19 +0100 Subject: [PATCH 3/4] Fix ValueType in range-based for --- lib/symboldatabase.cpp | 10 ++++++++-- test/testother.cpp | 3 ++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 19ad6fd44f3..dbf781f0d99 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -6342,8 +6342,14 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, Source setValueType(autoToken, autovt); setAutoTokenProperties(autoToken); ValueType varvt(autovt); - if (isconst) - varvt.constness |= 1; + if (autoToken->strAt(1) == "*" && autovt.pointer) + autovt.pointer--; + if (isconst) { + if (autovt.pointer) + varvt.constness |= (1 << autovt.pointer); + else + varvt.constness |= 1; + } setValueType(parent->previous(), varvt); Variable * var = const_cast(parent->previous()->variable()); if (var) { diff --git a/test/testother.cpp b/test/testother.cpp index 880c756bbfa..cc25a16fa46 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -3239,7 +3239,8 @@ class TestOther : public TestFixture { " for (const int* p : v)\n" " if (p == nullptr) {}\n" "}\n"); - ASSERT_EQUALS("[test.cpp:2]: (style) Variable 'p' can be declared as pointer to const\n", + ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'v' can be declared as reference to const\n" + "[test.cpp:2]: (style) Variable 'p' can be declared as pointer to const\n", errout.str()); check("void f(std::vector& v) {\n" From d99adf6bc7921e1a0bc4c09afaf88b948051d218 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Fri, 6 Jan 2023 20:39:41 +0100 Subject: [PATCH 4/4] Update symboldatabase.cpp --- lib/symboldatabase.cpp | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index dbf781f0d99..e130e11cf70 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -6131,12 +6131,8 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, Source vt.constness &= ~(1 << vt.pointer); if (autoTok->strAt(1) == "*" && vt.pointer) vt.pointer--; - if (Token::Match(autoTok->tokAt(-1), "const|constexpr")) { - if (vt.pointer) - vt.constness |= (1 << vt.pointer); - else - vt.constness |= 1; - } + if (Token::Match(autoTok->tokAt(-1), "const|constexpr")) + vt.constness |= (1 << vt.pointer); setValueType(autoTok, vt); setAutoTokenProperties(autoTok); if (vt2->pointer > vt.pointer) @@ -6344,12 +6340,8 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, Source ValueType varvt(autovt); if (autoToken->strAt(1) == "*" && autovt.pointer) autovt.pointer--; - if (isconst) { - if (autovt.pointer) - varvt.constness |= (1 << autovt.pointer); - else - varvt.constness |= 1; - } + if (isconst) + varvt.constness |= (1 << autovt.pointer); setValueType(parent->previous(), varvt); Variable * var = const_cast(parent->previous()->variable()); if (var) {