| 858 | } |
| 859 | |
| 860 | Library::Error Library::loadFunction(const tinyxml2::XMLElement * const node, const std::string &name, std::set<std::string> &unknown_elements) |
| 861 | { |
| 862 | if (name.empty()) |
| 863 | return Error(ErrorCode::OK); |
| 864 | |
| 865 | // TODO: write debug warning if we modify an existing entry |
| 866 | Function& func = mData->mFunctions[name]; |
| 867 | |
| 868 | for (const tinyxml2::XMLElement *functionnode = node->FirstChildElement(); functionnode; functionnode = functionnode->NextSiblingElement()) { |
| 869 | const std::string functionnodename = functionnode->Name(); |
| 870 | if (functionnodename == "noreturn") { |
| 871 | const char * const text = functionnode->GetText(); |
| 872 | if (strcmp(text, "false") == 0) |
| 873 | mData->mNoReturn[name] = LibraryData::FalseTrueMaybe::False; |
| 874 | else if (strcmp(text, "maybe") == 0) |
| 875 | mData->mNoReturn[name] = LibraryData::FalseTrueMaybe::Maybe; |
| 876 | else |
| 877 | mData->mNoReturn[name] = LibraryData::FalseTrueMaybe::True; // Safe |
| 878 | } else if (functionnodename == "pure") |
| 879 | func.ispure = true; |
| 880 | else if (functionnodename == "const") { |
| 881 | func.ispure = true; |
| 882 | func.isconst = true; // a constant function is pure |
| 883 | } else if (functionnodename == "leak-ignore") |
| 884 | func.leakignore = true; |
| 885 | else if (functionnodename == "not-overlapping-data") { |
| 886 | NonOverlappingData nonOverlappingData; |
| 887 | nonOverlappingData.ptr1Arg = functionnode->IntAttribute("ptr1-arg", -1); |
| 888 | nonOverlappingData.ptr2Arg = functionnode->IntAttribute("ptr2-arg", -1); |
| 889 | nonOverlappingData.sizeArg = functionnode->IntAttribute("size-arg", -1); |
| 890 | nonOverlappingData.strlenArg = functionnode->IntAttribute("strlen-arg", -1); |
| 891 | nonOverlappingData.countArg = functionnode->IntAttribute("count-arg", -1); |
| 892 | mData->mNonOverlappingData[name] = nonOverlappingData; |
| 893 | } else if (functionnodename == "use-retval") { |
| 894 | func.useretval = Library::UseRetValType::DEFAULT; |
| 895 | if (const char *type = functionnode->Attribute("type")) |
| 896 | if (std::strcmp(type, "error-code") == 0) |
| 897 | func.useretval = Library::UseRetValType::ERROR_CODE; |
| 898 | } else if (functionnodename == "returnValue") { |
| 899 | if (const char *expr = functionnode->GetText()) |
| 900 | mData->mReturnValue[name] = expr; |
| 901 | if (const char *type = functionnode->Attribute("type")) |
| 902 | mData->mReturnValueType[name] = type; |
| 903 | if (const char *container = functionnode->Attribute("container")) |
| 904 | mData->mReturnValueContainer[name] = strToInt<int>(container); |
| 905 | // cppcheck-suppress shadowFunction - TODO: fix this |
| 906 | if (const char *unknownReturnValues = functionnode->Attribute("unknownValues")) { |
| 907 | if (std::strcmp(unknownReturnValues, "all") == 0) { |
| 908 | std::vector<MathLib::bigint> values{LLONG_MIN, LLONG_MAX}; |
| 909 | mData->mUnknownReturnValues[name] = std::move(values); |
| 910 | } |
| 911 | } |
| 912 | } else if (functionnodename == "arg") { |
| 913 | const char* argNrString = functionnode->Attribute("nr"); |
| 914 | if (!argNrString) |
| 915 | return Error(ErrorCode::MISSING_ATTRIBUTE, "nr"); |
| 916 | const bool bAnyArg = strcmp(argNrString, "any") == 0; |
| 917 | const bool bVariadicArg = strcmp(argNrString, "variadic") == 0; |
nothing calls this directly
no test coverage detected