diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 6dd72bc4764..4785cb34e60 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -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; } diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index 433eaa49b27..a0326a9db1f 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -122,7 +122,7 @@ static int getMinFormatStringOutputLength(const std::vector ¶m 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; @@ -365,7 +365,7 @@ void CheckBufferOverrun::arrayIndex() static std::string stringifyIndexes(const std::string& array, const std::vector& indexValues) { if (indexValues.size() == 1) - return std::to_string(indexValues[0].intvalue); + return MathLib::toString(indexValues[0].intvalue); std::ostringstream ret; ret << array; @@ -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)); @@ -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."; @@ -1027,13 +1027,13 @@ bool CheckBufferOverrun::analyseWholeProgram1(const std::map 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; } diff --git a/lib/checkcondition.cpp b/lib/checkcondition.cpp index ddfa5a90546..45202ec1b44 100644 --- a/lib/checkcondition.cpp +++ b/lib/checkcondition.cpp @@ -1057,7 +1057,7 @@ static bool parseComparison(const Token *comp, bool ¬1, 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; @@ -1066,7 +1066,7 @@ static bool parseComparison(const Token *comp, bool ¬1, 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; @@ -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); } diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 297589902d7..c249014ab51 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -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."; diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index f3b83827bf9..647c8338b24 100644 --- a/lib/checkstl.cpp +++ b/lib/checkstl.cpp @@ -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; @@ -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; diff --git a/lib/mathlib.cpp b/lib/mathlib.cpp index 601463cab9c..b3d74793c81 100644 --- a/lib/mathlib.cpp +++ b/lib/mathlib.cpp @@ -519,6 +519,28 @@ double MathLib::toDoubleNumber(const std::string &str) return ret; } +template<> std::string MathLib::toString(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 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 value) { std::ostringstream result; @@ -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); @@ -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) @@ -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::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)) @@ -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 @@ -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 @@ -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."); diff --git a/lib/mathlib.h b/lib/mathlib.h index e4ae2a9cb1c..f83894c62b5 100644 --- a/lib/mathlib.h +++ b/lib/mathlib.h @@ -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 value); +template<> CPPCHECKLIB std::string MathLib::toString(MathLib::biguint value); template<> CPPCHECKLIB std::string MathLib::toString(double value); /// @} diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 4482ebad4e7..76cf60eadaf 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -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; diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index 53b185d43d0..b81ff82da9d 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -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) && diff --git a/lib/token.cpp b/lib/token.cpp index 30f82954f4e..4be1a973981 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -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(value.intvalue)); + outs += MathLib::toString(static_cast(value.intvalue)); outs += '\"'; } else { outs += "intvalue=\""; - outs += std::to_string(value.intvalue); + outs += MathLib::toString(value.intvalue); outs += '\"'; } break; @@ -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: @@ -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; } @@ -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"; diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 561a055adbd..d9566df2a5d 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -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; } @@ -3885,7 +3885,7 @@ void Tokenizer::arraySizeAfterValueFlow() if (maxIndex >= 0) { // insert array size auto* tok = const_cast(var->nameToken()->next()); - tok->insertToken(std::to_string(maxIndex + 1)); + tok->insertToken(MathLib::toString(maxIndex + 1)); // ast tok->astOperand2(tok->next()); // Token::scope @@ -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"); } } diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 690c4d06b05..4161810e43d 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -6837,7 +6837,7 @@ static void valueFlowDynamicBufferSize(const TokenList& tokenlist, const SymbolD continue; ValueFlow::Value value(sizeValue); - value.errorPath.emplace_back(tok->tokAt(2), "Assign " + tok->strAt(1) + ", buffer with size " + std::to_string(sizeValue)); + value.errorPath.emplace_back(tok->tokAt(2), "Assign " + tok->strAt(1) + ", buffer with size " + MathLib::toString(sizeValue)); value.valueType = ValueFlow::Value::ValueType::BUFFER_SIZE; value.setKnown(); valueFlowForward(const_cast(rhs), functionScope->bodyEnd, tok->next(), std::move(value), tokenlist, errorLogger, settings); @@ -6938,12 +6938,12 @@ static void valueFlowSafeFunctions(const TokenList& tokenlist, const SymbolDatab std::list argValues; if (isLow) { argValues.emplace_back(low); - argValues.back().errorPath.emplace_back(arg.nameToken(), std::string(safeLow ? "Safe checks: " : "") + "Assuming argument has value " + std::to_string(low)); + argValues.back().errorPath.emplace_back(arg.nameToken(), std::string(safeLow ? "Safe checks: " : "") + "Assuming argument has value " + MathLib::toString(low)); argValues.back().safe = safeLow; } if (isHigh) { argValues.emplace_back(high); - argValues.back().errorPath.emplace_back(arg.nameToken(), std::string(safeHigh ? "Safe checks: " : "") + "Assuming argument has value " + std::to_string(high)); + argValues.back().errorPath.emplace_back(arg.nameToken(), std::string(safeHigh ? "Safe checks: " : "") + "Assuming argument has value " + MathLib::toString(high)); argValues.back().safe = safeHigh; } diff --git a/lib/vfvalue.cpp b/lib/vfvalue.cpp index 166885b28c7..8e694c6eeb7 100644 --- a/lib/vfvalue.cpp +++ b/lib/vfvalue.cpp @@ -100,7 +100,7 @@ namespace ValueFlow { std::string Value::infoString() const { switch (valueType) { case ValueType::INT: - return std::to_string(intvalue); + return MathLib::toString(intvalue); case ValueType::TOK: return tokvalue->str(); case ValueType::FLOAT: @@ -111,20 +111,20 @@ namespace ValueFlow { return ""; case ValueType::BUFFER_SIZE: case ValueType::CONTAINER_SIZE: - return "size=" + std::to_string(intvalue); + return "size=" + MathLib::toString(intvalue); case ValueType::ITERATOR_START: - return "start=" + std::to_string(intvalue); + return "start=" + MathLib::toString(intvalue); case ValueType::ITERATOR_END: - return "end=" + std::to_string(intvalue); + return "end=" + MathLib::toString(intvalue); case ValueType::LIFETIME: return "lifetime=" + tokvalue->str(); case ValueType::SYMBOLIC: { std::string result = "symbolic=" + tokvalue->expressionString(); if (intvalue > 0) - result += "+" + std::to_string(intvalue); + result += "+" + MathLib::toString(intvalue); else if (intvalue < 0) - result += "-" + std::to_string(-intvalue); + result += "-" + MathLib::toString(-intvalue); return result; } }