@@ -1040,7 +1040,7 @@ bool isLikelyStreamRead(bool cpp, const Token *op)
10401040
10411041static bool nonLocal (const Variable* var)
10421042{
1043- return !var || (!var->isLocal () && !var->isArgument ()) || var->isStatic () || var->isReference ();
1043+ return !var || (!var->isLocal () && !var->isArgument ()) || var->isStatic () || var->isReference () || var-> isExtern () ;
10441044}
10451045
10461046static bool hasFunctionCall (const Token *tok)
@@ -1071,9 +1071,41 @@ struct FwdAnalysis::Result FwdAnalysis::checkRecursive(const Token *expr, const
10711071 return Result (Result::Type::BREAK, tok);
10721072 }
10731073
1074- if (Token::Match (tok, " continue|return|throw|goto" )) {
1074+ if (Token::simpleMatch (tok, " goto" ))
1075+ return Result (Result::Type::BAILOUT);
1076+
1077+ if (tok->str () == " continue" )
1078+ // TODO
1079+ return Result (Result::Type::BAILOUT);
1080+
1081+ if (Token::Match (tok, " return|throw" )) {
10751082 // TODO: Handle these better
1076- return Result (Result::Type::RETURN);
1083+ switch (mWhat ) {
1084+ case What::Reassign:
1085+ return Result (Result::Type::RETURN);
1086+ case What::UnusedValue:
1087+ // Is expr variable used in expression?
1088+ {
1089+ bool read = false ;
1090+ visitAstNodes (tok->astOperand1 (),
1091+ [&](const Token *tok2) {
1092+ if (!local && Token::Match (tok2, " %name% (" ))
1093+ read = true ;
1094+ if (tok2->varId () && exprVarIds.find (tok2->varId ()) != exprVarIds.end ())
1095+ read = true ;
1096+ return read ? ChildrenToVisit::done : ChildrenToVisit::op1_and_op2;
1097+ });
1098+
1099+ return Result (read ? Result::Type::READ : Result::Type::RETURN);
1100+ }
1101+ }
1102+ }
1103+
1104+ if (tok->str () == " }" ) {
1105+ Scope::ScopeType scopeType = tok->scope ()->type ;
1106+ if (scopeType == Scope::eWhile || scopeType == Scope::eFor || scopeType == Scope::eDo)
1107+ // TODO handle loops better
1108+ return Result (Result::Type::BAILOUT);
10771109 }
10781110
10791111 if (Token::simpleMatch (tok, " else {" ))
@@ -1088,6 +1120,10 @@ struct FwdAnalysis::Result FwdAnalysis::checkRecursive(const Token *expr, const
10881120 return Result (Result::Type::BAILOUT);
10891121 }
10901122
1123+ if (expr->isName () && Token::Match (tok, " %name% (" ) && tok->str ().find (" <" ) != std::string::npos && tok->str ().find (expr->str ()) != std::string::npos)
1124+ return Result (Result::Type::BAILOUT);
1125+
1126+
10911127 if (exprVarIds.find (tok->varId ()) != exprVarIds.end ()) {
10921128 const Token *parent = tok;
10931129 while (Token::Match (parent->astParent (), " .|::|[" ))
@@ -1098,7 +1134,7 @@ struct FwdAnalysis::Result FwdAnalysis::checkRecursive(const Token *expr, const
10981134 return Result (Result::Type::BAILOUT);
10991135 }
11001136 if (hasOperand (parent->astParent ()->astOperand2 (), expr)) {
1101- if (mReassign )
1137+ if (mWhat == What::Reassign )
11021138 return Result (Result::Type::READ);
11031139 continue ;
11041140 }
@@ -1113,6 +1149,9 @@ struct FwdAnalysis::Result FwdAnalysis::checkRecursive(const Token *expr, const
11131149 }
11141150
11151151 if (Token::Match (tok, " ) {" )) {
1152+ if (Token::simpleMatch (tok->link ()->previous (), " switch (" ))
1153+ // TODO: parse switch
1154+ return Result (Result::Type::BAILOUT);
11161155 const Result &result1 = checkRecursive (expr, tok->tokAt (2 ), tok->linkAt (1 ), exprVarIds, local);
11171156 if (result1.type == Result::Type::READ || result1.type == Result::Type::BAILOUT)
11181157 return result1;
@@ -1133,21 +1172,80 @@ struct FwdAnalysis::Result FwdAnalysis::checkRecursive(const Token *expr, const
11331172 return Result (Result::Type::NONE);
11341173}
11351174
1175+ bool FwdAnalysis::isGlobalData (const Token *expr) const
1176+ {
1177+ bool globalData = false ;
1178+ visitAstNodes (expr,
1179+ [&](const Token *tok) {
1180+ if (tok->originalName () == " ->" ) {
1181+ // TODO check if pointer points at local data
1182+ globalData = true ;
1183+ return ChildrenToVisit::none;
1184+ } else if (Token::Match (tok, " [*[]" ) && tok->astOperand1 () && tok->astOperand1 ()->variable ()) {
1185+ // TODO check if pointer points at local data
1186+ const Variable *lhsvar = tok->astOperand1 ()->variable ();
1187+ const ValueType *lhstype = tok->astOperand1 ()->valueType ();
1188+ if (lhsvar->isPointer ()) {
1189+ globalData = true ;
1190+ return ChildrenToVisit::none;
1191+ } else if (lhsvar->isArgument () && (!lhstype || (lhstype->type <= ValueType::Type::VOID && !lhstype->container ))) {
1192+ globalData = true ;
1193+ return ChildrenToVisit::none;
1194+ }
1195+ }
1196+ if (tok->varId () == 0 && tok->isName () && tok->previous ()->str () != " ." ) {
1197+ globalData = true ;
1198+ return ChildrenToVisit::none;
1199+ }
1200+ if (tok->variable ()) {
1201+ // TODO : Check references
1202+ if (tok->variable ()->isReference () && tok != tok->variable ()->nameToken ()) {
1203+ globalData = true ;
1204+ return ChildrenToVisit::none;
1205+ }
1206+ if ((tok->previous ()->str () != " ." && (!tok->variable ()->isLocal () && !tok->variable ()->isArgument ())) || tok->variable ()->isExtern ()) {
1207+ globalData = true ;
1208+ return ChildrenToVisit::none;
1209+ }
1210+ if (tok->variable ()->isArgument () && tok->variable ()->isPointer () && tok != expr) {
1211+ globalData = true ;
1212+ return ChildrenToVisit::none;
1213+ }
1214+ }
1215+ if (Token::Match (tok, " .|[" ))
1216+ return ChildrenToVisit::op1;
1217+ return ChildrenToVisit::op1_and_op2;
1218+ });
1219+ return globalData;
1220+ }
1221+
11361222FwdAnalysis::Result FwdAnalysis::check (const Token *expr, const Token *startToken, const Token *endToken)
11371223{
11381224 // all variable ids in expr.
11391225 std::set<unsigned int > exprVarIds;
11401226 bool local = true ;
11411227 visitAstNodes (expr,
11421228 [&](const Token *tok) {
1229+ if (tok->varId () == 0 && tok->isName () && tok->previous ()->str () != " ." )
1230+ // unknown variables are not local
1231+ local = false ;
11431232 if (tok->varId () > 0 ) {
11441233 exprVarIds.insert (tok->varId ());
1145- if (!Token::simpleMatch (tok->previous (), " ." ))
1234+ if (!Token::simpleMatch (tok->previous (), " ." )) {
1235+ const Variable *var = tok->variable ();
1236+ if (var && var->isReference () && var->isLocal () && Token::Match (var->nameToken (), " %var% [=(]" ) && !isGlobalData (var->nameToken ()->next ()->astOperand2 ()))
1237+ return ChildrenToVisit::none;
11461238 local &= !nonLocal (tok->variable ());
1239+ }
11471240 }
11481241 return ChildrenToVisit::op1_and_op2;
11491242 });
11501243
1244+ // In unused values checking we do not want to check assignments to
1245+ // global data.
1246+ if (mWhat == What::UnusedValue && isGlobalData (expr))
1247+ return Result (FwdAnalysis::Result::Type::BAILOUT);
1248+
11511249 Result result = checkRecursive (expr, startToken, endToken, exprVarIds, local);
11521250
11531251 // Break => continue checking in outer scope
@@ -1174,7 +1272,38 @@ bool FwdAnalysis::hasOperand(const Token *tok, const Token *lhs) const
11741272
11751273const Token *FwdAnalysis::reassign (const Token *expr, const Token *startToken, const Token *endToken)
11761274{
1177- mReassign = true ;
1275+ mWhat = What::Reassign ;
11781276 Result result = check (expr, startToken, endToken);
11791277 return result.type == FwdAnalysis::Result::Type::WRITE ? result.token : nullptr ;
11801278}
1279+
1280+ bool FwdAnalysis::unusedValue (const Token *expr, const Token *startToken, const Token *endToken)
1281+ {
1282+ mWhat = What::UnusedValue;
1283+ Result result = check (expr, startToken, endToken);
1284+ return (result.type == FwdAnalysis::Result::Type::NONE || result.type == FwdAnalysis::Result::Type::RETURN) && !possiblyAliased (expr, startToken);
1285+ }
1286+
1287+ bool FwdAnalysis::possiblyAliased (const Token *expr, const Token *startToken) const
1288+ {
1289+ if (expr->isUnaryOp (" *" ))
1290+ return true ;
1291+
1292+ const bool macro = false ;
1293+ const bool pure = false ;
1294+ const bool followVar = false ;
1295+ for (const Token *tok = startToken; tok; tok = tok->previous ()) {
1296+ if (tok->str () == " {" && tok->scope ()->type == Scope::eFunction)
1297+ continue ;
1298+ if (isSameExpression (mCpp , macro, expr, tok, mLibrary , pure, followVar)) {
1299+ const Token *parent = tok->astParent ();
1300+ if (parent && parent->isUnaryOp (" &" ))
1301+ return true ;
1302+ if (parent && Token::Match (parent->tokAt (-2 ), " & %name% =" ))
1303+ return true ;
1304+ if (parent && Token::simpleMatch (parent->tokAt (-3 ), " std :: ref (" ))
1305+ return true ;
1306+ }
1307+ }
1308+ return false ;
1309+ }
0 commit comments