From 7bbdc95f25f05905cb2ec69f354dc274ce97a10e Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Wed, 11 Jan 2023 22:04:06 +0100 Subject: [PATCH] Fix #11473 FP constVariable / #11448 FP constParameter / #11188 FP danglingTempReference (#4680) * Fix #11473 FP constVariable with range-based for / #11448 FP constParameter with unused non-const range loop variable * Fix ValueType / #11188 FP danglingTempReference with auto * Fix ValueType in range-based for * Update symboldatabase.cpp --- lib/checkother.cpp | 7 +++++++ lib/symboldatabase.cpp | 6 ++++-- test/testautovariables.cpp | 7 +++++++ test/testother.cpp | 13 +++++++++++-- test/testsymboldatabase.cpp | 37 +++++++++++++++++++++++++++++++++---- 5 files changed, 62 insertions(+), 8 deletions(-) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 3380aa770..d1e85de77 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1464,6 +1464,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/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 1ab4402f5..96e85e9d8 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -6132,7 +6132,7 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, Source if (autoTok->strAt(1) == "*" && vt.pointer) vt.pointer--; if (Token::Match(autoTok->tokAt(-1), "const|constexpr")) - vt.constness |= 1; + vt.constness |= (1 << vt.pointer); setValueType(autoTok, vt); setAutoTokenProperties(autoTok); if (vt2->pointer > vt.pointer) @@ -6338,8 +6338,10 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, Source setValueType(autoToken, autovt); setAutoTokenProperties(autoToken); ValueType varvt(autovt); + if (autoToken->strAt(1) == "*" && autovt.pointer) + autovt.pointer--; if (isconst) - varvt.constness |= 1; + varvt.constness |= (1 << autovt.pointer); setValueType(parent->previous(), varvt); Variable * var = const_cast(parent->previous()->variable()); if (var) { diff --git a/test/testautovariables.cpp b/test/testautovariables.cpp index e6b0c3769..854404485 100644 --- a/test/testautovariables.cpp +++ b/test/testautovariables.cpp @@ -2022,6 +2022,13 @@ private: " const int& x = (*e)[1];\n" "}\n"); ASSERT_EQUALS("", 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/testother.cpp b/test/testother.cpp index b19e3b5bc..cc25a16fa 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -2349,8 +2349,7 @@ private: 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 @@ private: " 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() { diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 452108535..2baee0221 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -500,6 +500,7 @@ private: 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 @@ private: 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 @@ private: 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 @@ private: 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"