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)) {
430 logChecker(
"CheckOther::checkRedundantAssignment");
442 tok = tok->linkAt(1);
443 if ((tok->isAssignmentOp() || tok->tokType() ==
Token::eIncDecOp) && tok->astOperand1()) {
444 if (tok->astParent())
449 bool isInitialization =
false;
450 if (
Token::Match(tok->tokAt(-2),
"; %var% =") && tok->tokAt(-2)->isSplittedVarDeclEq()) {
451 isInitialization =
true;
454 [&](
const Token *rhs) {
455 if (Token::simpleMatch(rhs,
"{ 0 }"))
456 return ChildrenToVisit::none;
457 if (Token::Match(rhs,
"%str%|%num%|%name%") && !rhs->varId())
458 return ChildrenToVisit::none;
459 if (Token::Match(rhs,
":: %name%") && rhs->hasKnownIntValue())
460 return ChildrenToVisit::none;
462 return ChildrenToVisit::op2;
464 return ChildrenToVisit::done;
475 if (tok->astOperand1()->variable() && tok->astOperand1()->variable()->isReference())
479 if (tok->astOperand1()->variable() && tok->astOperand1()->variable()->isStatic())
484 if (tok->isCpp() && tok->astOperand1()->valueType()) {
486 if (tok->astOperand1()->valueType()->typeScope) {
487 const std::string op =
"operator" + tok->str();
488 const std::list<Function>& fList = tok->astOperand1()->valueType()->typeScope->functionList;
490 return f.name() == op;
501 if (fwdAnalysis.
hasOperand(tok->astOperand2(), tok->astOperand1()))
506 if (tok->isAssignmentOp())
518 bool hasCase =
false;
519 for (
const Token *tok2 = tok; tok2 != nextAssign; tok2 = tok2->
next()) {
520 if (tok2->str() ==
"break" || tok2->str() ==
"return")
522 if (tok2->str() ==
"case") {
531 else if (isInitialization)
542 const std::list<const Token *> callstack = { tok1, tok2 };
544 "$symbol:" + var +
"\n"
553 "$symbol:" + var +
"\n"
554 "Variable '$symbol' is reassigned a value before the old one has been used if variable is no semaphore variable.\n"
555 "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);
558 "$symbol:" + var +
"\n"
566 "$symbol:" + var +
"\nRedundant initialization for '$symbol'. The initialized value is overwritten before it is read.",
575 "$symbol:" + var +
"\n"
576 "Variable '$symbol' is reassigned a value before the old one has been used. 'break;' missing?",
CWE563,
Certainty::normal);
599 logChecker(
"CheckOther::redundantBitwiseOperationInSwitch");
610 std::map<int, const Token*> varsWithBitsSet;
611 std::map<int, std::string> bitOperations;
614 if (tok2->str() ==
"{") {
618 if (
Token::Match(tok2->previous(),
")|else {") && tok2->link()) {
619 const Token* endOfConditional = tok2->
link();
620 for (
const Token* tok3 = tok2; tok3 != endOfConditional; tok3 = tok3->
next()) {
621 if (tok3->varId() != 0) {
622 varsWithBitsSet.erase(tok3->varId());
623 bitOperations.erase(tok3->varId());
625 varsWithBitsSet.clear();
626 bitOperations.clear();
629 tok2 = endOfConditional;
637 if (
Token::Match(tok2->previous(),
";|{|}|: %var% = %any% ;")) {
638 varsWithBitsSet.erase(tok2->varId());
639 bitOperations.erase(tok2->varId());
645 else if (
Token::Match(tok2->previous(),
";|{|}|: %var% %assign% %num% ;") &&
646 (tok2->strAt(1) ==
"|=" || tok2->strAt(1) ==
"&=") &&
648 const std::string bitOp = tok2->
strAt(1)[0] + tok2->strAt(2);
649 const std::map<int, const Token*>::const_iterator i2 = varsWithBitsSet.find(tok2->varId());
652 if (i2 == varsWithBitsSet.end()) {
653 varsWithBitsSet[tok2->varId()] = tok2;
654 bitOperations[tok2->varId()] = bitOp;
658 else if (bitOperations[tok2->varId()] == bitOp)
663 varsWithBitsSet.erase(tok2->varId());
664 bitOperations.erase(tok2->varId());
671 else if (
Token::Match(tok2->previous(),
";|{|}|: %var% = %name% %or%|& %num% ;") &&
672 tok2->varId() == tok2->tokAt(2)->varId()) {
673 const std::string bitOp = tok2->strAt(3) + tok2->strAt(4);
674 const std::map<int, const Token*>::const_iterator i2 = varsWithBitsSet.find(tok2->varId());
677 if (i2 == varsWithBitsSet.end()) {
678 varsWithBitsSet[tok2->varId()] = tok2;
679 bitOperations[tok2->varId()] = bitOp;
683 else if (bitOperations[tok2->varId()] == bitOp)
688 varsWithBitsSet.erase(tok2->varId());
689 bitOperations.erase(tok2->varId());
696 else if (tok2->varId() != 0 && tok2->strAt(1) !=
"|" && tok2->strAt(1) !=
"&") {
697 varsWithBitsSet.erase(tok2->varId());
698 bitOperations.erase(tok2->varId());
704 varsWithBitsSet.clear();
705 bitOperations.clear();
714 "redundantBitwiseOperationInSwitch",
715 "$symbol:" + varname +
"\n"
716 "Redundant bitwise operation on '$symbol' in 'switch' statement. 'break;' missing?");
728 logChecker(
"CheckOther::checkSuspiciousCaseInSwitch");
737 if (tok->str() ==
"case") {
738 const Token* finding =
nullptr;
739 for (
const Token* tok2 = tok->
next(); tok2; tok2 = tok2->
next()) {
740 if (tok2->str() ==
":")
745 if (tok2->str() ==
"?")
760 "Found suspicious case label in switch(). Operator '" + operatorString +
"' probably doesn't work as intended.\n"
761 "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);
779 logChecker(
"CheckOther::checkUnreachableCode");
785 const Token* secondBreak =
nullptr;
786 const Token* labelName =
nullptr;
790 secondBreak = tok->
tokAt(2);
791 else if (
Token::Match(tok,
"[;{}:] return|throw") && tok->next()->isKeyword()) {
795 for (
const Token *tok2 = tok->
next(); tok2; tok2 = tok2->
next()) {
796 if (tok2->str() ==
"(" || tok2->str() ==
"{")
798 if (tok2->str() ==
";") {
799 secondBreak = tok2->
next();
804 secondBreak = tok->
tokAt(3);
805 labelName = tok->
next();
807 if ((!tok->function() || (tok->function()->token != tok && tok->function()->tokenDef != tok)) && tok->linkAt(1)->strAt(1) !=
"{")
819 if (secondBreak && (printInconclusive || !
inconclusive)) {
823 }
else if (secondBreak->
str() ==
"break") {
824 if (tok->str() ==
"break")
831 }
else if (!
Token::Match(secondBreak,
"return|}|case|default") && secondBreak->
strAt(1) !=
":") {
834 bool labelInFollowingLoop =
false;
835 if (labelName &&
Token::Match(secondBreak,
"while|do|for")) {
838 for (
const Token *tokIter = scope2; tokIter != scope2->
link() && tokIter; tokIter = tokIter->next()) {
839 if (
Token::Match(tokIter,
"[;{}] %any% :") && labelName->
str() == tokIter->strAt(1)) {
840 labelInFollowingLoop =
true;
848 bool silencedCompilerWarningOnly =
false;
849 const Token *silencedWarning = secondBreak;
851 if (
Token::Match(silencedWarning,
"( void ) %name% ;")) {
852 silencedWarning = silencedWarning->
tokAt(5);
855 if (silencedWarning && silencedWarning == scope->
bodyEnd)
856 silencedCompilerWarningOnly =
true;
860 secondBreak = silencedWarning;
862 if (!labelInFollowingLoop && !silencedCompilerWarningOnly)
865 }
else if (secondBreak->
scope() && secondBreak->
scope()->isLoopScope() && secondBreak->
str() ==
"}" && tok->str() ==
"continue") {
882 "Consecutive return, break, continue, goto or throw statements are unnecessary.\n"
883 "Consecutive return, break, continue, goto or throw statements are unnecessary. "
889 std::string msg =
"Statements following ";
891 msg +=
"noreturn function '" + noreturn->
str() +
"()'";
892 else if (noreturn && noreturn->
isKeyword())
893 msg +=
"'" + noreturn->
str() +
"'";
895 msg +=
"return, break, continue, goto or throw";
896 msg +=
" will never be executed.";
912 bool needsCheck = tok->
varId() > 0;
920 else if (tok->
str() ==
"[") {
953 if (!var || !var->isLocal() || var->isConst())
956 if (var->nameToken()->isExpandedMacro())
959 const bool isPtrOrRef = var->isPointer() || var->isReference();
960 const bool isSimpleType = var->typeStartToken()->isStandardType() || var->typeStartToken()->isEnumType() || (var->typeStartToken()->isC() && var->type() && var->type()->isStructType());
961 if (!isPtrOrRef && !isSimpleType && !
astIsContainer(var->nameToken()))
968 if (
Token::Match(var->nameToken()->previous(),
"& %var% = %var% .")) {
969 const Token *otherVarToken = var->nameToken()->
tokAt(2);
977 bool forHead =
false;
978 for (
const Token* tok = var->typeStartToken(); tok; tok = tok->
previous()) {
979 if (tok->str() ==
"(") {
989 const Token* tok = var->nameToken()->
next();
990 bool isConstructor =
false;
991 if (
Token::Match(tok,
"; %varid% =", var->declarationId())) {
997 isConstructor =
true;
1020 for (; tok && tok != var->
scope()->bodyEnd; tok = tok->
next()) {
1038 }
else if (tok->
varId() == var->declarationId() || tok->
str() ==
"goto") {
1053 bool noContinue =
true;
1054 const Token* forHeadEnd =
nullptr;
1057 loopVariable =
true;
1061 }
else if (loopVariable && tok->
strAt(-1) ==
")") {
1076 bool bFirstAssignment=
false;
1077 for (; tok && tok != end; tok = tok->
next()) {
1078 if (tok->
str() ==
"goto")
1080 if (tok->
str() ==
"continue")
1084 forHeadEnd = tok->
linkAt(1);
1085 if (tok == forHeadEnd)
1086 forHeadEnd =
nullptr;
1089 loopVariable =
false;
1092 range.first = range.first->next();
1094 return tok2->varId() == var->declarationId();
1098 loopVariable =
true;
1111 bFirstAssignment =
true;
1122 if (scope == tok->
scope()) {
1132 if (ftok->next()->astParent()) {
1136 if (!ret.empty() && ret.back() ==
'*')
1152 "$symbol:" + varname +
"\n"
1153 "The scope of the variable '$symbol' can be reduced.\n"
1154 "The scope of the variable '$symbol' can be reduced. Warning: Be careful "
1155 "when fixing this message, especially when there are inner loops. Here is an "
1156 "example where cppcheck will write that the scope for 'i' can be reduced:\n"
1161 " // it's safe to move 'int i = 0;' here\n"
1162 " for (int n = 0; n < 10; ++n) {\n"
1163 " // it is possible but not safe to move 'int i = 0;' here\n"
1164 " do_something(&i);\n"
1168 "When you see this message it is always safe to reduce the variable scope 1 level.",
CWE398,
Certainty::normal);
1183 if (tok->str() ==
"return") {
1185 while (tok && tok->str() !=
";") {
1189 if (!tok->isExpandedMacro() && tok->str() ==
"," && tok->linenr() != tok->next()->linenr())
1205 "commaSeparatedReturn",
1206 "Comma is used in return statement. The comma can easily be misread as a ';'.\n"
1207 "Comma is used in return statement. When comma is used in a return statement it can "
1208 "easily be misread as a semicolon. For example in the code below the value "
1209 "of 'b' is returned if the condition is true, but it is easy to think that 'a+1' is "
1214 "However it can be useful to use comma in macros. Cppcheck does not warn when such a "
1215 "macro is then used in a return statement, it is less likely such code is misunderstood.",
CWE398,
Certainty::normal);
1223 logChecker(
"CheckOther::checkPassByReference");
1228 if (!var || !var->isClass() || var->isPointer() || var->isArray() || var->isReference() || var->isEnumType())
1232 if (!var->isArgument() && !isRangeBasedFor)
1235 if (!isRangeBasedFor && var->scope() && var->scope()->function->arg->link()->strAt(-1) ==
"...")
1238 const Token *
const varDeclEndToken = var->declEndToken();
1239 if ((varDeclEndToken && varDeclEndToken->
isExternC()) ||
1240 (var->scope() && var->scope()->function && var->scope()->function->tokenDef && var->scope()->function->tokenDef->isExternC()))
1245 const bool isContainer = var->valueType() && var->valueType()->type == ValueType::Type::CONTAINER && var->valueType()->container && !var->valueType()->container->view;
1247 if (var->type() && !var->type()->isEnumType()) {
1249 if (!var->type()->classScope)
1261 const bool isConst = var->isConst();
1268 if (!isRangeBasedFor && (!var->scope() || var->scope()->function->isImplicitlyVirtual()))
1279 std::string
id = isRangeBasedFor ?
"iterateByValue" :
"passedByValue";
1280 const std::string action = isRangeBasedFor ?
"declared as":
"passed by";
1281 const std::string type = isRangeBasedFor ?
"Range variable" :
"Function parameter";
1282 std::string msg =
"$symbol:" + (var ? var->
name() :
"") +
"\n" +
1283 type +
" '$symbol' should be " + action +
" const reference.";
1288 msg +=
" However it seems that '" + var->
scope()->
function->
name() +
"' is a callback function.";
1291 errorPath.emplace_back(var->
nameToken(), msg);
1292 if (isRangeBasedFor)
1293 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++.";
1295 msg +=
"\nParameter '$symbol' is passed by value. It could be passed as a const reference which is usually faster and recommended in C++.";
1305 for (
const Token *tok = start; tok != end; tok = tok->
next()) {
1306 if (tok->varId() != varid)
1308 if (tok->astParent()) {
1337 if (!var->isReference())
1339 if (var->isRValueReference())
1341 if (var->isPointer())
1345 const Scope* scope = var->scope();
1349 if (!
function && !scope->
isLocal())
1351 if (
function && var->isArgument()) {
1352 if (function->isImplicitlyVirtual() || function->templateDef)
1357 if (var->isGlobal())
1359 if (var->isStatic())
1361 if (var->isArray() && !var->isStlType())
1363 if (var->isEnumType())
1365 if (var->isVolatile())
1367 if (var->isMaybeUnused())
1369 if (var->nameToken()->isExpandedMacro())
1375 const bool hasFunction =
function !=
nullptr;
1377 const Scope* functionScope = scope;
1379 functionScope = functionScope->
nestedIn;
1380 }
while (functionScope && !(
function = functionScope->
function));
1384 if (std::any_of(returns.cbegin(), returns.cend(), [&](
const Token* retTok) {
1385 if (retTok->varId() == var->declarationId())
1387 while (retTok && retTok->isCast())
1388 retTok = retTok->astOperand2();
1389 while (Token::simpleMatch(retTok,
"."))
1390 retTok = retTok->astOperand2();
1391 if (Token::simpleMatch(retTok,
"&"))
1392 retTok = retTok->astOperand1();
1393 return ValueFlow::hasLifetimeToken(getParentLifetime(retTok), var->nameToken(), *mSettings);
1400 bool usedInAssignment =
false;
1401 for (
const Token* tok = var->nameToken(); tok != scope->
bodyEnd && tok !=
nullptr; tok = tok->
next()) {
1402 if (
Token::Match(tok,
"& %var% = %varid%", var->declarationId())) {
1403 const Variable* refvar = tok->next()->variable();
1405 usedInAssignment =
true;
1409 if (tok->isUnaryOp(
"&") &&
Token::Match(tok,
"& %varid%", var->declarationId())) {
1428 usedInAssignment =
true;
1432 const Variable* refvar = tok->astParent()->astOperand1()->variable();
1434 usedInAssignment =
true;
1439 if (usedInAssignment)
1453 start = start->
tokAt(3);
1458 struct CompareVariables {
1463 return fileA < fileB;
1467 return lineA < lineB;
1470 return columnA < columnB;
1484 std::set<const Variable*, CompareVariables> pointers, nonConstPointers;
1486 const Variable*
const var = tok->variable();
1492 if (tok == nameTok) {
1498 const ValueType*
const vt = tok->valueType();
1505 if (std::find(nonConstPointers.cbegin(), nonConstPointers.cend(), var) != nonConstPointers.cend())
1507 pointers.emplace(var);
1509 enum Deref { NONE, DEREF, MEMBER } deref = NONE;
1510 bool hasIncDec =
false;
1521 if (deref != NONE) {
1523 if (deref == MEMBER) {
1537 gparent = gparent ? gparent->
astParent() :
nullptr;
1546 bool takingRef =
false, nonConstPtrAssignment =
false;
1552 nonConstPtrAssignment =
true;
1553 if (!takingRef && !nonConstPtrAssignment)
1575 if (ftok->function()) {
1576 const bool isCastArg = parent->
isCast() && !ftok->function()->getOverloadedFunctions().empty();
1578 const Variable* argVar = ftok->function()->getArgumentVar(argn);
1597 nonConstPointers.emplace(var);
1599 for (
const Variable *p: pointers) {
1600 if (p->isArgument()) {
1601 if (!p->scope() || !p->scope()->function || p->scope()->function->isImplicitlyVirtual(
true) || p->scope()->function->hasVirtualSpecifier())
1603 if (p->isMaybeUnused())
1606 if (std::find(nonConstPointers.cbegin(), nonConstPointers.cend(), p) == nonConstPointers.cend()) {
1608 const int indirect = p->isArray() ? p->dimensions().size() : 1;
1611 if (p->typeStartToken() && p->typeStartToken()->isSimplifiedTypedef() && !(
Token::simpleMatch(p->typeEndToken(),
"*") && !p->typeEndToken()->isSimplifiedTypedef()))
1627 reportError(
nullptr,
Severity::style,
"constParameterCallback",
"Parameter 'x' can be declared with const, however it seems that 'f' is a callback function.");
1631 const std::string vartype(var->
isArgument() ?
"Parameter" :
"Variable");
1632 const std::string varname(var->
name());
1633 const std::string ptrRefArray = var->
isArray() ?
"const array" : (var->
isPointer() ?
"pointer to const" :
"reference to const");
1636 std::string
id =
"const" + vartype;
1637 std::string message =
"$symbol:" + varname +
"\n" + vartype +
" '$symbol' can be declared as " + ptrRefArray;
1638 errorPath.emplace_back(var->
nameToken(), message);
1639 if (var->
isArgument() &&
function &&
function->functionPointerUsage) {
1640 errorPath.emplace_front(function->functionPointerUsage,
"You might need to cast the function pointer here");
1642 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).";
1669 if (!tok->variable())
1671 if (!tok->variable()->isArray() && !tok->variable()->isPointer())
1684 v1 = tok->astOperand1()->getValueGE(0x80, *
mSettings);
1691 v1 = tok->astOperand2()->getValueGE(0x80, *
mSettings);
1711 "signedCharArrayIndex",
1712 "Signed 'char' type used as array index.\n"
1713 "Signed 'char' type used as array index. If the value "
1714 "can be greater than 127 there will be a buffer underflow "
1722 "unknownSignCharArrayIndex",
1723 "'char' type used as array index.\n"
1724 "'char' type used as array index. Values greater than 127 will be "
1733 "When using 'char' variables in bit operations, sign extension can generate unexpected results.\n"
1734 "When using 'char' variables in bit operations, sign extension can generate unexpected results. For example:\n"
1737 " if (i & 0x8000)\n"
1738 " printf(\"not expected\");\n"
1750 if (tok && tok->
varId())
1766 if (vartok && vartok->
variable() && vartok->
variable()->nameToken() == vartok)
1769 return isType(typetok, vartok && vartok->
varId() != 0);
1777 if (tok->
str() ==
".")
1783 return tok->
variable()->nameToken() != tok;
1796 if (tok->
varId() != 0)
1805 const Token* tok2 = tok;
1833 const Token* stream = lml;
1858 const Token *tok2 = tok;
1877 return tok->
astParent()->astOperand2() == tok;
1878 return tok->
astParent()->astOperand1() == tok;
1881 const Token* bracTok = tok;
1887 if (tok->
str() ==
"," && tok->
astParent()->isAssignmentOp())
1897 logChecker(
"CheckOther::checkIncompleteStatement");
1900 const Scope *scope = tok->scope();
1917 if (child->
tokType() == Token::Type::eIncDecOp)
1931 !(tok->isCpp() && tok->isCast() && !tok->astParent()) &&
1934 !(tok->str() ==
"," && tok->astParent() && tok->astParent()->isAssignmentOp()))
1943 if (tok->isCpp() && tok->str() ==
"&" && !(tok->astOperand1() && tok->astOperand1()->valueType() && tok->astOperand1()->valueType()->isIntegral()))
1954 const Token *valueTok = tok;
1955 while (valueTok && valueTok->
isCast())
1960 msg =
"Found suspicious equality comparison. Did you intend to assign a value instead?";
1962 msg =
"Found suspicious operator '" + tok->
str() +
"', result is not used.";
1964 msg =
"Unused variable value '" + tok->
str() +
"'";
1966 std::string typeStr(
"string");
1968 typeStr =
"numeric";
1972 typeStr =
"character";
1976 typeStr =
"enumerator";
1977 msg =
"Redundant code: Found a statement that begins with " + typeStr +
" constant.";
1980 msg =
"Redundant code: Found a statement that begins with " + type +
" constant.";
1981 else if (tok->
isCast() && tok->
tokType() == Token::Type::eExtendedOp) {
1982 msg =
"Redundant code: Found unused cast ";
1983 msg += valueTok ?
"of expression '" + valueTok->
expressionString() +
"'." :
"expression.";
1985 else if (tok->
str() ==
"?" && tok->
tokType() == Token::Type::eExtendedOp)
1986 msg =
"Redundant code: Found unused result of ternary operator.";
1987 else if (tok->
str() ==
"." && tok->
tokType() == Token::Type::eOther)
1988 msg =
"Redundant code: Found unused member access.";
1989 else if (tok->
str() ==
"[" && tok->
tokType() == Token::Type::eExtendedOp)
1990 msg =
"Redundant code: Found unused array access.";
2006 if (!tok->astOperand2() || !tok->astOperand1())
2008 if (tok->str() !=
"%" && tok->str() !=
"/" && tok->str() !=
"%=" && tok->str() !=
"/=")
2010 if (!tok->valueType() || !tok->valueType()->isIntegral())
2012 if (tok->scope() && tok->scope()->type ==
Scope::eEnum)
2024 if (!tok && !value) {
2032 std::ostringstream errmsg;
2034 const int line = tok ? tok->
linenr() : 0;
2036 <<
" or there is division by zero at line " << line <<
".";
2038 errmsg <<
"Division by zero.";
2042 value->
condition ?
"zerodivcond" :
"zerodiv",
2055 logChecker(
"CheckOther::checkNanInArithmeticExpression");
2057 if (tok->str() !=
"/")
2069 "Using NaN/Inf in a computation.\n"
2070 "Using NaN/Inf in a computation. "
2086 logChecker(
"CheckOther::checkMisusedScopedObject");
2088 auto getConstructorTok = [](
const Token* tok, std::string& typeStr) ->
const Token* {
2094 typeStr += tok->
str();
2096 tok = tok->
tokAt(2);
2098 typeStr += tok->
str();
2099 const Token* endTok = tok;
2101 endTok = endTok->
linkAt(1);
2109 auto isLibraryConstructor = [&](
const Token* tok,
const std::string& typeStr) ->
bool {
2117 std::string typeStr;
2120 const Token* ctorTok = getConstructorTok(tok, typeStr);
2123 && ctorTok->
str() !=
"void") || isLibraryConstructor(tok->
next(), typeStr))) {
2126 parTok = parTok->
link()->next();
2130 if (parTok->
str() ==
"(") {
2131 if (arg->varId() && !(arg->variable() && arg->variable()->nameToken() != arg))
2154 std::string msg =
"Instance of '$symbol' object is destroyed immediately";
2155 msg += isAssignment ?
", assignment has no effect." :
".";
2157 "unusedScopedObject",
2158 "$symbol:" + varname +
"\n" +
2192 logChecker(
"CheckOther::checkDuplicateBranch");
2206 if (tok->isExpandedMacro()) {
2218 const std::string tokIfStr = tokIf->
stringify(
false,
true,
false);
2219 if (tokIfStr.empty())
2222 const std::string tokElseStr = tokElse->
stringify(
false,
true,
false);
2224 if (tokIfStr == tokElseStr) {
2228 if (branch1.empty())
2235 if (branch1 == branch2) {
2248 if (branchTop1->
str() != branchTop2->
str())
2260 errors.emplace_back(tok2,
"");
2261 errors.emplace_back(tok1,
"");
2264 "Finding the same code in an 'if' and related 'else' branch is suspicious and "
2265 "might indicate a cut and paste or logic error. Please examine this code "
2278 std::map<int, std::string> allocation;
2288 if ((tok->isCpp() &&
Token::Match(tok,
"%var% = new")) ||
2290 allocation.insert(std::make_pair(tok->varId(), tok->strAt(2)));
2291 inconclusive.insert(std::make_pair(tok->varId(),
false));
2298 tok->varId() == tok->tokAt(2)->varId() &&
2299 allocation.find(tok->varId()) != allocation.end()) {
2300 if (printInconclusive)
2303 allocation.erase(tok->varId());
2311 allocation.erase(tok->varId());
2321 const int varIndex = tok->strAt(1) ==
"(" ? 2 :
2322 tok->strAt(3) ==
"(" ? 4 : 1;
2323 const int var1 = tok->tokAt(varIndex)->varId();
2324 const int var2 = tok->tokAt(varIndex + 2)->varId();
2325 const std::map<int, bool>::const_iterator alloc1 =
inconclusive.find(var1);
2326 const std::map<int, bool>::const_iterator alloc2 =
inconclusive.find(var2);
2339 while (tok2 !=
nullptr) {
2340 allocation.erase(tok->varId());
2351 std::string alloc = allocation;
2354 std::string deallocated = (alloc ==
"new") ?
"deleted" :
"freed";
2366 bool notconst(
const Function* func)
2371 void getConstFunctions(
const SymbolDatabase *symbolDatabase, std::list<const Function*> &constFunctions)
2376 using StringFunctionMap = std::map<std::string, std::list<const Function*>>;
2377 StringFunctionMap functionsByName;
2379 functionsByName[func.
tokenDef->
str()].push_back(&func);
2381 for (std::pair<
const std::string, std::list<const Function*>>& it : functionsByName) {
2382 const std::list<const Function*>::const_iterator nc = std::find_if(it.second.cbegin(), it.second.cend(), notconst);
2383 if (nc == it.second.cend()) {
2385 constFunctions.splice(constFunctions.end(), it.second);
2404 if (!styleEnabled && !premiumEnabled)
2408 logChecker(
"CheckOther::checkDuplicateExpression");
2413 std::list<const Function*> constFunctions;
2414 getConstFunctions(symbolDatabase, constFunctions);
2418 if (tok->str() ==
"=" &&
Token::Match(tok->astOperand1(),
"%var%")) {
2421 endStatement = endStatement->
tokAt(4);
2424 const Token * nextAssign = endStatement->
tokAt(1);
2435 tok->astOperand2()->isArithmeticalOp() ||
2436 tok->astOperand2()->str() ==
"." ||
2437 Token::Match(tok->astOperand2()->previous(),
"%name% (")
2442 tok->astOperand2()->expressionString() == nextAssign->
astOperand2()->expressionString()) {
2443 bool differentDomain =
false;
2448 if (!assignTok->astOperand1())
2450 if (!assignTok->astOperand2())
2453 if (assignTok->astOperand1()->varId() != var1->
varId() &&
2454 assignTok->astOperand1()->varId() != var2->
varId() &&
2457 assignTok->astOperand1(),
2462 if (assignTok->astOperand2()->varId() != var1->
varId() &&
2463 assignTok->astOperand2()->varId() != var2->
varId() &&
2466 assignTok->astOperand2(),
2471 differentDomain =
true;
2481 auto isInsideLambdaCaptureList = [](
const Token* tok) {
2488 if (tok->isOp() && tok->astOperand1() && !
Token::Match(tok,
"+|*|<<|>>|+=|*=|<<=|>>=") && !isInsideLambdaCaptureList(tok)) {
2491 const bool pointerDereference = (tok->astOperand1() && tok->astOperand1()->isUnaryOp(
"*")) ||
2492 (tok->astOperand2() && tok->astOperand2()->isUnaryOp(
"*"));
2505 const bool isEnum = tok->scope()->type ==
Scope::eEnum;
2506 const bool assignment = !isEnum && tok->str() ==
"=";
2526 tok->astOperand2()->astOperand1(),
2543 if (tok->astOperand2() && tok->str() == tok->astOperand1()->str() &&
2546 tok->astOperand1()->astOperand2(),
2554 auto checkDuplicate = [&](
const Token* exp1,
const Token* exp2,
const Token* ast1) {
2561 while (ast1 && tok->
str() == ast1->
str()) {
2562 checkDuplicate(ast1->
astOperand2(), tok->astOperand2(), ast1);
2564 checkDuplicate(ast1->
astOperand1(), tok->astOperand2(), ast1);
2569 }
else if (tok->astOperand1() && tok->astOperand2() && tok->str() ==
":" && tok->astParent() && tok->astParent()->str() ==
"?") {
2570 if (!tok->astOperand1()->values().empty() && !tok->astOperand2()->values().empty() &&
isEqualKnownValue(tok->astOperand1(), tok->astOperand2()) &&
2583 errors.emplace_back(opTok,
"");
2585 const std::string& op = opTok ? opTok->
str() :
"&&";
2588 "Finding the opposite expression on both sides of an operator is suspicious and might "
2589 "indicate a cut and paste or logic error. Please examine this code carefully to "
2595 errors.emplace_back(opTok,
"");
2600 const std::string& op = opTok ? opTok->
str() :
"&&";
2601 std::string msg =
"Same expression " + (hasMultipleExpr ?
"\'" + expr1 +
"\'" +
" found multiple times in chain of \'" + op +
"\' operators" :
"on both sides of \'" + op +
"\'");
2602 const char *
id =
"duplicateExpression";
2603 if (expr1 != expr2 && (!opTok ||
Token::Match(opTok,
"%oror%|%comp%|&&|?|!"))) {
2604 id =
"knownConditionTrueFalse";
2605 std::string exprMsg =
"The comparison \'" + expr1 +
" " + op +
" " + expr2 +
"\' is always ";
2607 msg = exprMsg +
"true";
2609 msg = exprMsg +
"false";
2613 msg +=
" because '" + expr1 +
"' and '" + expr2 +
"' represent the same value";
2616 (std::string(
".\nFinding the same expression ") + (hasMultipleExpr ?
"more than once in a condition" :
"on both sides of an operator")) +
2617 " is suspicious and might indicate a cut and paste or logic error. Please examine this code carefully to "
2623 const std::list<const Token *> toks = { tok2, tok1 };
2625 const std::string& var1 = tok1 ? tok1->
str() :
"x";
2626 const std::string& var2 = tok2 ? tok2->
str() :
"x";
2629 "Same expression used in consecutive assignments of '" + var1 +
"' and '" + var2 +
"'.\n"
2630 "Finding variables '" + var1 +
"' and '" + var2 +
"' that are assigned the same expression "
2631 "is suspicious and might indicate a cut and paste or logic error. Please examine this code carefully to "
2637 errors.emplace_back(tok,
"");
2639 "Finding the same expression in both branches of ternary operator is suspicious as "
2646 "Finding the same value in both branches of ternary operator is suspicious as "
2654 "$symbol:" + varname +
"\n"
2672 logChecker(
"CheckOther::checkComparisonFunctionIsAlwaysTrueOrFalse");
2677 if (tok->isName() &&
Token::Match(tok,
"isgreater|isless|islessgreater|isgreaterequal|islessequal ( %var% , %var% )")) {
2678 const int varidLeft = tok->tokAt(2)->varId();
2679 const int varidRight = tok->tokAt(4)->varId();
2682 if (varidLeft == varidRight) {
2683 const std::string& functionName = tok->str();
2684 const std::string& varNameLeft = tok->strAt(2);
2685 if (functionName ==
"isgreater" || functionName ==
"isless" || functionName ==
"islessgreater") {
2703 "$symbol:" + functionName +
"\n"
2704 "Comparison of two identical variables with $symbol(" + varName +
"," + varName +
") always evaluates to " + strResult +
".\n"
2705 "The function $symbol is designed to compare two variables. Calling this function with one variable (" + varName +
") "
2706 "for both parameters leads to a statement which is always " + strResult +
".", cweResult,
Certainty::normal);
2717 logChecker(
"CheckOther::checkSignOfUnsignedVariable");
2725 const Token *nonZeroExpr =
nullptr;
2762 if (var->typeStartToken()->isTemplateArg())
2794 "$symbol:" + varname +
"\n"
2795 "Checking if unsigned expression '$symbol' is less than zero.\n"
2796 "The unsigned expression '$symbol' will never be negative so it "
2803 "A pointer can not be negative so it is either pointless or an error to check if it is.",
CWE570,
Certainty::normal);
2809 "$symbol:" + varname +
"\n"
2810 "Unsigned expression '$symbol' can't be negative so it is unnecessary to test it.",
CWE570,
Certainty::normal);
2816 "A pointer can not be negative so it is either pointless or an error to check if it is not.",
CWE570,
Certainty::normal);
2823 if (constructor.isConstructor()) {
2824 for (int argnr = 0U; argnr < constructor.argCount(); argnr++) {
2825 const Variable * const argVar = constructor.getArgumentVar(argnr);
2826 if (argVar && argVar->isReference()) {
2844 logChecker(
"CheckOther::checkRedundantCopy");
2849 if (!var || var->isReference() || var->isPointer() ||
2850 (!var->type() && !var->isStlType()) ||
2854 const Token* startTok = var->nameToken();
2855 if (startTok->
strAt(1) ==
"=")
2857 else if (
Token::Match(startTok->
next(),
"(|{") && var->isClass() && var->typeScope()) {
2862 startTok = startTok->
tokAt(2);
2901 "$symbol:" + varname +
"\n"
2902 "Use const reference for '$symbol' to avoid unnecessary data copying.\n"
2903 "The const variable '$symbol' is assigned a copy of the data. You can avoid "
2904 "the unnecessary data copying by converting '$symbol' to const reference.",
2922 logChecker(
"CheckOther::checkNegativeBitwiseShift");
2925 if (!tok->astOperand1() || !tok->astOperand2())
2933 const ValueType * lhsType = tok->astOperand1()->valueType();
2939 bool ternary =
false;
2940 for (
const Token *parent = tok; parent; parent = parent->
astParent()) {
2978 if (!printPortability && !printWarning)
2981 logChecker(
"CheckOther::checkIncompleteArrayFill");
2989 if (tok2->
str() ==
"::")
2990 tok2 = tok2->
next();
2992 tok2 = tok2->
tokAt(2);
3007 if ((size != 1 && size != 100 && size != 0) || var->
isPointer()) {
3010 }
else if (var->
valueType()->
type == ValueType::Type::BOOL && printPortability)
3022 "$symbol:" + buffer +
"\n"
3023 "$symbol:" +
function +
"\n"
3024 "Array '" + buffer +
"' might be filled incompletely. Did you forget to multiply the size given to '" +
function +
"()' with 'sizeof(*" + buffer +
")'?\n"
3025 "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);
3028 "$symbol:" + buffer +
"\n"
3029 "$symbol:" +
function +
"\n"
3030 "Array '" + buffer +
"' is filled incompletely. Did you forget to multiply the size given to '" +
function +
"()' with 'sizeof(*" + buffer +
")'?\n"
3031 "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);
3043 logChecker(
"CheckOther::checkVarFuncNullUB");
3051 const Token *ftok = tok;
3053 while (ftok && ftok->
str() !=
"(") {
3054 if (ftok->
str() ==
")")
3055 ftok = ftok->
link();
3056 else if (ftok->
str() ==
",")
3060 ftok = ftok ? ftok->
previous() :
nullptr;
3061 if (ftok && ftok->
isName()) {
3066 tok2 = tok2 ? tok2->
link() :
nullptr;
3081 "Passing NULL after the last typed argument to a variadic function leads to undefined behaviour.\n"
3082 "Passing NULL after the last typed argument to a variadic function leads to undefined behaviour.\n"
3083 "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"
3084 "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"
3085 "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"
3086 "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"
3087 "#include <stdarg.h>\n"
3088 "#include <stdio.h>\n"
3090 "void f(char *s, ...) {\n"
3092 " va_start(ap,s);\n"
3094 " char *p = va_arg(ap,char*);\n"
3095 " printf(\"%018p, %s\\n\", p, (long)p & 255 ? p : \"\");\n"
3102 " char *s2 = \"x\";\n"
3103 " char *s3 = \"ERROR\";\n"
3105 " // changing 0 to 0L for the 7th argument (which is intended to act as sentinel) makes the error go away on x86_64\n"
3106 " f(\"first\", s2, s2, s2, s2, s2, 0, s3, (char*)0);\n"
3111 " volatile unsigned char a[1000];\n"
3112 " for (i = 0; i<sizeof(a); i++)\n"
3128 logChecker(
"CheckOther::checkRedundantPointerOp");
3131 if (tok->isExpandedMacro() && tok->str() ==
"(")
3134 bool addressOfDeref{};
3135 if (tok->isUnaryOp(
"&") && tok->astOperand1()->isUnaryOp(
"*"))
3136 addressOfDeref =
true;
3137 else if (tok->isUnaryOp(
"*") && tok->astOperand1()->isUnaryOp(
"&"))
3138 addressOfDeref =
false;
3147 if (!addressOfDeref) {
3148 if (tok->isExpandedMacro())
3155 if (!var || (addressOfDeref && !var->
isPointer()))
3164 std::string msg =
"$symbol:" + varname +
"\nRedundant pointer operation on '$symbol' - it's already a ";
3165 msg += addressOfDeref ?
"pointer." :
"variable.";
3175 logChecker(
"CheckOther::checkInterlockedDecrement");
3178 if (tok->isName() &&
Token::Match(tok,
"InterlockedDecrement ( & %name% ) ; if ( %name%|!|0")) {
3179 const Token* interlockedVarTok = tok->
tokAt(3);
3180 const Token* checkStartTok = interlockedVarTok->
tokAt(5);
3181 if ((
Token::Match(checkStartTok,
"0 %comp% %name% )") && checkStartTok->
strAt(2) == interlockedVarTok->
str()) ||
3182 (
Token::Match(checkStartTok,
"! %name% )") && checkStartTok->
strAt(1) == interlockedVarTok->
str()) ||
3183 (
Token::Match(checkStartTok,
"%name% )") && checkStartTok->
str() == interlockedVarTok->
str()) ||
3184 (
Token::Match(checkStartTok,
"%name% %comp% 0 )") && checkStartTok->
str() == interlockedVarTok->
str())) {
3187 }
else if (
Token::Match(tok,
"if ( ::| InterlockedDecrement ( & %name%")) {
3190 const Token* firstAccessTok = funcTok->
str() ==
"::" ? funcTok->
tokAt(4) : funcTok->
tokAt(3);
3191 if (condEnd && condEnd->
next() && condEnd->
next()->
link()) {
3194 const Token* secondAccessTok = ifEndTok->
tokAt(2);
3195 if (secondAccessTok->
str() == firstAccessTok->
str()) {
3198 }
else if (
Token::Match(ifEndTok,
"} else { return %name%")) {
3199 const Token* secondAccessTok = ifEndTok->
tokAt(4);
3200 if (secondAccessTok->
str() == firstAccessTok->
str()) {
3212 "Race condition: non-interlocked access after InterlockedDecrement(). Use InterlockedDecrement() return value instead.",
CWE362,
Certainty::normal);
3226 if (!tok->scope()->isExecutable())
3227 tok = tok->scope()->bodyEnd;
3229 if (
Token::Match(tok,
"{|}|; %name% :") && !tok->tokAt(1)->isKeyword()) {
3230 const std::string tmp(
"goto " + tok->strAt(1));
3243 std::string
id =
"unusedLabel";
3247 id +=
"Configuration";
3249 std::string msg =
"$symbol:" + (tok ? tok->
str() :
emptyString) +
"\nLabel '$symbol' is not used.";
3251 msg +=
" There is #if in function body so the label might be used in code that is removed by the preprocessor.";
3253 msg +=
" Should this be a 'case' of the enclosing switch()?";
3270 logChecker(
"CheckOther::checkEvaluationOrder");
3277 if (!tok->astOperand1())
3286 if (parent->
str() ==
",") {
3287 const Token *par = parent;
3298 while (par && (par->
previous() != parent))
3308 tok->str() ==
"=" &&
3309 parent->
str() ==
"=" &&
3318 bool foundError =
false;
3320 [&](
const Token *tok3) {
3321 if (tok3->str() ==
"&" && !tok3->astOperand2())
3322 return ChildrenToVisit::none;
3323 if (tok3->str() ==
"(" && Token::simpleMatch(tok3->previous(),
"sizeof"))
3324 return ChildrenToVisit::none;
3325 if (isSameExpression(false, tok->astOperand1(), tok3, *mSettings, true, false))
3327 return foundError ? ChildrenToVisit::done : ChildrenToVisit::op1_and_op2;
3349 logChecker(
"CheckOther::checkAccessOfMovedVariable");
3356 if (memberInitializationStart)
3357 scopeStart = memberInitializationStart;
3360 if (!tok->astParent())
3369 bool accessOfMoved =
false;
3370 if (tok->strAt(1) ==
".") {
3371 if (tok->next()->originalName() ==
"->")
3372 accessOfMoved =
true;
3378 accessOfMoved =
true;
3384 if (accessOfMoved || (
inconclusive && reportInconclusive))
3398 const char * errorId =
nullptr;
3399 std::string kindString;
3402 errorId =
"accessMoved";
3403 kindString =
"moved";
3406 errorId =
"accessForwarded";
3407 kindString =
"forwarded";
3412 const std::string errmsg(
"$symbol:" + varname +
"\nAccess of " + kindString +
" variable '$symbol'.");
3428 logChecker(
"CheckOther::checkFuncArgNamesDifferent");
3435 if (!
function || function->argCount() == 0)
3439 if (function->argDef == function->arg)
3443 std::vector<const Token *> declarations(function->argCount());
3444 std::vector<const Token *> definitions(function->argCount());
3445 const Token * decl =
function->argDef->
next();
3446 for (
int j = 0; j <
function->argCount(); ++j) {
3447 declarations[j] =
nullptr;
3448 definitions[j] =
nullptr;
3450 const Variable * variable =
function->getArgumentVar(j);
3459 if (decl->
str() ==
"=") {
3465 decl = decl->
link();
3466 else if (decl->
varId())
3467 declarations[j] = decl;
3468 decl = decl->
next();
3471 decl = decl->
next();
3475 bool order_different =
false;
3476 for (
int j = 0; j <
function->argCount(); ++j) {
3477 if (!declarations[j] || !definitions[j] || declarations[j]->str() == definitions[j]->str())
3480 for (
int k = 0; k <
function->argCount(); ++k) {
3481 if (j != k && definitions[k] && declarations[j]->str() == definitions[k]->str()) {
3482 order_different =
true;
3487 if (order_different) {
3488 funcArgOrderDifferent(function->name(), function->argDef->next(), function->arg->next(), declarations, definitions);
3494 for (
int j = 0; j <
function->argCount(); ++j) {
3495 if (declarations[j] && definitions[j] && declarations[j]->str() != definitions[j]->str())
3503 const Token* declaration,
const Token* definition)
3505 std::list<const Token *> tokens = { declaration,definition };
3507 "$symbol:" + functionName +
"\n"
3508 "Function '$symbol' argument " + std::to_string(index + 1) +
" names different: declaration '" +
3509 (declaration ? declaration->
str() : std::string(
"A")) +
"' definition '" +
3514 const Token* declaration,
const Token* definition,
3515 const std::vector<const Token *> & declarations,
3516 const std::vector<const Token *> & definitions)
3518 std::list<const Token *> tokens = {
3519 !declarations.empty() ? declarations[0] ? declarations[0] : declaration :
nullptr,
3520 !definitions.empty() ? definitions[0] ? definitions[0] : definition :
nullptr
3522 std::string msg =
"$symbol:" + functionName +
"\nFunction '$symbol' argument order different: declaration '";
3523 for (
int i = 0; i < declarations.size(); ++i) {
3526 if (declarations[i])
3527 msg += declarations[i]->
str();
3529 msg +=
"' definition '";
3530 for (
int i = 0; i < definitions.size(); ++i) {
3534 msg += definitions[i]->str();
3551 return f.type == Function::Type::eFunction && f.name() == var.name() && precedes(f.tokenDef, var.nameToken());
3554 return it->tokenDef;
3568 logChecker(
"CheckOther::checkShadowVariables");
3573 const Scope *functionScope = &scope;
3574 while (functionScope && functionScope->
type != Scope::ScopeType::eFunction && functionScope->
type != Scope::ScopeType::eLambda)
3575 functionScope = functionScope->
nestedIn;
3580 if (functionScope && functionScope->
type == Scope::ScopeType::eFunction && functionScope->
function) {
3582 auto it = std::find_if(argList.cbegin(), argList.cend(), [&](
const Variable& arg) {
3583 return arg.nameToken() && var.name() == arg.name();
3585 if (it != argList.end()) {
3609 errorPath.emplace_back(shadowed,
"Shadowed declaration");
3610 errorPath.emplace_back(var,
"Shadow variable");
3611 const std::string &varname = var ? var->
str() : type;
3612 const std::string
Type = char(std::toupper(type[0])) + type.substr(1);
3613 const std::string
id =
"shadow" +
Type;
3614 const std::string message =
"$symbol:" + varname +
"\nLocal variable \'$symbol\' shadows outer " + type;
3620 if (tok->
varId() != 0)
3649 logChecker(
"CheckOther::checkKnownArgument");
3653 if (!tok->hasKnownIntValue())
3659 if (tok->astParent()->isCast() || (tok->isCast() &&
Token::Match(tok->astOperand2(),
"++|--|%assign%")))
3669 if (tok == tok->astParent()->previous())
3675 const Token * tok2 = tok;
3680 if (tok->isComparisonOp() &&
3682 true, tok->astOperand1(), tok->astOperand2(), *
mSettings,
true,
true))
3685 const Token* vartok =
nullptr;
3692 return ChildrenToVisit::done;
3701 return Token::simpleMatch(child,
"sizeof");
3705 std::string funcname = ftok->
str();
3707 if (funcname.find(
"assert") != std::string::npos)
3717 reportError(tok,
Severity::style,
"knownArgument",
"Argument 'x-x' to function 'func' is always 0. It does not matter what value 'x' has.");
3718 reportError(tok,
Severity::style,
"knownArgumentHiddenVariableExpression",
"Argument 'x*0' to function 'func' is always 0. Constant literal calculation disable/hide variable expression 'x'.");
3724 const std::string &fun = ftok->
str();
3726 std::string ftype =
"function ";
3728 ftype =
"constructor ";
3729 else if (fun ==
"{")
3730 ftype =
"init list ";
3733 std::string errmsg =
"Argument '" + expr +
"' to " + ftype + fun +
" is always " + std::to_string(intvalue) +
". ";
3734 if (!isVariableExpressionHidden) {
3735 id =
"knownArgument";
3736 errmsg +=
"It does not matter what value '" + varexpr +
"' has.";
3738 id =
"knownArgumentHiddenVariableExpression";
3739 errmsg +=
"Constant literal calculation disable/hide variable expression '" + varexpr +
"'.";
3750 logChecker(
"CheckOther::checkKnownPointerToBool");
3754 if (!tok->hasKnownIntValue())
3758 if (
Token::Match(tok->astParent(),
"?|!|&&|%oror%|%comp%"))
3760 if (tok->astParent() &&
Token::Match(tok->astParent()->previous(),
"if|while|switch|sizeof ("))
3762 if (tok->isExpandedMacro())
3784 std::string errmsg =
"Pointer expression '" + expr +
"' converted to bool is always " + cond +
".";
3791 logChecker(
"CheckOther::checkComparePointers");
3816 if (var1 == parent2->variable())
3819 if (var2 == parent1->variable())
3829 std::string verb =
"Comparing";
3831 verb =
"Subtracting";
3832 const char *
const id = (verb[0] ==
'C') ?
"comparePointers" :
"subtractPointers";
3834 errorPath.emplace_back(v1->
tokvalue->
variable()->nameToken(),
"Variable declared here.");
3838 errorPath.emplace_back(v2->
tokvalue->
variable()->nameToken(),
"Variable declared here.");
3841 errorPath.emplace_back(tok,
"");
3854 if (!tok->astOperand2() || !tok->astOperand1())
3856 if (tok->str() !=
"%")
3858 if (!tok->valueType() || !tok->valueType()->isIntegral())
3863 if (value && value->
isKnown())
3880 const Token *bufToken, *offsetToken;
3888 const bool pointer1 = (expr->
astOperand1()->valueType() && expr->
astOperand1()->valueType()->pointer > 0);
3889 const bool pointer2 = (expr->
astOperand2()->valueType() && expr->
astOperand2()->valueType()->pointer > 0);
3890 if (pointer1 && !pointer2) {
3896 }
else if (!pointer1 && pointer2) {
3911 if (elementSize > 0) {
3912 *offset *= elementSize;
3914 *sizeValue *= elementSize;
3926 if (elementSize > 0) {
3927 *offset *= elementSize;
3929 *sizeValue *= elementSize;
3936 logChecker(
"CheckOther::checkOverlappingWrite");
3940 if (tok->isAssignmentOp()) {
3953 const Token *errorToken =
nullptr;
3954 visitAstNodes(tok->astOperand2(), [lhsvar, lhsmember, &errorToken](
const Token *rhs) {
3955 if (!Token::simpleMatch(rhs,
"."))
3956 return ChildrenToVisit::op1_and_op2;
3957 if (!rhs->isBinaryOp() || rhs->astOperand1()->variable() != lhsvar)
3958 return ChildrenToVisit::none;
3959 if (lhsmember->str() == rhs->astOperand2()->str())
3960 return ChildrenToVisit::none;
3961 const Variable* rhsmembervar = rhs->astOperand2()->variable();
3962 const Scope* varscope1 = lhsmember->variable() ? lhsmember->variable()->typeStartToken()->scope() : nullptr;
3963 const Scope* varscope2 = rhsmembervar ? rhsmembervar->typeStartToken()->scope() : nullptr;
3964 if (varscope1 && varscope1 == varscope2 && varscope1 != lhsvar->typeScope())
3966 return ChildrenToVisit::none;
3967 errorToken = rhs->astOperand2();
3968 return ChildrenToVisit::done;
3974 if (!nonOverlappingData)
3976 const std::vector<const Token *> args =
getArguments(tok);
3977 if (nonOverlappingData->
ptr1Arg <= 0 || nonOverlappingData->
ptr1Arg > args.size())
3979 if (nonOverlappingData->
ptr2Arg <= 0 || nonOverlappingData->
ptr2Arg > args.size())
3982 const Token *ptr1 = args[nonOverlappingData->
ptr1Arg - 1];
3986 const Token *ptr2 = args[nonOverlappingData->
ptr2Arg - 1];
3991 const int sizeArg = std::max(nonOverlappingData->
sizeArg, nonOverlappingData->
countArg);
3992 if (sizeArg <= 0 || sizeArg > args.size()) {
3993 if (nonOverlappingData->
sizeArg == -1) {
3995 constexpr
bool macro =
true;
3996 constexpr
bool pure =
true;
3997 constexpr
bool follow =
true;
4004 const bool isCountArg = nonOverlappingData->
countArg > 0;
4005 if (!args[sizeArg-1]->hasKnownIntValue())
4008 const Token *buf1, *buf2;
4015 if (offset1 < offset2 && offset1 + sizeValue <= offset2)
4017 if (offset2 < offset1 && offset2 + sizeValue <= offset1)
4021 constexpr
bool macro =
true;
4022 constexpr
bool pure =
true;
4023 constexpr
bool follow =
true;
4040 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)