45 static std::vector<std::string> 
getnames(
const char *names)
 
   47     std::vector<std::string> ret;
 
   48     while (
const char *p = std::strchr(names,
',')) {
 
   49         ret.emplace_back(names, p-names);
 
   52     ret.emplace_back(names);
 
   58     std::istringstream istr(valid + 
',');
 
   59     tokenList.
createTokens(istr, cpp ? Standards::Language::CPP : Standards::Language::C); 
 
   62             tok->str(
"-" + tok->strAt(1));
 
   70     if (std::strchr(path,
',') != 
nullptr) {
 
   73             const std::string::size_type pos = p.find(
',');
 
   74             if (pos == std::string::npos)
 
   76             const Error &e = 
load(exename, p.substr(0,pos).c_str());
 
   82             return load(exename, p.c_str());
 
   86     std::string absolute_path;
 
   88     tinyxml2::XMLDocument doc;
 
   89     tinyxml2::XMLError 
error = doc.LoadFile(path);
 
   92         error = tinyxml2::XML_ERROR_FILE_NOT_FOUND;
 
   93     if (
error == tinyxml2::XML_ERROR_FILE_NOT_FOUND) {
 
   95         std::string fullfilename(path);
 
   97             fullfilename += 
".cfg";
 
   98             error = doc.LoadFile(fullfilename.c_str());
 
   99             if (
error != tinyxml2::XML_ERROR_FILE_NOT_FOUND)
 
  103         std::list<std::string> cfgfolders;
 
  105         cfgfolders.emplace_back(FILESDIR 
"/cfg");
 
  109             cfgfolders.push_back(exepath + 
"cfg");
 
  110             cfgfolders.push_back(exepath + 
"../cfg");
 
  111             cfgfolders.push_back(exepath);
 
  114         while (
error == tinyxml2::XML_ERROR_FILE_NOT_FOUND && !cfgfolders.empty()) {
 
  115             const std::string cfgfolder(cfgfolders.back());
 
  116             cfgfolders.pop_back();
 
  117             const char *sep = (!cfgfolder.empty() && 
endsWith(cfgfolder,
'/') ? 
"" : 
"/");
 
  118             const std::string filename(cfgfolder + sep + fullfilename);
 
  119             error = doc.LoadFile(filename.c_str());
 
  120             if (
error != tinyxml2::XML_ERROR_FILE_NOT_FOUND)
 
  126     if (
error == tinyxml2::XML_SUCCESS) {
 
  130                 mFiles.insert(absolute_path);
 
  137     if (
error == tinyxml2::XML_ERROR_FILE_NOT_FOUND)
 
  146     if (yieldName == 
"at_index")
 
  148     if (yieldName == 
"item")
 
  150     if (yieldName == 
"buffer")
 
  152     if (yieldName == 
"buffer-nt")
 
  154     if (yieldName == 
"start-iterator")
 
  156     if (yieldName == 
"end-iterator")
 
  158     if (yieldName == 
"iterator")
 
  160     if (yieldName == 
"size")
 
  162     if (yieldName == 
"empty")
 
  168     if (actionName == 
"resize")
 
  170     if (actionName == 
"clear")
 
  172     if (actionName == 
"push")
 
  174     if (actionName == 
"pop")
 
  176     if (actionName == 
"find")
 
  178     if (actionName == 
"find-const")
 
  180     if (actionName == 
"insert")
 
  182     if (actionName == 
"erase")
 
  184     if (actionName == 
"change-content")
 
  186     if (actionName == 
"change-internal")
 
  188     if (actionName == 
"change")
 
  195     const tinyxml2::XMLElement * 
const rootnode = doc.FirstChildElement();
 
  197     if (rootnode == 
nullptr) {
 
  202     if (strcmp(rootnode->Name(),
"def") != 0)
 
  205     const int format = rootnode->IntAttribute(
"format", 1); 
 
  207     if (format > 2 || format <= 0)
 
  210     std::set<std::string> unknown_elements;
 
  212     for (
const tinyxml2::XMLElement *node = rootnode->FirstChildElement(); node; node = node->NextSiblingElement()) {
 
  213         const std::string nodename = node->Name();
 
  214         if (nodename == 
"memory" || nodename == 
"resource") {
 
  216             int allocationId = 0;
 
  217             for (
const tinyxml2::XMLElement *memorynode = node->FirstChildElement(); memorynode; memorynode = memorynode->NextSiblingElement()) {
 
  218                 if (strcmp(memorynode->Name(),
"dealloc")==0) {
 
  219                     const auto names = 
getnames(memorynode->GetText());
 
  220                     for (
const auto& n : names) {
 
  221                         const std::map<std::string, AllocFunc>::const_iterator it = 
mDealloc.find(n);
 
  223                             allocationId = it->second.groupId;
 
  227                     if (allocationId != 0)
 
  231             if (allocationId == 0) {
 
  232                 if (nodename == 
"memory")
 
  240             for (
const tinyxml2::XMLElement *memorynode = node->FirstChildElement(); memorynode; memorynode = memorynode->NextSiblingElement()) {
 
  241                 const std::string memorynodename = memorynode->Name();
 
  242                 const auto names = 
getnames(memorynode->GetText());
 
  243                 if (memorynodename == 
"alloc" || memorynodename == 
"realloc") {
 
  247                     temp.
initData = memorynode->BoolAttribute(
"init", 
true);
 
  248                     temp.
arg = memorynode->IntAttribute(
"arg", -1);
 
  250                     const char *bufferSize = memorynode->Attribute(
"buffer-size");
 
  254                         if (std::strncmp(bufferSize, 
"malloc", 6) == 0)
 
  256                         else if (std::strncmp(bufferSize, 
"calloc", 6) == 0)
 
  258                         else if (std::strncmp(bufferSize, 
"strdup", 6) == 0)
 
  264                         if (bufferSize[6] == 0) {
 
  266                         } 
else if (bufferSize[6] == 
':' && bufferSize[7] >= 
'1' && bufferSize[7] <= 
'5') {
 
  268                             if (bufferSize[8] == 
',' && bufferSize[9] >= 
'1' && bufferSize[9] <= 
'5')
 
  274                     if (memorynodename == 
"realloc")
 
  275                         temp.
reallocArg = memorynode->IntAttribute(
"realloc-arg", 1);
 
  278                     for (
const auto& n : names)
 
  280                 } 
else if (memorynodename == 
"dealloc") {
 
  283                     temp.
arg = memorynode->IntAttribute(
"arg", 1);
 
  284                     for (
const auto& n : names)
 
  286                 } 
else if (memorynodename == 
"use")
 
  287                     for (
const auto& n : names)
 
  290                     unknown_elements.insert(memorynodename);
 
  294         else if (nodename == 
"define") {
 
  295             const char *name = node->Attribute(
"name");
 
  298             const char *value = node->Attribute(
"value");
 
  299             if (value == 
nullptr)
 
  301             auto result = 
defines.insert(std::string(name) + 
" " + value);
 
  306         else if (nodename == 
"function") {
 
  307             const char *name = node->Attribute(
"name");
 
  310             for (
const std::string &s : 
getnames(name)) {
 
  317         else if (nodename == 
"reflection") {
 
  318             for (
const tinyxml2::XMLElement *reflectionnode = node->FirstChildElement(); reflectionnode; reflectionnode = reflectionnode->NextSiblingElement()) {
 
  319                 if (strcmp(reflectionnode->Name(), 
"call") != 0) {
 
  320                     unknown_elements.insert(reflectionnode->Name());
 
  324                 const char * 
const argString = reflectionnode->Attribute(
"arg");
 
  328                 mReflection[reflectionnode->GetText()] = strToInt<int>(argString);
 
  332         else if (nodename == 
"markup") {
 
  333             const char * 
const extension = node->Attribute(
"ext");
 
  338             mReportErrors[extension] = (node->Attribute(
"reporterrors", 
"true") != 
nullptr);
 
  339             mProcessAfterCode[extension] = (node->Attribute(
"aftercode", 
"true") != 
nullptr);
 
  341             for (
const tinyxml2::XMLElement *markupnode = node->FirstChildElement(); markupnode; markupnode = markupnode->NextSiblingElement()) {
 
  342                 const std::string markupnodename = markupnode->Name();
 
  343                 if (markupnodename == 
"keywords") {
 
  344                     for (
const tinyxml2::XMLElement *librarynode = markupnode->FirstChildElement(); librarynode; librarynode = librarynode->NextSiblingElement()) {
 
  345                         if (strcmp(librarynode->Name(), 
"keyword") == 0) {
 
  346                             const char* nodeName = librarynode->Attribute(
"name");
 
  347                             if (nodeName == 
nullptr)
 
  351                             unknown_elements.insert(librarynode->Name());
 
  355                 else if (markupnodename == 
"exported") {
 
  356                     for (
const tinyxml2::XMLElement *exporter = markupnode->FirstChildElement(); exporter; exporter = exporter->NextSiblingElement()) {
 
  357                         if (strcmp(exporter->Name(), 
"exporter") != 0) {
 
  358                             unknown_elements.insert(exporter->Name());
 
  362                         const char * 
const prefix = exporter->Attribute(
"prefix");
 
  366                         for (
const tinyxml2::XMLElement *e = exporter->FirstChildElement(); e; e = e->NextSiblingElement()) {
 
  367                             const std::string ename = e->Name();
 
  368                             if (ename == 
"prefix")
 
  370                             else if (ename == 
"suffix")
 
  373                                 unknown_elements.insert(ename);
 
  378                 else if (markupnodename == 
"imported") {
 
  379                     for (
const tinyxml2::XMLElement *librarynode = markupnode->FirstChildElement(); librarynode; librarynode = librarynode->NextSiblingElement()) {
 
  380                         if (strcmp(librarynode->Name(), 
"importer") == 0)
 
  381                             mImporters[extension].insert(librarynode->GetText());
 
  383                             unknown_elements.insert(librarynode->Name());
 
  387                 else if (markupnodename == 
"codeblocks") {
 
  388                     for (
const tinyxml2::XMLElement *blocknode = markupnode->FirstChildElement(); blocknode; blocknode = blocknode->NextSiblingElement()) {
 
  389                         const std::string blocknodename = blocknode->Name();
 
  390                         if (blocknodename == 
"block") {
 
  391                             const char * blockName = blocknode->Attribute(
"name");
 
  394                         } 
else if (blocknodename == 
"structure") {
 
  395                             const char * start = blocknode->Attribute(
"start");
 
  398                             const char * end = blocknode->Attribute(
"end");
 
  401                             const char * offset = blocknode->Attribute(
"offset");
 
  409                             unknown_elements.insert(blocknodename);
 
  414                     unknown_elements.insert(markupnodename);
 
  418         else if (nodename == 
"container") {
 
  419             const char* 
const id = node->Attribute(
"id");
 
  425             const char* 
const inherits = node->Attribute(
"inherits");
 
  427                 const std::unordered_map<std::string, Container>::const_iterator i = 
containers.find(inherits);
 
  429                     container = i->second; 
 
  434             const char* 
const startPattern = node->Attribute(
"startPattern");
 
  441             const char* 
const endPattern = node->Attribute(
"endPattern");
 
  444             const char* 
const itEndPattern = node->Attribute(
"itEndPattern");
 
  447             const char* 
const opLessAllowed = node->Attribute(
"opLessAllowed");
 
  449                 container.
opLessAllowed = strcmp(opLessAllowed, 
"true") == 0;
 
  450             const char* 
const hasInitializerListConstructor = node->Attribute(
"hasInitializerListConstructor");
 
  451             if (hasInitializerListConstructor)
 
  453             const char* 
const view = node->Attribute(
"view");
 
  455                 container.
view = strcmp(view, 
"true") == 0;
 
  457             for (
const tinyxml2::XMLElement *containerNode = node->FirstChildElement(); containerNode; containerNode = containerNode->NextSiblingElement()) {
 
  458                 const std::string containerNodeName = containerNode->Name();
 
  459                 if (containerNodeName == 
"size" || containerNodeName == 
"access" || containerNodeName == 
"other") {
 
  460                     for (
const tinyxml2::XMLElement *functionNode = containerNode->FirstChildElement(); functionNode; functionNode = functionNode->NextSiblingElement()) {
 
  461                         if (strcmp(functionNode->Name(), 
"function") != 0) {
 
  462                             unknown_elements.insert(functionNode->Name());
 
  466                         const char* 
const functionName = functionNode->Attribute(
"name");
 
  470                         const char* 
const action_ptr = functionNode->Attribute(
"action");
 
  473                             std::string actionName = action_ptr;
 
  479                         const char* 
const yield_ptr = functionNode->Attribute(
"yields");
 
  482                             std::string yieldName = yield_ptr;
 
  488                         const char* 
const returnType = functionNode->Attribute(
"returnType");
 
  490                             container.
functions[functionName].returnType = returnType;
 
  492                         container.
functions[functionName].action = action;
 
  493                         container.
functions[functionName].yield = yield;
 
  496                     if (containerNodeName == 
"size") {
 
  497                         const char* 
const templateArg = containerNode->Attribute(
"templateParameter");
 
  500                     } 
else if (containerNodeName == 
"access") {
 
  501                         const char* 
const indexArg = containerNode->Attribute(
"indexOperator");
 
  505                 } 
else if (containerNodeName == 
"type") {
 
  506                     const char* 
const templateArg = containerNode->Attribute(
"templateParameter");
 
  510                     const char* 
const string = containerNode->Attribute(
"string");
 
  513                     const char* 
const associative = containerNode->Attribute(
"associative");
 
  516                     const char* 
const unstable = containerNode->Attribute(
"unstable");
 
  518                         std::string unstableType = unstable;
 
  519                         if (unstableType.find(
"erase") != std::string::npos)
 
  521                         if (unstableType.find(
"insert") != std::string::npos)
 
  524                 } 
else if (containerNodeName == 
"rangeItemRecordType") {
 
  525                     for (
const tinyxml2::XMLElement* memberNode = node->FirstChildElement(); memberNode; memberNode = memberNode->NextSiblingElement()) {
 
  526                         const char *memberName = memberNode->Attribute(
"name");
 
  527                         const char *memberTemplateParameter = memberNode->Attribute(
"templateParameter");
 
  529                         member.
name = memberName ? memberName : 
"";
 
  530                         member.
templateParameter = memberTemplateParameter ? strToInt<int>(memberTemplateParameter) : -1;
 
  534                     unknown_elements.insert(containerNodeName);
 
  538         else if (nodename == 
"smart-pointer") {
 
  539             const char *className = node->Attribute(
"class-name");
 
  543             smartPointer.
name = className;
 
  544             for (
const tinyxml2::XMLElement* smartPointerNode = node->FirstChildElement(); smartPointerNode;
 
  545                  smartPointerNode = smartPointerNode->NextSiblingElement()) {
 
  546                 const std::string smartPointerNodeName = smartPointerNode->Name();
 
  547                 if (smartPointerNodeName == 
"unique")
 
  548                     smartPointer.
unique = 
true;
 
  552         else if (nodename == 
"type-checks") {
 
  553             for (
const tinyxml2::XMLElement *checkNode = node->FirstChildElement(); checkNode; checkNode = checkNode->NextSiblingElement()) {
 
  554                 const std::string &checkName = checkNode->Name();
 
  555                 for (
const tinyxml2::XMLElement *checkTypeNode = checkNode->FirstChildElement(); checkTypeNode; checkTypeNode = checkTypeNode->NextSiblingElement()) {
 
  556                     const std::string checkTypeName = checkTypeNode->Name();
 
  557                     const char *typeName = checkTypeNode->GetText();
 
  560                     if (checkTypeName == 
"check")
 
  562                     else if (checkTypeName == 
"suppress")
 
  564                     else if (checkTypeName == 
"checkFiniteLifetime")
 
  570         else if (nodename == 
"podtype") {
 
  571             const char * 
const name = node->Attribute(
"name");
 
  576             const char * 
const stdtype = node->Attribute(
"stdtype");
 
  578                 if (std::strcmp(stdtype, 
"bool") == 0)
 
  580                 else if (std::strcmp(stdtype, 
"char") == 0)
 
  582                 else if (std::strcmp(stdtype, 
"short") == 0)
 
  584                 else if (std::strcmp(stdtype, 
"int") == 0)
 
  586                 else if (std::strcmp(stdtype, 
"long") == 0)
 
  588                 else if (std::strcmp(stdtype, 
"long long") == 0)
 
  591             const char * 
const size = node->Attribute(
"size");
 
  593                 podType.
size = strToInt<unsigned int>(size);
 
  594             const char * 
const sign = node->Attribute(
"sign");
 
  597             for (
const std::string &s : 
getnames(name))
 
  601         else if (nodename == 
"platformtype") {
 
  602             const char * 
const type_name = node->Attribute(
"name");
 
  603             if (type_name == 
nullptr)
 
  605             const char *value = node->Attribute(
"value");
 
  606             if (value == 
nullptr)
 
  610             std::set<std::string> platform;
 
  611             for (
const tinyxml2::XMLElement *typenode = node->FirstChildElement(); typenode; typenode = typenode->NextSiblingElement()) {
 
  612                 const std::string typenodename = typenode->Name();
 
  613                 if (typenodename == 
"platform") {
 
  614                     const char * 
const type_attribute = typenode->Attribute(
"type");
 
  615                     if (type_attribute == 
nullptr)
 
  617                     platform.insert(type_attribute);
 
  618                 } 
else if (typenodename == 
"signed")
 
  620                 else if (typenodename == 
"unsigned")
 
  622                 else if (typenodename == 
"long")
 
  624                 else if (typenodename == 
"pointer")
 
  626                 else if (typenodename == 
"ptr_ptr")
 
  628                 else if (typenodename == 
"const_ptr")
 
  631                     unknown_elements.insert(typenodename);
 
  633             if (platform.empty()) {
 
  636                     if (*type_ptr == type)
 
  642                 for (
const std::string &p : platform) {
 
  645                         if (*type_ptr == type)
 
  649                     mPlatforms[p].mPlatformTypes[type_name] = type;
 
  654         else if (nodename == 
"entrypoint") {
 
  655             const char * 
const type_name = node->Attribute(
"name");
 
  656             if (type_name == 
nullptr)
 
  662             unknown_elements.insert(nodename);
 
  664     if (!unknown_elements.empty()) {
 
  666         for (std::set<std::string>::const_iterator i = unknown_elements.cbegin(); i != unknown_elements.cend();) {
 
  668             if (++i != unknown_elements.end())
 
  684     for (
const tinyxml2::XMLElement *functionnode = node->FirstChildElement(); functionnode; functionnode = functionnode->NextSiblingElement()) {
 
  685         const std::string functionnodename = functionnode->Name();
 
  686         if (functionnodename == 
"noreturn") {
 
  687             const char * 
const text = functionnode->GetText();
 
  688             if (strcmp(text, 
"false") == 0)
 
  690             else if (strcmp(text, 
"maybe") == 0)
 
  694         } 
else if (functionnodename == 
"pure")
 
  696         else if (functionnodename == 
"const") {
 
  699         } 
else if (functionnodename == 
"leak-ignore")
 
  701         else if (functionnodename == 
"not-overlapping-data") {
 
  703             nonOverlappingData.
ptr1Arg = functionnode->IntAttribute(
"ptr1-arg", -1);
 
  704             nonOverlappingData.
ptr2Arg = functionnode->IntAttribute(
"ptr2-arg", -1);
 
  705             nonOverlappingData.
sizeArg = functionnode->IntAttribute(
"size-arg", -1);
 
  706             nonOverlappingData.
strlenArg = functionnode->IntAttribute(
"strlen-arg", -1);
 
  707             nonOverlappingData.
countArg = functionnode->IntAttribute(
"count-arg", -1);
 
  709         } 
else if (functionnodename == 
"use-retval") {
 
  711             if (
const char *type = functionnode->Attribute(
"type"))
 
  712                 if (std::strcmp(type, 
"error-code") == 0)
 
  714         } 
else if (functionnodename == 
"returnValue") {
 
  715             if (
const char *expr = functionnode->GetText())
 
  717             if (
const char *type = functionnode->Attribute(
"type"))
 
  719             if (
const char *container = functionnode->Attribute(
"container"))
 
  724                     std::vector<MathLib::bigint> values{LLONG_MIN, LLONG_MAX};
 
  728         } 
else if (functionnodename == 
"arg") {
 
  729             const char* argNrString = functionnode->Attribute(
"nr");
 
  732             const bool bAnyArg = strcmp(argNrString, 
"any") == 0;
 
  733             const bool bVariadicArg = strcmp(argNrString, 
"variadic") == 0;
 
  734             const int nr = (bAnyArg || bVariadicArg) ? -1 : strToInt<int>(argNrString);
 
  736             ac.
optional  = functionnode->Attribute(
"default") != 
nullptr;
 
  738             const char * 
const argDirection = functionnode->Attribute(
"direction");
 
  740                 const size_t argDirLen = strlen(argDirection);
 
  741                 if (!strncmp(argDirection, 
"in", argDirLen)) {
 
  743                 } 
else if (!strncmp(argDirection, 
"out", argDirLen)) {
 
  745                 } 
else if (!strncmp(argDirection, 
"inout", argDirLen)) {
 
  749             for (
const tinyxml2::XMLElement *argnode = functionnode->FirstChildElement(); argnode; argnode = argnode->NextSiblingElement()) {
 
  750                 const std::string argnodename = argnode->Name();
 
  752                 const char * 
const indirectStr = argnode->Attribute(
"indirect");
 
  754                     indirect = strToInt<int>(indirectStr);
 
  755                 if (argnodename == 
"not-bool")
 
  757                 else if (argnodename == 
"not-null")
 
  759                 else if (argnodename == 
"not-uninit")
 
  761                 else if (argnodename == 
"formatstr")
 
  763                 else if (argnodename == 
"strz")
 
  765                 else if (argnodename == 
"valid") {
 
  767                     const char *p = argnode->GetText();
 
  773                 else if (argnodename == 
"minsize") {
 
  774                     const char *typeattr = argnode->Attribute(
"type");
 
  779                     if (strcmp(typeattr,
"strlen")==0)
 
  781                     else if (strcmp(typeattr,
"argvalue")==0)
 
  783                     else if (strcmp(typeattr,
"sizeof")==0)
 
  785                     else if (strcmp(typeattr,
"mul")==0)
 
  787                     else if (strcmp(typeattr,
"value")==0)
 
  793                         const char *valueattr = argnode->Attribute(
"value");
 
  796                         long long minsizevalue = 0;
 
  798                             minsizevalue = strToInt<long long>(valueattr);
 
  799                         } 
catch (
const std::runtime_error&) {
 
  802                         if (minsizevalue <= 0)
 
  805                         ac.
minsizes.back().value = minsizevalue;
 
  807                         const char *argattr = argnode->Attribute(
"arg");
 
  810                         if (strlen(argattr) != 1 || argattr[0]<
'0' || argattr[0]>
'9')
 
  814                         ac.
minsizes.emplace_back(type, argattr[0] - 
'0');
 
  816                             const char *arg2attr = argnode->Attribute(
"arg2");
 
  819                             if (strlen(arg2attr) != 1 || arg2attr[0]<
'0' || arg2attr[0]>
'9')
 
  821                             ac.
minsizes.back().arg2 = arg2attr[0] - 
'0';
 
  824                     const char* baseTypeAttr = argnode->Attribute(
"baseType"); 
 
  826                         ac.
minsizes.back().baseType = baseTypeAttr;
 
  829                 else if (argnodename == 
"iterator") {
 
  831                     const char* str = argnode->Attribute(
"type");
 
  838                     unknown_elements.insert(argnodename);
 
  842         } 
else if (functionnodename == 
"ignorefunction") {
 
  844         } 
else if (functionnodename == 
"formatstr") {
 
  846             const tinyxml2::XMLAttribute* scan = functionnode->FindAttribute(
"scan");
 
  847             const tinyxml2::XMLAttribute* secure = functionnode->FindAttribute(
"secure");
 
  850         } 
else if (functionnodename == 
"warn") {
 
  852             const char* 
const severity = functionnode->Attribute(
"severity");
 
  853             if (severity == 
nullptr)
 
  857             const char* 
const cstd = functionnode->Attribute(
"cstd");
 
  864             const char* 
const cppstd = functionnode->Attribute(
"cppstd");
 
  871             const char* 
const reason = functionnode->Attribute(
"reason");
 
  872             const char* 
const alternatives = functionnode->Attribute(
"alternatives");
 
  873             if (reason && alternatives) {
 
  875                 wi.
message = std::string(reason) + 
" function '" + name + 
"' called. It is recommended to use ";
 
  876                 std::vector<std::string> alt = 
getnames(alternatives);
 
  877                 for (std::size_t i = 0; i < alt.size(); ++i) {
 
  878                     wi.
message += 
"'" + alt[i] + 
"'";
 
  879                     if (i == alt.size() - 1)
 
  881                     else if (i == alt.size() - 2)
 
  887                 const char * 
const message = functionnode->GetText();
 
  895         } 
else if (functionnodename == 
"container") {
 
  896             const char* 
const action_ptr = functionnode->Attribute(
"action");
 
  899                 std::string actionName = action_ptr;
 
  906             const char* 
const yield_ptr = functionnode->Attribute(
"yields");
 
  909                 std::string yieldName = yield_ptr;
 
  916             const char* 
const returnType = functionnode->Attribute(
"returnType");
 
  920             unknown_elements.insert(functionnodename);
 
  928     if (!ac || ac->
valid.empty())
 
  930     if (ac->
valid.find(
'.') != std::string::npos)
 
  934     for (
const Token *tok = tokenList.
front(); tok; tok = tok->
next()) {
 
  950     if (!ac || ac->
valid.empty())
 
  954     for (
const Token *tok = tokenList.
front(); tok; tok = tok->
next()) {
 
  978         for (
const Scope *scope = ftok->
scope(); scope; scope = scope->nestedIn) {
 
  979             if (!scope->isClassOrStruct())
 
  981             const std::vector<Type::BaseInfo> &derivedFrom = scope->definedType->derivedFrom;
 
  984                 const Token* tok = baseInfo.nameTok; 
 
  985                 if (tok->
str() == 
"::")
 
  991                 name += 
"::" + ftok->
str();
 
  998     if (ftok->
str() == 
"::") {
 
 1038     std::string ret(ftok->
str());
 
 1039     ftok = ftok->
tokAt(-2);
 
 1041         ret = ftok->
str() + 
"::" + ret;
 
 1042         ftok = ftok->
tokAt(-2);
 
 1053         const std::unordered_map<std::string, Function>::const_iterator it = 
functions.find(funcname);
 
 1054         if (it != 
functions.cend() && it->second.formatstr && it->second.formatstr_scan)
 
 1066         const std::unordered_map<std::string, Function>::const_iterator it = 
functions.find(funcname);
 
 1067         if (it != 
functions.cend() && it->second.formatstr && !it->second.formatstr_scan)
 
 1070     if (hasIndirect && arg && arg->
notuninit >= 1)
 
 1071         *hasIndirect = 
true;
 
 1072     return arg && arg->
notuninit >= indirect;
 
 1107     return (af && af->
arg == arg) ? af->
groupId : 0;
 
 1114     return (af && af->
arg == arg) ? af->
groupId : 0;
 
 1121     return (af && af->
arg == arg) ? af->
groupId : 0;
 
 1132     const std::map<int,ArgumentChecks>::const_iterator it2 = it1->second.argumentChecks.find(argnr);
 
 1133     if (it2 != it1->second.argumentChecks.cend())
 
 1134         return &it2->second;
 
 1135     const std::map<int,ArgumentChecks>::const_iterator it3 = it1->second.argumentChecks.find(-1);
 
 1136     if (it3 != it1->second.argumentChecks.cend())
 
 1137         return &it3->second;
 
 1144         unknownFunc->clear();
 
 1158     const Token *start = funcname;
 
 1161         start = funcname->
tokAt(-3);
 
 1162     } 
else if (funcname->
isName()) {
 
 1171         if (funcname->
str() == 
"exit")
 
 1175                 *unknownFunc = funcname->
str();
 
 1184     const Token* firstLinkedTok = 
nullptr;
 
 1185     for (
const Token* tok = typeStart; tok && !tok->
varId(); tok = tok->next()) {
 
 1189         firstLinkedTok = tok;
 
 1193     for (
const std::pair<const std::string, Library::Container> & c : 
containers) {
 
 1210         if (!firstLinkedTok)
 
 1214         if (!matchedStartPattern)
 
 1254     if (cond->
str() == 
"(") {
 
 1256         if (tok && tok->
str() == 
".") {
 
 1261             } 
else if (!fallback.empty()) {
 
 1273         if (tok && tok->
str() == 
".") {
 
 1277                         return container->getYield(tok->
astOperand2()->str());
 
 1303     if (functionName.empty())
 
 1306     const std::unordered_map<std::string, Function>::const_iterator it = 
functions.find(functionName);
 
 1310     int firstOptionalArg = -1;
 
 1311     for (
const std::pair<const int, Library::ArgumentChecks> & argCheck : it->second.argumentChecks) {
 
 1312         if (argCheck.first > args)
 
 1313             args = argCheck.first;
 
 1314         if (argCheck.second.optional && (firstOptionalArg == -1 || firstOptionalArg > argCheck.first))
 
 1315             firstOptionalArg = argCheck.first;
 
 1317         if (argCheck.second.formatstr || argCheck.second.variadic)
 
 1318             return args <= callargs;
 
 1320     return (firstOptionalArg < 0) ? args == callargs : (callargs >= firstOptionalArg-1 && callargs <= args);
 
 1340     bool has_dot = 
false;
 
 1345         if (std::isdigit(*p)) {
 
 1346             error |= (*(p + 1) == 
'-');
 
 1348         else if (*p == 
':') {
 
 1350             error |= range | (*(p + 1) == 
'.');
 
 1355         else if ((*p == 
'-') || (*p == 
'+')) {
 
 1356             error |= (!std::isdigit(*(p + 1)));
 
 1358         else if (*p == 
',') {
 
 1360             error |= *(p + 1) == 
'.';
 
 1363         } 
else if (*p == 
'.') {
 
 1365             error |= has_dot | (!std::isdigit(*(p + 1)));
 
 1367         } 
else if (*p == 
'E' || *p == 
'e') {
 
 1370         } 
else if (*p == 
'!') {
 
 1371             error |= !((*(p+1) == 
'-') || (*(p+1) == 
'+') || (std::isdigit(*(p + 1))));
 
 1385         return it->second.formatstr;
 
 1391     const std::map<int, Library::ArgumentChecks>& argumentChecksFunc = 
functions.at(
getFunctionName(ftok)).argumentChecks;
 
 1392     auto it = std::find_if(argumentChecksFunc.cbegin(), argumentChecksFunc.cend(), [](
const std::pair<const int, Library::ArgumentChecks>& a) {
 
 1393         return a.second.formatstr;
 
 1395     return it == argumentChecksFunc.cend() ? -1 : it->first - 1;
 
 1423             if (yield == Yield::START_ITERATOR || yield == Yield::END_ITERATOR || yield == Yield::AT_INDEX ||
 
 1424                 yield == Yield::SIZE || yield == Yield::EMPTY || yield == Yield::BUFFER || yield == Yield::BUFFER_NT ||
 
 1432         return it->second.useretval;
 
 1469         return std::vector<MathLib::bigint>();
 
 1481     return &it1->second;
 
 1492     return std::any_of(it->second.argumentChecks.cbegin(), it->second.argumentChecks.cend(), [](
const std::pair<const int, Library::ArgumentChecks>& a) {
 
 1493         return !a.second.minsizes.empty();
 
 1504         if (fs_argno >= 0 && argnr >= fs_argno) {
 
 1515     const std::unordered_map<std::string, Function>::const_iterator it = 
functions.find(functionName);
 
 1517         return it->second.ignore;
 
 1522     const std::unordered_map<std::string, Function>::const_iterator it = 
functions.find(functionName);
 
 1524         return it->second.use;
 
 1529     const std::unordered_map<std::string, Function>::const_iterator it = 
functions.find(functionName);
 
 1531         return it->second.leakignore;
 
 1536     const std::unordered_map<std::string, Function>::const_iterator it = 
functions.find(functionName);
 
 1538         return pure ? it->second.ispure : it->second.isconst;
 
 1549             if (yield == Yield::EMPTY || yield == Yield::SIZE || yield == Yield::BUFFER_NT)
 
 1555     return (it != 
functions.cend() && it->second.isconst);
 
 1619     const std::unordered_map<std::string, CodeBlock>::const_iterator map_it
 
 1623         offset = map_it->second.offset();
 
 1630     const std::unordered_map<std::string, CodeBlock>::const_iterator map_it
 
 1634         return map_it->second.start();
 
 1641     const std::unordered_map<std::string, CodeBlock>::const_iterator map_it
 
 1645         return map_it->second.end();
 
 1652     const std::map<std::string, std::set<std::string>>::const_iterator it =
 
 1654     return (it != 
mKeywords.end() && it->second.count(keyword));
 
 1659     const std::map<std::string, std::set<std::string>>::const_iterator it =
 
 1661     return (it != 
mImporters.end() && it->second.count(importer) > 0);
 
 1674             return containerTok;
 
 1676             return containerTok;
 
 1678             return containerTok;
 
 1681             if (f->containerYield == yield) {
 
 1700             return containerTok;
 
 1702             return containerTok;
 
 1705             if (f->containerAction == action) {
 
 1720     std::string typestr = withoutStd ? 
"std::" : 
"";
 
 1722         typestr += tok->
str();
 
 1739             if (!v.isLocalLifetimeValue())
 
 1753     auto it = 
mTypeChecks.find(std::pair<std::string, std::string>(std::move(check), std::move(typeName)));
 
 1760         return tc.first.second == typeName;
 
 1767                                                  std::unordered_map<nonneg int, const Token*>* lookupVarId)
 
 1769     std::shared_ptr<TokenList> tokenList = std::make_shared<TokenList>(&settings);
 
 1771         const std::string code = 
"return " + 
returnValue + 
";";
 
 1772         std::istringstream istr(code);
 
 1773         if (!tokenList->createTokens(istr, cpp ? Standards::Language::CPP : Standards::Language::C))
 
 1778     std::stack<Token*> lpar;
 
 1779     for (
Token* tok2 = tokenList->front(); tok2; tok2 = tok2->
next()) {
 
 1781             tok2->str(tok2->str() + 
"=");
 
 1783         } 
else if (tok2->str() == 
"(")
 
 1785         else if (tok2->str() == 
")") {
 
 1796     for (
Token* tok2 = tokenList->front(); tok2; tok2 = tok2->
next()) {
 
 1799         nonneg int const id = strToInt<nonneg int>(tok2->str().c_str() + 3);
 
 1802             (*lookupVarId)[id] = tok2;
 
 1806     tokenList->createAst();
 
 1809     return {tokenList, expr};
 
int numberOfArgumentsWithoutAst(const Token *start)
Get number of arguments without using AST.
 
bool astIsContainer(const Token *tok)
 
bool astIsPointer(const Token *tok)
 
Library::Container::Action astContainerAction(const Token *tok, const Token **ftok)
 
std::string astCanonicalType(const Token *expr, bool pointedToType)
Get canonical type of expression.
 
Library::Container::Yield astContainerYield(const Token *tok, const Token **ftok)
 
static int sign(const T v)
 
static bool isIterator(const Variable *var, bool &inconclusiveType)
 
const std::string & getReturnType(const std::string &function) const
 
bool hasInitializerListConstructor
 
static Yield yieldFrom(const std::string &yieldName)
 
static Action actionFrom(const std::string &actionName)
 
std::string startPattern2
 
std::vector< RangeItemRecordTypeItem > rangeItemRecordType
 
std::map< std::string, Function > functions
 
Action getAction(const std::string &function) const
 
Yield getYield(const std::string &function) const
 
const Container * detectContainerOrIterator(const Token *typeStart, bool *isIterator=nullptr, bool withoutStd=false) const
 
bool isexecutableblock(const std::string &file, const std::string &token) const
 
std::map< std::string, AllocFunc > mAlloc
 
std::set< std::string > mFiles
 
ArgumentChecks::Direction getArgDirection(const Token *ftok, int argnr) const
 
static bool isresource(const int id)
is allocation type resource?
 
std::map< std::string, std::vector< MathLib::bigint > > mUnknownReturnValues
 
@ DUPLICATE_PLATFORM_TYPE
 
@ PLATFORM_TYPE_REDEFINED
 
bool isuninitargbad(const Token *ftok, int argnr, int indirect=0, bool *hasIndirect=nullptr) const
 
int getAllocId(const Token *tok, int arg) const
get allocation id for function
 
static bool isContainerYield(const Token *const cond, Library::Container::Yield y, const std::string &fallback=emptyString)
 
std::vector< MathLib::bigint > unknownReturnValues(const Token *ftok) const
 
const NonOverlappingData * getNonOverlappingData(const Token *ftok) const
 
const Token * getContainerFromAction(const Token *tok, Container::Action action) const
 
bool isnullargbad(const Token *ftok, int argnr) const
 
Error loadFunction(const tinyxml2::XMLElement *const node, const std::string &name, std::set< std::string > &unknown_elements)
 
const Token * getContainerFromYield(const Token *tok, Container::Yield yield) const
 
bool formatstr_function(const Token *ftok) const
 
const SmartPointer * detectSmartPointer(const Token *tok, bool withoutStd=false) const
 
std::map< std::string, std::set< std::string > > mKeywords
 
const Container * detectIterator(const Token *typeStart) const
 
bool hasAnyTypeCheck(const std::string &typeName) const
 
bool isSmartPointer(const Token *tok) const
 
std::map< std::string, std::set< std::string > > mImporters
 
std::map< std::pair< std::string, std::string >, TypeCheck > mTypeChecks
 
static bool ismemory(const int id)
is allocation type memory?
 
int getDeallocId(const Token *tok, int arg) const
get deallocation id for function
 
bool isFloatArgValid(const Token *ftok, int argnr, double argvalue) const
 
const std::string & blockstart(const std::string &file) const
 
const std::string & returnValue(const Token *ftok) const
 
bool isIntArgValid(const Token *ftok, int argnr, const MathLib::bigint argvalue) const
 
bool formatstr_secure(const Token *ftok) const
 
static const AllocFunc * getAllocDealloc(const std::map< std::string, AllocFunc > &data, const std::string &name)
 
bool isnoreturn(const Token *ftok) const
 
bool hasminsize(const Token *ftok) const
 
bool isLeakIgnore(const std::string &functionName) const
 
std::map< std::string, ExportedFunctions > mExporters
 
bool isnotnoreturn(const Token *ftok) const
 
const ArgumentChecks * getarg(const Token *ftok, int argnr) const
 
int getReallocId(const Token *tok, int arg) const
get reallocation id for function
 
const std::string & blockend(const std::string &file) const
 
Error load(const char exename[], const char path[])
 
UseRetValType getUseRetValType(const Token *ftok) const
 
const AllocFunc * getAllocFuncInfo(const Token *tok) const
get allocation info for function
 
const Library::Container * detectContainerInternal(const Token *typeStart, DetectContainer detect, bool *isIterator=nullptr, bool withoutStd=false) const
 
int formatstr_argno(const Token *ftok) const
 
std::unordered_set< std::string > mEntrypoints
 
std::map< std::string, AllocFunc > mDealloc
 
static Library::Container::Yield getContainerYield(const Token *const cond)
 
const WarnInfo * getWarnInfo(const Token *ftok) const
 
bool isScopeNoReturn(const Token *end, std::string *unknownFunc) const
 
std::set< std::string > mMarkupExtensions
 
TypeCheck getTypeCheck(std::string check, std::string typeName) const
 
static bool isCompliantValidationExpression(const char *p)
 
const AllocFunc * getReallocFuncInfo(const Token *tok) const
get reallocation info for function
 
std::set< std::string > defines
 
TypeCheck
Suppress/check a type.
 
std::map< std::string, std::string > mReturnValue
 
std::map< std::string, int > mReturnValueContainer
 
bool reportErrors(const std::string &path) const
 
const Function * getFunction(const Token *ftok) const
 
bool iskeyword(const std::string &file, const std::string &keyword) const
 
std::map< std::string, bool > mProcessAfterCode
 
std::string getFunctionName(const Token *ftok) const
Get function name for function call.
 
std::unordered_map< std::string, CodeBlock > mExecutableBlocks
 
const AllocFunc * getDeallocFuncInfo(const Token *tok) const
get deallocation info for function
 
std::map< std::string, bool > mReportErrors
 
std::map< std::string, std::string > mReturnValueType
 
std::map< std::string, PlatformType > mPlatformTypes
 
bool isUse(const std::string &functionName) const
 
int returnValueContainer(const Token *ftok) const
 
bool markupFile(const std::string &path) const
 
std::map< std::string, WarnInfo > functionwarn
 
std::unordered_map< std::string, Container > containers
 
std::unordered_map< std::string, SmartPointer > smartPointers
 
std::unordered_map< std::string, PodType > mPodTypes
 
bool isimporter(const std::string &file, const std::string &importer) const
 
std::unordered_map< std::string, NonOverlappingData > mNonOverlappingData
 
bool isNotLibraryFunction(const Token *ftok) const
 
std::unordered_map< std::string, FalseTrueMaybe > mNoReturn
 
const Container * detectContainer(const Token *typeStart) const
 
std::map< std::string, AllocFunc > mRealloc
 
const std::string & returnValueType(const Token *ftok) const
 
std::unordered_map< std::string, Function > functions
 
bool matchArguments(const Token *ftok, const std::string &functionName) const
 
bool processMarkupAfterCode(const std::string &path) const
 
bool isFunctionConst(const std::string &functionName, bool pure) const
 
bool ignorefunction(const std::string &functionName) const
 
const PlatformType * platform_type(const std::string &name, const std::string &platform) const
 
int blockstartoffset(const std::string &file) const
 
std::map< std::string, int > mReflection
 
std::map< std::string, Platform > mPlatforms
 
bool formatstr_scan(const Token *ftok) const
 
static std::string toString(T value)=delete
 
static bool isEqual(const std::string &first, const std::string &second)
 
static bool isNotEqual(const std::string &first, const std::string &second)
 
static bigint toBigNumber(const std::string &str)
for conversion of numeric literals - for atoi-like conversions please use strToInt()
 
static bool isFloat(const std::string &str)
 
static double toDoubleNumber(const std::string &str)
for conversion of numeric literals
 
static std::string getFilenameExtension(const std::string &path, bool lowercase=false)
Get an extension of the filename.
 
static std::string fromNativeSeparators(std::string path)
Convert path to use internal path separators.
 
static std::string getCurrentExecutablePath(const char *fallback)
Returns the absolute path to the current executable.
 
static std::string getPathFromFilename(const std::string &filename)
Lookup the path part from a filename (e.g., '/tmp/a.h' -> '/tmp/', 'a.h' -> '')
 
static std::string getAbsoluteFilePath(const std::string &filePath)
Get an absolute file path from a relative one.
 
static std::string getFilenameExtensionInLowerCase(const std::string &path)
Get an extension of the filename in lower case.
 
This is just a container for general settings so that we don't need to pass individual values to func...
 
const Token * front() const
get first token of list
 
bool createTokens(std::istream &code, const std::string &file0)
Create tokens from code.
 
The token list that the TokenList generates is a linked-list of this class.
 
static bool Match(const Token *tok, const char pattern[], nonneg int varid=0)
Match given token (or list of tokens) to a pattern list.
 
const std::string & originalName() const
 
static void createMutualLinks(Token *begin, Token *end)
Links two elements against each other.
 
const ValueType * valueType() const
 
const std::string & strAt(int index) const
 
void astOperand1(Token *tok)
 
void function(const Function *f)
Associate this token with given function.
 
bool isUnaryOp(const std::string &s) const
 
const Token * tokAt(int index) const
 
void astOperand2(Token *tok)
 
void scope(const Scope *s)
Associate this token with given scope.
 
void link(Token *linkToToken)
Create link to given token.
 
const Token * linkAt(int index) const
 
bool isStandardType() const
 
static bool simpleMatch(const Token *tok, const char(&pattern)[count])
Match given token (or list of tokens) to a pattern list.
 
void astParent(Token *tok)
 
const Library::Container * container
If the type is a container defined in a cfg file, this is the used.
 
static const std::string emptyString
 
std::shared_ptr< Token > createTokenFromExpression(const std::string &returnValue, const Settings &settings, bool cpp, std::unordered_map< nonneg int, const Token * > *lookupVarId)
 
Severity severityFromString(const std::string &severity)
 
const Library::Container * getLibraryContainer(const Token *tok)
 
@ error
Programming error.
 
static void gettokenlistfromvalid(const std::string &valid, bool cpp, TokenList &tokenList)
 
static std::vector< std::string > getnames(const char *names)
 
const Value * valueFlowConstantFoldAST(Token *expr, const Settings &settings)
Constant folding of expression. This can be used before the full ValueFlow has been executed (ValueFl...
 
std::vector< MinSize > minsizes
 
IteratorInfo iteratorInfo
 
@ DIR_UNKNOWN
direction not known / specified
 
@ DIR_IN
Input to called function. Data is treated as read-only.
 
@ DIR_OUT
Output to caller. Data is passed by reference or address and is potentially written.
 
@ DIR_INOUT
Input to called function, and output to caller. Data is passed by reference or address and is potenti...
 
std::map< int, ArgumentChecks > argumentChecks
 
Container::Action containerAction
 
Container::Yield containerYield
 
enum Library::PodType::Type stdtype
 
bool setC(const std::string &str)
 
bool setCPP(std::string str)
 
enum Standards::cppstd_t cpp
 
bool startsWith(const std::string &str, const char start[], std::size_t startlen)
 
bool endsWith(const std::string &str, char c)