36 #include <unordered_set> 
  116     if (tok->
str() == 
"+")
 
  120     if (tok->
str() == 
"-")
 
  136         for (std::list<ValueFlow::Value>::const_iterator it = tok->
values().cbegin(); it != tok->
values().cend(); ++it) {
 
  152     if (tok->
str() == 
"+")
 
  183             if (op->
str() == 
"[")
 
  197     for (
const Token *tok = start; tok && tok != scope->
bodyEnd; tok = tok->
next()) {
 
  198         if (tok->varId() == varId)
 
  216     logChecker(
"CheckAutoVariables::assignFunctionArg"); 
 
  222             if (tok->astParent())
 
  231                 if (vartok->
variable()->isPointer() && printWarning)
 
  252         if (vt->container && vt->container->stdStringLike)
 
  255             return std::any_of(vt->typeScope->functionList.begin(), vt->typeScope->functionList.end(), [](
const Function& f) { 
 
  256                 return f.name() == 
"operator=";
 
  266     logChecker(
"CheckAutoVariables::autoVariables");
 
  274                 tok = lambdaEndToken;
 
  299                      (tok->isCpp() && 
Token::Match(tok, 
"delete [| ]| (| %var%|%str% !!["))) {
 
  305                 else if (tok->variable() && tok->variable()->isPointer()) {
 
  307                         if (v.isImpossible())
 
  317                        (tok->isCpp() && 
Token::Match(tok, 
"delete [| ]| (| & %var% !!["))) {
 
  330     for (
const Token *tok = startToken; tok; tok = tok->
next()) {
 
  331         if (tok->str() == 
"}" && tok->scope()->type == Scope::ScopeType::eFunction)
 
  339             const Token *lhs = tok;
 
  346             const Token *e = expr;
 
  347             while (e->
str() != 
"=" && lhs->
str() == e->
str()) {
 
  351             if (lhs->
str() == 
"=")
 
  360             tok = tok->linkAt(2);
 
  371                     "Address of local auto-variable assigned to a function parameter.\n" 
  372                     "Dangerous assignment - the function parameter is assigned the address of a local " 
  373                     "auto-variable. Local auto-variables are reserved from the stack which " 
  374                     "is freed when the function ends. So the pointer to a local variable " 
  378                     "Address of local auto-variable assigned to a function parameter.\n" 
  379                     "Function parameter is assigned the address of a local auto-variable. " 
  380                     "Local auto-variables are reserved from the stack which is freed when " 
  381                     "the function ends. The address is invalid after the function ends and it " 
  382                     "might 'leak' from the function through the parameter.",
 
  392                 "uselessAssignmentArg",
 
  400                 "uselessAssignmentPtrArg",
 
  401                 "Assignment of function parameter has no effect outside the function. Did you forget dereferencing it?", 
CWE398, 
Certainty::normal);
 
  422     if (tok->
scope() && !tok->
scope()->isClassOrStructOrUnion() && tok->
scope()->isNestedIn(scope))
 
  431             return argScope && argScope->isNestedIn(scope);
 
  460     for (
const Token* tok2 = decl.first; tok2 != decl.second; tok2 = tok2->
next())
 
  493     if (!varDeclEndToken)
 
  553     for (
const Token *tok = start; tok && tok != end; tok = tok->
next()) {
 
  557                 if (!printInconclusive && lt.inconclusive)
 
  559                 const Variable* var = lt.token->variable();
 
  571         } 
else if (
Token::Match(tok->previous(), 
"&|&& %var% =") && tok->astParent() == tok->next() &&
 
  572                    tok->variable() && tok->variable()->nameToken() == tok &&
 
  573                    tok->variable()->declarationId() == tok->varId() && tok->variable()->isStatic() &&
 
  574                    !tok->variable()->isArgument()) {
 
  582         } 
else if (tok->variable() && (tok->variable()->isReference() || tok->variable()->isRValueReference())) {
 
  584                 if (!printInconclusive && lt.inconclusive)
 
  586                 const Token * tokvalue = lt.token;
 
  595         std::unordered_set<const Token*> exprs;
 
  597             if (!val.isLocalLifetimeValue() && !val.isSubFunctionLifetimeValue())
 
  599             if (!printInconclusive && val.isInconclusive())
 
  602             if (!exprs.insert(parent).second)
 
  605                 const Token * tokvalue = lt.token;
 
  606                 if (val.isLocalLifetimeValue()) {
 
  612                         if (tokvalue->
exprId() == tok->exprId() && !(tok->variable() && tok->variable()->isArray()) &&
 
  634                     const Token * tok2 = tok;
 
  640                     } 
else if (tok->variable() && tok->variable()->declarationId() == tok->varId()) {
 
  641                         var = tok->variable();
 
  647                         nextTok = tok->
next();
 
  648                     if (var && !var->
isLocal() && !var->
isArgument() && !(val.tokvalue && val.tokvalue->variable() && val.tokvalue->variable()->isStatic()) &&
 
  650                                            tok->
scope()->bodyEnd,
 
  661         if (lambdaEndToken) {
 
  663             tok = lambdaEndToken;
 
  665         if (tok->str() == 
"{" && tok->scope()) {
 
  670                 for (
const Function& f:tok->scope()->functionList) {
 
  682     logChecker(
"CheckAutoVariables::checkVarLifetime");
 
  696     errorPath.emplace_back(tok, 
"");
 
  705     errorPath.emplace_back(tok, 
"");
 
  714     errorPath.emplace_back(tempTok, 
"Temporary created here.");
 
  715     errorPath.emplace_back(tok, 
"");
 
  718                 "danglingTemporaryLifetime",
 
  719                 msg + 
" that is a temporary.",
 
  729     std::string msg = 
"Non-local variable '" + tokName + 
"' will use " + 
lifetimeMessage(tok, val, errorPath);
 
  730     errorPath.emplace_back(tok, 
"");
 
  736     errorPath.emplace_back(tok, 
"");
 
  743     errorPath.emplace_back(tok, 
"");
 
  750     std::string tokName = tok ? tok->
str() : 
"x";
 
  751     std::string varName = var ? var->
name() : 
"y";
 
  752     std::string msg = 
"Non-local reference variable '" + tokName + 
"' to local variable '" + varName + 
"'";
 
  753     errorPath.emplace_back(tok, 
"");
 
  759     errorPath.emplace_back(tok, 
"");
 
  768     std::string type = 
"an auto-variable";
 
  770         type = 
"a string literal";
 
  772         type = 
"a pointer pointing to a string literal";
 
  775             type = 
"a global variable";
 
  777             type = 
"a static variable";
 
  785                 "autovarInvalidDeallocation",
 
  786                 "Deallocation of " + type + 
" results in undefined behaviour.\n" 
  787                 "The deallocation of " + type + 
" results in undefined behaviour. You should only free memory " 
bool astIsContainerView(const Token *tok)
 
bool exprDependsOnThis(const Token *expr, bool onVar, nonneg int depth)
 
bool isTemporary(const Token *tok, const Library *library, bool unknown)
 
bool precedes(const Token *tok1, const Token *tok2)
If tok2 comes after tok1.
 
bool astIsRHS(const Token *tok)
 
const Token * findLambdaEndToken(const Token *first)
find lambda function end token
 
const Token * nextAfterAstRightmostLeaf(const Token *tok)
 
const Token * getParentLifetime(const Token *tok)
 
Library::Container::Yield astContainerYield(const Token *tok, const Token **ftok)
 
bool isVariableChanged(const Token *tok, int indirect, const Settings &settings, int depth)
 
static const CWE CWE398(398U)
 
static bool isArrayVar(const Token *tok)
 
static bool isDeadScope(const Token *tok, const Scope *scope)
 
static bool isDeadTemporary(const Token *tok, const Token *expr, const Library *library)
 
static const Variable * getParentVar(const Token *tok)
 
static bool isAutoVar(const Token *tok)
 
static const CWE CWE590(590U)
 
static int getPointerDepth(const Token *tok)
 
static bool isEscapedReference(const Variable *var)
 
static bool isDanglingSubFunction(const Token *tokvalue, const Token *tok)
 
static bool isAutoVarArray(const Token *tok)
 
static bool isAssignedToNonLocal(const Token *tok)
 
static bool isInScope(const Token *tok, const Scope *scope)
 
static bool isAddressOfLocalVariable(const Token *expr)
 
static bool isAutoVariableRHS(const Token *tok)
 
static bool isArrayArg(const Token *tok, const Settings &settings)
 
static bool hasOverloadedAssignment(const Token *tok, bool &inconclusive)
 
static const CWE CWE562(562U)
 
static bool isNonReferenceArg(const Token *tok)
 
static bool isPtrArg(const Token *tok)
 
static bool isRefPtrArg(const Token *tok)
 
static bool variableIsUsedInScope(const Token *start, nonneg int varId, const Scope *scope)
 
static bool isLocalContainerBuffer(const Token *tok)
 
Various small checks for automatic variables.
 
void errorUselessAssignmentPtrArg(const Token *tok)
 
void errorReturnReference(const Token *tok, ErrorPath errorPath, bool inconclusive)
 
void errorReturnDanglingLifetime(const Token *tok, const ValueFlow::Value *val)
 
void errorInvalidLifetime(const Token *tok, const ValueFlow::Value *val)
 
void errorDanglingTemporaryLifetime(const Token *tok, const ValueFlow::Value *val, const Token *tempTok)
 
void checkVarLifetimeScope(const Token *start, const Token *end)
 
void errorDanglingTempReference(const Token *tok, ErrorPath errorPath, bool inconclusive)
 
void errorUselessAssignmentArg(const Token *tok)
 
void errorDanglingReference(const Token *tok, const Variable *var, ErrorPath errorPath)
 
void errorAutoVariableAssignment(const Token *tok, bool inconclusive)
 
void assignFunctionArg()
assign function argument
 
void errorDanglngLifetime(const Token *tok, const ValueFlow::Value *val)
 
bool diag(const Token *tokvalue)
returns true if tokvalue has already been diagnosed
 
bool checkAutoVariableAssignment(const Token *expr, bool inconclusive, const Token *startToken=nullptr)
Check variable assignment.
 
void autoVariables()
Check auto variables.
 
void errorInvalidDeallocation(const Token *tok, const ValueFlow::Value *val)
 
std::set< const Token * > mDiagDanglingTemp
 
void errorReturnTempReference(const Token *tok, ErrorPath errorPath, bool inconclusive)
 
void reportError(const Token *tok, const Severity severity, const std::string &id, const std::string &msg)
report an error
 
const Settings *const mSettings
 
ErrorPath getErrorPath(const Token *errtok, const ValueFlow::Value *value, std::string bug) const
 
const Tokenizer *const mTokenizer
 
void logChecker(const char id[])
log checker
 
static bool returnsReference(const Function *function, bool unknown=false, bool includeRValueRef=false)
 
static bool returnsStandardType(const Function *function, bool unknown=false)
 
Library definitions handling.
 
bool isentrypoint(const std::string &func) const
 
const AllocFunc * getDeallocFuncInfo(const Token *tok) const
get deallocation info for function
 
std::vector< Scope * > nestedList
 
static Function * nestedInFunction(const Scope *scope)
 
Function * function
function info for this function
 
const Token * bodyStart
'{' token
 
const Token * bodyEnd
'}' token
 
This is just a container for general settings so that we don't need to pass individual values to func...
 
bool isPremiumEnabled(const char id[]) const
Is checker id enabled by premiumArgs.
 
SimpleEnableGroup< Certainty > certainty
 
SimpleEnableGroup< Severity > severity
 
bool isEnabled(T flag) 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.
 
nonneg int exprId() const
 
const std::string & originalName() const
 
static const Token * findmatch(const Token *const startTok, const char pattern[], const nonneg int varId=0)
 
static std::pair< const Token *, const Token * > typeDecl(const Token *tok, bool pointedToType=false)
 
const ValueType * valueType() const
 
void astOperand1(Token *tok)
 
std::string expressionString() const
 
bool isUnaryOp(const std::string &s) const
 
static const Token * findsimplematch(const Token *const startTok, const char(&pattern)[count])
 
const Token * tokAt(int index) const
 
Token::Type tokType() 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 variable(const Variable *v)
Associate this token with given variable.
 
const std::list< ValueFlow::Value > & values() 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 SymbolDatabase * getSymbolDatabase() const
 
const Token * tokvalue
token value - the token that has the value.
 
bool isInconclusive() const
 
enum ValueType::Type type
 
nonneg int pointer
0=>not pointer, 1=>*, 2=>**, 3=>***, etc
 
Information about a member variable.
 
bool isArgument() const
Is variable a function argument.
 
bool isExtern() const
Is variable extern.
 
bool isReference() const
Is reference variable.
 
bool isRValueReference() const
Is reference variable.
 
bool isLocal() const
Is variable local.
 
const Token * declEndToken() const
Get end token of variable declaration E.g.
 
const Type * type() const
Get Type pointer of known type.
 
const Scope * scope() const
Get Scope pointer of enclosing scope.
 
bool isGlobal() const
Is variable global.
 
const std::string & name() const
Get name string.
 
bool isArray() const
Is variable an array.
 
const Token * nameToken() const
Get name token.
 
nonneg int declarationId() const
Get declaration ID (varId used for variable in its declaration).
 
bool isPointer() const
Is pointer variable.
 
bool isStatic() const
Is variable static.
 
const ValueType * valueType() const
 
std::list< ErrorPathItem > ErrorPath
 
@ error
Programming error.
 
std::vector< LifetimeToken > getLifetimeTokens(const Token *tok, const Settings &settings, bool escape=false, Value::ErrorPath errorPath=Value::ErrorPath{})
 
std::string lifetimeMessage(const Token *tok, const Value *val, Value::ErrorPath &errorPath)
 
bool isLifetimeBorrowed(const Token *tok, const Settings &settings)
 
const Variable * getLifetimeVariable(const Token *tok, Value::ErrorPath &errorPath, const Settings &settings, bool *addressOf=nullptr)