58 static constexpr 
int NEW = -1;
 
   60 static const std::array<std::pair<std::string, std::string>, 4> 
alloc_failed_conds {{{
"==", 
"0"}, {
"<", 
"0"}, {
"==", 
"-1"}, {
"<=", 
"-1"}}};
 
   61 static const std::array<std::pair<std::string, std::string>, 4> 
alloc_success_conds {{{
"!=", 
"0"}, {
">", 
"0"}, {
"!=", 
"-1"}, {
">=", 
"0"}}};
 
   69     if (std::any_of(varlist.begin(), varlist.end(), [](
const Variable& v) {
 
   70         return !v.valueType() || (!v.valueType()->isPrimitive() && !v.valueType()->container);
 
   74         return isAutoDeallocType(bi.type);
 
   96 template<std::
size_t N>
 
   98                                const std::array<std::pair<std::string, std::string>, N>& ops)
 
  100     return std::any_of(ops.cbegin(), ops.cend(), [&](
const std::pair<std::string, std::string>& op) {
 
  101         return astIsVariableComparison(tok, op.first, op.second, vartok);
 
  109     std::cout << 
"size=" << alloctype.size() << std::endl;
 
  110     for (std::map<int, AllocInfo>::const_iterator it = alloctype.cbegin(); it != alloctype.cend(); ++it) {
 
  111         std::string strusage;
 
  112         const auto use = possibleUsage.find(it->first);
 
  113         if (use != possibleUsage.end())
 
  114             strusage = use->second.first->str();
 
  117         switch (it->second.status) {
 
  138         std::cout << 
"status=" << status << 
" " 
  139                   << 
"alloctype='" << it->second.type << 
"' " 
  140                   << 
"possibleUsage='" << strusage << 
"' " 
  141                   << 
"conditionalAlloc=" << (conditionalAlloc.find(it->first) != conditionalAlloc.end() ? 
"yes" : 
"no") << 
" " 
  142                   << 
"referenced=" << (referenced.find(it->first) != referenced.end() ? 
"yes" : 
"no") << 
" " 
  143                   << 
"reallocedFrom=" << it->second.reallocedFromType
 
  150     possibleUsage.clear();
 
  151     for (std::map<int, AllocInfo>::const_iterator it = alloctype.cbegin(); it != alloctype.cend(); ++it)
 
  152         possibleUsage[it->first] = functionUsage;
 
  168     const std::list<const Token *> callstack = { allocTok, deallocTok };
 
  180     const std::list<const Token *> locations = { deallocTok, tok };
 
  187         (!functionUsage.first || !functionUsage.first->function() || !functionUsage.first->function()->hasBody())) {
 
  190             funcStr = 
"unknown::" + functionUsage.first->str();
 
  193                     "checkLibraryUseIgnore",
 
  194                     "--check-library: Function " + funcStr + 
"() should have <use>/<leak-ignore> configuration");
 
  200     const std::list<const Token *> locations = { prevFreeTok, tok };
 
  219     const std::set<int> notzero;
 
  237     if (tok->
varId() == varid)
 
  246     for (
const Token *tok = startToken; tok && tok != endToken; tok = tok->
next()) {
 
  247         if (tok->varId() != varid)
 
  271     if (varTok->
isCpp()) {
 
  292         nameToken = nameToken->
next();
 
  294         if (nameToken && nameToken->
link() && nameToken->
str() == 
"<") {
 
  296             nameToken = nameToken->
link()->next();
 
  299         if (nameToken && nameToken->
link() && !nameToken->
isCast() && nameToken->
str() == 
"(") {
 
  309                                   std::set<int> notzero,
 
  310                                   nonneg int recursiveCount)
 
  313     static const nonneg int recursiveLimit = 300;
 
  314 #elif defined(__MINGW32__) 
  316     static constexpr 
nonneg int recursiveLimit = 600;
 
  318     static constexpr 
nonneg int recursiveLimit = 1000;
 
  320     if (++recursiveCount > recursiveLimit)    
 
  323     std::map<int, VarInfo::AllocInfo> &alloctype = varInfo.alloctype;
 
  324     auto& possibleUsage = varInfo.possibleUsage;
 
  325     const std::set<int> conditionalAlloc(varInfo.conditionalAlloc);
 
  328     const Token * 
const endToken = startToken->
link();
 
  329     for (
const Token *tok = startToken; tok && tok != endToken; tok = tok->
next()) {
 
  330         if (!tok->scope()->isExecutable()) {
 
  331             tok = tok->scope()->bodyEnd;
 
  338             const bool isInit = 
Token::Match(tok, 
"%var% {|(") && tok->variable() && tok == tok->variable()->nameToken() && tok->variable()->isPointer();
 
  348         const bool isInit = 
Token::Match(tok->tokAt(-1), 
"%var% {|(") && tok->tokAt(-1)->variable() && tok->tokAt(-1) == tok->tokAt(-1)->variable()->nameToken();
 
  357         if (!tok || tok == endToken)
 
  361             tok = tok->linkAt(1);
 
  368         while (!isInit && tok->str() == 
"(")
 
  370         while (tok->isUnaryOp(
"*") && tok->astOperand1()->isUnaryOp(
"&"))
 
  371             tok = tok->astOperand1()->astOperand1();
 
  374         const Token* varTok = isInit ? tok->
tokAt(-1) : tok;
 
  376             varTok = varTok->
tokAt(2);
 
  378         const Token *ftok = tok;
 
  379         if (ftok->
str() == 
"::")
 
  382             ftok = ftok->
tokAt(2);
 
  384         auto isAssignment = [](
const Token* varTok) -> 
const Token* {
 
  385             if (varTok->
varId()) {
 
  386                 const Token* top = varTok;
 
  399         if (
const Token* 
const tokAssignOp = isInit ? varTok : isAssignment(varTok)) {
 
  404             if (
Token::Match(tokAssignOp, 
"= %var% +|;|?|%comp%")) {
 
  410                     for (
const Token *tok2 = varTok; tok2; tok2 = tok2->
next()) {
 
  411                         if (tok2->str() == 
";") {
 
  415                             varInfo.erase(tok2->varId());
 
  423             while (tokRightAstOperand && tokRightAstOperand->
isCast())
 
  431             if (conditionalAlloc.find(varTok->
varId()) == conditionalAlloc.end())
 
  433             varInfo.erase(varTok->
varId());
 
  439             const Token *
const fTok = tokRightAstOperand ? tokRightAstOperand->
previous() : 
nullptr;
 
  442                 if (f && f->
arg == -1) {
 
  445                     varAlloc.
status = VarInfo::ALLOC;
 
  455                 varAlloc.
status = VarInfo::ALLOC;
 
  462                 notzero.insert(varTok->
varId());
 
  464                 notzero.insert(varTok->
varId());
 
  466                 notzero.erase(varTok->
varId());
 
  474             for (
const Token *innerTok = tok->
tokAt(2); innerTok && innerTok != closingParenthesis; innerTok = innerTok->
next()) {
 
  476                     innerTok = innerTok->
linkAt(1);
 
  488                 if (
Token::Match(innerTok, 
"%var% =") && innerTok->astParent() == innerTok->next() &&
 
  489                     !(innerTok->next()->astParent() && innerTok->next()->astParent()->isAssignmentOp())) {
 
  493                     while (tokRightAstOperand && tokRightAstOperand->
isCast())
 
  498                         if (f && f->
arg == -1) {
 
  501                             varAlloc.
status = VarInfo::ALLOC;
 
  505                             alloctype.erase(innerTok->varId());
 
  508                     } 
else if (innerTok->isCpp() && 
Token::Match(innerTok->tokAt(2), 
"new !!(")) {
 
  510                         const bool arrayNew = (tok2 && (tok2->
str() == 
"[" || (tok2->
str() == 
"(" && tok2->
astOperand1() && tok2->
astOperand1()->str() == 
"[")));
 
  513                         varAlloc.
status = VarInfo::ALLOC;
 
  523                     functionCall(innerTok, openingPar, varInfo, allocation, allocFunc);
 
  524                     innerTok = openingPar->
link();
 
  529                 VarInfo varInfo1(varInfo);  
 
  530                 VarInfo varInfo2(varInfo);  
 
  535                     astOperand2AfterCommas = astOperand2AfterCommas->
astOperand2();
 
  541                     if (tok3->
str() == 
"&&" || tok3->
str() == 
"||") {
 
  543                         return ChildrenToVisit::op1_and_op2;
 
  546                         return ChildrenToVisit::op2;
 
  549                         const std::vector<const Token *> params = getArguments(tok3->previous());
 
  550                         for (const Token *par : params) {
 
  551                             if (!par->isComparisonOp())
 
  553                             const Token *vartok = nullptr;
 
  554                             if (isVarTokComparison(par, &vartok, alloc_success_conds) ||
 
  555                                 (isVarTokComparison(par, &vartok, alloc_failed_conds))) {
 
  556                                 varInfo1.erase(vartok->varId());
 
  557                                 varInfo2.erase(vartok->varId());
 
  563                     const Token *vartok = 
nullptr;
 
  565                         varInfo2.reallocToAlloc(vartok->
varId());
 
  566                         varInfo2.erase(vartok->
varId());
 
  568                             (notzero.find(vartok->
varId()) != notzero.end()))
 
  571                         varInfo1.reallocToAlloc(vartok->
varId());
 
  572                         varInfo1.erase(vartok->
varId());
 
  577                 if (!
checkScope(closingParenthesis->
next(), varInfo1, notzero, recursiveCount)) {
 
  581                 closingParenthesis = closingParenthesis->
linkAt(1);
 
  583                     if (!
checkScope(closingParenthesis->
tokAt(2), varInfo2, notzero, recursiveCount)) {
 
  589                     tok = closingParenthesis->
previous();
 
  595                 std::map<int, VarInfo::AllocInfo>::const_iterator it;
 
  597                 for (it = old.alloctype.cbegin(); it != old.alloctype.cend(); ++it) {
 
  598                     const int varId = it->first;
 
  599                     if (old.conditionalAlloc.find(varId) == old.conditionalAlloc.end())
 
  601                     if (varInfo1.alloctype.find(varId) == varInfo1.alloctype.end() ||
 
  602                         varInfo2.alloctype.find(varId) == varInfo2.alloctype.end()) {
 
  603                         varInfo1.erase(varId);
 
  604                         varInfo2.erase(varId);
 
  609                 for (it = varInfo1.alloctype.cbegin(); it != varInfo1.alloctype.cend(); ++it) {
 
  610                     if (varInfo2.alloctype.find(it->first) == varInfo2.alloctype.end() &&
 
  611                         old.alloctype.find(it->first) == old.alloctype.end()) {
 
  612                         varInfo.conditionalAlloc.insert(it->first);
 
  617                 for (it = varInfo2.alloctype.cbegin(); it != varInfo2.alloctype.cend(); ++it) {
 
  618                     if (varInfo1.alloctype.find(it->first) == varInfo1.alloctype.end() &&
 
  619                         old.alloctype.find(it->first) == old.alloctype.end()) {
 
  620                         varInfo.conditionalAlloc.insert(it->first);
 
  625                 for (it = varInfo1.alloctype.cbegin(); it != varInfo1.alloctype.cend(); ++it) {
 
  626                     if (it->second.managed() && conditionalAlloc.find(it->first) != conditionalAlloc.end()) {
 
  627                         varInfo.conditionalAlloc.erase(it->first);
 
  628                         varInfo2.erase(it->first);
 
  631                 for (it = varInfo2.alloctype.cbegin(); it != varInfo2.alloctype.cend(); ++it) {
 
  632                     if (it->second.managed() && conditionalAlloc.find(it->first) != conditionalAlloc.end()) {
 
  633                         varInfo.conditionalAlloc.erase(it->first);
 
  634                         varInfo1.erase(it->first);
 
  638                 alloctype.insert(varInfo1.alloctype.cbegin(), varInfo1.alloctype.cend());
 
  639                 alloctype.insert(varInfo2.alloctype.cbegin(), varInfo2.alloctype.cend());
 
  641                 possibleUsage.insert(varInfo1.possibleUsage.cbegin(), varInfo1.possibleUsage.cend());
 
  642                 possibleUsage.insert(varInfo2.possibleUsage.cbegin(), varInfo2.possibleUsage.cend());
 
  653         else if (tok->str() == 
"return") {
 
  659         else if (tok->isCpp() && tok->str() == 
"throw") {
 
  660             bool tryFound = 
false;
 
  661             const Scope* scope = tok->scope();
 
  674         else if (tok->isCpp() && tok->str() == 
"delete") {
 
  675             const Token * delTok = tok;
 
  683             if (tok->str() == 
"(")
 
  687             const bool isnull = tok->hasKnownIntValue() && tok->values().front().intvalue == 0;
 
  688             if (!isnull && tok->varId() && tok->strAt(1) != 
"[") {
 
  698             if (allocation.
type == 0)
 
  699                 allocation.
status = VarInfo::NOALLOC;
 
  702             functionCall(ftok, openingPar, varInfo, allocation, af);
 
  704             tok = ftok->next()->link();
 
  708                 if (ftok->isKeyword())
 
  710                 bool unknown = 
false;
 
  715                         if (ftok->function() && !ftok->function()->isAttributeNoreturn() &&
 
  721                             varInfo.possibleUsageAll({ ftok, usage });
 
  731         else if (tok->str() == 
"goto") {
 
  744             if (!
Token::Match(typeEndTok, 
"> %var% {|( %var% ,|)|}"))
 
  747             tok = typeEndTok->
linkAt(2);
 
  749             const int varid = typeEndTok->
next()->
varId();
 
  753             bool arrayDelete = 
false;
 
  758             const Token * deleterToken = 
nullptr;
 
  759             const Token * endDeleterToken = 
nullptr;
 
  762                 deleterToken = ftok->
tokAt(4);
 
  763                 endDeleterToken = typeEndTok;
 
  764             } 
else if (
Token::Match(typeEndTok, 
"> %var% {|( %var% ,")) {
 
  765                 deleterToken = typeEndTok->
tokAt(5);
 
  766                 endDeleterToken = typeEndTok->
linkAt(2);
 
  770                 if (deleterToken->
str() == 
"+") {
 
  771                     deleterToken = deleterToken->
next();
 
  780                     const Token * tscopeStart = 
nullptr;
 
  781                     const Token * tscopeEnd = 
nullptr;
 
  783                     if (deleterToken->
str() == 
"[" &&
 
  787                         tscopeStart = deleterToken->
link()->linkAt(1)->tokAt(1);
 
  788                         tscopeEnd = tscopeStart->
link();
 
  790                     } 
else if (dtok && dtok->
function()) {
 
  797                     } 
else if ((dtok = 
Token::findmatch(deleterToken, 
"%type%", endDeleterToken)) && dtok->
type()) {
 
  798                         const Scope * tscope = dtok->
type()->classScope;
 
  805                     if (tscopeStart && tscopeEnd) {
 
  806                         for (
const Token *tok2 = tscopeStart; tok2 != tscopeEnd; tok2 = tok2->
next()) {
 
  824     ret(endToken, varInfo, 
true);
 
  832     if (tok->
varId() > 0) {
 
  834         const std::map<int, VarInfo::AllocInfo>::const_iterator var = varInfo.alloctype.find(tok->
varId());
 
  835         if (var != varInfo.alloctype.end()) {
 
  836             bool unknown = 
false;
 
  840                 varInfo.erase(tok->
varId());
 
  843                 const Token *rhs = tok;
 
  844                 bool isAssignment = 
false;
 
  855                 if (rhs->
varId() == tok->
varId() && isAssignment) {
 
  857                     varInfo.erase(tok->
varId());
 
  865                             const std::string arg = 
"arg" + std::to_string(argn + 1);
 
  866                             if (returnValue == arg) {
 
  867                                 varInfo.erase(tok->
varId());
 
  874             varInfo.referenced.insert(tok->
tokAt(2)->
varId());
 
  884             alloc.
status = VarInfo::NOALLOC;
 
  902         if (alloctype.find(argTok->
varId()) != alloctype.end()) {
 
  906             argAlloc.
status = VarInfo::REALLOC;
 
  911         retAlloc.
status = VarInfo::ALLOC;
 
  920     std::map<int, VarInfo::AllocInfo> &alloctype = varInfo.alloctype;
 
  921     const std::map<int, VarInfo::AllocInfo>::iterator var = alloctype.find(arg->
varId());
 
  922     if (var != alloctype.end()) {
 
  923         if (allocation.
status == VarInfo::NOALLOC) {
 
  925             varInfo.possibleUsage[arg->
varId()] = { tok, VarInfo::USED };
 
  926             if (var->second.status == VarInfo::DEALLOC && arg->
previous()->
str() == 
"&")
 
  927                 varInfo.erase(arg->
varId());
 
  928         } 
else if (var->second.managed()) {
 
  930             var->second.status = allocation.
status;
 
  931         } 
else if (var->second.type != allocation.
type && var->second.type != 0) {
 
  934             varInfo.erase(arg->
varId());
 
  937             var->second.status = allocation.
status;
 
  938             var->second.type = allocation.
type;
 
  939             var->second.allocTok = allocation.
allocTok;
 
  942         alloctype[arg->
varId()].status = VarInfo::DEALLOC;
 
  943         alloctype[arg->
varId()].allocTok = tok;
 
  956     const Token * 
const tokFirstArg = tokOpeningPar->
next();
 
  957     if (!tokFirstArg || tokFirstArg->
str() == 
")") {
 
  963     for (
const Token *funcArg = tokFirstArg; funcArg; funcArg = funcArg->
nextArgument()) {
 
  964         const Token* arg = funcArg;
 
  967             if (arg->
str() == 
"new")
 
  971             if (tokAdvance > 0) {
 
  972                 arg = arg->
tokAt(tokAdvance);
 
  981         while (arg && arg->
isCast())
 
  983         const Token * 
const argTypeStartTok = arg;
 
  991             const bool isAddressOf = arg->
str() == 
"&";
 
  998             if (!isnull && (!af || af->
arg == argNr)) {
 
 1005                     if (allocFunc->arg == argNr &&
 
 1010                         varAlloc.
type = allocFunc->groupId;
 
 1011                         varAlloc.
status = VarInfo::ALLOC;
 
 1015                 else if (isLeakIgnore)
 
 1024             const Token * allocTok = 
nullptr;
 
 1028             bool arrayDelete = 
false;
 
 1033             const Token * deleterToken = 
nullptr;
 
 1034             const Token * endDeleterToken = 
nullptr;
 
 1037                 deleterToken = arg->
tokAt(4);
 
 1038                 endDeleterToken = typeEndTok;
 
 1039             } 
else if (
Token::Match(typeEndTok, 
"> {|( %var% ,")) {
 
 1040                 deleterToken = typeEndTok->
tokAt(4);
 
 1041                 endDeleterToken = typeEndTok->
linkAt(1);
 
 1051                     if (dtok && dtok->
type()) {
 
 1052                         const Scope * tscope = dtok->
type()->classScope;
 
 1069             while (arg && ((nextArg && arg != nextArg) || (!nextArg && arg != tokOpeningPar->
link()))) {
 
 1084                                        const VarInfo &varInfo)
 
 1086     const std::map<int, VarInfo::AllocInfo> &alloctype = varInfo.alloctype;
 
 1087     const auto& possibleUsage = varInfo.possibleUsage;
 
 1089     const std::map<int, VarInfo::AllocInfo>::const_iterator var = alloctype.find(vartok->
varId());
 
 1090     if (var != alloctype.cend() && var->second.status == VarInfo::ALLOC) {
 
 1091         const auto use = possibleUsage.find(vartok->
varId());
 
 1092         if (use == possibleUsage.end()) {
 
 1109         if (allocFunc->arg == argn + 1)
 
 1117     const std::map<int, VarInfo::AllocInfo> &alloctype = varInfo.alloctype;
 
 1118     const auto& possibleUsage = varInfo.possibleUsage;
 
 1119     std::vector<int> toRemove;
 
 1122     for (std::map<int, VarInfo::AllocInfo>::const_iterator it = alloctype.cbegin(); it != alloctype.cend(); ++it) {
 
 1124         if (!isEndOfScope && !it->second.managed() && varInfo.conditionalAlloc.find(it->first) != varInfo.conditionalAlloc.end())
 
 1128         if (varInfo.referenced.find(it->first) != varInfo.referenced.end())
 
 1131         const int varid = it->first;
 
 1137             enum class PtrUsage { NONE, DEREF, PTR } used = PtrUsage::NONE;
 
 1138             for (
const Token *tok2 = tok; tok2; tok2 = tok2->
next()) {
 
 1139                 if (tok2->str() == 
";")
 
 1150                 if (tok3 && tok3->
varId() == varid)
 
 1151                     tok2 = tok3->
next();
 
 1152                 else if (
Token::Match(tok3, 
"& %varid% . %name%", varid))
 
 1153                     tok2 = tok3->
tokAt(4);
 
 1159                     used = PtrUsage::PTR;
 
 1163                     used = PtrUsage::DEREF;
 
 1169             const Token* outparamFunc{};
 
 1170             if ((tok->
scope()->type == Scope::ScopeType::eIf || tok->
scope()->type== Scope::ScopeType::eElse) &&
 
 1173                 if (scope->
type == Scope::ScopeType::eElse) {
 
 1177                 const Token* 
const ifStart = ifEnd->
link();
 
 1178                 const Token* 
const alloc = it->second.allocTok;
 
 1180                     if (
Token::Match(outparamFunc->next()->astParent(), 
"%comp%"))
 
 1185                         bool isRetComp = 
false;
 
 1186                         for (
const Token* tok2 = ifStart; tok2 != ifEnd; tok2 = tok2->
next()) {
 
 1187                             if (tok2->varId() == retAssign->
astOperand1()->varId()) {
 
 1199             if (used != PtrUsage::NONE && it->second.status == VarInfo::DEALLOC)
 
 1202             else if (used != PtrUsage::PTR && !it->second.managed() && !var->
isReference()) {
 
 1203                 const auto use = possibleUsage.find(varid);
 
 1204                 if (use == possibleUsage.end()) {
 
 1206                 } 
else if (!use->second.first->variable()) { 
 
 1210             toRemove.push_back(varid);
 
 1213     for (
const int varId : toRemove)
 
 1214         varInfo.erase(varId);
 
const Token * astIsVariableComparison(const Token *tok, const std::string &comp, const std::string &rhs, const Token **vartok)
Is given syntax tree a variable comparison against value.
 
std::vector< const Token * > getArguments(const Token *ftok)
Get arguments (AST)
 
bool precedes(const Token *tok1, const Token *tok2)
If tok2 comes after tok1.
 
const Token * getTokenArgumentFunction(const Token *tok, int &argn)
Return the token to the function and the argument number.
 
bool astIsBool(const Token *tok)
Is expression of boolean type?
 
bool isCPPCast(const Token *tok)
 
bool isUnevaluated(const Token *tok)
 
bool succeeds(const Token *tok1, const Token *tok2)
If tok1 comes after tok2.
 
int numberOfArguments(const Token *ftok)
Determines the number of arguments - if token is a function call or macro.
 
void visitAstNodes(T *ast, const TFunc &visitor)
Visit AST nodes recursively.
 
static bool isVarUsedInTree(const Token *tok, nonneg int varid)
 
static bool isAutoDeallocType(const Type *type)
 
static bool isVarTokComparison(const Token *tok, const Token **vartok, const std::array< std::pair< std::string, std::string >, N > &ops)
 
static bool isAutoDealloc(const Variable *var)
Is variable type some class with automatic deallocation?
 
static const Token * isFunctionCall(const Token *nameToken)
checks if nameToken is a name of a function in a function call: func(arg) or func<temp1_arg>(arg)
 
static const CWE CWE415(415U)
 
static const std::array< std::pair< std::string, std::string >, 4 > alloc_failed_conds
 
static const std::array< std::pair< std::string, std::string >, 4 > alloc_success_conds
 
static bool isPointerReleased(const Token *startToken, const Token *endToken, nonneg int varid)
 
static bool isLocalVarNoAutoDealloc(const Token *varTok)
 
static const Token * getOutparamAllocation(const Token *tok, const Settings &settings)
 
static constexpr int NEW_ARRAY
 
static const CWE CWE672(672U)
 
void ret(const Token *tok, VarInfo &varInfo, const bool isEndOfScope=false)
return.
 
void functionCall(const Token *tokName, const Token *tokOpeningPar, VarInfo &varInfo, const VarInfo::AllocInfo &allocation, const Library::AllocFunc *af)
parse function call
 
bool checkScope(const Token *const startToken, VarInfo &varInfo, std::set< int > notzero, nonneg int recursiveCount)
check for leaks in a function scope
 
void configurationInfo(const Token *tok, const std::pair< const Token *, VarInfo::Usage > &functionUsage)
message: user configuration is needed to complete analysis
 
void leakError(const Token *tok, const std::string &varname, int type) const
 
void deallocUseError(const Token *tok, const std::string &varname) const
 
const Token * checkTokenInsideExpression(const Token *const tok, VarInfo &varInfo, bool inFuncCall=false)
Check token inside expression.
 
void leakIfAllocated(const Token *vartok, const VarInfo &varInfo)
if variable is allocated then there is a leak
 
void changeAllocStatus(VarInfo &varInfo, const VarInfo::AllocInfo &allocation, const Token *tok, const Token *arg)
parse changes in allocation status
 
void check()
check for leaks in all scopes
 
void changeAllocStatusIfRealloc(std::map< int, VarInfo::AllocInfo > &alloctype, const Token *fTok, const Token *retTok) const
update allocation status if reallocation function
 
void mismatchError(const Token *deallocTok, const Token *allocTok, const std::string &varname) const
 
void doubleFreeError(const Token *tok, const Token *prevFreeTok, const std::string &varname, int type)
 
void deallocReturnError(const Token *tok, const Token *deallocTok, const std::string &varname)
 
Base class for memory leaks checking.
 
void deallocuseError(const Token *tok, const std::string &varname) const
 
void resourceLeakError(const Token *tok, const std::string &varname) const
Report that there is a resource leak (fopen/popen/etc)
 
void mismatchAllocDealloc(const std::list< const Token * > &callstack, const std::string &varname) const
 
void memleakError(const Token *tok, const std::string &varname) const
Report that there is a memory leak (new/malloc/etc)
 
bool isPointerDeRef(const Token *tok, bool &unknown) const
Is there a pointer dereference? Everything that should result in a nullpointer dereference error mess...
 
void reportError(const Token *tok, const Severity severity, const std::string &id, const std::string &msg)
report an error
 
const Settings *const mSettings
 
ErrorLogger *const mErrorLogger
 
const Tokenizer *const mTokenizer
 
void logChecker(const char id[])
log checker
 
static bool isresource(const int id)
is allocation type resource?
 
bool isSmartPointer(const Token *tok) const
 
const std::string & returnValue(const Token *ftok) const
 
bool isLeakIgnore(const std::string &functionName) const
 
const AllocFunc * getAllocFuncInfo(const Token *tok) const
get allocation info for function
 
const AllocFunc * getReallocFuncInfo(const Token *tok) const
get reallocation info for function
 
std::string getFunctionName(const Token *ftok) const
Get function name for function call.
 
const AllocFunc * getDeallocFuncInfo(const Token *tok) const
get deallocation info for function
 
bool isUse(const std::string &functionName) const
 
static bigint toBigNumber(const std::string &str)
for conversion of numeric literals - for atoi-like conversions please use strToInt()
 
bool hasInlineOrLambdaFunction() const
 
std::list< Variable > varlist
 
const Token * bodyStart
'{' token
 
const Token * bodyEnd
'}' token
 
nonneg int numConstructors
 
bool isExecutable() const
 
This is just a container for general settings so that we don't need to pass individual values to func...
 
bool checkLibrary
Check for incomplete info in library files?
 
const Variable * getVariableFromVarId(nonneg int varId) const
 
std::vector< const Scope * > functionScopes
Fast access to function scopes.
 
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.
 
static const Token * findmatch(const Token *const startTok, const char pattern[], const nonneg int varId=0)
 
bool hasKnownIntValue() const
 
bool isUpperCaseName() const
 
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.
 
static const Token * findsimplematch(const Token *const startTok, const char(&pattern)[count])
 
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
 
void type(const ::Type *t)
Associate this token with given type.
 
bool isStandardType() const
 
void variable(const Variable *v)
Associate this token with given variable.
 
const std::list< ValueFlow::Value > & values() const
 
const Token * nextArgument() 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)
 
bool isScopeNoReturn(const Token *endScopeToken, bool *unknown=nullptr) const
Check if inner scope ends with a call to a noreturn function.
 
const SymbolDatabase * getSymbolDatabase() const
 
Information about a class type.
 
std::vector< BaseInfo > derivedFrom
 
enum ValueType::Type type
 
const Library::Container * container
If the type is a container defined in a cfg file, this is the used.
 
MathLib::bigint typeSize(const Platform &platform, bool p=false) const
 
nonneg int pointer
0=>not pointer, 1=>*, 2=>**, 3=>***, etc
 
void possibleUsageAll(const std::pair< const Token *, Usage > &functionUsage)
set possible usage for all variables
 
Information about a member variable.
 
bool isArgument() const
Is variable a function argument.
 
bool isReference() const
Is reference variable.
 
bool isLocal() const
Is variable local.
 
const Type * type() const
Get Type pointer of known type.
 
const Scope * scope() const
Get Scope pointer of enclosing scope.
 
const std::string & name() const
Get name string.
 
const Token * typeStartToken() const
Get type start token.
 
bool isPointer() const
Is pointer variable.
 
bool isStatic() const
Is variable static.
 
const ValueType * valueType() const
 
@ information
Checking information.
 
@ error
Programming error.
 
Simple container to be thrown when internal error is detected.
 
const Token * isLambdaCaptureList(const Token *tok)
 
bool startsWith(const std::string &str, const char start[], std::size_t startlen)