Skip to content

Commit

Permalink
Fix #12447 FN cstyleCast when casting to reference (#5998)
Browse files Browse the repository at this point in the history
  • Loading branch information
chrchr-github committed Feb 21, 2024
1 parent fa40b5e commit cec4b11
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 13 deletions.
23 changes: 15 additions & 8 deletions lib/checkother.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -321,11 +321,17 @@ void CheckOther::warningOldStylePointerCast()
if (Token::simpleMatch(castTok, "<") && castTok->link())
castTok = castTok->link()->next();
}
if (castTok == tok->next() || !Token::simpleMatch(castTok, "*"))
continue;
while (Token::Match(castTok, "*|const|&"))
if (castTok == tok->next())
continue;
bool isPtr = false, isRef = false;
while (Token::Match(castTok, "*|const|&")) {
if (castTok->str() == "*")
isPtr = true;
else if (castTok->str() == "&")
isRef = true;
castTok = castTok->next();
if (!Token::Match(castTok, ") (| %name%|%num%|%bool%|%char%|%str%|&"))
}
if ((!isPtr && !isRef) || !Token::Match(castTok, ") (| %name%|%num%|%bool%|%char%|%str%|&"))
continue;

if (Token::Match(tok->previous(), "%type%"))
Expand All @@ -344,16 +350,17 @@ void CheckOther::warningOldStylePointerCast()
continue;

if (typeTok->tokType() == Token::eType || typeTok->tokType() == Token::eName)
cstyleCastError(tok);
cstyleCastError(tok, isPtr);
}
}
}

void CheckOther::cstyleCastError(const Token *tok)
void CheckOther::cstyleCastError(const Token *tok, bool isPtr)
{
const std::string type = isPtr ? "pointer" : "reference";
reportError(tok, Severity::style, "cstyleCast",
"C-style pointer casting\n"
"C-style pointer casting detected. C++ offers four different kinds of casts as replacements: "
"C-style " + type + " casting\n"
"C-style " + type + " casting detected. C++ offers four different kinds of casts as replacements: "
"static_cast, const_cast, dynamic_cast and reinterpret_cast. A C-style cast could evaluate to "
"any of those automatically, thus it is considered safer if the programmer explicitly states "
"which kind of cast is expected.", CWE398, Certainty::normal);
Expand Down
2 changes: 1 addition & 1 deletion lib/checkother.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ class CPPCHECKLIB CheckOther : public Check {
void checkCastIntToCharAndBackError(const Token *tok, const std::string &strFunctionName);
void clarifyCalculationError(const Token *tok, const std::string &op);
void clarifyStatementError(const Token* tok);
void cstyleCastError(const Token *tok);
void cstyleCastError(const Token *tok, bool isPtr = true);
void invalidPointerCastError(const Token* tok, const std::string& from, const std::string& to, bool inconclusive, bool toIsInt);
void passedByValueError(const Variable* var, bool inconclusive, bool isRangeBasedFor = false);
void constVariableError(const Variable *var, const Function *function);
Expand Down
19 changes: 15 additions & 4 deletions test/testother.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1911,6 +1911,13 @@ class TestOther : public TestFixture {
"[test.cpp:8]: (style) C-style pointer casting\n"
"[test.cpp:9]: (style) C-style pointer casting\n",
errout.str());

// #12447
checkOldStylePointerCast("void f(const int& i) {\n"
" int& r = (int&)i;\n"
" r = 0;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:2]: (style) C-style reference casting\n", errout.str());
}

#define checkInvalidPointerCast(...) checkInvalidPointerCast_(__FILE__, __LINE__, __VA_ARGS__)
Expand Down Expand Up @@ -2884,27 +2891,31 @@ class TestOther : public TestFixture {
" x.dostuff();\n"
" const U& y = (const U&)(x);\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 'x' can be declared as reference to const\n", errout.str());
ASSERT_EQUALS("[test.cpp:4]: (style) C-style reference casting\n"
"[test.cpp:2]: (style) Parameter 'x' can be declared as reference to const\n",
errout.str());
check("struct T : public U { void dostuff() const {}};\n"
"void a(T& x) {\n"
" x.dostuff();\n"
" U& y = (U&)(x);\n"
" y.mutate();\n" // to avoid warnings that y can be const
"}");
ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("[test.cpp:4]: (style) C-style reference casting\n", errout.str());
check("struct T : public U { void dostuff() const {}};\n"
"void a(T& x) {\n"
" x.dostuff();\n"
" const U& y = (typename const U&)(x);\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 'x' can be declared as reference to const\n", errout.str());
ASSERT_EQUALS("[test.cpp:4]: (style) C-style reference casting\n"
"[test.cpp:2]: (style) Parameter 'x' can be declared as reference to const\n",
errout.str());
check("struct T : public U { void dostuff() const {}};\n"
"void a(T& x) {\n"
" x.dostuff();\n"
" U& y = (typename U&)(x);\n"
" y.mutate();\n" // to avoid warnings that y can be const
"}");
ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("[test.cpp:4]: (style) C-style reference casting\n", errout.str());
check("struct T : public U { void dostuff() const {}};\n"
"void a(T& x) {\n"
" x.dostuff();\n"
Expand Down

0 comments on commit cec4b11

Please sign in to comment.