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)