89 logChecker(
"CheckOther::checkCastIntToCharAndBack");
93 std::map<int, std::string> vars;
98 if (
Token::Match(tok,
"%var% = fclose|fflush|fputc|fputs|fscanf|getchar|getc|fgetc|putchar|putc|puts|scanf|sscanf|ungetc (")) {
99 const Variable *var = tok->variable();
101 vars[tok->varId()] = tok->strAt(2);
103 }
else if (
Token::Match(tok,
"EOF %comp% ( %var% = fclose|fflush|fputc|fputs|fscanf|getchar|getc|fgetc|putchar|putc|puts|scanf|sscanf|ungetc (")) {
105 const Variable *var = tok->variable();
109 }
else if (tok->isCpp() && (
Token::Match(tok,
"EOF %comp% ( %var% = std :: cin . get (") ||
Token::Match(tok,
"EOF %comp% ( %var% = cin . get ("))) {
111 const Variable *var = tok->variable();
115 }
else if (tok->isCpp() && (
Token::Match(tok,
"%var% = std :: cin . get (") ||
Token::Match(tok,
"%var% = cin . get ("))) {
116 const Variable *var = tok->variable();
118 vars[tok->varId()] =
"cin.get";
121 if (vars.find(tok->varId()) != vars.end()) {
126 if (vars.find(tok->varId()) != vars.end()) {
139 "checkCastIntToCharAndBack",
140 "$symbol:" + strFunctionName +
"\n"
141 "Storing $symbol() return value in char variable and then comparing with EOF.\n"
142 "When saving $symbol() return value in char variable there is loss of precision. "
143 " When $symbol() returns EOF this value is truncated. Comparing the char "
144 "variable with EOF can have unexpected results. For instance a loop \"while (EOF != (c = $symbol());\" "
145 "loops forever on some compilers/platforms and on other compilers/platforms it will stop "
165 if (tok->str() !=
"?" || !tok->astOperand1() || !tok->astOperand1()->isCalculation())
167 if (!tok->astOperand1()->isArithmeticalOp() && tok->astOperand1()->tokType() !=
Token::eBitOp)
171 if (tok->astOperand1()->isBinaryOp() &&
Token::Match(tok->astOperand1(),
"%or%|&|%|*|/") && tok->astOperand2()->valueType() && tok->astOperand2()->valueType()->pointer > 0)
179 if (tok->astOperand1()->isBinaryOp() && tok->astOperand1()->astOperand2()->hasKnownIntValue()) {
189 for (; tok2; tok2 = tok2->
next()) {
190 if (tok2->
str() ==
"(")
192 else if (tok2->
str() ==
")")
194 else if (tok2->
str() ==
"?") {
206 const std::string calc(
"'a" + op +
"b?c:d'");
209 const std::string s1(
"'(a" + op +
"b)?c:d'");
212 const std::string s2(
"'a" + op +
"(b?c:d)'");
216 "clarifyCalculation",
217 "Clarify calculation precedence for '" + op +
"' and '?'.\n"
218 "Suspicious calculation. Please use parentheses to clarify the code. "
219 "The code '" + calc +
"' should be written as either '" + s1 +
"' or '" + s2 +
"'.",
CWE783,
Certainty::normal);
235 if (tok->astOperand1() &&
Token::Match(tok,
"* %name%")) {
238 while (tok2 && tok2->
str() ==
"*")
253 reportError(tok,
Severity::warning,
"clarifyStatement",
"In expression like '*A++' the result of '*' is unused. Did you intend to write '(*A)++;'?\n"
254 "A statement like '*A++;' might not do what you intended. Postfix 'operator++' is executed before 'operator*'. "
268 logChecker(
"CheckOther::checkSuspiciousSemicolon");
304 logChecker(
"CheckOther::warningOldStylePointerCast");
313 for (; tok && tok != scope->
bodyEnd; tok = tok->
next()) {
315 if (tok->
str() !=
"(")
318 while (
Token::Match(castTok,
"const|volatile|class|struct|union|%type%|::")) {
319 castTok = castTok->
next();
321 castTok = castTok->
link()->next();
323 if (castTok == tok->
next())
325 bool isPtr =
false, isRef =
false;
327 if (castTok->
str() ==
"*")
329 else if (castTok->
str() ==
"&")
331 castTok = castTok->
next();
333 if ((!isPtr && !isRef) || !
Token::Match(castTok,
") (| %name%|%num%|%bool%|%char%|%str%|&"))
344 if (tok->
strAt(3) ==
"const")
359 const std::string type = isPtr ?
"pointer" :
"reference";
361 "C-style " + type +
" casting\n"
362 "C-style " + type +
" casting detected. C++ offers four different kinds of casts as replacements: "
363 "static_cast, const_cast, dynamic_cast and reinterpret_cast. A C-style cast could evaluate to "
364 "any of those automatically, thus it is considered safer if the programmer explicitly states "
383 const Token* toTok =
nullptr;
384 const Token* fromTok =
nullptr;
386 if (
Token::Match(tok,
"( const|volatile| const|volatile| %type% %type%| const| * )")) {
398 if (!fromType || !toType || !fromType->
pointer || !toType->
pointer)
401 if (fromType->
type != toType->
type && fromType->
type >= ValueType::Type::BOOL && toType->
type >= ValueType::Type::BOOL && (toType->
type != ValueType::Type::CHAR || printInconclusive)) {
432 logChecker(
"CheckOther::checkRedundantAssignment");
444 tok = tok->linkAt(1);
445 if ((tok->isAssignmentOp() || tok->tokType() ==
Token::eIncDecOp) && tok->astOperand1()) {
446 if (tok->astParent())
451 bool isInitialization =
false;
452 if (
Token::Match(tok->tokAt(-2),
"; %var% =") && tok->tokAt(-2)->isSplittedVarDeclEq()) {
453 isInitialization =
true;
456 [&](
const Token *rhs) {
457 if (Token::simpleMatch(rhs,
"{ 0 }"))
458 return ChildrenToVisit::none;
459 if (Token::Match(rhs,
"%str%|%num%|%name%") && !rhs->varId())
460 return ChildrenToVisit::none;
461 if (Token::Match(rhs,
":: %name%") && rhs->hasKnownIntValue())
462 return ChildrenToVisit::none;
464 return ChildrenToVisit::op2;
466 return ChildrenToVisit::done;
477 if (tok->astOperand1()->variable() && tok->astOperand1()->variable()->isReference())
481 if (tok->astOperand1()->variable() && tok->astOperand1()->variable()->isStatic())
486 if (tok->isCpp() && tok->astOperand1()->valueType()) {
488 if (tok->astOperand1()->valueType()->typeScope) {
489 const std::string op =
"operator" + tok->str();
490 const std::list<Function>& fList = tok->astOperand1()->valueType()->typeScope->functionList;
492 return f.name() == op;
503 if (fwdAnalysis.
hasOperand(tok->astOperand2(), tok->astOperand1()))
508 if (tok->isAssignmentOp())
520 bool hasCase =
false;
521 for (
const Token *tok2 = tok; tok2 != nextAssign; tok2 = tok2->
next()) {
522 if (tok2->str() ==
"break" || tok2->str() ==
"return")
524 if (tok2->str() ==
"case") {
533 else if (isInitialization)
544 const std::list<const Token *> callstack = { tok1, tok2 };
546 "$symbol:" + var +
"\n"
555 "$symbol:" + var +
"\n"
556 "Variable '$symbol' is reassigned a value before the old one has been used if variable is no semaphore variable.\n"
557 "Variable '$symbol' is reassigned a value before the old one has been used. Make sure that this variable is not used like a semaphore in a threading environment before simplifying this code.",
CWE563,
Certainty::inconclusive);
560 "$symbol:" + var +
"\n"
568 "$symbol:" + var +
"\nRedundant initialization for '$symbol'. The initialized value is overwritten before it is read.",
577 "$symbol:" + var +
"\n"
578 "Variable '$symbol' is reassigned a value before the old one has been used. 'break;' missing?",
CWE563,
Certainty::normal);
601 logChecker(
"CheckOther::redundantBitwiseOperationInSwitch");
612 std::map<int, const Token*> varsWithBitsSet;
613 std::map<int, std::string> bitOperations;
616 if (tok2->str() ==
"{") {
620 if (
Token::Match(tok2->previous(),
")|else {") && tok2->link()) {
621 const Token* endOfConditional = tok2->
link();
622 for (
const Token* tok3 = tok2; tok3 != endOfConditional; tok3 = tok3->
next()) {
623 if (tok3->varId() != 0) {
624 varsWithBitsSet.erase(tok3->varId());
625 bitOperations.erase(tok3->varId());
627 varsWithBitsSet.clear();
628 bitOperations.clear();
631 tok2 = endOfConditional;
639 if (
Token::Match(tok2->previous(),
";|{|}|: %var% = %any% ;")) {
640 varsWithBitsSet.erase(tok2->varId());
641 bitOperations.erase(tok2->varId());
647 else if (
Token::Match(tok2->previous(),
";|{|}|: %var% %assign% %num% ;") &&
648 (tok2->strAt(1) ==
"|=" || tok2->strAt(1) ==
"&=") &&
650 const std::string bitOp = tok2->
strAt(1)[0] + tok2->strAt(2);
651 const std::map<int, const Token*>::const_iterator i2 = varsWithBitsSet.find(tok2->varId());
654 if (i2 == varsWithBitsSet.end()) {
655 varsWithBitsSet[tok2->varId()] = tok2;
656 bitOperations[tok2->varId()] = bitOp;
660 else if (bitOperations[tok2->varId()] == bitOp)
665 varsWithBitsSet.erase(tok2->varId());
666 bitOperations.erase(tok2->varId());
673 else if (
Token::Match(tok2->previous(),
";|{|}|: %var% = %name% %or%|& %num% ;") &&
674 tok2->varId() == tok2->tokAt(2)->varId()) {
675 const std::string bitOp = tok2->strAt(3) + tok2->strAt(4);
676 const std::map<int, const Token*>::const_iterator i2 = varsWithBitsSet.find(tok2->varId());
679 if (i2 == varsWithBitsSet.end()) {
680 varsWithBitsSet[tok2->varId()] = tok2;
681 bitOperations[tok2->varId()] = bitOp;
685 else if (bitOperations[tok2->varId()] == bitOp)
690 varsWithBitsSet.erase(tok2->varId());
691 bitOperations.erase(tok2->varId());
698 else if (tok2->varId() != 0 && tok2->strAt(1) !=
"|" && tok2->strAt(1) !=
"&") {
699 varsWithBitsSet.erase(tok2->varId());
700 bitOperations.erase(tok2->varId());
706 varsWithBitsSet.clear();
707 bitOperations.clear();
716 "redundantBitwiseOperationInSwitch",
717 "$symbol:" + varname +
"\n"
718 "Redundant bitwise operation on '$symbol' in 'switch' statement. 'break;' missing?");
730 logChecker(
"CheckOther::checkSuspiciousCaseInSwitch");
739 if (tok->str() ==
"case") {
740 const Token* finding =
nullptr;
741 for (
const Token* tok2 = tok->
next(); tok2; tok2 = tok2->
next()) {
742 if (tok2->str() ==
":")
747 if (tok2->str() ==
"?")
762 "Found suspicious case label in switch(). Operator '" + operatorString +
"' probably doesn't work as intended.\n"
763 "Using an operator like '" + operatorString +
"' in a case label is suspicious. Did you intend to use a bitwise operator, multiple case labels or if/else instead?",
CWE398,
Certainty::inconclusive);
781 logChecker(
"CheckOther::checkUnreachableCode");
787 const Token* secondBreak =
nullptr;
788 const Token* labelName =
nullptr;
792 secondBreak = tok->
tokAt(2);
793 else if (
Token::Match(tok,
"[;{}:] return|throw") && tok->next()->isKeyword()) {
797 for (
const Token *tok2 = tok->
next(); tok2; tok2 = tok2->
next()) {
798 if (tok2->str() ==
"(" || tok2->str() ==
"{")
800 if (tok2->str() ==
";") {
801 secondBreak = tok2->
next();
806 secondBreak = tok->
tokAt(3);
807 labelName = tok->
next();
809 if ((!tok->function() || (tok->function()->token != tok && tok->function()->tokenDef != tok)) && tok->linkAt(1)->strAt(1) !=
"{")
821 if (secondBreak && (printInconclusive || !
inconclusive)) {
825 }
else if (secondBreak->
str() ==
"break") {
826 if (tok->str() ==
"break")
833 }
else if (!
Token::Match(secondBreak,
"return|}|case|default") && secondBreak->
strAt(1) !=
":") {
836 bool labelInFollowingLoop =
false;
837 if (labelName &&
Token::Match(secondBreak,
"while|do|for")) {
840 for (
const Token *tokIter = scope2; tokIter != scope2->
link() && tokIter; tokIter = tokIter->next()) {
841 if (
Token::Match(tokIter,
"[;{}] %any% :") && labelName->
str() == tokIter->strAt(1)) {
842 labelInFollowingLoop =
true;
850 bool silencedCompilerWarningOnly =
false;
851 const Token *silencedWarning = secondBreak;
853 if (
Token::Match(silencedWarning,
"( void ) %name% ;")) {
854 silencedWarning = silencedWarning->
tokAt(5);
857 if (silencedWarning && silencedWarning == scope->
bodyEnd)
858 silencedCompilerWarningOnly =
true;
862 secondBreak = silencedWarning;
864 if (!labelInFollowingLoop && !silencedCompilerWarningOnly)
867 }
else if (secondBreak->
scope() && secondBreak->
scope()->isLoopScope() && secondBreak->
str() ==
"}" && tok->str() ==
"continue") {
884 "Consecutive return, break, continue, goto or throw statements are unnecessary.\n"
885 "Consecutive return, break, continue, goto or throw statements are unnecessary. "
891 std::string msg =
"Statements following ";
893 msg +=
"noreturn function '" + noreturn->
str() +
"()'";
894 else if (noreturn && noreturn->
isKeyword())
895 msg +=
"'" + noreturn->
str() +
"'";
897 msg +=
"return, break, continue, goto or throw";
898 msg +=
" will never be executed.";
914 bool needsCheck = tok->
varId() > 0;
922 else if (tok->
str() ==
"[") {
955 if (!var || !var->isLocal() || var->isConst())
958 if (var->nameToken()->isExpandedMacro())
961 const bool isPtrOrRef = var->isPointer() || var->isReference();
962 const bool isSimpleType = var->typeStartToken()->isStandardType() || var->typeStartToken()->isEnumType() || (var->typeStartToken()->isC() && var->type() && var->type()->isStructType());
963 if (!isPtrOrRef && !isSimpleType && !
astIsContainer(var->nameToken()))
970 if (
Token::Match(var->nameToken()->previous(),
"& %var% = %var% .")) {
971 const Token *otherVarToken = var->nameToken()->
tokAt(2);
979 bool forHead =
false;
980 for (
const Token* tok = var->typeStartToken(); tok; tok = tok->
previous()) {
981 if (tok->str() ==
"(") {
991 const Token* tok = var->nameToken()->
next();
992 bool isConstructor =
false;
993 if (
Token::Match(tok,
"; %varid% =", var->declarationId())) {
999 isConstructor =
true;
1022 for (; tok && tok != var->
scope()->bodyEnd; tok = tok->
next()) {
1040 }
else if (tok->
varId() == var->declarationId() || tok->
str() ==
"goto") {
1055 bool noContinue =
true;
1056 const Token* forHeadEnd =
nullptr;
1059 loopVariable =
true;
1063 }
else if (loopVariable && tok->
strAt(-1) ==
")") {
1078 bool bFirstAssignment=
false;
1079 for (; tok && tok != end; tok = tok->
next()) {
1080 if (tok->
str() ==
"goto")
1082 if (tok->
str() ==
"continue")
1086 forHeadEnd = tok->
linkAt(1);
1087 if (tok == forHeadEnd)
1088 forHeadEnd =
nullptr;
1091 loopVariable =
false;
1094 range.first = range.first->next();
1096 return tok2->varId() == var->declarationId();
1100 loopVariable =
true;
1113 bFirstAssignment =
true;
1124 if (scope == tok->
scope()) {
1134 if (ftok->next()->astParent()) {
1138 if (!ret.empty() && ret.back() ==
'*')
1154 "$symbol:" + varname +
"\n"
1155 "The scope of the variable '$symbol' can be reduced.\n"
1156 "The scope of the variable '$symbol' can be reduced. Warning: Be careful "
1157 "when fixing this message, especially when there are inner loops. Here is an "
1158 "example where cppcheck will write that the scope for 'i' can be reduced:\n"
1163 " // it's safe to move 'int i = 0;' here\n"
1164 " for (int n = 0; n < 10; ++n) {\n"
1165 " // it is possible but not safe to move 'int i = 0;' here\n"
1166 " do_something(&i);\n"
1170 "When you see this message it is always safe to reduce the variable scope 1 level.",
CWE398,
Certainty::normal);
1185 if (tok->str() ==
"return") {
1187 while (tok && tok->str() !=
";") {
1191 if (!tok->isExpandedMacro() && tok->str() ==
"," && tok->linenr() != tok->next()->linenr())
1207 "commaSeparatedReturn",
1208 "Comma is used in return statement. The comma can easily be misread as a ';'.\n"
1209 "Comma is used in return statement. When comma is used in a return statement it can "
1210 "easily be misread as a semicolon. For example in the code below the value "
1211 "of 'b' is returned if the condition is true, but it is easy to think that 'a+1' is "
1216 "However it can be useful to use comma in macros. Cppcheck does not warn when such a "
1217 "macro is then used in a return statement, it is less likely such code is misunderstood.",
CWE398,
Certainty::normal);
1225 logChecker(
"CheckOther::checkPassByReference");
1230 if (!var || !var->isClass() || var->isPointer() || var->isArray() || var->isReference() || var->isEnumType())
1234 if (!var->isArgument() && !isRangeBasedFor)
1237 if (!isRangeBasedFor && var->scope() && var->scope()->function->arg->link()->strAt(-1) ==
"...")
1240 const Token *
const varDeclEndToken = var->declEndToken();
1241 if ((varDeclEndToken && varDeclEndToken->
isExternC()) ||
1242 (var->scope() && var->scope()->function && var->scope()->function->tokenDef && var->scope()->function->tokenDef->isExternC()))
1247 const bool isContainer = var->valueType() && var->valueType()->type == ValueType::Type::CONTAINER && var->valueType()->container && !var->valueType()->container->view;
1249 if (var->type() && !var->type()->isEnumType()) {
1251 if (!var->type()->classScope)
1263 const bool isConst = var->isConst();
1270 if (!isRangeBasedFor && (!var->scope() || var->scope()->function->isImplicitlyVirtual()))
1281 std::string
id = isRangeBasedFor ?
"iterateByValue" :
"passedByValue";
1282 const std::string action = isRangeBasedFor ?
"declared as":
"passed by";
1283 const std::string type = isRangeBasedFor ?
"Range variable" :
"Function parameter";
1284 std::string msg =
"$symbol:" + (var ? var->
name() :
"") +
"\n" +
1285 type +
" '$symbol' should be " + action +
" const reference.";
1290 msg +=
" However it seems that '" + var->
scope()->
function->
name() +
"' is a callback function.";
1293 errorPath.emplace_back(var->
nameToken(), msg);
1294 if (isRangeBasedFor)
1295 msg +=
"\nVariable '$symbol' is used to iterate by value. It could be declared as a const reference which is usually faster and recommended in C++.";
1297 msg +=
"\nParameter '$symbol' is passed by value. It could be passed as a const reference which is usually faster and recommended in C++.";
1307 for (
const Token *tok = start; tok != end; tok = tok->
next()) {
1308 if (tok->varId() != varid)
1310 if (tok->astParent()) {
1334 logChecker(
"CheckOther::checkConstVariable");
1341 if (!var->isReference())
1343 if (var->isRValueReference())
1345 if (var->isPointer())
1349 const Scope* scope = var->scope();
1353 if (!
function && !scope->
isLocal())
1355 if (
function && var->isArgument()) {
1356 if (function->isImplicitlyVirtual() || function->templateDef)
1361 if (var->isGlobal())
1363 if (var->isStatic())
1365 if (var->isArray() && !var->isStlType())
1367 if (var->isEnumType())
1369 if (var->isVolatile())
1371 if (var->isMaybeUnused())
1373 if (var->nameToken()->isExpandedMacro())
1379 const bool hasFunction =
function !=
nullptr;
1381 const Scope* functionScope = scope;
1383 functionScope = functionScope->
nestedIn;
1384 }
while (functionScope && !(
function = functionScope->
function));
1388 if (std::any_of(returns.cbegin(), returns.cend(), [&](
const Token* retTok) {
1389 if (retTok->varId() == var->declarationId())
1391 while (retTok && retTok->isCast())
1392 retTok = retTok->astOperand2();
1393 while (Token::simpleMatch(retTok,
"."))
1394 retTok = retTok->astOperand2();
1395 if (Token::simpleMatch(retTok,
"&"))
1396 retTok = retTok->astOperand1();
1397 return ValueFlow::hasLifetimeToken(getParentLifetime(retTok), var->nameToken(), *mSettings);
1404 bool usedInAssignment =
false;
1405 for (
const Token* tok = var->nameToken(); tok != scope->
bodyEnd && tok !=
nullptr; tok = tok->
next()) {
1406 if (
Token::Match(tok,
"& %var% = %varid%", var->declarationId())) {
1407 const Variable* refvar = tok->next()->variable();
1409 usedInAssignment =
true;
1413 if (tok->isUnaryOp(
"&") &&
Token::Match(tok,
"& %varid%", var->declarationId())) {
1432 usedInAssignment =
true;
1436 const Variable* refvar = tok->astParent()->astOperand1()->variable();
1438 usedInAssignment =
true;
1443 if (usedInAssignment)
1457 start = start->
tokAt(3);
1462 struct CompareVariables {
1467 return fileA < fileB;
1471 return lineA < lineB;
1474 return columnA < columnB;
1489 std::set<const Variable*, CompareVariables> pointers, nonConstPointers;
1491 const Variable*
const var = tok->variable();
1497 if (tok == nameTok) {
1503 const ValueType*
const vt = tok->valueType();
1510 if (std::find(nonConstPointers.cbegin(), nonConstPointers.cend(), var) != nonConstPointers.cend())
1512 pointers.emplace(var);
1514 enum Deref { NONE, DEREF, MEMBER } deref = NONE;
1515 bool hasIncDec =
false;
1526 if (deref != NONE) {
1528 if (deref == MEMBER) {
1542 gparent = gparent ? gparent->
astParent() :
nullptr;
1551 bool takingRef =
false, nonConstPtrAssignment =
false;
1557 nonConstPtrAssignment =
true;
1558 if (!takingRef && !nonConstPtrAssignment)
1580 if (ftok->function()) {
1581 const bool isCastArg = parent->
isCast() && !ftok->function()->getOverloadedFunctions().empty();
1583 const Variable* argVar = ftok->function()->getArgumentVar(argn);
1602 nonConstPointers.emplace(var);
1604 for (
const Variable *p: pointers) {
1605 if (p->isArgument()) {
1606 if (!p->scope() || !p->scope()->function || p->scope()->function->isImplicitlyVirtual(
true) || p->scope()->function->hasVirtualSpecifier())
1608 if (p->isMaybeUnused())
1611 if (std::find(nonConstPointers.cbegin(), nonConstPointers.cend(), p) == nonConstPointers.cend()) {
1613 const int indirect = p->isArray() ? p->dimensions().size() : 1;
1616 if (p->typeStartToken() && p->typeStartToken()->isSimplifiedTypedef() && !(
Token::simpleMatch(p->typeEndToken(),
"*") && !p->typeEndToken()->isSimplifiedTypedef()))
1632 reportError(
nullptr,
Severity::style,
"constParameterCallback",
"Parameter 'x' can be declared with const, however it seems that 'f' is a callback function.");
1636 const std::string vartype(var->
isArgument() ?
"Parameter" :
"Variable");
1637 const std::string varname(var->
name());
1638 const std::string ptrRefArray = var->
isArray() ?
"const array" : (var->
isPointer() ?
"pointer to const" :
"reference to const");
1641 std::string
id =
"const" + vartype;
1642 std::string message =
"$symbol:" + varname +
"\n" + vartype +
" '$symbol' can be declared as " + ptrRefArray;
1643 errorPath.emplace_back(var->
nameToken(), message);
1644 if (var->
isArgument() &&
function &&
function->functionPointerUsage) {
1645 errorPath.emplace_front(function->functionPointerUsage,
"You might need to cast the function pointer here");
1647 message +=
". However it seems that '" +
function->name() +
"' is a callback function, if '$symbol' is declared with const you might also need to cast function pointer(s).";
1674 if (!tok->variable())
1676 if (!tok->variable()->isArray() && !tok->variable()->isPointer())
1689 v1 = tok->astOperand1()->getValueGE(0x80, *
mSettings);
1696 v1 = tok->astOperand2()->getValueGE(0x80, *
mSettings);
1716 "signedCharArrayIndex",
1717 "Signed 'char' type used as array index.\n"
1718 "Signed 'char' type used as array index. If the value "
1719 "can be greater than 127 there will be a buffer underflow "
1727 "unknownSignCharArrayIndex",
1728 "'char' type used as array index.\n"
1729 "'char' type used as array index. Values greater than 127 will be "
1738 "When using 'char' variables in bit operations, sign extension can generate unexpected results.\n"
1739 "When using 'char' variables in bit operations, sign extension can generate unexpected results. For example:\n"
1742 " if (i & 0x8000)\n"
1743 " printf(\"not expected\");\n"
1755 if (tok && tok->
varId())
1771 if (vartok && vartok->
variable() && vartok->
variable()->nameToken() == vartok)
1774 return isType(typetok, vartok && vartok->
varId() != 0);
1782 if (tok->
str() ==
".")
1788 return tok->
variable()->nameToken() != tok;
1801 if (tok->
varId() != 0)
1810 const Token* tok2 = tok;
1838 const Token* stream = lml;
1863 const Token *tok2 = tok;
1882 return tok->
astParent()->astOperand2() == tok;
1883 return tok->
astParent()->astOperand1() == tok;
1886 const Token* bracTok = tok;
1892 if (tok->
str() ==
"," && tok->
astParent()->isAssignmentOp())
1902 logChecker(
"CheckOther::checkIncompleteStatement");
1905 const Scope *scope = tok->scope();
1922 if (child->
tokType() == Token::Type::eIncDecOp)
1936 !(tok->isCpp() && tok->isCast() && !tok->astParent()) &&
1939 !(tok->str() ==
"," && tok->astParent() && tok->astParent()->isAssignmentOp()))
1948 if (tok->isCpp() && tok->str() ==
"&" && !(tok->astOperand1() && tok->astOperand1()->valueType() && tok->astOperand1()->valueType()->isIntegral()))
1959 const Token *valueTok = tok;
1960 while (valueTok && valueTok->
isCast())
1965 msg =
"Found suspicious equality comparison. Did you intend to assign a value instead?";
1967 msg =
"Found suspicious operator '" + tok->
str() +
"', result is not used.";
1969 msg =
"Unused variable value '" + tok->
str() +
"'";
1971 std::string typeStr(
"string");
1973 typeStr =
"numeric";
1977 typeStr =
"character";
1981 typeStr =
"enumerator";
1982 msg =
"Redundant code: Found a statement that begins with " + typeStr +
" constant.";
1985 msg =
"Redundant code: Found a statement that begins with " + type +
" constant.";
1986 else if (tok->
isCast() && tok->
tokType() == Token::Type::eExtendedOp) {
1987 msg =
"Redundant code: Found unused cast ";
1988 msg += valueTok ?
"of expression '" + valueTok->
expressionString() +
"'." :
"expression.";
1990 else if (tok->
str() ==
"?" && tok->
tokType() == Token::Type::eExtendedOp)
1991 msg =
"Redundant code: Found unused result of ternary operator.";
1992 else if (tok->
str() ==
"." && tok->
tokType() == Token::Type::eOther)
1993 msg =
"Redundant code: Found unused member access.";
1994 else if (tok->
str() ==
"[" && tok->
tokType() == Token::Type::eExtendedOp)
1995 msg =
"Redundant code: Found unused array access.";
2011 if (!tok->astOperand2() || !tok->astOperand1())
2013 if (tok->str() !=
"%" && tok->str() !=
"/" && tok->str() !=
"%=" && tok->str() !=
"/=")
2015 if (!tok->valueType() || !tok->valueType()->isIntegral())
2017 if (tok->scope() && tok->scope()->type ==
Scope::eEnum)
2029 if (!tok && !value) {
2037 std::ostringstream errmsg;
2039 const int line = tok ? tok->
linenr() : 0;
2041 <<
" or there is division by zero at line " << line <<
".";
2043 errmsg <<
"Division by zero.";
2047 value->
condition ?
"zerodivcond" :
"zerodiv",
2060 logChecker(
"CheckOther::checkNanInArithmeticExpression");
2062 if (tok->str() !=
"/")
2074 "Using NaN/Inf in a computation.\n"
2075 "Using NaN/Inf in a computation. "
2091 logChecker(
"CheckOther::checkMisusedScopedObject");
2093 auto getConstructorTok = [](
const Token* tok, std::string& typeStr) ->
const Token* {
2099 typeStr += tok->
str();
2101 tok = tok->
tokAt(2);
2103 typeStr += tok->
str();
2104 const Token* endTok = tok;
2106 endTok = endTok->
linkAt(1);
2114 auto isLibraryConstructor = [&](
const Token* tok,
const std::string& typeStr) ->
bool {
2122 std::string typeStr;
2125 const Token* ctorTok = getConstructorTok(tok, typeStr);
2128 && ctorTok->
str() !=
"void") || isLibraryConstructor(tok->
next(), typeStr))) {
2131 parTok = parTok->
link()->next();
2135 if (parTok->
str() ==
"(") {
2136 if (arg->varId() && !(arg->variable() && arg->variable()->nameToken() != arg))
2159 std::string msg =
"Instance of '$symbol' object is destroyed immediately";
2160 msg += isAssignment ?
", assignment has no effect." :
".";
2162 "unusedScopedObject",
2163 "$symbol:" + varname +
"\n" +
2197 logChecker(
"CheckOther::checkDuplicateBranch");
2211 if (tok->isExpandedMacro()) {
2223 const std::string tokIfStr = tokIf->
stringify(
false,
true,
false);
2224 if (tokIfStr.empty())
2227 const std::string tokElseStr = tokElse->
stringify(
false,
true,
false);
2229 if (tokIfStr == tokElseStr) {
2233 if (branch1.empty())
2240 if (branch1 == branch2) {
2253 if (branchTop1->
str() != branchTop2->
str())
2265 errors.emplace_back(tok2,
"");
2266 errors.emplace_back(tok1,
"");
2269 "Finding the same code in an 'if' and related 'else' branch is suspicious and "
2270 "might indicate a cut and paste or logic error. Please examine this code "
2283 std::map<int, std::string> allocation;
2293 if ((tok->isCpp() &&
Token::Match(tok,
"%var% = new")) ||
2295 allocation.insert(std::make_pair(tok->varId(), tok->strAt(2)));
2296 inconclusive.insert(std::make_pair(tok->varId(),
false));
2303 tok->varId() == tok->tokAt(2)->varId() &&
2304 allocation.find(tok->varId()) != allocation.end()) {
2305 if (printInconclusive)
2308 allocation.erase(tok->varId());
2316 allocation.erase(tok->varId());
2326 const int varIndex = tok->strAt(1) ==
"(" ? 2 :
2327 tok->strAt(3) ==
"(" ? 4 : 1;
2328 const int var1 = tok->tokAt(varIndex)->varId();
2329 const int var2 = tok->tokAt(varIndex + 2)->varId();
2330 const std::map<int, bool>::const_iterator alloc1 =
inconclusive.find(var1);
2331 const std::map<int, bool>::const_iterator alloc2 =
inconclusive.find(var2);
2344 while (tok2 !=
nullptr) {
2345 allocation.erase(tok->varId());
2356 std::string alloc = allocation;
2359 std::string deallocated = (alloc ==
"new") ?
"deleted" :
"freed";
2371 bool notconst(
const Function* func)
2376 void getConstFunctions(
const SymbolDatabase *symbolDatabase, std::list<const Function*> &constFunctions)
2381 using StringFunctionMap = std::map<std::string, std::list<const Function*>>;
2382 StringFunctionMap functionsByName;
2384 functionsByName[func.
tokenDef->
str()].push_back(&func);
2386 for (std::pair<
const std::string, std::list<const Function*>>& it : functionsByName) {
2387 const std::list<const Function*>::const_iterator nc = std::find_if(it.second.cbegin(), it.second.cend(), notconst);
2388 if (nc == it.second.cend()) {
2390 constFunctions.splice(constFunctions.end(), it.second);
2409 if (!styleEnabled && !premiumEnabled)
2413 logChecker(
"CheckOther::checkDuplicateExpression");
2418 std::list<const Function*> constFunctions;
2419 getConstFunctions(symbolDatabase, constFunctions);
2423 if (tok->str() ==
"=" &&
Token::Match(tok->astOperand1(),
"%var%")) {
2426 endStatement = endStatement->
tokAt(4);
2429 const Token * nextAssign = endStatement->
tokAt(1);
2440 tok->astOperand2()->isArithmeticalOp() ||
2441 tok->astOperand2()->str() ==
"." ||
2442 Token::Match(tok->astOperand2()->previous(),
"%name% (")
2447 tok->astOperand2()->expressionString() == nextAssign->
astOperand2()->expressionString()) {
2448 bool differentDomain =
false;
2453 if (!assignTok->astOperand1())
2455 if (!assignTok->astOperand2())
2458 if (assignTok->astOperand1()->varId() != var1->
varId() &&
2459 assignTok->astOperand1()->varId() != var2->
varId() &&
2462 assignTok->astOperand1(),
2467 if (assignTok->astOperand2()->varId() != var1->
varId() &&
2468 assignTok->astOperand2()->varId() != var2->
varId() &&
2471 assignTok->astOperand2(),
2476 differentDomain =
true;
2486 auto isInsideLambdaCaptureList = [](
const Token* tok) {
2493 if (tok->isOp() && tok->astOperand1() && !
Token::Match(tok,
"+|*|<<|>>|+=|*=|<<=|>>=") && !isInsideLambdaCaptureList(tok)) {
2496 const bool pointerDereference = (tok->astOperand1() && tok->astOperand1()->isUnaryOp(
"*")) ||
2497 (tok->astOperand2() && tok->astOperand2()->isUnaryOp(
"*"));
2510 const bool isEnum = tok->scope()->type ==
Scope::eEnum;
2511 const bool assignment = !isEnum && tok->str() ==
"=";
2531 tok->astOperand2()->astOperand1(),
2548 if (tok->astOperand2() && tok->str() == tok->astOperand1()->str() &&
2551 tok->astOperand1()->astOperand2(),
2559 auto checkDuplicate = [&](
const Token* exp1,
const Token* exp2,
const Token* ast1) {
2566 while (ast1 && tok->
str() == ast1->
str()) {
2567 checkDuplicate(ast1->
astOperand2(), tok->astOperand2(), ast1);
2569 checkDuplicate(ast1->
astOperand1(), tok->astOperand2(), ast1);
2574 }
else if (tok->astOperand1() && tok->astOperand2() && tok->str() ==
":" && tok->astParent() && tok->astParent()->str() ==
"?") {
2575 if (!tok->astOperand1()->values().empty() && !tok->astOperand2()->values().empty() &&
isEqualKnownValue(tok->astOperand1(), tok->astOperand2()) &&
2588 errors.emplace_back(opTok,
"");
2590 const std::string& op = opTok ? opTok->
str() :
"&&";
2593 "Finding the opposite expression on both sides of an operator is suspicious and might "
2594 "indicate a cut and paste or logic error. Please examine this code carefully to "
2600 errors.emplace_back(opTok,
"");
2605 const std::string& op = opTok ? opTok->
str() :
"&&";
2606 std::string msg =
"Same expression " + (hasMultipleExpr ?
"\'" + expr1 +
"\'" +
" found multiple times in chain of \'" + op +
"\' operators" :
"on both sides of \'" + op +
"\'");
2607 const char *
id =
"duplicateExpression";
2608 if (expr1 != expr2 && (!opTok ||
Token::Match(opTok,
"%oror%|%comp%|&&|?|!"))) {
2609 id =
"knownConditionTrueFalse";
2610 std::string exprMsg =
"The comparison \'" + expr1 +
" " + op +
" " + expr2 +
"\' is always ";
2612 msg = exprMsg +
"true";
2614 msg = exprMsg +
"false";
2618 msg +=
" because '" + expr1 +
"' and '" + expr2 +
"' represent the same value";
2621 (std::string(
".\nFinding the same expression ") + (hasMultipleExpr ?
"more than once in a condition" :
"on both sides of an operator")) +
2622 " is suspicious and might indicate a cut and paste or logic error. Please examine this code carefully to "
2628 const std::list<const Token *> toks = { tok2, tok1 };
2630 const std::string& var1 = tok1 ? tok1->
str() :
"x";
2631 const std::string& var2 = tok2 ? tok2->
str() :
"x";
2634 "Same expression used in consecutive assignments of '" + var1 +
"' and '" + var2 +
"'.\n"
2635 "Finding variables '" + var1 +
"' and '" + var2 +
"' that are assigned the same expression "
2636 "is suspicious and might indicate a cut and paste or logic error. Please examine this code carefully to "
2642 errors.emplace_back(tok,
"");
2644 "Finding the same expression in both branches of ternary operator is suspicious as "
2651 "Finding the same value in both branches of ternary operator is suspicious as "
2659 "$symbol:" + varname +
"\n"
2677 logChecker(
"CheckOther::checkComparisonFunctionIsAlwaysTrueOrFalse");
2682 if (tok->isName() &&
Token::Match(tok,
"isgreater|isless|islessgreater|isgreaterequal|islessequal ( %var% , %var% )")) {
2683 const int varidLeft = tok->tokAt(2)->varId();
2684 const int varidRight = tok->tokAt(4)->varId();
2687 if (varidLeft == varidRight) {
2688 const std::string& functionName = tok->str();
2689 const std::string& varNameLeft = tok->strAt(2);
2690 if (functionName ==
"isgreater" || functionName ==
"isless" || functionName ==
"islessgreater") {
2708 "$symbol:" + functionName +
"\n"
2709 "Comparison of two identical variables with $symbol(" + varName +
"," + varName +
") always evaluates to " + strResult +
".\n"
2710 "The function $symbol is designed to compare two variables. Calling this function with one variable (" + varName +
") "
2711 "for both parameters leads to a statement which is always " + strResult +
".", cweResult,
Certainty::normal);
2722 logChecker(
"CheckOther::checkSignOfUnsignedVariable");
2730 const Token *nonZeroExpr =
nullptr;
2767 if (var->typeStartToken()->isTemplateArg())
2799 "$symbol:" + varname +
"\n"
2800 "Checking if unsigned expression '$symbol' is less than zero.\n"
2801 "The unsigned expression '$symbol' will never be negative so it "
2808 "A pointer can not be negative so it is either pointless or an error to check if it is.",
CWE570,
Certainty::normal);
2814 "$symbol:" + varname +
"\n"
2815 "Unsigned expression '$symbol' can't be negative so it is unnecessary to test it.",
CWE570,
Certainty::normal);
2821 "A pointer can not be negative so it is either pointless or an error to check if it is not.",
CWE570,
Certainty::normal);
2828 if (constructor.isConstructor()) {
2829 for (int argnr = 0U; argnr < constructor.argCount(); argnr++) {
2830 const Variable * const argVar = constructor.getArgumentVar(argnr);
2831 if (argVar && argVar->isReference()) {
2849 logChecker(
"CheckOther::checkRedundantCopy");
2854 if (!var || var->isReference() || var->isPointer() ||
2855 (!var->type() && !var->isStlType()) ||
2859 const Token* startTok = var->nameToken();
2860 if (startTok->
strAt(1) ==
"=")
2862 else if (
Token::Match(startTok->
next(),
"(|{") && var->isClass() && var->typeScope()) {
2867 startTok = startTok->
tokAt(2);
2906 "$symbol:" + varname +
"\n"
2907 "Use const reference for '$symbol' to avoid unnecessary data copying.\n"
2908 "The const variable '$symbol' is assigned a copy of the data. You can avoid "
2909 "the unnecessary data copying by converting '$symbol' to const reference.",
2927 logChecker(
"CheckOther::checkNegativeBitwiseShift");
2930 if (!tok->astOperand1() || !tok->astOperand2())
2938 const ValueType * lhsType = tok->astOperand1()->valueType();
2944 bool ternary =
false;
2945 for (
const Token *parent = tok; parent; parent = parent->
astParent()) {
2983 if (!printPortability && !printWarning)
2986 logChecker(
"CheckOther::checkIncompleteArrayFill");
2994 if (tok2->
str() ==
"::")
2995 tok2 = tok2->
next();
2997 tok2 = tok2->
tokAt(2);
3012 if ((size != 1 && size != 100 && size != 0) || var->
isPointer()) {
3015 }
else if (var->
valueType()->
type == ValueType::Type::BOOL && printPortability)
3027 "$symbol:" + buffer +
"\n"
3028 "$symbol:" +
function +
"\n"
3029 "Array '" + buffer +
"' might be filled incompletely. Did you forget to multiply the size given to '" +
function +
"()' with 'sizeof(*" + buffer +
")'?\n"
3030 "The array '" + buffer +
"' is filled incompletely. The function '" +
function +
"()' needs the size given in bytes, but the type 'bool' is larger than 1 on some platforms. Did you forget to multiply the size with 'sizeof(*" + buffer +
")'?",
CWE131,
Certainty::inconclusive);
3033 "$symbol:" + buffer +
"\n"
3034 "$symbol:" +
function +
"\n"
3035 "Array '" + buffer +
"' is filled incompletely. Did you forget to multiply the size given to '" +
function +
"()' with 'sizeof(*" + buffer +
")'?\n"
3036 "The array '" + buffer +
"' is filled incompletely. The function '" +
function +
"()' needs the size given in bytes, but an element of the given array is larger than one byte. Did you forget to multiply the size with 'sizeof(*" + buffer +
")'?",
CWE131,
Certainty::inconclusive);
3048 logChecker(
"CheckOther::checkVarFuncNullUB");
3056 const Token *ftok = tok;
3058 while (ftok && ftok->
str() !=
"(") {
3059 if (ftok->
str() ==
")")
3060 ftok = ftok->
link();
3061 else if (ftok->
str() ==
",")
3065 ftok = ftok ? ftok->
previous() :
nullptr;
3066 if (ftok && ftok->
isName()) {
3071 tok2 = tok2 ? tok2->
link() :
nullptr;
3086 "Passing NULL after the last typed argument to a variadic function leads to undefined behaviour.\n"
3087 "Passing NULL after the last typed argument to a variadic function leads to undefined behaviour.\n"
3088 "The C99 standard, in section 7.15.1.1, states that if the type used by va_arg() is not compatible with the type of the actual next argument (as promoted according to the default argument promotions), the behavior is undefined.\n"
3089 "The value of the NULL macro is an implementation-defined null pointer constant (7.17), which can be any integer constant expression with the value 0, or such an expression casted to (void*) (6.3.2.3). This includes values like 0, 0L, or even 0LL.\n"
3090 "In practice on common architectures, this will cause real crashes if sizeof(int) != sizeof(void*), and NULL is defined to 0 or any other null pointer constant that promotes to int.\n"
3091 "To reproduce you might be able to use this little code example on 64bit platforms. If the output includes \"ERROR\", the sentinel had only 4 out of 8 bytes initialized to zero and was not detected as the final argument to stop argument processing via va_arg(). Changing the 0 to (void*)0 or 0L will make the \"ERROR\" output go away.\n"
3092 "#include <stdarg.h>\n"
3093 "#include <stdio.h>\n"
3095 "void f(char *s, ...) {\n"
3097 " va_start(ap,s);\n"
3099 " char *p = va_arg(ap,char*);\n"
3100 " printf(\"%018p, %s\\n\", p, (long)p & 255 ? p : \"\");\n"
3107 " char *s2 = \"x\";\n"
3108 " char *s3 = \"ERROR\";\n"
3110 " // changing 0 to 0L for the 7th argument (which is intended to act as sentinel) makes the error go away on x86_64\n"
3111 " f(\"first\", s2, s2, s2, s2, s2, 0, s3, (char*)0);\n"
3116 " volatile unsigned char a[1000];\n"
3117 " for (i = 0; i<sizeof(a); i++)\n"
3133 logChecker(
"CheckOther::checkRedundantPointerOp");
3136 if (tok->isExpandedMacro() && tok->str() ==
"(")
3139 bool addressOfDeref{};
3140 if (tok->isUnaryOp(
"&") && tok->astOperand1()->isUnaryOp(
"*"))
3141 addressOfDeref =
true;
3142 else if (tok->isUnaryOp(
"*") && tok->astOperand1()->isUnaryOp(
"&"))
3143 addressOfDeref =
false;
3152 if (!addressOfDeref) {
3153 if (tok->isExpandedMacro())
3160 if (!var || (addressOfDeref && !var->
isPointer()))
3169 std::string msg =
"$symbol:" + varname +
"\nRedundant pointer operation on '$symbol' - it's already a ";
3170 msg += addressOfDeref ?
"pointer." :
"variable.";
3180 logChecker(
"CheckOther::checkInterlockedDecrement");
3183 if (tok->isName() &&
Token::Match(tok,
"InterlockedDecrement ( & %name% ) ; if ( %name%|!|0")) {
3184 const Token* interlockedVarTok = tok->
tokAt(3);
3185 const Token* checkStartTok = interlockedVarTok->
tokAt(5);
3186 if ((
Token::Match(checkStartTok,
"0 %comp% %name% )") && checkStartTok->
strAt(2) == interlockedVarTok->
str()) ||
3187 (
Token::Match(checkStartTok,
"! %name% )") && checkStartTok->
strAt(1) == interlockedVarTok->
str()) ||
3188 (
Token::Match(checkStartTok,
"%name% )") && checkStartTok->
str() == interlockedVarTok->
str()) ||
3189 (
Token::Match(checkStartTok,
"%name% %comp% 0 )") && checkStartTok->
str() == interlockedVarTok->
str())) {
3192 }
else if (
Token::Match(tok,
"if ( ::| InterlockedDecrement ( & %name%")) {
3195 const Token* firstAccessTok = funcTok->
str() ==
"::" ? funcTok->
tokAt(4) : funcTok->
tokAt(3);
3196 if (condEnd && condEnd->
next() && condEnd->
next()->
link()) {
3199 const Token* secondAccessTok = ifEndTok->
tokAt(2);
3200 if (secondAccessTok->
str() == firstAccessTok->
str()) {
3203 }
else if (
Token::Match(ifEndTok,
"} else { return %name%")) {
3204 const Token* secondAccessTok = ifEndTok->
tokAt(4);
3205 if (secondAccessTok->
str() == firstAccessTok->
str()) {
3217 "Race condition: non-interlocked access after InterlockedDecrement(). Use InterlockedDecrement() return value instead.",
CWE362,
Certainty::normal);
3231 if (!tok->scope()->isExecutable())
3232 tok = tok->scope()->bodyEnd;
3234 if (
Token::Match(tok,
"{|}|; %name% :") && !tok->tokAt(1)->isKeyword()) {
3235 const std::string tmp(
"goto " + tok->strAt(1));
3248 std::string
id =
"unusedLabel";
3252 id +=
"Configuration";
3254 std::string msg =
"$symbol:" + (tok ? tok->
str() :
emptyString) +
"\nLabel '$symbol' is not used.";
3256 msg +=
" There is #if in function body so the label might be used in code that is removed by the preprocessor.";
3258 msg +=
" Should this be a 'case' of the enclosing switch()?";
3275 logChecker(
"CheckOther::checkEvaluationOrder");
3282 if (!tok->astOperand1())
3291 if (parent->
str() ==
",") {
3292 const Token *par = parent;
3303 while (par && (par->
previous() != parent))
3313 tok->str() ==
"=" &&
3314 parent->
str() ==
"=" &&
3323 bool foundError =
false;
3325 [&](
const Token *tok3) {
3326 if (tok3->str() ==
"&" && !tok3->astOperand2())
3327 return ChildrenToVisit::none;
3328 if (tok3->str() ==
"(" && Token::simpleMatch(tok3->previous(),
"sizeof"))
3329 return ChildrenToVisit::none;
3330 if (isSameExpression(false, tok->astOperand1(), tok3, *mSettings, true, false))
3332 return foundError ? ChildrenToVisit::done : ChildrenToVisit::op1_and_op2;
3356 logChecker(
"CheckOther::checkAccessOfMovedVariable");
3363 if (memberInitializationStart)
3364 scopeStart = memberInitializationStart;
3367 if (!tok->astParent())
3376 bool accessOfMoved =
false;
3377 if (tok->strAt(1) ==
".") {
3378 if (tok->next()->originalName() ==
"->")
3379 accessOfMoved =
true;
3385 accessOfMoved =
true;
3391 if (accessOfMoved || (
inconclusive && reportInconclusive))
3405 const char * errorId =
nullptr;
3406 std::string kindString;
3409 errorId =
"accessMoved";
3410 kindString =
"moved";
3413 errorId =
"accessForwarded";
3414 kindString =
"forwarded";
3419 const std::string errmsg(
"$symbol:" + varname +
"\nAccess of " + kindString +
" variable '$symbol'.");
3435 logChecker(
"CheckOther::checkFuncArgNamesDifferent");
3442 if (!
function || function->argCount() == 0)
3446 if (function->argDef == function->arg)
3450 std::vector<const Token *> declarations(function->argCount());
3451 std::vector<const Token *> definitions(function->argCount());
3452 const Token * decl =
function->argDef->
next();
3453 for (
int j = 0; j <
function->argCount(); ++j) {
3454 declarations[j] =
nullptr;
3455 definitions[j] =
nullptr;
3457 const Variable * variable =
function->getArgumentVar(j);
3466 if (decl->
str() ==
"=") {
3472 decl = decl->
link();
3473 else if (decl->
varId())
3474 declarations[j] = decl;
3475 decl = decl->
next();
3478 decl = decl->
next();
3482 bool order_different =
false;
3483 for (
int j = 0; j <
function->argCount(); ++j) {
3484 if (!declarations[j] || !definitions[j] || declarations[j]->str() == definitions[j]->str())
3487 for (
int k = 0; k <
function->argCount(); ++k) {
3488 if (j != k && definitions[k] && declarations[j]->str() == definitions[k]->str()) {
3489 order_different =
true;
3494 if (order_different) {
3495 funcArgOrderDifferent(function->name(), function->argDef->next(), function->arg->next(), declarations, definitions);
3501 for (
int j = 0; j <
function->argCount(); ++j) {
3502 if (declarations[j] && definitions[j] && declarations[j]->str() != definitions[j]->str())
3510 const Token* declaration,
const Token* definition)
3512 std::list<const Token *> tokens = { declaration,definition };
3514 "$symbol:" + functionName +
"\n"
3515 "Function '$symbol' argument " + std::to_string(index + 1) +
" names different: declaration '" +
3516 (declaration ? declaration->
str() : std::string(
"A")) +
"' definition '" +
3521 const Token* declaration,
const Token* definition,
3522 const std::vector<const Token *> & declarations,
3523 const std::vector<const Token *> & definitions)
3525 std::list<const Token *> tokens = {
3526 !declarations.empty() ? declarations[0] ? declarations[0] : declaration :
nullptr,
3527 !definitions.empty() ? definitions[0] ? definitions[0] : definition :
nullptr
3529 std::string msg =
"$symbol:" + functionName +
"\nFunction '$symbol' argument order different: declaration '";
3530 for (
int i = 0; i < declarations.size(); ++i) {
3533 if (declarations[i])
3534 msg += declarations[i]->
str();
3536 msg +=
"' definition '";
3537 for (
int i = 0; i < definitions.size(); ++i) {
3541 msg += definitions[i]->str();
3558 return f.type == Function::Type::eFunction && f.name() == var.name() && precedes(f.tokenDef, var.nameToken());
3561 return it->tokenDef;
3575 logChecker(
"CheckOther::checkShadowVariables");
3580 const Scope *functionScope = &scope;
3581 while (functionScope && functionScope->
type != Scope::ScopeType::eFunction && functionScope->
type != Scope::ScopeType::eLambda)
3582 functionScope = functionScope->
nestedIn;
3587 if (functionScope && functionScope->
type == Scope::ScopeType::eFunction && functionScope->
function) {
3589 auto it = std::find_if(argList.cbegin(), argList.cend(), [&](
const Variable& arg) {
3590 return arg.nameToken() && var.name() == arg.name();
3592 if (it != argList.end()) {
3616 errorPath.emplace_back(shadowed,
"Shadowed declaration");
3617 errorPath.emplace_back(var,
"Shadow variable");
3618 const std::string &varname = var ? var->
str() : type;
3619 const std::string
Type = char(std::toupper(type[0])) + type.substr(1);
3620 const std::string
id =
"shadow" +
Type;
3621 const std::string message =
"$symbol:" + varname +
"\nLocal variable \'$symbol\' shadows outer " + type;
3627 if (tok->
varId() != 0)
3656 logChecker(
"CheckOther::checkKnownArgument");
3660 if (!tok->hasKnownIntValue())
3666 if (tok->astParent()->isCast() || (tok->isCast() &&
Token::Match(tok->astOperand2(),
"++|--|%assign%")))
3676 if (tok == tok->astParent()->previous())
3682 const Token * tok2 = tok;
3687 if (tok->isComparisonOp() &&
3689 true, tok->astOperand1(), tok->astOperand2(), *
mSettings,
true,
true))
3692 const Token* vartok =
nullptr;
3699 return ChildrenToVisit::done;
3708 return Token::simpleMatch(child,
"sizeof");
3712 std::string funcname = ftok->
str();
3714 if (funcname.find(
"assert") != std::string::npos)
3724 reportError(tok,
Severity::style,
"knownArgument",
"Argument 'x-x' to function 'func' is always 0. It does not matter what value 'x' has.");
3725 reportError(tok,
Severity::style,
"knownArgumentHiddenVariableExpression",
"Argument 'x*0' to function 'func' is always 0. Constant literal calculation disable/hide variable expression 'x'.");
3731 const std::string &fun = ftok->
str();
3733 std::string ftype =
"function ";
3735 ftype =
"constructor ";
3736 else if (fun ==
"{")
3737 ftype =
"init list ";
3740 std::string errmsg =
"Argument '" + expr +
"' to " + ftype + fun +
" is always " + std::to_string(intvalue) +
". ";
3741 if (!isVariableExpressionHidden) {
3742 id =
"knownArgument";
3743 errmsg +=
"It does not matter what value '" + varexpr +
"' has.";
3745 id =
"knownArgumentHiddenVariableExpression";
3746 errmsg +=
"Constant literal calculation disable/hide variable expression '" + varexpr +
"'.";
3757 logChecker(
"CheckOther::checkKnownPointerToBool");
3761 if (!tok->hasKnownIntValue())
3765 if (
Token::Match(tok->astParent(),
"?|!|&&|%oror%|%comp%"))
3767 if (tok->astParent() &&
Token::Match(tok->astParent()->previous(),
"if|while|switch|sizeof ("))
3769 if (tok->isExpandedMacro())
3791 std::string errmsg =
"Pointer expression '" + expr +
"' converted to bool is always " + cond +
".";
3798 logChecker(
"CheckOther::checkComparePointers");
3823 if (var1 == parent2->variable())
3826 if (var2 == parent1->variable())
3836 std::string verb =
"Comparing";
3838 verb =
"Subtracting";
3839 const char *
const id = (verb[0] ==
'C') ?
"comparePointers" :
"subtractPointers";
3841 errorPath.emplace_back(v1->
tokvalue->
variable()->nameToken(),
"Variable declared here.");
3845 errorPath.emplace_back(v2->
tokvalue->
variable()->nameToken(),
"Variable declared here.");
3848 errorPath.emplace_back(tok,
"");
3861 if (!tok->astOperand2() || !tok->astOperand1())
3863 if (tok->str() !=
"%")
3865 if (!tok->valueType() || !tok->valueType()->isIntegral())
3870 if (value && value->
isKnown())
3887 const Token *bufToken, *offsetToken;
3895 const bool pointer1 = (expr->
astOperand1()->valueType() && expr->
astOperand1()->valueType()->pointer > 0);
3896 const bool pointer2 = (expr->
astOperand2()->valueType() && expr->
astOperand2()->valueType()->pointer > 0);
3897 if (pointer1 && !pointer2) {
3903 }
else if (!pointer1 && pointer2) {
3918 if (elementSize > 0) {
3919 *offset *= elementSize;
3921 *sizeValue *= elementSize;
3933 if (elementSize > 0) {
3934 *offset *= elementSize;
3936 *sizeValue *= elementSize;
3943 logChecker(
"CheckOther::checkOverlappingWrite");
3947 if (tok->isAssignmentOp()) {
3960 const Token *errorToken =
nullptr;
3961 visitAstNodes(tok->astOperand2(), [lhsvar, lhsmember, &errorToken](
const Token *rhs) {
3962 if (!Token::simpleMatch(rhs,
"."))
3963 return ChildrenToVisit::op1_and_op2;
3964 if (!rhs->isBinaryOp() || rhs->astOperand1()->variable() != lhsvar)
3965 return ChildrenToVisit::none;
3966 if (lhsmember->str() == rhs->astOperand2()->str())
3967 return ChildrenToVisit::none;
3968 const Variable* rhsmembervar = rhs->astOperand2()->variable();
3969 const Scope* varscope1 = lhsmember->variable() ? lhsmember->variable()->typeStartToken()->scope() : nullptr;
3970 const Scope* varscope2 = rhsmembervar ? rhsmembervar->typeStartToken()->scope() : nullptr;
3971 if (varscope1 && varscope1 == varscope2 && varscope1 != lhsvar->typeScope())
3973 return ChildrenToVisit::none;
3974 errorToken = rhs->astOperand2();
3975 return ChildrenToVisit::done;
3981 if (!nonOverlappingData)
3983 const std::vector<const Token *> args =
getArguments(tok);
3984 if (nonOverlappingData->
ptr1Arg <= 0 || nonOverlappingData->
ptr1Arg > args.size())
3986 if (nonOverlappingData->
ptr2Arg <= 0 || nonOverlappingData->
ptr2Arg > args.size())
3989 const Token *ptr1 = args[nonOverlappingData->
ptr1Arg - 1];
3993 const Token *ptr2 = args[nonOverlappingData->
ptr2Arg - 1];
3998 const int sizeArg = std::max(nonOverlappingData->
sizeArg, nonOverlappingData->
countArg);
3999 if (sizeArg <= 0 || sizeArg > args.size()) {
4000 if (nonOverlappingData->
sizeArg == -1) {
4002 constexpr
bool macro =
true;
4003 constexpr
bool pure =
true;
4004 constexpr
bool follow =
true;
4011 const bool isCountArg = nonOverlappingData->
countArg > 0;
4012 if (!args[sizeArg-1]->hasKnownIntValue())
4015 const Token *buf1, *buf2;
4022 if (offset1 < offset2 && offset1 + sizeValue <= offset2)
4024 if (offset2 < offset1 && offset2 + sizeValue <= offset1)
4028 constexpr
bool macro =
true;
4029 constexpr
bool pure =
true;
4030 constexpr
bool follow =
true;
4047 reportError(tok,
Severity::error,
"overlappingWriteFunction",
"Overlapping read/write in " + funcname +
"() is undefined behavior");
bool astIsContainer(const Token *tok)
std::vector< const Token * > getArguments(const Token *ftok)
Get arguments (AST)
bool isOppositeExpression(const Token *const tok1, const Token *const tok2, const Settings &settings, bool pure, bool followVar, ErrorPath *errors)
bool isSameExpression(bool macro, const Token *tok1, const Token *tok2, const Settings &settings, bool pure, bool followVar, ErrorPath *errors)
bool astIsIntegral(const Token *tok, bool unknown)
Is expression of integral type?
bool exprDependsOnThis(const Token *expr, bool onVar, nonneg int depth)
bool isTemporary(const Token *tok, const Library *library, bool unknown)
bool astIsRangeBasedForDecl(const Token *tok)
Is given token a range-declaration in a range-based for loop.
const Token * getTokenArgumentFunction(const Token *tok, int &argn)
Return the token to the function and the argument number.
bool isUsedAsBool(const Token *const tok, const Settings &settings)
Is token used as boolean, that is to say cast to a bool, or used as a condition in a if/while/for.
bool astIsPointer(const Token *tok)
const Token * isInLoopCondition(const Token *tok)
bool isUniqueExpression(const Token *tok)
const Token * findExpressionChanged(const Token *expr, const Token *start, const Token *end, const Settings &settings, int depth)
bool isStructuredBindingVariable(const Variable *var)
bool isLeafDot(const Token *tok)
bool isNullOperand(const Token *expr)
bool isWithinScope(const Token *tok, const Variable *var, Scope::ScopeType type)
Is tok within a scope of the given type, nested within var's scope?
bool astIsSignedChar(const Token *tok)
Is expression a 'signed char' if no promotion is used.
bool isConstVarExpression(const Token *tok, const std::function< bool(const Token *)> &skipPredicate)
bool isWithoutSideEffects(const Token *tok, bool checkArrayAccess, bool checkReference)
bool astIsFloat(const Token *tok, bool unknown)
Is expression of floating point type?
const Token * nextAfterAstRightmostLeaf(const Token *tok)
ExprUsage getExprUsage(const Token *tok, int indirect, const Settings &settings)
bool isVariableChangedByFunctionCall(const Token *tok, int indirect, nonneg int varid, const Settings &settings, bool *inconclusive)
Is variable changed by function call? In case the answer of the question is inconclusive,...
const Token * previousBeforeAstLeftmostLeaf(const Token *tok)
bool isCPPCast(const Token *tok)
bool isEqualKnownValue(const Token *const tok1, const Token *const tok2)
bool isConstExpression(const Token *tok, const Library &library)
const Token * getParentLifetime(const Token *tok)
bool isLikelyStream(const Token *stream)
bool astIsUnknownSignChar(const Token *tok)
Is expression a 'char' if no promotion is used?
bool succeeds(const Token *tok1, const Token *tok2)
If tok1 comes after tok2.
const Token * findExpression(const nonneg int exprid, const Token *start, const Token *end, const std::function< bool(const Token *)> &pred)
bool isVariableChanged(const Token *tok, int indirect, const Settings &settings, int depth)
void visitAstNodes(T *ast, const TFunc &visitor)
Visit AST nodes recursively.
const Token * findParent(const Token *tok, const TFunc &pred)
const Token * findAstNode(const Token *ast, const TFunc &pred)
static const CWE CWE571(571U)
static const Token * findShadowed(const Scope *scope, const Variable &var, int linenr)
static const CWE CWE362(362U)
static const CWE CWE563(563U)
static bool isVariableMutableInInitializer(const Token *start, const Token *end, nonneg int varid)
static const CWE CWE398(398U)
static const CWE CWE783(783U)
static bool isVariableExpression(const Token *tok)
static bool getBufAndOffset(const Token *expr, const Token *&buf, MathLib::bigint *offset, const Settings &settings, MathLib::bigint *sizeValue=nullptr)
static const CWE CWE475(475U)
static const CWE CWE369(369U)
static const CWE CWE704(704U)
static const CWE CWE768(768U)
static const CWE CWE758(758U)
static const CWE CWE570(570U)
static bool isConstStatement(const Token *tok, bool isNestedBracket=false)
static const Token * getSingleExpressionInBlock(const Token *tok)
static bool isFunctionOrBreakPattern(const Token *tok)
static bool isConstTop(const Token *tok)
static bool constructorTakesReference(const Scope *const classScope)
static bool isConstant(const Token *tok)
static const CWE CWE128(128U)
static const CWE CWE561(561U)
static const CWE CWE683(683U)
static bool isType(const Token *tok, bool unknown)
static bool isVoidStmt(const Token *tok)
static bool isSimpleExpr(const Token *tok, const Variable *var, const Settings &settings)
static const CWE CWE131(131U)
static bool isVarDeclOp(const Token *tok)
static bool isNegative(const Token *tok, const Settings &settings)
static const CWE CWE628(628U)
static bool isVariableExprHidden(const Token *tok)
static bool isBracketAccess(const Token *tok)
static const CWE CWE197(197U)
static const Token * getVariableChangedStart(const Variable *p)
static const CWE CWE672(672U)
void unknownEvaluationOrder(const Token *tok)
void cstyleCastError(const Token *tok, bool isPtr=true)
void redundantAssignmentError(const Token *tok1, const Token *tok2, const std::string &var, bool inconclusive)
void checkVariableScope()
Check scope of variables
void unknownSignCharArrayIndexError(const Token *tok)
void checkInterlockedDecrement()
Check for race condition with non-interlocked access after InterlockedDecrement()
static bool testIfNonZeroExpressionIsPositive(const Token *tok, const ValueFlow::Value *&zeroValue, const Token *&nonZeroExpr)
Is expression a comparison that checks if a nonzero (unsigned/pointer) expression is positive?
void clarifyCalculationError(const Token *tok, const std::string &op)
void signedCharArrayIndexError(const Token *tok)
void duplicateExpressionError(const Token *tok1, const Token *tok2, const Token *opTok, ErrorPath errors, bool hasMultipleExpr=false)
void warningOldStylePointerCast()
Are there C-style pointer casts in a c++ file?
void duplicateBranchError(const Token *tok1, const Token *tok2, ErrorPath errors)
void checkDuplicateExpression()
Check for suspicious code with the same expression on both sides of operator (e.g "if (a && a)")
void funcArgOrderDifferent(const std::string &functionName, const Token *declaration, const Token *definition, const std::vector< const Token * > &declarations, const std::vector< const Token * > &definitions)
void shadowError(const Token *var, const Token *shadowed, const std::string &type)
void funcArgNamesDifferent(const std::string &functionName, nonneg int index, const Token *declaration, const Token *definition)
void checkRedundantAssignment()
copying to memory or assigning to a variable twice
void unsignedPositiveError(const Token *tok, const ValueFlow::Value *v, const std::string &varname)
void checkCharVariable()
Using char variable as array index / as operand in bit operation.
void checkFuncArgNamesDifferent()
Check if function declaration and definition argument names different
void comparePointersError(const Token *tok, const ValueFlow::Value *v1, const ValueFlow::Value *v2)
void checkConstVariable()
void incompleteArrayFillError(const Token *tok, const std::string &buffer, const std::string &function, bool boolean)
void clarifyStatementError(const Token *tok)
void redundantContinueError(const Token *tok)
void checkEvaluationOrder()
Check for expression that depends on order of evaluation of side effects
void unsignedLessThanZeroError(const Token *tok, const ValueFlow::Value *v, const std::string &varname)
void checkCastIntToCharAndBackError(const Token *tok, const std::string &strFunctionName)
void unusedLabelError(const Token *tok, bool inSwitch, bool hasIfdef)
void checkKnownArgument()
void constStatementError(const Token *tok, const std::string &type, bool inconclusive)
void checkModuloOfOneError(const Token *tok)
void checkSuspiciousSemicolon()
Check for suspicious use of semicolon
void checkAccessOfMovedVariable()
Check for access of moved or forwarded variable
void varFuncNullUBError(const Token *tok)
void knownArgumentError(const Token *tok, const Token *ftok, const ValueFlow::Value *value, const std::string &varexpr, bool isVariableExpressionHidden)
void overlappingWriteUnion(const Token *tok)
void checkUnusedLabel()
Check for unused labels
void knownPointerToBoolError(const Token *tok, const ValueFlow::Value *value)
void pointerLessThanZeroError(const Token *tok, const ValueFlow::Value *v)
void pointerPositiveError(const Token *tok, const ValueFlow::Value *v)
void checkComparePointers()
void checkUnreachableCode()
Check for code that gets never executed, such as duplicate break statements
void redundantPointerOpError(const Token *tok, const std::string &varname, bool inconclusive, bool addressOfDeref)
void overlappingWriteFunction(const Token *tok)
void checkDuplicateBranch()
Check for suspicious code where if and else branch are the same (e.g "if (a) b = true; else b = true;...
void checkZeroDivision()
Check zero division
void selfAssignmentError(const Token *tok, const std::string &varname)
void oppositeExpressionError(const Token *opTok, ErrorPath errors)
void suspiciousCaseInSwitchError(const Token *tok, const std::string &operatorString)
void checkRedundantPointerOp()
Check for redundant pointer operations
void suspiciousSemicolonError(const Token *tok)
void checkIncompleteArrayFill()
Check for buffers that are filled incompletely with memset and similar functions
void duplicateBreakError(const Token *tok, bool inconclusive)
void zerodivError(const Token *tok, const ValueFlow::Value *value)
void checkComparisonFunctionIsAlwaysTrueOrFalseError(const Token *tok, const std::string &functionName, const std::string &varName, const bool result)
void invalidPointerCastError(const Token *tok, const std::string &from, const std::string &to, bool inconclusive, bool toIsInt)
void checkShadowVariables()
Check for shadow variables.
void checkComparisonFunctionIsAlwaysTrueOrFalse()
Check for using of comparison functions evaluating always to true or false.
void checkRedundantCopy()
Check for code creating redundant copies
void checkNegativeBitwiseShift()
Check for bitwise shift with negative right operand
void unreachableCodeError(const Token *tok, const Token *noreturn, bool inconclusive)
void redundantInitializationError(const Token *tok1, const Token *tok2, const std::string &var, bool inconclusive)
void duplicateAssignExpressionError(const Token *tok1, const Token *tok2, bool inconclusive)
void checkSignOfUnsignedVariable()
Check for testing sign of unsigned variable
void checkPassByReference()
Check for function parameters that should be passed by reference
void charBitOpError(const Token *tok)
void misusedScopeObjectError(const Token *tok, const std::string &varname, bool isAssignment=false)
void passedByValueError(const Variable *var, bool inconclusive, bool isRangeBasedFor=false)
void checkSuspiciousCaseInSwitch()
Check for code like 'case A||B:'
void clarifyStatement()
Suspicious statement like '*A++;'.
void accessMovedError(const Token *tok, const std::string &varname, const ValueFlow::Value *value, bool inconclusive)
void checkCastIntToCharAndBack()
Check to avoid casting a return value to unsigned char and then back to integer type.
void checkCommaSeparatedReturn()
Check for comma separated statements in return
void checkNanInArithmeticExpression()
Check for NaN (not-a-number) in an arithmetic expression.
void invalidFreeError(const Token *tok, const std::string &allocation, bool inconclusive)
void checkKnownPointerToBool()
void checkOverlappingWrite()
void checkVarFuncNullUB()
Check that variadic function calls don't use NULL.
void duplicateValueTernaryError(const Token *tok)
void checkMisusedScopedObject()
Check for objects that are destroyed immediately
void nanInArithmeticExpressionError(const Token *tok)
bool checkInnerScope(const Token *tok, const Variable *var, bool &used) const
void redundantAssignmentInSwitchError(const Token *tok1, const Token *tok2, const std::string &var)
void commaSeparatedReturnError(const Token *tok)
void raceAfterInterlockedDecrementError(const Token *tok)
void invalidPointerCast()
Check for pointer casts to a type with an incompatible binary data representation.
void variableScopeError(const Token *tok, const std::string &varname)
void negativeBitwiseShiftError(const Token *tok, int op)
void clarifyCalculation()
Clarify calculation for ".. a * b ? ..".
void constVariableError(const Variable *var, const Function *function)
void checkInvalidFree()
Check for free() operations on invalid memory locations
static bool comparisonNonZeroExpressionLessThanZero(const Token *tok, const ValueFlow::Value *&zeroValue, const Token *&nonZeroExpr, bool suppress=false)
Is expression a comparison that checks if a nonzero (unsigned/pointer) expression is less than zero?
void redundantBitwiseOperationInSwitchError()
Check for redundant bitwise operation in switch statement
void checkIncompleteStatement()
Incomplete statement.
void duplicateExpressionTernaryError(const Token *tok, ErrorPath errors)
void redundantCopyError(const Token *tok1, const Token *tok2, const std::string &var)
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 std::vector< const Token * > findReturns(const Function *f)
const std::string & name() const
const Token * functionPointerUsage
function pointer usage
const Token * argDef
function argument start '(' in class definition
const Scope * functionScope
scope of function body
static bool returnsConst(const Function *function, bool unknown=false)
static bool returnsPointer(const Function *function, bool unknown=false)
static bool returnsReference(const Function *function, bool unknown=false, bool includeRValueRef=false)
nonneg int argCount() const
const Token * constructorMemberInitialization() const
const Token * tokenDef
function name token in class definition
std::list< Variable > argumentList
argument list, must remain list due to clangimport usage!
bool isConstructor() const
Forward data flow analysis for checks.
bool hasOperand(const Token *tok, const Token *lhs) const
const Token * reassign(const Token *expr, const Token *startToken, const Token *endToken)
Check if "expr" is reassigned.
const Container * detectContainerOrIterator(const Token *typeStart, bool *isIterator=nullptr, bool withoutStd=false) const
ArgumentChecks::Direction getArgDirection(const Token *ftok, int argnr) const
const NonOverlappingData * getNonOverlappingData(const Token *ftok) const
bool isnoreturn(const Token *ftok) const
const AllocFunc * getAllocFuncInfo(const Token *tok) const
get allocation info for function
TypeCheck getTypeCheck(std::string check, std::string typeName) const
TypeCheck
Suppress/check a type.
const AllocFunc * getDeallocFuncInfo(const Token *tok) const
get deallocation info for function
const std::string & returnValueType(const Token *ftok) const
bool isFunctionConst(const std::string &functionName, bool pure) const
static bigint toBigNumber(const std::string &str)
for conversion of numeric literals - for atoi-like conversions please use strToInt()
static bool isNullValue(const std::string &str)
Does the string represent the numerical value of 0? In case leading or trailing white space is provid...
std::list< Function > functionList
std::list< Variable > varlist
std::vector< Scope * > nestedList
Function * function
function info for this function
const Token * classDef
class/struct/union/namespace token
const Token * bodyStart
'{' token
const Token * bodyEnd
'}' token
const Scope * functionOf
scope this function belongs to
bool isClassOrStructOrUnion() const
bool isExecutable() const
This is just a container for general settings so that we don't need to pass individual values to func...
bool isEnabled(const ValueFlow::Value *value, bool inconclusiveCheck=false) const
Returns true if given value can be shown.
bool isPremiumEnabled(const char id[]) const
Is checker id enabled by premiumArgs.
bool daca
Are we running from DACA script?
SimpleEnableGroup< Certainty > certainty
SimpleEnableGroup< Severity > severity
bool debugwarnings
Is –debug-warnings given?
Standards standards
Struct contains standards settings.
bool isEnabled(T flag) const
const std::vector< const Variable * > & variableList() const
std::vector< const Scope * > functionScopes
Fast access to function scopes.
std::list< Scope > scopeList
Information about all namespaces/classes/structures.
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.
bool isSimplifiedScope() const
nonneg int exprId() const
bool isEnumerator() const
static const Token * findmatch(const Token *const startTok, const char pattern[], const nonneg int varId=0)
std::string stringify(const stringifyOptions &options) const
bool hasKnownIntValue() const
MathLib::bigint getKnownIntValue() const
bool isExpandedMacro() const
bool isTemplateArg() const
Is current token a template argument?
bool isArithmeticalOp() const
std::string stringifyList(const stringifyOptions &options, const std::vector< std::string > *fileNames=nullptr, const Token *end=nullptr) const
const ValueType * valueType() const
const std::string & strAt(int index) const
void astOperand1(Token *tok)
bool isCalculation() const
Is current token a calculation? Only true for operands.
void function(const Function *f)
Associate this token with given function.
std::pair< const Token *, const Token * > findExpressionStartEndTokens() const
std::string expressionString() const
bool isUnaryOp(const std::string &s) const
const ValueFlow::Value * getValueGE(const MathLib::bigint val, const Settings &settings) 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 type(const ::Type *t)
Associate this token with given type.
bool isAssignmentOp() const
bool isSplittedVarDeclEq() const
const ValueFlow::Value * getValueLE(const MathLib::bigint val, const Settings &settings) const
nonneg int linenr() const
bool isStandardType() const
void variable(const Variable *v)
Associate this token with given variable.
bool isComparisonOp() const
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.
nonneg int fileIndex() const
nonneg int column() const
void astParent(Token *tok)
nonneg int sizeOfType(const Token *type) const
Calculates sizeof value for given type.
const Token * tokens() const
bool isC() const
Is the code C.
const SymbolDatabase * getSymbolDatabase() const
bool isCPP() const
Is the code CPP.
bool hasIfdef(const Token *start, const Token *end) const
Information about a class type.
bool errorSeverity() const
const Token * condition
Condition that this value depends on.
const Token * tokvalue
token value - the token that has the value.
long long intvalue
int value (or sometimes bool value?)
bool isLocalLifetimeValue() const
enum ValueFlow::Value::MoveKind moveKind
bool isInconclusive() const
enum ValueType::Type type
const Library::Container * container
If the type is a container defined in a cfg file, this is the used.
bool isConst(nonneg int indirect=0) const
nonneg int constness
bit 0=data, bit 1=*, bit 2=**
Reference reference
Is the outermost indirection of this type a reference or rvalue.
nonneg int pointer
0=>not pointer, 1=>*, 2=>**, 3=>***, etc
std::string originalTypeName
original type name as written in the source code.
enum ValueType::Sign sign
Information about a member variable.
bool isArgument() const
Is variable a function argument.
bool isClass() const
Is variable a user defined (or unknown) type.
bool isArrayOrPointer() const
Is array or pointer variable.
bool isReference() const
Is reference variable.
bool isRValueReference() const
Is reference variable.
bool isLocal() const
Is variable local.
const Scope * scope() const
Get Scope pointer of enclosing scope.
const Scope * typeScope() const
Get Scope pointer of known type.
const std::string & name() const
Get name string.
const Token * typeEndToken() const
Get type end token.
bool isConst() const
Is variable const.
MathLib::bigint dimension(nonneg int index_) const
Get array dimension length.
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).
const Token * typeStartToken() const
Get type start token.
bool isInit() const
Is variable initialized in its declaration.
const std::vector< Dimension > & dimensions() const
Get array dimensions.
bool isPointer() const
Is pointer variable.
bool isStatic() const
Is variable static.
const ValueType * valueType() const
static const std::string emptyString
std::pair< const Token *, std::string > ErrorPathItem
std::list< ErrorPathItem > ErrorPath
@ portability
Portability warning.
@ performance
Performance warning.
@ error
Programming error.
std::string eitherTheConditionIsRedundant(const Token *condition)
CPPCHECKLIB Value getLifetimeObjValue(const Token *tok, bool inconclusive=false)
size_t getSizeOf(const ValueType &vt, const Settings &settings, int maxRecursion=0)
static constexpr char CWE[]
@ DIR_IN
Input to called function. Data is treated as read-only.
enum Standards::cppstd_t cpp
const Token * isLambdaCaptureList(const Token *tok)
void strTolower(std::string &str)
static const char * bool_to_string(bool b)