diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp
index 3d45a21be12..7cb25f742c0 100644
--- a/lib/cppcheck.cpp
+++ b/lib/cppcheck.cpp
@@ -315,8 +315,8 @@ static void createDumpFile(const Settings& settings,
break;
}
- fdump << "" << std::endl;
- fdump << "" << std::endl;
+ fdump << "\n";
+ fdump << "\n";
fdump << " \n";
+ << "/>" << '\n';
}
static std::string executeAddon(const AddonInfo &addonInfo,
@@ -571,16 +571,16 @@ unsigned int CppCheck::check(const std::string &path)
std::string dumpFile;
createDumpFile(mSettings, path, fdump, dumpFile);
if (fdump.is_open()) {
- fdump << "" << std::endl;
+ fdump << "\n";
for (const ErrorMessage& errmsg: compilerWarnings)
fdump << " \n";
- fdump << " " << std::endl;
- fdump << " " << std::endl;
- fdump << " " << std::endl;
- fdump << " " << std::endl;
+ fdump << " \n";
+ fdump << " \n";
+ fdump << " \n";
+ fdump << " \n";
tokenizer.dump(fdump);
- fdump << "" << std::endl;
- fdump << "" << std::endl;
+ fdump << "\n";
+ fdump << "\n";
fdump.close();
}
diff --git a/lib/errorlogger.cpp b/lib/errorlogger.cpp
index efe89308852..8d916531cfe 100644
--- a/lib/errorlogger.cpp
+++ b/lib/errorlogger.cpp
@@ -720,36 +720,36 @@ std::string ErrorMessage::FileLocation::stringify() const
std::string ErrorLogger::toxml(const std::string &str)
{
- std::ostringstream xml;
+ std::string xml;
for (const unsigned char c : str) {
switch (c) {
case '<':
- xml << "<";
+ xml += "<";
break;
case '>':
- xml << ">";
+ xml += ">";
break;
case '&':
- xml << "&";
+ xml += "&";
break;
case '\"':
- xml << """;
+ xml += """;
break;
case '\'':
- xml << "'";
+ xml += "'";
break;
case '\0':
- xml << "\\0";
+ xml += "\\0";
break;
default:
if (c >= ' ' && c <= 0x7f)
- xml << c;
+ xml += c;
else
- xml << 'x';
+ xml += 'x';
break;
}
}
- return xml.str();
+ return xml;
}
std::string ErrorLogger::plistHeader(const std::string &version, const std::vector &files)
diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp
index 01d2a94f142..04505d02b23 100644
--- a/lib/symboldatabase.cpp
+++ b/lib/symboldatabase.cpp
@@ -3615,26 +3615,50 @@ bool Variable::arrayDimensions(const Settings* settings, bool& isContainer)
return arr;
}
+static std::string scopeTypeToString(Scope::ScopeType type)
+{
+ switch (type) {
+ case Scope::ScopeType::eGlobal:
+ return "Global";
+ case Scope::ScopeType::eClass:
+ return "Class";
+ case Scope::ScopeType::eStruct:
+ return "Struct";
+ case Scope::ScopeType::eUnion:
+ return "Union";
+ case Scope::ScopeType::eNamespace:
+ return "Namespace";
+ case Scope::ScopeType::eFunction:
+ return "Function";
+ case Scope::ScopeType::eIf:
+ return "If";
+ case Scope::ScopeType::eElse:
+ return "Else";
+ case Scope::ScopeType::eFor:
+ return "For";
+ case Scope::ScopeType::eWhile:
+ return "While";
+ case Scope::ScopeType::eDo:
+ return "Do";
+ case Scope::ScopeType::eSwitch:
+ return "Switch";
+ case Scope::ScopeType::eTry:
+ return "Try";
+ case Scope::ScopeType::eCatch:
+ return "Catch";
+ case Scope::ScopeType::eUnconditional:
+ return "Unconditional";
+ case Scope::ScopeType::eLambda:
+ return "Lambda";
+ case Scope::ScopeType::eEnum:
+ return "Enum";
+ }
+ return "Unknown";
+}
+
static std::ostream & operator << (std::ostream & s, Scope::ScopeType type)
{
- s << (type == Scope::eGlobal ? "Global" :
- type == Scope::eClass ? "Class" :
- type == Scope::eStruct ? "Struct" :
- type == Scope::eUnion ? "Union" :
- type == Scope::eNamespace ? "Namespace" :
- type == Scope::eFunction ? "Function" :
- type == Scope::eIf ? "If" :
- type == Scope::eElse ? "Else" :
- type == Scope::eFor ? "For" :
- type == Scope::eWhile ? "While" :
- type == Scope::eDo ? "Do" :
- type == Scope::eSwitch ? "Switch" :
- type == Scope::eTry ? "Try" :
- type == Scope::eCatch ? "Catch" :
- type == Scope::eUnconditional ? "Unconditional" :
- type == Scope::eLambda ? "Lambda" :
- type == Scope::eEnum ? "Enum" :
- "Unknown");
+ s << scopeTypeToString(type);
return s;
}
@@ -4010,137 +4034,223 @@ void SymbolDatabase::printOut(const char *title) const
void SymbolDatabase::printXml(std::ostream &out) const
{
- out << std::setiosflags(std::ios::boolalpha);
+ std::string outs;
std::set variables;
// Scopes..
- out << " " << std::endl;
+ outs += " \n";
for (std::list::const_iterator scope = scopeList.cbegin(); scope != scopeList.cend(); ++scope) {
- out << " type << "\"";
- if (!scope->className.empty())
- out << " className=\"" << ErrorLogger::toxml(scope->className) << "\"";
- if (scope->bodyStart)
- out << " bodyStart=\"" << scope->bodyStart << '\"';
- if (scope->bodyEnd)
- out << " bodyEnd=\"" << scope->bodyEnd << '\"';
- if (scope->nestedIn)
- out << " nestedIn=\"" << scope->nestedIn << "\"";
- if (scope->function)
- out << " function=\"" << scope->function << "\"";
- if (scope->definedType)
- out << " definedType=\"" << scope->definedType << "\"";
+ outs += " type);
+ outs += "\"";
+ if (!scope->className.empty()) {
+ outs += " className=\"";
+ outs += ErrorLogger::toxml(scope->className);
+ outs += "\"";
+ }
+ if (scope->bodyStart) {
+ outs += " bodyStart=\"";
+ outs += ptr_to_string(scope->bodyStart);
+ outs += '\"';
+ }
+ if (scope->bodyEnd) {
+ outs += " bodyEnd=\"";
+ outs += ptr_to_string(scope->bodyEnd);
+ outs += '\"';
+ }
+ if (scope->nestedIn) {
+ outs += " nestedIn=\"";
+ outs += ptr_to_string(scope->nestedIn);
+ outs += "\"";
+ }
+ if (scope->function) {
+ outs += " function=\"";
+ outs += ptr_to_string(scope->function);
+ outs += "\"";
+ }
+ if (scope->definedType) {
+ outs += " definedType=\"";
+ outs += ptr_to_string(scope->definedType);
+ outs += "\"";
+ }
if (scope->functionList.empty() && scope->varlist.empty())
- out << "/>" << std::endl;
+ outs += "/>\n";
else {
- out << '>' << std::endl;
+ outs += ">\n";
if (!scope->functionList.empty()) {
- out << " " << std::endl;
+ outs += " \n";
for (std::list::const_iterator function = scope->functionList.cbegin(); function != scope->functionList.cend(); ++function) {
- out << " token
- << "\" tokenDef=\"" << function->tokenDef
- << "\" name=\"" << ErrorLogger::toxml(function->name()) << '\"';
- out << " type=\"" << (function->type == Function::eConstructor? "Constructor" :
- function->type == Function::eCopyConstructor ? "CopyConstructor" :
- function->type == Function::eMoveConstructor ? "MoveConstructor" :
- function->type == Function::eOperatorEqual ? "OperatorEqual" :
- function->type == Function::eDestructor ? "Destructor" :
- function->type == Function::eFunction ? "Function" :
- function->type == Function::eLambda ? "Lambda" :
- "Unknown") << '\"';
+ outs += " token);
+ outs += "\" tokenDef=\"";
+ outs += ptr_to_string(function->tokenDef);
+ outs += "\" name=\"";
+ outs += ErrorLogger::toxml(function->name());
+ outs += '\"';
+ outs += " type=\"";
+ outs += (function->type == Function::eConstructor? "Constructor" :
+ function->type == Function::eCopyConstructor ? "CopyConstructor" :
+ function->type == Function::eMoveConstructor ? "MoveConstructor" :
+ function->type == Function::eOperatorEqual ? "OperatorEqual" :
+ function->type == Function::eDestructor ? "Destructor" :
+ function->type == Function::eFunction ? "Function" :
+ function->type == Function::eLambda ? "Lambda" :
+ "Unknown");
+ outs += '\"';
if (function->nestedIn->definedType) {
if (function->hasVirtualSpecifier())
- out << " hasVirtualSpecifier=\"true\"";
+ outs += " hasVirtualSpecifier=\"true\"";
else if (function->isImplicitlyVirtual())
- out << " isImplicitlyVirtual=\"true\"";
+ outs += " isImplicitlyVirtual=\"true\"";
+ }
+ if (function->access == AccessControl::Public || function->access == AccessControl::Protected || function->access == AccessControl::Private) {
+ outs += " access=\"";
+ outs += accessControlToString(function->access);
+ outs +="\"";
}
- if (function->access == AccessControl::Public || function->access == AccessControl::Protected || function->access == AccessControl::Private)
- out << " access=\"" << accessControlToString(function->access) << "\"";
if (function->isInlineKeyword())
- out << " isInlineKeyword=\"true\"";
+ outs += " isInlineKeyword=\"true\"";
if (function->isStatic())
- out << " isStatic=\"true\"";
+ outs += " isStatic=\"true\"";
if (function->isAttributeNoreturn())
- out << " isAttributeNoreturn=\"true\"";
- if (const Function* overriddenFunction = function->getOverriddenFunction())
- out << " overriddenFunction=\"" << overriddenFunction << "\"";
+ outs += " isAttributeNoreturn=\"true\"";
+ if (const Function* overriddenFunction = function->getOverriddenFunction()) {
+ outs += " overriddenFunction=\"";
+ outs += ptr_to_string(overriddenFunction);
+ outs += "\"";
+ }
if (function->argCount() == 0U)
- out << "/>" << std::endl;
+ outs += "/>\n";
else {
- out << ">" << std::endl;
+ outs += ">\n";
for (unsigned int argnr = 0; argnr < function->argCount(); ++argnr) {
const Variable *arg = function->getArgumentVar(argnr);
- out << " " << std::endl;
+ outs += " \n";
variables.insert(arg);
}
- out << " " << std::endl;
+ outs += " \n";
}
}
- out << " " << std::endl;
+ outs += " \n";
}
if (!scope->varlist.empty()) {
- out << " " << std::endl;
- for (std::list::const_iterator var = scope->varlist.cbegin(); var != scope->varlist.cend(); ++var)
- out << " " << std::endl;
- out << " " << std::endl;
+ outs += " \n";
+ for (std::list::const_iterator var = scope->varlist.cbegin(); var != scope->varlist.cend(); ++var) {
+ outs += " \n";
+ }
+ outs += " \n";
}
- out << " " << std::endl;
+ outs += " \n";
}
}
- out << " " << std::endl;
+ outs += " \n";
if (!typeList.empty()) {
- out << " \n";
+ outs += " \n";
for (const Type& type:typeList) {
- out << " \n";
+ outs += "/>\n";
continue;
}
- out << ">\n";
+ outs += ">\n";
for (const Type::BaseInfo& baseInfo: type.derivedFrom) {
- out << " \n";
- }
- out << " \n";
- }
- out << " \n";
+ outs += " \n";
+ }
+ outs += " \n";
+ }
+ outs += " \n";
}
// Variables..
for (const Variable *var : mVariableList)
variables.insert(var);
- out << " " << std::endl;
+ outs += " \n";
for (const Variable *var : variables) {
if (!var)
continue;
- out << " nameToken() << '\"';
- out << " typeStartToken=\"" << var->typeStartToken() << '\"';
- out << " typeEndToken=\"" << var->typeEndToken() << '\"';
- out << " access=\"" << accessControlToString(var->mAccess) << '\"';
- out << " scope=\"" << var->scope() << '\"';
- if (var->valueType())
- out << " constness=\"" << var->valueType()->constness << '\"';
- out << " isArray=\"" << var->isArray() << '\"';
- out << " isClass=\"" << var->isClass() << '\"';
- out << " isConst=\"" << var->isConst() << '\"';
- out << " isExtern=\"" << var->isExtern() << '\"';
- out << " isPointer=\"" << var->isPointer() << '\"';
- out << " isReference=\"" << var->isReference() << '\"';
- out << " isStatic=\"" << var->isStatic() << '\"';
- out << " isVolatile=\"" << var->isVolatile() << '\"';
- out << "/>" << std::endl;
- }
- out << " " << std::endl;
- out << std::resetiosflags(std::ios::boolalpha);
+ outs += " nameToken());
+ outs += '\"';
+ outs += " typeStartToken=\"";
+ outs += ptr_to_string(var->typeStartToken());
+ outs += '\"';
+ outs += " typeEndToken=\"";
+ outs += ptr_to_string(var->typeEndToken());
+ outs += '\"';
+ outs += " access=\"";
+ outs += accessControlToString(var->mAccess);
+ outs += '\"';
+ outs += " scope=\"";
+ outs += ptr_to_string(var->scope());
+ outs += '\"';
+ if (var->valueType()) {
+ outs += " constness=\"";
+ outs += std::to_string(var->valueType()->constness);
+ outs += '\"';
+ }
+ outs += " isArray=\"";
+ outs += bool_to_string(var->isArray());
+ outs += '\"';
+ outs += " isClass=\"";
+ outs += bool_to_string(var->isClass());
+ outs += '\"';
+ outs += " isConst=\"";
+ outs += bool_to_string(var->isConst());
+ outs += '\"';
+ outs += " isExtern=\"";
+ outs += bool_to_string(var->isExtern());
+ outs += '\"';
+ outs += " isPointer=\"";
+ outs += bool_to_string(var->isPointer());
+ outs += '\"';
+ outs += " isReference=\"";
+ outs += bool_to_string(var->isReference());
+ outs += '\"';
+ outs += " isStatic=\"";
+ outs += bool_to_string(var->isStatic());
+ outs += '\"';
+ outs += " isVolatile=\"";
+ outs += bool_to_string(var->isVolatile());
+ outs += '\"';
+ outs += "/>\n";
+ }
+ outs += " \n";
+
+ out << outs;
}
//---------------------------------------------------------------------------
@@ -7443,64 +7553,67 @@ bool ValueType::fromLibraryType(const std::string &typestr, const Settings &sett
std::string ValueType::dump() const
{
- std::ostringstream ret;
+ std::string ret;
switch (type) {
case UNKNOWN_TYPE:
return "";
case NONSTD:
- ret << "valueType-type=\"nonstd\"";
+ ret += "valueType-type=\"nonstd\"";
break;
case POD:
- ret << "valueType-type=\"pod\"";
+ ret += "valueType-type=\"pod\"";
break;
case RECORD:
- ret << "valueType-type=\"record\"";
+ ret += "valueType-type=\"record\"";
break;
case SMART_POINTER:
- ret << "valueType-type=\"smart-pointer\"";
+ ret += "valueType-type=\"smart-pointer\"";
break;
- case CONTAINER:
- ret << "valueType-type=\"container\"";
- ret << " valueType-containerId=\"" << container << "\"";
+ case CONTAINER: {
+ ret += "valueType-type=\"container\"";
+ ret += " valueType-containerId=\"";
+ ret += ptr_to_string(container);
+ ret += "\"";
break;
+ }
case ITERATOR:
- ret << "valueType-type=\"iterator\"";
+ ret += "valueType-type=\"iterator\"";
break;
case VOID:
- ret << "valueType-type=\"void\"";
+ ret += "valueType-type=\"void\"";
break;
case BOOL:
- ret << "valueType-type=\"bool\"";
+ ret += "valueType-type=\"bool\"";
break;
case CHAR:
- ret << "valueType-type=\"char\"";
+ ret += "valueType-type=\"char\"";
break;
case SHORT:
- ret << "valueType-type=\"short\"";
+ ret += "valueType-type=\"short\"";
break;
case WCHAR_T:
- ret << "valueType-type=\"wchar_t\"";
+ ret += "valueType-type=\"wchar_t\"";
break;
case INT:
- ret << "valueType-type=\"int\"";
+ ret += "valueType-type=\"int\"";
break;
case LONG:
- ret << "valueType-type=\"long\"";
+ ret += "valueType-type=\"long\"";
break;
case LONGLONG:
- ret << "valueType-type=\"long long\"";
+ ret += "valueType-type=\"long long\"";
break;
case UNKNOWN_INT:
- ret << "valueType-type=\"unknown int\"";
+ ret += "valueType-type=\"unknown int\"";
break;
case FLOAT:
- ret << "valueType-type=\"float\"";
+ ret += "valueType-type=\"float\"";
break;
case DOUBLE:
- ret << "valueType-type=\"double\"";
+ ret += "valueType-type=\"double\"";
break;
case LONGDOUBLE:
- ret << "valueType-type=\"long double\"";
+ ret += "valueType-type=\"long double\"";
break;
}
@@ -7508,36 +7621,51 @@ std::string ValueType::dump() const
case Sign::UNKNOWN_SIGN:
break;
case Sign::SIGNED:
- ret << " valueType-sign=\"signed\"";
+ ret += " valueType-sign=\"signed\"";
break;
case Sign::UNSIGNED:
- ret << " valueType-sign=\"unsigned\"";
+ ret += " valueType-sign=\"unsigned\"";
break;
}
- if (bits > 0)
- ret << " valueType-bits=\"" << bits << '\"';
+ if (bits > 0) {
+ ret += " valueType-bits=\"";
+ ret += std::to_string(bits);
+ ret += '\"';
+ }
- if (pointer > 0)
- ret << " valueType-pointer=\"" << pointer << '\"';
+ if (pointer > 0) {
+ ret += " valueType-pointer=\"";
+ ret += std::to_string(pointer);
+ ret += '\"';
+ }
- if (constness > 0)
- ret << " valueType-constness=\"" << constness << '\"';
+ if (constness > 0) {
+ ret += " valueType-constness=\"";
+ ret += std::to_string(constness);
+ ret += '\"';
+ }
if (reference == Reference::None)
- ret << " valueType-reference=\"None\"";
+ ret += " valueType-reference=\"None\"";
else if (reference == Reference::LValue)
- ret << " valueType-reference=\"LValue\"";
+ ret += " valueType-reference=\"LValue\"";
else if (reference == Reference::RValue)
- ret << " valueType-reference=\"RValue\"";
+ ret += " valueType-reference=\"RValue\"";
- if (typeScope)
- ret << " valueType-typeScope=\"" << typeScope << '\"';
+ if (typeScope) {
+ ret += " valueType-typeScope=\"";
+ ret += ptr_to_string(typeScope);
+ ret += '\"';
+ }
- if (!originalTypeName.empty())
- ret << " valueType-originalTypeName=\"" << ErrorLogger::toxml(originalTypeName) << '\"';
+ if (!originalTypeName.empty()) {
+ ret += " valueType-originalTypeName=\"";
+ ret += ErrorLogger::toxml(originalTypeName);
+ ret += '\"';
+ }
- return ret.str();
+ return ret;
}
bool ValueType::isConst(nonneg int indirect) const
diff --git a/lib/token.cpp b/lib/token.cpp
index a13f98763d4..0a8524f1681 100644
--- a/lib/token.cpp
+++ b/lib/token.cpp
@@ -1695,119 +1695,171 @@ std::string Token::astStringZ3() const
void Token::printValueFlow(bool xml, std::ostream &out) const
{
+ std::string outs;
+
int line = 0;
if (xml)
- out << " " << std::endl;
+ outs += " \n";
else
- out << "\n\n##Value flow" << std::endl;
+ outs += "\n\n##Value flow\n";
for (const Token *tok = this; tok; tok = tok->next()) {
const auto* const values = tok->mImpl->mValues;
if (!values)
continue;
if (values->empty()) // Values might be removed by removeContradictions
continue;
- if (xml)
- out << " " << std::endl;
- else if (line != tok->linenr())
- out << "Line " << tok->linenr() << std::endl;
+ if (xml) {
+ outs += " ";
+ outs += '\n';
+ }
+ else if (line != tok->linenr()) {
+ outs += "Line ";
+ outs += std::to_string(tok->linenr());
+ outs += '\n';
+ }
line = tok->linenr();
if (!xml) {
ValueFlow::Value::ValueKind valueKind = values->front().valueKind;
const bool same = std::all_of(values->begin(), values->end(), [&](const ValueFlow::Value& value) {
return value.valueKind == valueKind;
});
- out << " " << tok->str() << " ";
+ outs += " ";
+ outs += tok->str();
+ outs += " ";
if (same) {
switch (valueKind) {
case ValueFlow::Value::ValueKind::Impossible:
case ValueFlow::Value::ValueKind::Known:
- out << "always ";
+ outs += "always ";
break;
case ValueFlow::Value::ValueKind::Inconclusive:
- out << "inconclusive ";
+ outs += "inconclusive ";
break;
case ValueFlow::Value::ValueKind::Possible:
- out << "possible ";
+ outs += "possible ";
break;
}
}
if (values->size() > 1U)
- out << '{';
+ outs += '{';
}
for (const ValueFlow::Value& value : *values) {
if (xml) {
- out << " valueType() && tok->valueType()->sign == ValueType::UNSIGNED)
- out << "intvalue=\"" << (MathLib::biguint)value.intvalue << '\"';
- else
- out << "intvalue=\"" << value.intvalue << '\"';
+ if (tok->valueType() && tok->valueType()->sign == ValueType::UNSIGNED) {
+ outs += "intvalue=\"";
+ outs += std::to_string(static_cast(value.intvalue));
+ outs += '\"';
+ }
+ else {
+ outs += "intvalue=\"";
+ outs += std::to_string(value.intvalue);
+ outs += '\"';
+ }
break;
case ValueFlow::Value::ValueType::TOK:
- out << "tokvalue=\"" << value.tokvalue << '\"';
+ outs += "tokvalue=\"";
+ outs += ptr_to_string(value.tokvalue);
+ outs += '\"';
break;
case ValueFlow::Value::ValueType::FLOAT:
- out << "floatvalue=\"" << value.floatValue << '\"';
+ outs += "floatvalue=\"";
+ outs += std::to_string(value.floatValue); // TODO: should this be MathLib::toString()?
+ outs += '\"';
break;
case ValueFlow::Value::ValueType::MOVED:
- out << "movedvalue=\"" << ValueFlow::Value::toString(value.moveKind) << '\"';
+ outs += "movedvalue=\"";
+ outs += ValueFlow::Value::toString(value.moveKind);
+ outs += '\"';
break;
case ValueFlow::Value::ValueType::UNINIT:
- out << "uninit=\"1\"";
+ outs += "uninit=\"1\"";
break;
case ValueFlow::Value::ValueType::BUFFER_SIZE:
- out << "buffer-size=\"" << value.intvalue << "\"";
+ outs += "buffer-size=\"";
+ outs += std::to_string(value.intvalue);
+ outs += "\"";
break;
case ValueFlow::Value::ValueType::CONTAINER_SIZE:
- out << "container-size=\"" << value.intvalue << '\"';
+ outs += "container-size=\"";
+ outs += std::to_string(value.intvalue);
+ outs += '\"';
break;
case ValueFlow::Value::ValueType::ITERATOR_START:
- out << "iterator-start=\"" << value.intvalue << '\"';
+ outs += "iterator-start=\"";
+ outs += std::to_string(value.intvalue);
+ outs += '\"';
break;
case ValueFlow::Value::ValueType::ITERATOR_END:
- out << "iterator-end=\"" << value.intvalue << '\"';
+ outs += "iterator-end=\"";
+ outs += std::to_string(value.intvalue);
+ outs += '\"';
break;
case ValueFlow::Value::ValueType::LIFETIME:
- out << "lifetime=\"" << value.tokvalue << '\"';
- out << " lifetime-scope=\"" << ValueFlow::Value::toString(value.lifetimeScope) << "\"";
- out << " lifetime-kind=\"" << ValueFlow::Value::toString(value.lifetimeKind) << "\"";
+ outs += "lifetime=\"";
+ outs += ptr_to_string(value.tokvalue);
+ outs += '\"';
+ outs += " lifetime-scope=\"";
+ outs += ValueFlow::Value::toString(value.lifetimeScope);
+ outs += "\"";
+ outs += " lifetime-kind=\"";
+ outs += ValueFlow::Value::toString(value.lifetimeKind);
+ outs += "\"";
break;
case ValueFlow::Value::ValueType::SYMBOLIC:
- out << "symbolic=\"" << value.tokvalue << '\"';
- out << " symbolic-delta=\"" << value.intvalue << '\"';
+ outs += "symbolic=\"";
+ outs += ptr_to_string(value.tokvalue);
+ outs += '\"';
+ outs += " symbolic-delta=\"";
+ outs += std::to_string(value.intvalue);
+ outs += '\"';
break;
}
- out << " bound=\"" << ValueFlow::Value::toString(value.bound) << "\"";
- if (value.condition)
- out << " condition-line=\"" << value.condition->linenr() << '\"';
+ outs += " bound=\"";
+ outs += ValueFlow::Value::toString(value.bound);
+ outs += "\"";
+ if (value.condition) {
+ outs += " condition-line=\"";
+ outs += std::to_string(value.condition->linenr());
+ outs += '\"';
+ }
if (value.isKnown())
- out << " known=\"true\"";
+ outs += " known=\"true\"";
else if (value.isPossible())
- out << " possible=\"true\"";
+ outs += " possible=\"true\"";
else if (value.isImpossible())
- out << " impossible=\"true\"";
+ outs += " impossible=\"true\"";
else if (value.isInconclusive())
- out << " inconclusive=\"true\"";
- out << " path=\"" << value.path << "\"";
- out << "/>" << std::endl;
+ outs += " inconclusive=\"true\"";
+
+ outs += " path=\"";
+ outs += std::to_string(value.path);
+ outs += "\"";
+
+ outs += "/>\n";
}
else {
if (&value != &values->front())
- out << ",";
- out << value.toString();
+ outs += ",";
+ outs += value.toString();
}
}
if (xml)
- out << " " << std::endl;
+ outs += " \n";
else if (values->size() > 1U)
- out << '}' << std::endl;
+ outs += "}\n";
else
- out << std::endl;
+ outs += '\n';
}
if (xml)
- out << " " << std::endl;
+ outs += " \n";
+
+ out << outs;
}
const ValueFlow::Value * Token::getValueLE(const MathLib::bigint val, const Settings *settings) const
diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp
index 86a843c9632..81fe6abba57 100644
--- a/lib/tokenize.cpp
+++ b/lib/tokenize.cpp
@@ -4014,8 +4014,8 @@ void Tokenizer::simplifyTemplates()
/** Class used in Tokenizer::setVarIdPass1 */
class VariableMap {
private:
- std::map mVariableId;
- std::map mVariableId_global;
+ std::unordered_map mVariableId;
+ std::unordered_map mVariableId_global;
std::stack>> mScopeInfo;
mutable nonneg int mVarId{};
public:
@@ -4027,7 +4027,7 @@ class VariableMap {
return mVariableId.find(varname) != mVariableId.end();
}
- const std::map& map(bool global) const {
+ const std::unordered_map& map(bool global) const {
return global ? mVariableId_global : mVariableId;
}
nonneg int getVarId() const {
@@ -4067,7 +4067,7 @@ void VariableMap::addVariable(const std::string& varname, bool globalNamespace)
mVariableId_global[varname] = mVariableId[varname];
return;
}
- std::map::iterator it = mVariableId.find(varname);
+ std::unordered_map::iterator it = mVariableId.find(varname);
if (it == mVariableId.end()) {
mScopeInfo.top().emplace_back(varname, 0);
mVariableId[varname] = ++mVarId;
@@ -4330,7 +4330,7 @@ void Tokenizer::setVarIdClassDeclaration(Token* const startToken,
--indentlevel;
inEnum = false;
} else if (initList && indentlevel == 0 && Token::Match(tok->previous(), "[,:] %name% [({]")) {
- const std::map::const_iterator it = variableMap.map(false).find(tok->str());
+ const std::unordered_map::const_iterator it = variableMap.map(false).find(tok->str());
if (it != variableMap.map(false).end()) {
tok->varId(it->second);
}
@@ -4348,7 +4348,7 @@ void Tokenizer::setVarIdClassDeclaration(Token* const startToken,
}
if (!inEnum) {
- const std::map::const_iterator it = variableMap.map(false).find(tok->str());
+ const std::unordered_map::const_iterator it = variableMap.map(false).find(tok->str());
if (it != variableMap.map(false).end()) {
tok->varId(it->second);
setVarIdStructMembers(&tok, structMembers, variableMap.getVarId());
@@ -4692,7 +4692,7 @@ void Tokenizer::setVarIdPass1()
while (tok != end) {
if (tok->isName() && !(Token::simpleMatch(tok->next(), "<") &&
Token::Match(tok->tokAt(-1), ":: %name%"))) {
- const std::map::const_iterator it = variableMap.map(false).find(tok->str());
+ const std::unordered_map::const_iterator it = variableMap.map(false).find(tok->str());
if (it != variableMap.map(false).end())
tok->varId(it->second);
}
@@ -4757,7 +4757,7 @@ void Tokenizer::setVarIdPass1()
if ((!scopeStack.top().isEnum || !(Token::Match(tok->previous(), "{|,") && Token::Match(tok->next(), ",|=|}"))) &&
!Token::simpleMatch(tok->next(), ": ;")) {
- const std::map::const_iterator it = variableMap.map(globalNamespace).find(tok->str());
+ const std::unordered_map::const_iterator it = variableMap.map(globalNamespace).find(tok->str());
if (it != variableMap.map(globalNamespace).end()) {
tok->varId(it->second);
setVarIdStructMembers(&tok, structMembers, variableMap.getVarId());
@@ -5797,134 +5797,223 @@ void Tokenizer::dump(std::ostream &out) const
// The idea is not that this will be readable for humans. It's a
// data dump that 3rd party tools could load and get useful info from.
+ std::string outs;
+
std::set containers;
// tokens..
- out << " " << std::endl;
+ outs += " ";
+ outs += '\n';
for (const Token *tok = list.front(); tok; tok = tok->next()) {
- out << " linenr() << "\" column=\"" << tok->column() << "\"";
- out << " str=\"" << ErrorLogger::toxml(tok->str()) << '\"';
- out << " scope=\"" << tok->scope() << '\"';
+ outs += " linenr());
+ outs += "\" column=\"";
+ outs += std::to_string(tok->column());
+ outs += "\"";
+
+ outs += " str=\"";
+ outs += ErrorLogger::toxml(tok->str());
+ outs += '\"';
+
+ outs += " scope=\"";
+ outs += ptr_to_string(tok->scope());
+ outs += '\"';
if (tok->isName()) {
- out << " type=\"name\"";
+ outs += " type=\"name\"";
if (tok->isUnsigned())
- out << " isUnsigned=\"true\"";
+ outs += " isUnsigned=\"true\"";
else if (tok->isSigned())
- out << " isSigned=\"true\"";
+ outs += " isSigned=\"true\"";
} else if (tok->isNumber()) {
- out << " type=\"number\"";
+ outs += " type=\"number\"";
if (MathLib::isInt(tok->str()))
- out << " isInt=\"true\"";
+ outs += " isInt=\"true\"";
if (MathLib::isFloat(tok->str()))
- out << " isFloat=\"true\"";
- } else if (tok->tokType() == Token::eString)
- out << " type=\"string\" strlen=\"" << Token::getStrLength(tok) << '\"';
+ outs += " isFloat=\"true\"";
+ } else if (tok->tokType() == Token::eString) {
+ outs += " type=\"string\" strlen=\"";
+ outs += std::to_string(Token::getStrLength(tok));
+ outs += '\"';
+ }
else if (tok->tokType() == Token::eChar)
- out << " type=\"char\"";
+ outs += " type=\"char\"";
else if (tok->isBoolean())
- out << " type=\"boolean\"";
+ outs += " type=\"boolean\"";
else if (tok->isOp()) {
- out << " type=\"op\"";
+ outs += " type=\"op\"";
if (tok->isArithmeticalOp())
- out << " isArithmeticalOp=\"true\"";
+ outs += " isArithmeticalOp=\"true\"";
else if (tok->isAssignmentOp())
- out << " isAssignmentOp=\"true\"";
+ outs += " isAssignmentOp=\"true\"";
else if (tok->isComparisonOp())
- out << " isComparisonOp=\"true\"";
+ outs += " isComparisonOp=\"true\"";
else if (tok->tokType() == Token::eLogicalOp)
- out << " isLogicalOp=\"true\"";
+ outs += " isLogicalOp=\"true\"";
}
if (tok->isCast())
- out << " isCast=\"true\"";
+ outs += " isCast=\"true\"";
if (tok->isExternC())
- out << " externLang=\"C\"";
+ outs += " externLang=\"C\"";
if (tok->isExpandedMacro())
- out << " isExpandedMacro=\"true\"";
+ outs += " isExpandedMacro=\"true\"";
if (tok->isTemplateArg())
- out << " isTemplateArg=\"true\"";
+ outs += " isTemplateArg=\"true\"";
if (tok->isRemovedVoidParameter())
- out << " isRemovedVoidParameter=\"true\"";
+ outs += " isRemovedVoidParameter=\"true\"";
if (tok->isSplittedVarDeclComma())
- out << " isSplittedVarDeclComma=\"true\"";
+ outs += " isSplittedVarDeclComma=\"true\"";
if (tok->isSplittedVarDeclEq())
- out << " isSplittedVarDeclEq=\"true\"";
+ outs += " isSplittedVarDeclEq=\"true\"";
if (tok->isImplicitInt())
- out << " isImplicitInt=\"true\"";
+ outs += " isImplicitInt=\"true\"";
if (tok->isComplex())
- out << " isComplex=\"true\"";
+ outs += " isComplex=\"true\"";
if (tok->isRestrict())
- out << " isRestrict=\"true\"";
+ outs += " isRestrict=\"true\"";
if (tok->isAtomic())
- out << " isAtomic=\"true\"";
+ outs += " isAtomic=\"true\"";
if (tok->isAttributeExport())
- out << " isAttributeExport=\"true\"";
- if (tok->link())
- out << " link=\"" << tok->link() << '\"';
- if (tok->varId() > 0)
- out << " varId=\"" << tok->varId() << '\"';
- if (tok->exprId() > 0)
- out << " exprId=\"" << tok->exprId() << '\"';
- if (tok->variable())
- out << " variable=\"" << tok->variable() << '\"';
- if (tok->function())
- out << " function=\"" << tok->function() << '\"';
- if (!tok->values().empty())
- out << " values=\"" << &tok->values() << '\"';
- if (tok->type())
- out << " type-scope=\"" << tok->type()->classScope << '\"';
- if (tok->astParent())
- out << " astParent=\"" << tok->astParent() << '\"';
- if (tok->astOperand1())
- out << " astOperand1=\"" << tok->astOperand1() << '\"';
- if (tok->astOperand2())
- out << " astOperand2=\"" << tok->astOperand2() << '\"';
- if (!tok->originalName().empty())
- out << " originalName=\"" << tok->originalName() << '\"';
+ outs += " isAttributeExport=\"true\"";
+ if (tok->link()) {
+ outs += " link=\"";
+ outs += ptr_to_string(tok->link());
+ outs += '\"';
+ }
+ if (tok->varId() > 0) {
+ outs += " varId=\"";
+ outs += std::to_string(tok->varId());
+ outs += '\"';
+ }
+ if (tok->exprId() > 0) {
+ outs += " exprId=\"";
+ outs += std::to_string(tok->exprId());
+ outs += '\"';
+ }
+ if (tok->variable()) {
+ outs += " variable=\"";
+ outs += ptr_to_string(tok->variable());
+ outs += '\"';
+ }
+ if (tok->function()) {
+ outs += " function=\"";
+ outs += ptr_to_string(tok->function());
+ outs += '\"';
+ }
+ if (!tok->values().empty()) {
+ outs += " values=\"";
+ outs += ptr_to_string(&tok->values());
+ outs += '\"';
+ }
+ if (tok->type()) {
+ outs += " type-scope=\"";
+ outs += ptr_to_string(tok->type()->classScope);
+ outs += '\"';
+ }
+ if (tok->astParent()) {
+ outs += " astParent=\"";
+ outs += ptr_to_string(tok->astParent());
+ outs += '\"';
+ }
+ if (tok->astOperand1()) {
+ outs += " astOperand1=\"";
+ outs += ptr_to_string(tok->astOperand1());
+ outs += '\"';
+ }
+ if (tok->astOperand2()) {
+ outs += " astOperand2=\"";
+ outs += ptr_to_string(tok->astOperand2());
+ outs += '\"';
+ }
+ if (!tok->originalName().empty()) {
+ outs += " originalName=\"";
+ outs += tok->originalName();
+ outs += '\"';
+ }
if (tok->valueType()) {
const std::string vt = tok->valueType()->dump();
- if (!vt.empty())
- out << ' ' << vt;
+ if (!vt.empty()) {
+ outs += ' ';
+ outs += vt;
+ }
containers.insert(tok->valueType()->container);
}
if (!tok->varId() && tok->scope()->isExecutable() && Token::Match(tok, "%name% (")) {
if (mSettings->library.isnoreturn(tok))
- out << " noreturn=\"true\"";
+ outs += " noreturn=\"true\"";
}
- out << "/>" << std::endl;
+ outs += "/>";
+ outs += '\n';
}
- out << " " << std::endl;
+ outs += " ";
+ outs += '\n';
+
+ out << outs;
+ outs.clear();
mSymbolDatabase->printXml(out);
containers.erase(nullptr);
if (!containers.empty()) {
- out << " \n";
+ outs += " ";
+ outs += '\n';
for (const Library::Container* c: containers) {
- out << " arrayLike_indexOp ? "true" : "false") << "\" "
- << "std-string-like=\"" << (c->stdStringLike ? "true" : "false") << "\"/>\n";
+ outs += " arrayLike_indexOp ? "true" : "false");
+ outs += "\" ";
+ outs += "std-string-like=\"";
+ outs +=(c->stdStringLike ? "true" : "false");
+ outs += "\"/>";
+ outs += '\n';
}
- out << " \n";
+ outs += " ";
+ outs += '\n';
}
if (list.front())
list.front()->printValueFlow(true, out);
if (!mTypedefInfo.empty()) {
- out << " " << std::endl;
+ outs += " ";
+ outs += '\n';
for (const TypedefInfo &typedefInfo: mTypedefInfo) {
- out << " " << std::endl;
+ outs += " ";
+ outs += '\n';
}
- out << " " << std::endl;
+ outs += " ";
+ outs += '\n';
}
- out << mTemplateSimplifier->dump();
+ outs += mTemplateSimplifier->dump();
+
+ out << outs;
}
void Tokenizer::simplifyHeadersAndUnusedTemplates()
diff --git a/lib/utils.h b/lib/utils.h
index e942c82f1da..3f53f6fbc46 100644
--- a/lib/utils.h
+++ b/lib/utils.h
@@ -26,6 +26,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -269,4 +270,76 @@ std::size_t getArrayLength(const T (& /*unused*/)[size])
return size;
}
+/** this is meant as a replacement for when we cannot print a pointer via the stream insertion operator (operator<<) for performance reasons */
+// TODO: should give portable value / only used by Tokenizer::dump() and underlying functions - something deterministic would also help with comparing the output
+static inline std::string ptr_to_string(const void* p)
+{
+#if (defined(__APPLE__) && defined(__MACH__))
+ if (p == nullptr)
+ return "0x0";
+#elif !defined(_WIN32) || defined(__MINGW32__)
+ if (p == nullptr)
+ return "0";
+#endif
+
+ static constexpr int ptr_size = sizeof(void*);
+
+#if defined(_WIN32) && !defined(__MINGW32__)
+ // two characters of each byte / contains terminating \0
+ static constexpr int buf_size = (ptr_size * 2) + 1;
+#else
+ // two characters of each byte / contains 0x prefix and contains terminating \0
+ static constexpr int buf_size = (ptr_size * 2) + 2 + 1;
+#endif
+ char buf[buf_size];
+
+ // needs to be signed so we don't underflow in padding loop
+ int idx = sizeof(buf) - 1;
+ buf[idx--] = '\0'; // terminate string
+
+ uintptr_t l = reinterpret_cast(p);
+ while (l != 0)
+ {
+ char c;
+ const uintptr_t temp = l % 16; // get the remainder
+ if (temp < 10) {
+ // 0-9
+ c = '0' + temp;
+ }
+ else {
+#if !defined(_WIN32) || defined(__MINGW32__)
+ // a-f
+ c = 'a' + (temp - 10);
+#else
+ // A-F
+ c = 'A' + (temp - 10);
+#endif
+ }
+ buf[idx--] = c; // store in reverse order
+ l = l / 16;
+ }
+
+#if defined(_WIN32) && !defined(__MINGW32__)
+ // pad address with 0
+ while (idx >= 0) {
+ buf[idx--] = '0';
+ }
+
+ // 000000F0A61FF122 or 0230FB33
+ return buf;
+#else
+ // add 0x prefix
+ buf[idx--] = 'x';
+ buf[idx--] = '0';
+
+ // 0x7ffc5aa334d8
+ return &buf[idx+1];
+#endif
+}
+
+static inline std::string bool_to_string(bool b)
+{
+ return b ? "true" : "false";
+}
+
#endif
diff --git a/test/testutils.cpp b/test/testutils.cpp
index 09f92d3815a..b4c143441a8 100644
--- a/test/testutils.cpp
+++ b/test/testutils.cpp
@@ -22,6 +22,8 @@
#include
#include
#include
+#include
+#include
#include
#include
@@ -36,6 +38,7 @@ class TestUtils : public TestFixture {
TEST_CASE(isStringLiteral);
TEST_CASE(isCharLiteral);
TEST_CASE(strToInt);
+ TEST_CASE(ptrToString);
}
void isValidGlobPattern() const {
@@ -330,6 +333,58 @@ class TestUtils : public TestFixture {
ASSERT_EQUALS("out of range (stoull)", err);
}
}
+
+ void ptrToString() const
+ {
+ struct Dummy {};
+ // stack address
+ {
+ const Dummy d;
+ const Dummy* const dp = &d;
+ std::ostringstream oss;
+ oss << dp;
+ ASSERT_EQUALS(oss.str(), ptr_to_string(dp));
+ }
+ // highest address
+ {
+ // NOLINTNEXTLINE(performance-no-int-to-ptr)
+ const void* const p = reinterpret_cast(std::numeric_limits::max());
+ std::ostringstream oss;
+ oss << p;
+ ASSERT_EQUALS(oss.str(), ptr_to_string(p));
+ }
+ // same in-between address
+ {
+ const Dummy d;
+ const Dummy* dp = &d;
+ dp = dp - ((unsigned long long)dp / 2);
+ std::ostringstream oss;
+ oss << dp;
+ ASSERT_EQUALS(oss.str(), ptr_to_string(dp));
+ }
+ // lowest address
+ {
+ // NOLINTNEXTLINE(performance-no-int-to-ptr)
+ const void* const p = reinterpret_cast(std::numeric_limits::min() + 1);
+ std::ostringstream oss;
+ oss << p;
+ ASSERT_EQUALS(oss.str(), ptr_to_string(p));
+ }
+ // heap address
+ {
+ const auto dp = std::unique_ptr(new Dummy);
+ std::ostringstream oss;
+ oss << dp.get();
+ ASSERT_EQUALS(oss.str(), ptr_to_string(dp.get()));
+ }
+ // NULL pointer
+ {
+ const Dummy* const dp = nullptr;
+ std::ostringstream oss;
+ oss << dp;
+ ASSERT_EQUALS(oss.str(), ptr_to_string(dp));
+ }
+ }
};
REGISTER_TEST(TestUtils)