Skip to content

Commit

Permalink
Fix #12349, #12350, #12351 FN constParameterReference when taking con…
Browse files Browse the repository at this point in the history
…st reference (danmar#5882)
  • Loading branch information
chrchr-github authored Jan 18, 2024
1 parent c5b50ed commit c8bc6f5
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 5 deletions.
5 changes: 5 additions & 0 deletions lib/astutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2474,6 +2474,11 @@ bool isVariableChangedByFunctionCall(const Token *tok, int indirect, const Setti
return true;
}

if (const Variable* var = tok->variable()) {
if (tok == var->nameToken() && (!var->isReference() || var->isConst()) && (var->isStlType() || !var->isClass())) // const ref or passed to (copy) ctor
return false;
}

std::vector<const Variable*> args = getArgumentVars(tok, argnr);
bool conclusive = false;
for (const Variable *arg:args) {
Expand Down
2 changes: 1 addition & 1 deletion lib/checkother.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1547,7 +1547,7 @@ void CheckOther::checkConstPointer()
else if (Token::Match(gparent, "%assign%") && parent == gparent->astOperand2()) {
bool takingRef = false, nonConstPtrAssignment = false;
const Token *lhs = gparent->astOperand1();
if (lhs && lhs->variable() && lhs->variable()->isReference() && lhs->variable()->nameToken() == lhs)
if (lhs && lhs->variable() && lhs->variable()->isReference() && lhs->variable()->nameToken() == lhs && !lhs->variable()->isConst())
takingRef = true;
if (lhs && lhs->valueType() && lhs->valueType()->pointer && (lhs->valueType()->constness & 1) == 0 &&
parent->valueType() && parent->valueType()->pointer)
Expand Down
2 changes: 1 addition & 1 deletion lib/symboldatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2381,7 +2381,7 @@ void Variable::evaluate(const Settings* settings)
std::string strtype = mTypeStartToken->str();
for (const Token *typeToken = mTypeStartToken; Token::Match(typeToken, "%type% :: %type%"); typeToken = typeToken->tokAt(2))
strtype += "::" + typeToken->strAt(2);
setFlag(fIsClass, !lib->podtype(strtype) && !mTypeStartToken->isStandardType() && !isEnumType() && !isPointer() && !isReference() && strtype != "...");
setFlag(fIsClass, !lib->podtype(strtype) && !mTypeStartToken->isStandardType() && !isEnumType() && !isPointer() && strtype != "...");
setFlag(fIsStlType, Token::simpleMatch(mTypeStartToken, "std ::"));
setFlag(fIsStlString, ::isStlStringType(mTypeStartToken));
setFlag(fIsSmartPointer, mTypeStartToken->isCpp() && lib->isSmartPointer(mTypeStartToken));
Expand Down
2 changes: 1 addition & 1 deletion test/testnullpointer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3717,7 +3717,7 @@ class TestNullPointer : public TestFixture {
ASSERT_EQUALS("[test.cpp:9]: (error) Null pointer dereference: p\n"
"[test.cpp:10]: (error) Null pointer dereference: p\n"
"[test.cpp:11]: (error) Null pointer dereference: p\n"
"[test.cpp:12]: (warning, inconclusive) Possible null pointer dereference: p\n"
"[test.cpp:12]: (error) Null pointer dereference: p\n"
"[test.cpp:3]: (error) Null pointer dereference\n"
"[test.cpp:5]: (error) Null pointer dereference\n"
"[test.cpp:7]: (error) Null pointer dereference\n"
Expand Down
41 changes: 41 additions & 0 deletions test/testother.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3479,6 +3479,47 @@ class TestOther : public TestFixture {
ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'v' can be declared as reference to const\n"
"[test.cpp:8]: (style) Parameter 'v' can be declared as reference to const\n",
errout.str());

check("void cb(const std::string&);\n" // #12349, #12350, #12351
"void f(std::string& s) {\n"
" const std::string& str(s);\n"
" cb(str);\n"
"}\n"
"void g(std::string& s) {\n"
" const std::string& str{ s };\n"
" cb(str);\n"
"}\n"
"void h(std::string* s) {\n"
" const std::string& str(*s);\n"
" cb(str);\n"
"}\n"
"void k(std::string* s) {\n"
" const std::string& str = *s;\n"
" cb(str);\n"
"}\n"
"void m(std::string& s) {\n"
" const std::string str(s);\n"
" cb(str);\n"
"}\n"
"void n(std::string* s) {\n"
" const std::string& str(*s);\n"
" cb(str);\n"
"}\n");
ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 's' can be declared as reference to const\n"
"[test.cpp:6]: (style) Parameter 's' can be declared as reference to const\n"
"[test.cpp:18]: (style) Parameter 's' can be declared as reference to const\n"
"[test.cpp:10]: (style) Parameter 's' can be declared as pointer to const\n"
"[test.cpp:14]: (style) Parameter 's' can be declared as pointer to const\n"
"[test.cpp:22]: (style) Parameter 's' can be declared as pointer to const\n",
errout.str());

check("struct S {\n"
" S(std::string& r);\n"
"};\n"
"void f(std::string& str) {\n"
" const S& s(str);\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}

void constParameterCallback() {
Expand Down
2 changes: 1 addition & 1 deletion test/teststl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -925,7 +925,7 @@ class TestStl : public TestFixture {
" std::string_view sv(s);\n"
" return s[2];\n"
"}\n");
TODO_ASSERT_EQUALS("test.cpp:4:error:Out of bounds access in expression 's[2]' because 's' is empty.\n", "", errout.str());
ASSERT_EQUALS("test.cpp:4:error:Out of bounds access in expression 's[2]' because 's' is empty.\n", errout.str());
}

void outOfBoundsSymbolic()
Expand Down
2 changes: 1 addition & 1 deletion test/testuninitvar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5562,7 +5562,7 @@ class TestUninitVar : public TestFixture {
" p = new S(io);\n"
" p->Write();\n"
"}");
ASSERT_EQUALS("[test.cpp:8] -> [test.cpp:10]: (warning) Uninitialized variable: p.rIo\n", errout.str());
ASSERT_EQUALS("", errout.str());

// Unknown types
{
Expand Down

0 comments on commit c8bc6f5

Please sign in to comment.