Skip to content

Commit

Permalink
Fix FP truncLongCastReturn on Windows
Browse files Browse the repository at this point in the history
  • Loading branch information
chrchr-github committed Jul 24, 2023
1 parent d2546d5 commit f5b81ac
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 20 deletions.
32 changes: 21 additions & 11 deletions lib/checktype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,17 @@ void CheckType::signConversionError(const Token *tok, const ValueFlow::Value *ne
// Checking for long cast of int result const long x = var1 * var2;
//---------------------------------------------------------------------------

static bool isSmallerTypeSize(const ValueType* a, const ValueType* b, const Tokenizer* tokenizer)
{
std::string strArr[] = { a->str(), b->str() };
for (std::string& s : strArr) {
const std::size_t pos = s.rfind(' '); // get bare type string
if (pos != std::string::npos)
s.erase(s.begin(), s.begin() + pos + 1);
}
return tokenizer->sizeOfType(strArr[0]) < tokenizer->sizeOfType(strArr[1]);
}

void CheckType::checkLongCast()
{
if (!mSettings->severity.isEnabled(Severity::style))
Expand Down Expand Up @@ -319,7 +330,8 @@ void CheckType::checkLongCast()
(lhstype->type == ValueType::Type::LONG || lhstype->type == ValueType::Type::LONGLONG) &&
lhstype->pointer == 0U &&
lhstype->constness == 1U &&
lhstype->originalTypeName.empty())
lhstype->originalTypeName.empty() &&
isSmallerTypeSize(rhstype, lhstype, mTokenizer))
longCastAssignError(tok);
}

Expand All @@ -329,15 +341,10 @@ void CheckType::checkLongCast()

// function must return long data
const Token * def = scope->classDef;
bool islong = false;
while (Token::Match(def, "%type%|::")) {
if (def->str() == "long" && def->originalName().empty()) {
islong = true;
break;
}
def = def->previous();
}
if (!islong)
if (!Token::Match(def, "%name% (") || !def->next()->valueType())
continue;
const ValueType* retVt = def->next()->valueType();
if (retVt->type != ValueType::Type::LONG && retVt->type != ValueType::Type::LONGLONG)
continue;

// return statements
Expand All @@ -346,7 +353,10 @@ void CheckType::checkLongCast()
if (tok->str() == "return") {
if (Token::Match(tok->astOperand1(), "<<|*")) {
const ValueType *type = tok->astOperand1()->valueType();
if (type && type->type == ValueType::Type::INT && type->pointer == 0U && type->originalTypeName.empty())
if (type && type->type == ValueType::Type::INT &&
type->pointer == 0U &&
type->originalTypeName.empty() &&
isSmallerTypeSize(type, retVt, mTokenizer))
ret = tok;
}
// All return statements must have problem otherwise no warning
Expand Down
26 changes: 17 additions & 9 deletions test/testtype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,12 +326,16 @@ class TestType : public TestFixture {

void longCastAssign() {
const Settings settings = settingsBuilder().severity(Severity::style).platform(cppcheck::Platform::Type::Unix64).build();
const Settings settingsWin = settingsBuilder().severity(Severity::style).platform(cppcheck::Platform::Type::Win64).build();

check("long f(int x, int y) {\n"
" const long ret = x * y;\n"
" return ret;\n"
"}\n", settings);
const char code[] = "long f(int x, int y) {\n"
" const long ret = x * y;\n"
" return ret;\n"
"}\n";
check(code, settings);
ASSERT_EQUALS("[test.cpp:2]: (style) int result is assigned to long variable. If the variable is long to avoid loss of information, then you have loss of information.\n", errout.str());
check(code, settingsWin);
ASSERT_EQUALS("", errout.str());

check("long f() {\n"
" const long long ret = 256 * (1 << 10);\n"
Expand All @@ -355,18 +359,22 @@ class TestType : public TestFixture {
}

void longCastReturn() {
const Settings settings = settingsBuilder().severity(Severity::style).build();
const Settings settings = settingsBuilder().severity(Severity::style).platform(cppcheck::Platform::Type::Unix64).build();
const Settings settingsWin = settingsBuilder().severity(Severity::style).platform(cppcheck::Platform::Type::Win64).build();

check("long f(int x, int y) {\n"
" return x * y;\n"
"}\n", settings);
const char code[] = "long f(int x, int y) {\n"
" return x * y;\n"
"}\n";
check(code, settings);
ASSERT_EQUALS("[test.cpp:2]: (style) int result is returned as long value. If the return value is long to avoid loss of information, then you have loss of information.\n", errout.str());
check(code, settingsWin);
ASSERT_EQUALS("", errout.str());

// typedef
check("size_t f(int x, int y) {\n"
" return x * y;\n"
"}\n", settings);
ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (style) int result is returned as long value. If the return value is long to avoid loss of information, then you have loss of information.\n", errout.str());
}

// This function ensure that test works with different compilers. Floats can
Expand Down

0 comments on commit f5b81ac

Please sign in to comment.