MCPcopy Create free account
hub / github.com/cppcheck-opensource/cppcheck / isFunctionParUsage

Method isFunctionParUsage

lib/checkuninitvar.cpp:1367–1435  ·  view source on GitHub ↗

* Is function parameter "used" so a "usage of uninitialized variable" can * be written? If parameter is passed "by value" then it is "used". If it * is passed "by reference" then it is not necessarily "used". * @return -1 => unknown 0 => not used 1 => used */

Source from the content-addressed store, hash-verified

1365 * @return -1 => unknown 0 => not used 1 => used
1366 */
1367int CheckUninitVarImpl::isFunctionParUsage(const Token *vartok, const Library& library, bool pointer, Alloc alloc, int indirect)
1368{
1369 bool unknown = false;
1370 const Token *parent = getAstParentSkipPossibleCastAndAddressOf(vartok, &unknown);
1371 if (unknown || !Token::Match(parent, "[(,]"))
1372 return -1;
1373
1374 // locate start parentheses in function call..
1375 int argumentNumber = 0;
1376 const Token *start = vartok;
1377 while (start && !Token::Match(start, "[;{}(]")) {
1378 if (start->str() == ")")
1379 start = start->link();
1380 else if (start->str() == ",")
1381 ++argumentNumber;
1382 start = start->previous();
1383 }
1384 if (!start)
1385 return -1;
1386
1387 if (Token::simpleMatch(start->link(), ") {") && Token::Match(start->previous(), "if|for|while|switch"))
1388 return (!pointer || alloc == NO_ALLOC);
1389
1390 // is this a function call?
1391 if (Token::Match(start->previous(), "%name% (")) {
1392 const bool address(vartok->strAt(-1) == "&");
1393 const bool array(vartok->variable() && vartok->variable()->isArray());
1394 // check how function handle uninitialized data arguments..
1395 const Function *func = start->previous()->function();
1396 if (func) {
1397 const Variable *arg = func->getArgumentVar(argumentNumber);
1398 if (arg) {
1399 const Token *argStart = arg->typeStartToken();
1400 if (!address && !array && Token::Match(argStart, "%type% %name%| [,)]"))
1401 return 1;
1402 if (pointer && !address && alloc == NO_ALLOC && Token::Match(argStart, "%type% * %name% [,)]"))
1403 return 1;
1404 while (argStart->previous() && argStart->previous()->isName())
1405 argStart = argStart->previous();
1406 if (Token::Match(argStart, "const %type% & %name% [,)]")) {
1407 // If it's a record it's ok to pass a partially uninitialized struct.
1408 if (vartok->variable() && vartok->variable()->valueType() && vartok->variable()->valueType()->type == ValueType::Type::RECORD)
1409 return -1;
1410 return 1;
1411 }
1412 if ((pointer || address) && Token::Match(argStart, "const %type% %name% [") && Token::Match(argStart->linkAt(3), "] [,)]"))
1413 return 1;
1414 }
1415
1416 } else if (Token::Match(start->previous(), "if|while|for")) {
1417 // control-flow statement reading the variable "by value"
1418 return alloc == NO_ALLOC;
1419 } else {
1420 const bool isnullbad = library.isnullargbad(start->previous(), argumentNumber + 1);
1421 if (indirect == 0 && pointer && !address && isnullbad && alloc == NO_ALLOC)
1422 return 1;
1423 if (vartok->varId() == 0 && vartok->valueType())
1424 indirect = vartok->valueType()->pointer;

Callers

nothing calls this directly

Calls 10

variableMethod · 0.80
isArrayMethod · 0.80
getArgumentVarMethod · 0.80
linkAtMethod · 0.80
isnullargbadMethod · 0.80
isuninitargbadMethod · 0.80
simpleMatchFunction · 0.70
strMethod · 0.45
functionMethod · 0.45

Tested by

no test coverage detected