Skip to content

Commit

Permalink
MathLib: added toString() overload for big{u}int (#7084)
Browse files Browse the repository at this point in the history
  • Loading branch information
firewave authored Jan 1, 2025
1 parent 7396c64 commit 8576ec9
Show file tree
Hide file tree
Showing 13 changed files with 72 additions and 48 deletions.
2 changes: 1 addition & 1 deletion lib/astutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ static bool match(const Token *tok, const std::string &rhs)
{
if (tok->str() == rhs)
return true;
if (!tok->varId() && tok->hasKnownIntValue() && std::to_string(tok->values().front().intvalue) == rhs)
if (!tok->varId() && tok->hasKnownIntValue() && MathLib::toString(tok->values().front().intvalue) == rhs)
return true;
return false;
}
Expand Down
14 changes: 7 additions & 7 deletions lib/checkbufferoverrun.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ static int getMinFormatStringOutputLength(const std::vector<const Token*> &param
i_d_x_f_found = true;
parameterLength = 1;
if (inputArgNr < parameters.size() && parameters[inputArgNr]->hasKnownIntValue())
parameterLength = std::to_string(parameters[inputArgNr]->getKnownIntValue()).length();
parameterLength = MathLib::toString(parameters[inputArgNr]->getKnownIntValue()).length();

handleNextParameter = true;
break;
Expand Down Expand Up @@ -365,7 +365,7 @@ void CheckBufferOverrun::arrayIndex()
static std::string stringifyIndexes(const std::string& array, const std::vector<ValueFlow::Value>& indexValues)
{
if (indexValues.size() == 1)
return std::to_string(indexValues[0].intvalue);
return MathLib::toString(indexValues[0].intvalue);

std::ostringstream ret;
ret << array;
Expand All @@ -386,7 +386,7 @@ static std::string arrayIndexMessage(const Token* tok,
const Token* condition)
{
auto add_dim = [](const std::string &s, const Dimension &dim) {
return s + "[" + std::to_string(dim.num) + "]";
return s + "[" + MathLib::toString(dim.num) + "]";
};
const std::string array = std::accumulate(dimensions.cbegin(), dimensions.cend(), tok->astOperand1()->expressionString(), std::move(add_dim));

Expand Down Expand Up @@ -533,7 +533,7 @@ void CheckBufferOverrun::pointerArithmeticError(const Token *tok, const Token *i

std::string errmsg;
if (indexValue->condition)
errmsg = "Undefined behaviour, when '" + indexToken->expressionString() + "' is " + std::to_string(indexValue->intvalue) + " the pointer arithmetic '" + tok->expressionString() + "' is out of bounds.";
errmsg = "Undefined behaviour, when '" + indexToken->expressionString() + "' is " + MathLib::toString(indexValue->intvalue) + " the pointer arithmetic '" + tok->expressionString() + "' is out of bounds.";
else
errmsg = "Undefined behaviour, pointer arithmetic '" + tok->expressionString() + "' is out of bounds.";

Expand Down Expand Up @@ -1027,13 +1027,13 @@ bool CheckBufferOverrun::analyseWholeProgram1(const std::map<std::string, std::l
if (type == 1) {
errorId = "ctuArrayIndex";
if (unsafeUsage.value > 0)
errmsg = "Array index out of bounds; '" + unsafeUsage.myArgumentName + "' buffer size is " + std::to_string(functionCall->callArgValue) + " and it is accessed at offset " + std::to_string(unsafeUsage.value) + ".";
errmsg = "Array index out of bounds; '" + unsafeUsage.myArgumentName + "' buffer size is " + MathLib::toString(functionCall->callArgValue) + " and it is accessed at offset " + MathLib::toString(unsafeUsage.value) + ".";
else
errmsg = "Array index out of bounds; buffer '" + unsafeUsage.myArgumentName + "' is accessed at offset " + std::to_string(unsafeUsage.value) + ".";
errmsg = "Array index out of bounds; buffer '" + unsafeUsage.myArgumentName + "' is accessed at offset " + MathLib::toString(unsafeUsage.value) + ".";
cwe = (unsafeUsage.value > 0) ? CWE_BUFFER_OVERRUN : CWE_BUFFER_UNDERRUN;
} else {
errorId = "ctuPointerArith";
errmsg = "Pointer arithmetic overflow; '" + unsafeUsage.myArgumentName + "' buffer size is " + std::to_string(functionCall->callArgValue);
errmsg = "Pointer arithmetic overflow; '" + unsafeUsage.myArgumentName + "' buffer size is " + MathLib::toString(functionCall->callArgValue);
cwe = CWE_POINTER_ARITHMETIC_OVERFLOW;
}

Expand Down
6 changes: 3 additions & 3 deletions lib/checkcondition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1057,7 +1057,7 @@ static bool parseComparison(const Token *comp, bool &not1, std::string &op, std:
return false;
op = invertOperatorForOperandSwap(comp->str());
if (op1->enumerator() && op1->enumerator()->value_known)
value = std::to_string(op1->enumerator()->value);
value = MathLib::toString(op1->enumerator()->value);
else
value = op1->str();
expr = op2;
Expand All @@ -1066,7 +1066,7 @@ static bool parseComparison(const Token *comp, bool &not1, std::string &op, std:
return false;
op = comp->str();
if (op2->enumerator() && op2->enumerator()->value_known)
value = std::to_string(op2->enumerator()->value);
value = MathLib::toString(op2->enumerator()->value);
else
value = op2->str();
expr = op1;
Expand Down Expand Up @@ -2043,7 +2043,7 @@ void CheckCondition::compareValueOutOfTypeRangeError(const Token *comparison, co
comparison,
Severity::style,
"compareValueOutOfTypeRangeError",
"Comparing expression of type '" + type + "' against value " + std::to_string(value) + ". Condition is always " + bool_to_string(result) + ".",
"Comparing expression of type '" + type + "' against value " + MathLib::toString(value) + ". Condition is always " + bool_to_string(result) + ".",
CWE398,
Certainty::normal);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/checkother.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4007,7 +4007,7 @@ void CheckOther::knownArgumentError(const Token *tok, const Token *ftok, const V
ftype = "init list ";

const char *id;
std::string errmsg = "Argument '" + expr + "' to " + ftype + fun + " is always " + std::to_string(intvalue) + ". ";
std::string errmsg = "Argument '" + expr + "' to " + ftype + fun + " is always " + MathLib::toString(intvalue) + ". ";
if (!isVariableExpressionHidden) {
id = "knownArgument";
errmsg += "It does not matter what value '" + varexpr + "' has.";
Expand Down
12 changes: 6 additions & 6 deletions lib/checkstl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,14 +205,14 @@ void CheckStl::outOfBounds()
static std::string indexValueString(const ValueFlow::Value& indexValue, const std::string& containerName = emptyString)
{
if (indexValue.isIteratorStartValue())
return "at position " + std::to_string(indexValue.intvalue) + " from the beginning";
return "at position " + MathLib::toString(indexValue.intvalue) + " from the beginning";
if (indexValue.isIteratorEndValue())
return "at position " + std::to_string(-indexValue.intvalue) + " from the end";
std::string indexString = std::to_string(indexValue.intvalue);
return "at position " + MathLib::toString(-indexValue.intvalue) + " from the end";
std::string indexString = MathLib::toString(indexValue.intvalue);
if (indexValue.isSymbolicValue()) {
indexString = containerName + ".size()";
if (indexValue.intvalue != 0)
indexString += "+" + std::to_string(indexValue.intvalue);
indexString += "+" + MathLib::toString(indexValue.intvalue);
}
if (indexValue.bound == ValueFlow::Value::Bound::Lower)
return "greater or equal to " + indexString;
Expand Down Expand Up @@ -244,11 +244,11 @@ void CheckStl::outOfBoundsError(const Token *tok, const std::string &containerNa
errmsg = "Out of bounds access in expression '" + expression + "' because '$symbol' is empty.";
} else if (indexValue) {
if (containerSize->condition)
errmsg = ValueFlow::eitherTheConditionIsRedundant(containerSize->condition) + " or size of '$symbol' can be " + std::to_string(containerSize->intvalue) + ". Expression '" + expression + "' causes access out of bounds.";
errmsg = ValueFlow::eitherTheConditionIsRedundant(containerSize->condition) + " or size of '$symbol' can be " + MathLib::toString(containerSize->intvalue) + ". Expression '" + expression + "' causes access out of bounds.";
else if (indexValue->condition)
errmsg = ValueFlow::eitherTheConditionIsRedundant(indexValue->condition) + " or '" + index + "' can have the value " + indexValueString(*indexValue) + ". Expression '" + expression + "' causes access out of bounds.";
else
errmsg = "Out of bounds access in '" + expression + "', if '$symbol' size is " + std::to_string(containerSize->intvalue) + " and '" + index + "' is " + indexValueString(*indexValue);
errmsg = "Out of bounds access in '" + expression + "', if '$symbol' size is " + MathLib::toString(containerSize->intvalue) + " and '" + index + "' is " + indexValueString(*indexValue);
} else {
// should not happen
return;
Expand Down
38 changes: 30 additions & 8 deletions lib/mathlib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,28 @@ double MathLib::toDoubleNumber(const std::string &str)
return ret;
}

template<> std::string MathLib::toString<MathLib::bigint>(MathLib::bigint value)
{
#if defined(HAVE_BOOST) && defined(HAVE_BOOST_INT128)
std::ostringstream result;
result << value;
return result.str();
#else
return std::to_string(value);
#endif
}

template<> std::string MathLib::toString<MathLib::biguint>(MathLib::biguint value)
{
#if defined(HAVE_BOOST) && defined(HAVE_BOOST_INT128)
std::ostringstream result;
result << value;
return result.str();
#else
return std::to_string(value);
#endif
}

template<> std::string MathLib::toString<double>(double value)
{
std::ostringstream result;
Expand Down Expand Up @@ -1059,7 +1081,7 @@ std::string MathLib::add(const std::string & first, const std::string & second)
return (value(first) + value(second)).str();
#else
if (MathLib::isInt(first) && MathLib::isInt(second)) {
return std::to_string(toBigNumber(first) + toBigNumber(second)) + intsuffix(first, second);
return MathLib::toString(toBigNumber(first) + toBigNumber(second)) + intsuffix(first, second);
}

double d1 = toDoubleNumber(first);
Expand All @@ -1081,7 +1103,7 @@ std::string MathLib::subtract(const std::string &first, const std::string &secon
return (value(first) - value(second)).str();
#else
if (MathLib::isInt(first) && MathLib::isInt(second)) {
return std::to_string(toBigNumber(first) - toBigNumber(second)) + intsuffix(first, second);
return MathLib::toString(toBigNumber(first) - toBigNumber(second)) + intsuffix(first, second);
}

if (first == second)
Expand Down Expand Up @@ -1112,7 +1134,7 @@ std::string MathLib::divide(const std::string &first, const std::string &second)
throw InternalError(nullptr, "Internal Error: Division by zero");
if (a == std::numeric_limits<bigint>::min() && std::abs(b)<=1)
throw InternalError(nullptr, "Internal Error: Division overflow");
return std::to_string(toBigNumber(first) / b) + intsuffix(first, second);
return MathLib::toString(toBigNumber(first) / b) + intsuffix(first, second);
}
if (isNullValue(second)) {
if (isNullValue(first))
Expand All @@ -1129,7 +1151,7 @@ std::string MathLib::multiply(const std::string &first, const std::string &secon
return (value(first) * value(second)).str();
#else
if (MathLib::isInt(first) && MathLib::isInt(second)) {
return std::to_string(toBigNumber(first) * toBigNumber(second)) + intsuffix(first, second);
return MathLib::toString(toBigNumber(first) * toBigNumber(second)) + intsuffix(first, second);
}
return toString(toDoubleNumber(first) * toDoubleNumber(second));
#endif
Expand All @@ -1144,7 +1166,7 @@ std::string MathLib::mod(const std::string &first, const std::string &second)
const bigint b = toBigNumber(second);
if (b == 0)
throw InternalError(nullptr, "Internal Error: Division by zero");
return std::to_string(toBigNumber(first) % b) + intsuffix(first, second);
return MathLib::toString(toBigNumber(first) % b) + intsuffix(first, second);
}
return toString(std::fmod(toDoubleNumber(first),toDoubleNumber(second)));
#endif
Expand All @@ -1169,13 +1191,13 @@ std::string MathLib::calculate(const std::string &first, const std::string &seco
return MathLib::mod(first, second);

case '&':
return std::to_string(MathLib::toBigNumber(first) & MathLib::toBigNumber(second)) + intsuffix(first, second);
return MathLib::toString(MathLib::toBigNumber(first) & MathLib::toBigNumber(second)) + intsuffix(first, second);

case '|':
return std::to_string(MathLib::toBigNumber(first) | MathLib::toBigNumber(second)) + intsuffix(first, second);
return MathLib::toString(MathLib::toBigNumber(first) | MathLib::toBigNumber(second)) + intsuffix(first, second);

case '^':
return std::to_string(MathLib::toBigNumber(first) ^ MathLib::toBigNumber(second)) + intsuffix(first, second);
return MathLib::toString(MathLib::toBigNumber(first) ^ MathLib::toBigNumber(second)) + intsuffix(first, second);

default:
throw InternalError(nullptr, std::string("Unexpected action '") + action + "' in MathLib::calculate(). Please report this to Cppcheck developers.");
Expand Down
2 changes: 2 additions & 0 deletions lib/mathlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ MathLib::value operator^(const MathLib::value &v1, const MathLib::value &v2);
MathLib::value operator<<(const MathLib::value &v1, const MathLib::value &v2);
MathLib::value operator>>(const MathLib::value &v1, const MathLib::value &v2);

template<> CPPCHECKLIB std::string MathLib::toString<MathLib::bigint>(MathLib::bigint value);
template<> CPPCHECKLIB std::string MathLib::toString<MathLib::biguint>(MathLib::biguint value);
template<> CPPCHECKLIB std::string MathLib::toString<double>(double value);

/// @}
Expand Down
2 changes: 1 addition & 1 deletion lib/symboldatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1809,7 +1809,7 @@ void SymbolDatabase::setArrayDimensionsUsingValueFlow()
tokenList.addtoken(tok->str(), 0, 0, 0, false);

else if (tok->hasKnownIntValue())
tokenList.addtoken(std::to_string(tok->getKnownIntValue()), 0, 0, 0, false);
tokenList.addtoken(MathLib::toString(tok->getKnownIntValue()), 0, 0, 0, false);

else {
fail = true;
Expand Down
2 changes: 1 addition & 1 deletion lib/templatesimplifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2689,7 +2689,7 @@ bool TemplateSimplifier::simplifyCalculations(Token* frontToken, const Token *ba

if (validTokenEnd(bounded, tok, backToken, 3) &&
Token::Match(tok->previous(), "(|&&|%oror% %char% %comp% %num% &&|%oror%|)")) {
tok->str(std::to_string(MathLib::toBigNumber(tok->str())));
tok->str(MathLib::toString(MathLib::toBigNumber(tok->str())));
}

if (validTokenEnd(bounded, tok, backToken, 5) &&
Expand Down
16 changes: 8 additions & 8 deletions lib/token.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1773,12 +1773,12 @@ void Token::printValueFlow(bool xml, std::ostream &out) const
case ValueFlow::Value::ValueType::INT:
if (tok->valueType() && tok->valueType()->sign == ValueType::UNSIGNED) {
outs += "intvalue=\"";
outs += std::to_string(static_cast<MathLib::biguint>(value.intvalue));
outs += MathLib::toString(static_cast<MathLib::biguint>(value.intvalue));
outs += '\"';
}
else {
outs += "intvalue=\"";
outs += std::to_string(value.intvalue);
outs += MathLib::toString(value.intvalue);
outs += '\"';
}
break;
Expand All @@ -1802,22 +1802,22 @@ void Token::printValueFlow(bool xml, std::ostream &out) const
break;
case ValueFlow::Value::ValueType::BUFFER_SIZE:
outs += "buffer-size=\"";
outs += std::to_string(value.intvalue);
outs += MathLib::toString(value.intvalue);
outs += "\"";
break;
case ValueFlow::Value::ValueType::CONTAINER_SIZE:
outs += "container-size=\"";
outs += std::to_string(value.intvalue);
outs += MathLib::toString(value.intvalue);
outs += '\"';
break;
case ValueFlow::Value::ValueType::ITERATOR_START:
outs += "iterator-start=\"";
outs += std::to_string(value.intvalue);
outs += MathLib::toString(value.intvalue);
outs += '\"';
break;
case ValueFlow::Value::ValueType::ITERATOR_END:
outs += "iterator-end=\"";
outs += std::to_string(value.intvalue);
outs += MathLib::toString(value.intvalue);
outs += '\"';
break;
case ValueFlow::Value::ValueType::LIFETIME:
Expand All @@ -1836,7 +1836,7 @@ void Token::printValueFlow(bool xml, std::ostream &out) const
outs += id_string(value.tokvalue);
outs += '\"';
outs += " symbolic-delta=\"";
outs += std::to_string(value.intvalue);
outs += MathLib::toString(value.intvalue);
outs += '\"';
break;
}
Expand All @@ -1858,7 +1858,7 @@ void Token::printValueFlow(bool xml, std::ostream &out) const
outs += " inconclusive=\"true\"";

outs += " path=\"";
outs += std::to_string(value.path);
outs += MathLib::toString(value.path);
outs += "\"";

outs += "/>\n";
Expand Down
6 changes: 3 additions & 3 deletions lib/tokenize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3857,7 +3857,7 @@ void Tokenizer::arraySize()
}

if (sz != 0)
tok->insertToken(std::to_string(sz));
tok->insertToken(MathLib::toString(sz));

tok = end->next() ? end->next() : end;
}
Expand Down Expand Up @@ -3885,7 +3885,7 @@ void Tokenizer::arraySizeAfterValueFlow()
if (maxIndex >= 0) {
// insert array size
auto* tok = const_cast<Token*>(var->nameToken()->next());
tok->insertToken(std::to_string(maxIndex + 1));
tok->insertToken(MathLib::toString(maxIndex + 1));
// ast
tok->astOperand2(tok->next());
// Token::scope
Expand Down Expand Up @@ -4028,7 +4028,7 @@ void Tokenizer::simplifyCaseRange()
tok->insertToken("case");
for (MathLib::bigint i = end-1; i > start; i--) {
tok->insertToken(":");
tok->insertToken(std::to_string(i));
tok->insertToken(MathLib::toString(i));
tok->insertToken("case");
}
}
Expand Down
Loading

0 comments on commit 8576ec9

Please sign in to comment.