@@ -275,6 +275,77 @@ const Token *parseCompareInt(const Token *tok, ValueFlow::Value &true_value, Val
275275 });
276276}
277277
278+ static bool isInConstructorList (const Token* tok)
279+ {
280+ if (!tok)
281+ return false ;
282+ if (!astIsRHS (tok))
283+ return false ;
284+ const Token* parent = tok->astParent ();
285+ if (!Token::Match (parent, " {|(" ))
286+ return false ;
287+ if (!Token::Match (parent->previous (), " %var% {|(" ))
288+ return false ;
289+ if (!parent->astOperand1 () || !parent->astOperand2 ())
290+ return false ;
291+ do {
292+ parent = parent->astParent ();
293+ } while (Token::simpleMatch (parent, " ," ));
294+ return Token::simpleMatch (parent, " :" ) && !Token::simpleMatch (parent->astParent (), " ?" );
295+ }
296+
297+ static std::vector<ValueType> getParentValueTypes (const Token* tok,
298+ const Settings* settings = nullptr ,
299+ const Token** parent = nullptr )
300+ {
301+ if (!tok)
302+ return {};
303+ if (!tok->astParent ())
304+ return {};
305+ if (isInConstructorList (tok)) {
306+ if (parent)
307+ *parent = tok->astParent ()->astOperand1 ();
308+ if (tok->astParent ()->astOperand1 ()->valueType ())
309+ return {*tok->astParent ()->astOperand1 ()->valueType ()};
310+ return {};
311+ } else if (Token::Match (tok->astParent (), " (|{|," )) {
312+ int argn = -1 ;
313+ const Token* ftok = getTokenArgumentFunction (tok, argn);
314+ if (ftok && ftok->function ()) {
315+ std::vector<ValueType> result;
316+ std::vector<const Variable*> argsVars = getArgumentVars (ftok, argn);
317+ const Token* nameTok = nullptr ;
318+ for (const Variable* var : getArgumentVars (ftok, argn)) {
319+ if (!var)
320+ continue ;
321+ if (!var->valueType ())
322+ continue ;
323+ nameTok = var->nameToken ();
324+ result.push_back (*var->valueType ());
325+ }
326+ if (result.size () == 1 && nameTok && parent) {
327+ *parent = nameTok;
328+ }
329+ return result;
330+ }
331+ }
332+ if (settings && Token::Match (tok->astParent ()->tokAt (-2 ), " . push_back|push_front|insert|push (" ) &&
333+ astIsContainer (tok->astParent ()->tokAt (-2 )->astOperand1 ())) {
334+ const Token* contTok = tok->astParent ()->tokAt (-2 )->astOperand1 ();
335+ const ValueType* vtCont = contTok->valueType ();
336+ if (!vtCont->containerTypeToken )
337+ return {};
338+ ValueType vtParent = ValueType::parseDecl (vtCont->containerTypeToken , settings);
339+ return {std::move (vtParent)};
340+ }
341+ if (Token::Match (tok->astParent (), " return|(|{|%assign%" ) && parent) {
342+ *parent = tok->astParent ();
343+ }
344+ if (tok->astParent ()->valueType ())
345+ return {*tok->astParent ()->valueType ()};
346+ return {};
347+ }
348+
278349static bool isEscapeScope (const Token* tok, TokenList * tokenlist, bool unknown = false )
279350{
280351 if (!Token::simpleMatch (tok, " {" ))
@@ -1547,6 +1618,17 @@ static std::vector<MathLib::bigint> minUnsignedValue(const Token* tok, int depth
15471618 return result;
15481619}
15491620
1621+ static bool isConvertedToIntegral (const Token* tok, const Settings* settings)
1622+ {
1623+ if (!tok)
1624+ return false ;
1625+ std::vector<ValueType> parentTypes = getParentValueTypes (tok, settings);
1626+ if (parentTypes.empty ())
1627+ return false ;
1628+ const ValueType& vt = parentTypes.front ();
1629+ return vt.type != ValueType::UNKNOWN_INT && vt.isIntegral ();
1630+ }
1631+
15501632static void valueFlowImpossibleValues (TokenList* tokenList, const Settings* settings)
15511633{
15521634 for (Token* tok = tokenList->front (); tok; tok = tok->next ()) {
@@ -1602,6 +1684,11 @@ static void valueFlowImpossibleValues(TokenList* tokenList, const Settings* sett
16021684 ValueFlow::Value value{0 };
16031685 value.setImpossible ();
16041686 setTokenValue (tok, value, settings);
1687+ } else if (tok->isIncompleteVar () && tok->astParent () && tok->astParent ()->isUnaryOp (" -" ) &&
1688+ isConvertedToIntegral (tok->astParent (), settings)) {
1689+ ValueFlow::Value value{0 };
1690+ value.setImpossible ();
1691+ setTokenValue (tok, value, settings);
16051692 }
16061693 }
16071694}
@@ -3359,77 +3446,6 @@ static bool isDifferentType(const Token* src, const Token* dst)
33593446 return false ;
33603447}
33613448
3362- static bool isInConstructorList (const Token* tok)
3363- {
3364- if (!tok)
3365- return false ;
3366- if (!astIsRHS (tok))
3367- return false ;
3368- const Token* parent = tok->astParent ();
3369- if (!Token::Match (parent, " {|(" ))
3370- return false ;
3371- if (!Token::Match (parent->previous (), " %var% {|(" ))
3372- return false ;
3373- if (!parent->astOperand1 () || !parent->astOperand2 ())
3374- return false ;
3375- do {
3376- parent = parent->astParent ();
3377- } while (Token::simpleMatch (parent, " ," ));
3378- return Token::simpleMatch (parent, " :" ) && !Token::simpleMatch (parent->astParent (), " ?" );
3379- }
3380-
3381- static std::vector<ValueType> getParentValueTypes (const Token* tok,
3382- const Settings* settings = nullptr ,
3383- const Token** parent = nullptr )
3384- {
3385- if (!tok)
3386- return {};
3387- if (!tok->astParent ())
3388- return {};
3389- if (isInConstructorList (tok)) {
3390- if (parent)
3391- *parent = tok->astParent ()->astOperand1 ();
3392- if (tok->astParent ()->astOperand1 ()->valueType ())
3393- return {*tok->astParent ()->astOperand1 ()->valueType ()};
3394- return {};
3395- } else if (Token::Match (tok->astParent (), " (|{|," )) {
3396- int argn = -1 ;
3397- const Token* ftok = getTokenArgumentFunction (tok, argn);
3398- if (ftok && ftok->function ()) {
3399- std::vector<ValueType> result;
3400- std::vector<const Variable*> argsVars = getArgumentVars (ftok, argn);
3401- const Token* nameTok = nullptr ;
3402- for (const Variable* var : getArgumentVars (ftok, argn)) {
3403- if (!var)
3404- continue ;
3405- if (!var->valueType ())
3406- continue ;
3407- nameTok = var->nameToken ();
3408- result.push_back (*var->valueType ());
3409- }
3410- if (result.size () == 1 && nameTok && parent) {
3411- *parent = nameTok;
3412- }
3413- return result;
3414- }
3415- }
3416- if (settings && Token::Match (tok->astParent ()->tokAt (-2 ), " . push_back|push_front|insert|push (" ) &&
3417- astIsContainer (tok->astParent ()->tokAt (-2 )->astOperand1 ())) {
3418- const Token* contTok = tok->astParent ()->tokAt (-2 )->astOperand1 ();
3419- const ValueType* vtCont = contTok->valueType ();
3420- if (!vtCont->containerTypeToken )
3421- return {};
3422- ValueType vtParent = ValueType::parseDecl (vtCont->containerTypeToken , settings);
3423- return {std::move (vtParent)};
3424- }
3425- if (Token::Match (tok->astParent (), " return|(|{|%assign%" ) && parent) {
3426- *parent = tok->astParent ();
3427- }
3428- if (tok->astParent ()->valueType ())
3429- return {*tok->astParent ()->valueType ()};
3430- return {};
3431- }
3432-
34333449bool isLifetimeBorrowed (const Token *tok, const Settings *settings)
34343450{
34353451 if (!tok)
0 commit comments