41 #include <unordered_map> 
   70         return "copy constructor";
 
   72         return "move constructor";
 
   87     bool isOpEqual = 
false;
 
  112         if (isVclTypeInit(baseInfo.type))
 
  120     : 
Check(myName(), tokenizer, settings, errorLogger),
 
  121     mSymbolDatabase(tokenizer?tokenizer->getSymbolDatabase():nullptr)
 
  145             if (unionScope.type != Scope::eUnion)
 
  147             return std::any_of(unionScope.varlist.cbegin(), unionScope.varlist.cend(), [&](const Variable& var) {
 
  148                 return var.type() && var.type()->classScope == scope;
 
  155             int needInit = 0, haveInit = 0;
 
  156             std::vector<const Variable*> uninitVars;
 
  162                         uninitVars.emplace_back(&var);
 
  167             if (needInit > haveInit) {
 
  171                     for (
const Variable* uv : uninitVars)
 
  172                         uninitVarError(uv->typeStartToken(), uv->scope()->className, uv->name());
 
  183                 return nestedScope->type == Scope::eUnion;
 
  208             for (
Usage &usage : usageList) {
 
  217             std::list<const Function *> callstack;
 
  221             for (
const Usage &usage : usageList) {
 
  223                 if (!usage.assign && !usage.init)
 
  226                 while (varScope1->
type == Scope::ScopeType::eStruct)
 
  228                 if (varScope1->
type == Scope::ScopeType::eUnion) {
 
  229                     for (
Usage &usage2 : usageList) {
 
  231                         if (usage2.assign || usage2.init || var2.
isStatic())
 
  234                         while (varScope2->
type == Scope::ScopeType::eStruct)
 
  236                         if (varScope1 == varScope2)
 
  237                             usage2.assign = 
true;
 
  243             for (
const Usage &usage : usageList) {
 
  246                 if (usage.assign || usage.init || var.
isStatic())
 
  288                 bool missingCopy = 
false;
 
  293                     if (!printInconclusive)
 
  303                     bool classNameUsed = 
false;
 
  304                     for (
const Token *operTok = operStart; operTok != operStart->
link(); operTok = operTok->next()) {
 
  305                         if (operTok->str() == scope->
className) {
 
  306                             classNameUsed = 
true;
 
  319                         const bool derived = scope != var.
scope();
 
  326                             if (printInconclusive)
 
  328                         } 
else if (missingCopy)
 
  344     logChecker(
"CheckClass::checkExplicitConstructors"); 
 
  354             return func.isPure();
 
  377                 func.
argumentList.front().getTypeName() != 
"std::initializer_list") {
 
  413     logChecker(
"CheckClass::checkCopyConstructors"); 
 
  416         std::map<int, const Token*> allocatedVars;
 
  427                         allocatedVars[tok->
varId()] = tok;
 
  435                         allocatedVars[tok->
varId()] = tok;
 
  440         if (!allocatedVars.empty()) {
 
  441             const Function *funcCopyCtor = 
nullptr;
 
  442             const Function *funcOperatorEq = 
nullptr;
 
  443             const Function *funcDestructor = 
nullptr;
 
  446                     funcCopyCtor = &func;
 
  448                     funcOperatorEq = &func;
 
  450                     funcDestructor = &func;
 
  452             if (!funcCopyCtor || funcCopyCtor->
isDefault()) {
 
  453                 bool unknown = 
false;
 
  457             if (!funcOperatorEq || funcOperatorEq->
isDefault()) {
 
  458                 bool unknown = 
false;
 
  460                     noOperatorEqError(scope, funcOperatorEq, allocatedVars.cbegin()->second, unknown);
 
  462             if (!funcDestructor || funcDestructor->
isDefault()) {
 
  463                 const Token * mustDealloc = 
nullptr;
 
  464                 for (std::map<int, const Token*>::const_iterator it = allocatedVars.cbegin(); it != allocatedVars.cend(); ++it) {
 
  465                     if (!
Token::Match(it->second, 
"%var% [(=] new %type%")) {
 
  466                         mustDealloc = it->second;
 
  469                     if (it->second->valueType() && it->second->valueType()->isIntegral()) {
 
  470                         mustDealloc = it->second;
 
  473                     const Variable *var = it->second->variable();
 
  475                         mustDealloc = it->second;
 
  484         std::set<const Token*> copiedVars;
 
  485         const Token* copyCtor = 
nullptr;
 
  491                 allocatedVars.clear();
 
  495             if (tok->
str()==
":") {
 
  498                     if (allocatedVars.find(tok->
varId()) != allocatedVars.end()) {
 
  500                             copiedVars.insert(tok);
 
  502                             allocatedVars.erase(tok->
varId()); 
 
  510                     allocatedVars.erase(tok->
varId());
 
  511                 } 
else if (
Token::Match(tok, 
"%var% = %name% . %name% ;") && allocatedVars.find(tok->
varId()) != allocatedVars.end()) {
 
  512                     copiedVars.insert(tok);
 
  517         if (copyCtor && !copiedVars.empty()) {
 
  518             for (
const Token *cv : copiedVars)
 
  543                 "$symbol:" + varname + 
"\nValue of pointer '$symbol', which points to allocated memory, is copied in copy constructor instead of allocating new memory.", 
CWE398, 
Certainty::normal);
 
  548     const std::string &classname = scope ? scope->
className : 
"class";
 
  549     const std::string type = (scope && scope->
type == 
Scope::eStruct) ? 
"Struct" : 
"Class";
 
  550     const bool isDestructor = (
function[0] == 
'd');
 
  551     std::string errmsg = 
"$symbol:" + classname + 
'\n';
 
  554         errmsg += type + 
" '$symbol' has dynamic memory/resource allocation(s). The " + 
function + 
" is explicitly defaulted but the default " + 
function + 
" does not work well.";
 
  556             errmsg += 
" It is recommended to define the " + std::string(
function) + 
'.';
 
  558             errmsg += 
" It is recommended to define or delete the " + std::string(
function) + 
'.';
 
  560         errmsg += type + 
" '$symbol' does not have a " + 
function + 
" which is recommended since it has dynamic memory/resource allocation(s).";
 
  583     bool constructor = 
false;
 
  584     bool publicAssign = 
false;
 
  585     bool publicCopy = 
false;
 
  602     return constructor && !(publicAssign || publicCopy);
 
  607     bool constructor = 
false;
 
  608     bool publicAssign = 
false;
 
  609     bool publicCopy = 
false;
 
  610     bool publicMove = 
false;
 
  631     return constructor && !(publicAssign || publicCopy || publicMove);
 
  636     std::transform(scope->
varlist.cbegin(), scope->
varlist.cend(), std::back_inserter(varList), [](
const Variable& var) {
 
  652     std::vector<Usage> ret;
 
  653     std::vector<const Variable *> varlist;
 
  655     ret.reserve(varlist.size());
 
  656     std::transform(varlist.cbegin(), varlist.cend(), std::back_inserter(ret), [](
const Variable* var) {
 
  664     auto it = std::find_if(usageList.begin(), usageList.end(), [varid](
const Usage& usage) {
 
  665         return usage.var->declarationId() == varid;
 
  667     if (it != usageList.end())
 
  673     if (vartok->
varId() > 0) {
 
  677     auto it = std::find_if(usageList.begin(), usageList.end(), [vartok](
const Usage& usage) {
 
  679         return usage.var->name() == vartok->str();
 
  681     if (it != usageList.end())
 
  687     auto it = std::find_if(usageList.begin(), usageList.end(), [varid](
const Usage& usage) {
 
  688         return usage.var->declarationId() == varid;
 
  690     if (it != usageList.end())
 
  696     for (
Usage & i : usageList)
 
  702     for (
Usage& usage : usageList) {
 
  703         if (usage.var->scope() == scope)
 
  718     for (
Usage & i : usageList) {
 
  734             if (std::any_of(functionList.cbegin(), functionList.cend(), [&](
const Function& func) {
 
  735                 return func.tokenDef->str() == tok->str() && !func.isStatic() && !func.isConst();
 
  764                 if (ftok->
str() != func.
name()) {
 
  768                         for (
Usage& u : usage) {
 
  769                             if (u.var->scope() != scope) 
 
  783                     if (std::find(callstack.cbegin(), callstack.cend(), member) != callstack.cend()) {
 
  792                         callstack.push_back(member);
 
  794                         callstack.pop_back();
 
  802             } 
else if (level != 0 && 
Token::Match(ftok, 
"%name% =")) 
 
  808             else if (ftok->
str() == 
"{") {
 
  848                 return var.declarationId() == ftok->next()->varId();
 
  853             ftok = ftok->
tokAt(2);
 
  866         if (ftok->
str() == 
"return")
 
  871             ftok = ftok->
tokAt(5);
 
  876             ftok = ftok->
tokAt(2);
 
  882             ftok = ftok->
tokAt(2);
 
  891         if (
Token::Match(ftok, 
"::| memset ( &| this . %name%")) {
 
  892             if (ftok->
str() == 
"::")
 
  894             int offsetToMember = 4;
 
  895             if (ftok->
strAt(2) == 
"&")
 
  904             if (ftok->
str() == 
"::")
 
  917                 if (std::find(callstack.cbegin(), callstack.cend(), member) != callstack.cend()) {
 
  926                     callstack.push_back(member);
 
  928                     callstack.pop_back();
 
  948             if (ftok->
str() == 
"::")
 
  953                 if (tok2->str() == 
"this") {
 
  961                 !ftok->
function()->isConstructor()) {
 
  966                 if (std::find(callstack.cbegin(), callstack.cend(), member) != callstack.cend()) {
 
  974                     callstack.push_back(member);
 
  976                     callstack.pop_back();
 
  979                     for (
const Token *tok2 = ftok; tok2; tok2 = tok2->
next()) {
 
  984                             if (tok2->str() == 
"&")
 
  999                     for (
Usage& i: usage) {
 
 1000                         if (i.var->isMutable())
 
 1023                     for (
const Token *tok = ftok->
tokAt(2); tok && tok != ftok->
next()->
link(); tok = tok->next()) {
 
 1024                         if (tok->isName()) {
 
 1037             if (tok2->
str() == 
"&") {
 
 1038                 tok2 = tok2->
next();
 
 1047             const Token *tok2 = ftok;
 
 1049                 if (tok2->
strAt(1) == 
"[")
 
 1052                     tok2 = tok2->
tokAt(2);
 
 1056             if (tok2 && tok2->
strAt(1) == 
"=")
 
 1067                 if (rangeVar->isReference() && !rangeVar->isConst())
 
 1082     const std::string message {
"The " + std::string(isStruct ? 
"struct" : 
"class") + 
" '$symbol' does not declare a constructor although it has private member variables which likely require initialization."};
 
 1083     const std::string verbose {message + 
" Member variables of native types, pointers, or references are left uninitialized when the class is instantiated. That may cause bugs or undefined behavior."};
 
 1089     const std::string message(std::string(isStruct ? 
"Struct" : 
"Class") + 
" '$symbol' has a constructor with 1 argument that is not explicit.");
 
 1090     const std::string verbose(message + 
" Such, so called \"Converting constructors\", should in general be explicit for type safety reasons as that prevents unintended implicit conversions.");
 
 1101     std::string message(
"Member variable '$symbol' is not initialized in the " + ctor + 
"constructor.");
 
 1103         message += 
" Maybe it should be initialized directly in the class " + classname + 
"?";
 
 1104     std::string 
id = std::string(
"uninit") + (derived ? 
"Derived" : 
"") + 
"MemberVar" + (isprivate ? 
"Private" : 
"");
 
 1105     const std::string verbose {message + 
" Member variables of native types, pointers, or references are left uninitialized when the class is instantiated. That may cause bugs or undefined behavior."};
 
 1111     const std::string message(
"Member variable '$symbol' is not initialized."); 
 
 1112     const std::string verbose {message + 
" Member variables of native types, pointers, or references are left uninitialized when the class is instantiated. That may cause bugs or undefined behavior."};
 
 1113     const std::string 
id = std::string(
"uninitMemberVarPrivate");
 
 1119     const std::string ctor(functionType == Function::Type::eCopyConstructor ? 
"copy" : 
"move");
 
 1120     const std::string action(functionType == Function::Type::eCopyConstructor ? 
"copied?" : 
"moved?");
 
 1121     const std::string message =
 
 1122         "$symbol:" + classname + 
"::" + varname + 
"\n" +
 
 1123         "Member variable '$symbol' is not assigned in the " + ctor + 
" constructor. Should it be " + action;
 
 1141     logChecker(
"CheckClass::initializationListUsage"); 
 
 1160             if (!
Token::Match(tok, 
"%var% =") || tok->strAt(-1) == 
"*" || tok->strAt(-1) == 
".")
 
 1163             const Variable* var = tok->variable();
 
 1176             bool localmember = 
false;
 
 1178                           [&](
const Token *rhs) {
 
 1179                 if (rhs->str() == 
"." && rhs->astOperand1() && rhs->astOperand1()->variable() && rhs->astOperand1()->variable()->isLocal())
 
 1181                 return ChildrenToVisit::op1_and_op2;
 
 1186             bool allowed = 
true;
 
 1188                           [&](
const Token *tok2) {
 
 1189                 const Variable* var2 = tok2->variable();
 
 1191                     if (var2->scope() == owner && tok2->strAt(-1)!=
".") { 
 
 1193                         return ChildrenToVisit::done;
 
 1195                     if (var2->isArray() && var2->isLocal()) { 
 
 1197                         return ChildrenToVisit::done;
 
 1199                 } 
else if (tok2->
str() == 
"this") { 
 
 1201                     return ChildrenToVisit::done;
 
 1218     reportError(tok, 
Severity::performance, 
"useInitializationList", 
"$symbol:" + varname + 
"\nVariable '$symbol' is assigned in constructor body. Consider performing initialization in initialization list.\n" 
 1219                 "When an object of a class is created, the constructors of all member variables are called consecutively " 
 1220                 "in the order the variables are declared, even if you don't explicitly write them to the initialization list. You " 
 1221                 "could avoid assigning '$symbol' a value by passing the value to the constructor in the initialization list.", 
CWE398, 
Certainty::normal);
 
 1233     for (std::list<Function>::const_iterator func = scope->
functionList.cbegin(); func != scope->
functionList.cend(); ++func) {
 
 1234         if (func->functionScope) {
 
 1236                 for (
const Token *ftok = func->tokenDef->
tokAt(2); ftok && ftok->
str() != 
")"; ftok = ftok->next()) {
 
 1237                     if (
Token::Match(ftok, 
"= %name% [(,)]") && ftok->strAt(1) == privfunc->
name())
 
 1239                     if (ftok->str() == 
"(")
 
 1240                         ftok = ftok->link();
 
 1243             for (
const Token *ftok = func->functionScope->classDef->
linkAt(1); ftok != func->functionScope->bodyEnd; ftok = ftok->
next()) {
 
 1244                 if (ftok->function() == privfunc)
 
 1246                 if (ftok->varId() == 0U && ftok->str() == privfunc->
name()) 
 
 1255     const std::map<std::string, Type*>::const_iterator end = scope->
definedTypesMap.cend();
 
 1256     for (std::map<std::string, Type*>::const_iterator iter = scope->
definedTypesMap.cbegin(); iter != end; ++iter) {
 
 1257         const Type *type = iter->second;
 
 1266                 tok = tok->
tokAt(2);
 
 1267             while (tok && tok->
str() != 
";") {
 
 1291         std::list<const Function*> privateFuncs;
 
 1295                 privateFuncs.push_back(&func);
 
 1301             for (std::list<const Function*>::iterator it = privateFuncs.begin(); it != privateFuncs.end();) {
 
 1302                 if ((*it)->isImplicitlyVirtual(
true)) 
 
 1303                     it = privateFuncs.erase(it);
 
 1309         while (!privateFuncs.empty()) {
 
 1310             const auto& pf = privateFuncs.front();
 
 1311             if (pf->retDef && pf->retDef->isAttributeMaybeUnused()) {
 
 1312                 privateFuncs.pop_front();
 
 1319             for (
int i = 0; i < friendList.size() && !used; i++) {
 
 1320                 if (friendList[i].type)
 
 1329             privateFuncs.pop_front();
 
 1369                 const Token *typeTok = 
nullptr;
 
 1370                 const Scope *type = 
nullptr;
 
 1379                     typeTok = sizeofTok->
tokAt(2);
 
 1380                 else if (
Token::Match(sizeofTok, 
"sizeof ( %type% :: %type% )"))
 
 1381                     typeTok = sizeofTok->
tokAt(4);
 
 1382                 else if (
Token::Match(sizeofTok, 
"sizeof ( struct %type% )"))
 
 1383                     typeTok = sizeofTok->
tokAt(3);
 
 1387                     int numIndirToVariableType = 0; 
 
 1388                     for (;; arg1 = arg1->
next()) {
 
 1389                         if (arg1->
str() == 
"&")
 
 1390                             ++numIndirToVariableType;
 
 1391                         else if (arg1->
str() == 
"*")
 
 1392                             --numIndirToVariableType;
 
 1398                     if (var && arg1->
strAt(1) == 
",") {
 
 1402                                 ++numIndirToVariableType;
 
 1408                             numIndirToVariableType += int(var->
dimensions().size());
 
 1410                         if (numIndirToVariableType == 1)
 
 1421                 if (!typeTok && !type)
 
 1424                 if (typeTok && typeTok->
str() == 
"(")
 
 1425                     typeTok = typeTok->
next();
 
 1427                 if (!type && typeTok->
type())
 
 1428                     type = typeTok->
type()->classScope;
 
 1431                     const std::set<const Scope *> parsedTypes;
 
 1434             } 
else if (tok->variable() && tok->variable()->isPointer() && tok->variable()->typeScope() && 
Token::Match(tok, 
"%var% = %name% (")) {
 
 1440                 const std::set<const Scope *> parsedTypes;
 
 1441                 checkMemsetType(scope, tok->tokAt(2), tok->variable()->typeScope(), 
true, parsedTypes);
 
 1443                 if (printWarnings && tok->variable()->typeScope()->numConstructors > 0)
 
 1453     if (parsedTypes.find(type) != parsedTypes.end())
 
 1455     parsedTypes.insert(type);
 
 1487             std::string typeName;
 
 1489                 const Token *typeTok = tok1;
 
 1491                     typeName += typeTok->
str() + 
"::";
 
 1492                     typeTok = typeTok->
tokAt(2);
 
 1494                 typeName += typeTok->
str();
 
 1506             else if (typeScope && typeScope != type)
 
 1518     std::list<const Token *> toks = { tok, classTok };
 
 1520                 "$symbol:" + memfunc +
"\n" 
 1521                 "Memory for class instance allocated with $symbol(), but class provides constructors.\n" 
 1522                 "Memory for class instance allocated with $symbol(), but class provides constructors. This is unsafe, " 
 1523                 "since no constructor is called and class members remain uninitialized. Consider using 'new' instead.", 
CWE762, 
Certainty::normal);
 
 1528     std::list<const Token *> toks = { tok, classTok };
 
 1530                 "$symbol:" + memfunc +
"\n" 
 1531                 "$symbol:" + classname +
"\n" 
 1532                 "Memory for class instance allocated with " + memfunc + 
"(), but class contains a " + classname + 
".\n" 
 1533                 "Memory for class instance allocated with " + memfunc + 
"(), but class a " + classname + 
". This is unsafe, " 
 1534                 "since no constructor is called and class members remain uninitialized. Consider using 'new' instead.", 
CWE665, 
Certainty::normal);
 
 1539     const std::string typeStr = isContainer ? std::string() : (type + 
" that contains a ");
 
 1540     const std::string msg = 
"$symbol:" + memfunc + 
"\n" 
 1541                             "$symbol:" + classname + 
"\n" 
 1542                             "Using '" + memfunc + 
"' on " + typeStr + classname + 
".\n" 
 1543                             "Using '" + memfunc + 
"' on " + typeStr + classname + 
" is unsafe, because constructor, destructor " 
 1544                             "and copy operator calls are omitted. These are necessary for this non-POD type to ensure that a valid object " 
 1552                 "$symbol:" + memfunc +
"\n" 
 1559                 "Using memset() on " + type + 
" which contains a floating point number." 
 1560                 " This is not portable because memset() sets each byte of a block of memory to a specific value and" 
 1561                 " the actual representation of a floating-point value is implementation defined." 
 1562                 " Note: In case of an IEEE754-1985 compatible implementation setting all bits to zero results in the value 0.0.", 
CWE758, 
Certainty::normal);
 
 1576     logChecker(
"CheckClass::operatorEqRetRefThis"); 
 
 1579         for (std::list<Function>::const_iterator func = scope->
functionList.cbegin(); func != scope->
functionList.cend(); ++func) {
 
 1582                 if (func->retType == func->nestedIn->definedType && func->tokenDef->strAt(-1) == 
"&") {
 
 1592     std::set<const Function*> analyzedFunctions;
 
 1598     bool foundReturn = 
false;
 
 1600     const Token* 
const startTok = tok;
 
 1602     for (; tok && tok != last; tok = tok->
next()) {
 
 1606             tok = lScope->
link();
 
 1608         if (tok->
str() != 
"return")
 
 1614         if (retExpr && retExpr->
str() == 
"=")
 
 1619         std::string cast(
"( " + scope->
className + 
" & )");
 
 1621             tok = tok->
tokAt(4);
 
 1624         if (tok->
strAt(2) == 
"(" &&
 
 1627             for (std::list<Function>::const_iterator it = scope->
functionList.cbegin(); it != scope->
functionList.cend(); ++it) {
 
 1630                     it->token->str() == tok->
next()->
str()) {
 
 1632                     if (it->tokenDef->previous()->str() == 
"&" &&
 
 1633                         it->tokenDef->strAt(-2) == scope->
className) {
 
 1635                         if (!it->isConst()) {
 
 1638                             if (analyzedFunctions.find(&*it) == analyzedFunctions.end()) {
 
 1639                                 analyzedFunctions.insert(&*it);
 
 1640                                 checkReturnPtrThis(scope, &*it, it->arg->link()->next(), it->arg->link()->next()->link(),
 
 1662     if (startTok->
next() == last) {
 
 1663         const std::string tmp(
"( const " + scope->
className + 
" &");
 
 1733                 while (typeTok->
str() == 
"const" || typeTok->
str() == 
"&" || typeTok->
str() == 
"*")
 
 1742                     const Token* out_ifStatementScopeStart = 
nullptr;
 
 1743                     if (!
hasAssignSelf(&func, rhs, out_ifStatementScopeStart)) {
 
 1746                     } 
else if (out_ifStatementScopeStart != 
nullptr) {
 
 1759     if (ifStatementScopeStart->
str() == 
"{")
 
 1760         end = ifStatementScopeStart->
link();
 
 1763     return hasAllocation(func, scope, ifStatementScopeStart, end);
 
 1775     for (
const Token *tok = start; tok && (tok != end); tok = tok->
next()) {
 
 1776         if (((tok->isCpp() && 
Token::Match(tok, 
"%var% = new")) ||
 
 1784             var = tok->
tokAt(2);
 
 1785         else if (tok->isCpp() && 
Token::Match(tok, 
"delete [ ] %var%"))
 
 1786             var = tok->
tokAt(3);
 
 1787         else if (tok->isCpp() && 
Token::Match(tok, 
"delete %var%"))
 
 1793             for (
const Token *tok1 = var->
next(); tok1 && (tok1 != end); tok1 = tok1->
next()) {
 
 1820     for (
const Token *itr = tok; itr && itr->
str()!=
"("; itr=itr->astParent()) {
 
 1854             return top->
link()->next();
 
 1856             return top->
link()->next()->link();
 
 1873                       [&](
const Token *tok2) {
 
 1874             if (!Token::Match(tok2, 
"==|!="))
 
 1875                 return ChildrenToVisit::op1_and_op2;
 
 1876             if (Token::simpleMatch(tok2->astOperand1(), 
"this"))
 
 1877                 tok2 = tok2->astOperand2();
 
 1878             else if (Token::simpleMatch(tok2->astOperand2(), 
"this"))
 
 1879                 tok2 = tok2->astOperand1();
 
 1881                 return ChildrenToVisit::op1_and_op2;
 
 1882             if (tok2 && tok2->isUnaryOp(
"&") && tok2->astOperand1()->str() == rhs->str())
 
 1885                 out_ifStatementScopeStart = getIfStmtBodyStart(tok2, rhs);
 
 1899                 "'operator=' should check for assignment to self to avoid problems with dynamic memory.\n" 
 1900                 "'operator=' should check for assignment to self to ensure that each block of dynamically " 
 1918     std::list<const Function *> inconclusiveErrors;
 
 1926             if (printInconclusive) {
 
 1930                         return func.hasVirtualSpecifier();
 
 1932                         inconclusiveErrors.push_back(destructor);
 
 1944             if (!destructor || !destructor->
hasBody())
 
 1953         const Token *derivedClass = derived->
next();
 
 1961                 if (!derivedFromScope)
 
 1971                     std::set<int> baseClassPointers;
 
 1974                         if (var && var->isPointer() && var->type() == derivedFrom)
 
 1975                             baseClassPointers.insert(var->declarationId());
 
 1979                     std::set<int> dontDelete;
 
 1986                             baseClassPointers.find(tok->next()->varId()) != baseClassPointers.end()) {
 
 1988                             const std::string tmp(
"new " + derivedClass->
str());
 
 1990                                 dontDelete.insert(tok->next()->varId());
 
 1996                                  dontDelete.find(tok->next()->varId()) != dontDelete.end()) {
 
 2011                 if (!baseDestructor) {
 
 2029                             const std::list<const Function *>::iterator found = find(inconclusiveErrors.begin(), inconclusiveErrors.end(), baseDestructor);
 
 2030                             if (found != inconclusiveErrors.end())
 
 2031                                 inconclusiveErrors.erase(found);
 
 2039     for (
const Function *func : inconclusiveErrors)
 
 2050                     "$symbol:" + Base +
"\n" 
 2051                     "$symbol:" + Derived +
"\n" 
 2052                     "Class '" + Base + 
"' which is inherited by class '" + Derived + 
"' does not have a virtual destructor.\n" 
 2053                     "Class '" + Base + 
"' which is inherited by class '" + Derived + 
"' does not have a virtual destructor. " 
 2054                     "If you destroy instances of the derived class by deleting a pointer that points to the base class, only " 
 2055                     "the destructor of the base class is executed. Thus, dynamic memory that is managed by the derived class " 
 2056                     "could leak. This can be avoided by adding a virtual destructor to the base class.", 
CWE404, 
Certainty::normal);
 
 2077         if (tok->
strAt(-1) != 
"*")
 
 2116             auto isPointerOrReference = [
this](
const Token* start, 
const Token* end) -> 
bool {
 
 2117                 bool inTemplArgList = 
false, isConstTemplArg = 
false;
 
 2118                 for (
const Token* tok = start; tok != end; tok = tok->
next()) {
 
 2119                     if (tok->str() == 
"{") 
 
 2121                     if (tok->str() == 
"<") {
 
 2123                             mSymbolDatabase->
debugMessage(tok, 
"debug", 
"CheckClass::checkConst found unlinked template argument list '" + tok->expressionString() + 
"'.");
 
 2124                         inTemplArgList = 
true;
 
 2126                     else if (tok->str() == 
">") {
 
 2127                         inTemplArgList = 
false;
 
 2128                         isConstTemplArg = 
false;
 
 2130                     else if (tok->str() == 
"const") {
 
 2131                         if (!inTemplArgList)
 
 2133                         isConstTemplArg = 
true;
 
 2141             const bool returnsPtrOrRef = isPointerOrReference(func.
retDef, func.
tokenDef);
 
 2144                 bool isTemplateArg = 
false;
 
 2146                     if (tok2->isTemplateArg() && tok2->str() == 
"const") {
 
 2147                         isTemplateArg = 
true;
 
 2156                 if (opName.compare(8, 5, 
"const") != 0 && (
endsWith(opName,
'&') || 
endsWith(opName,
'*')))
 
 2178             if ((returnsPtrOrRef || func.
isConst()) && !suggestStatic)
 
 2181             std::string classname = scope->
className;
 
 2184                 classname = std::string(nest->
className + 
"::" + classname);
 
 2192                 functionName += 
")";
 
 2194                 functionName += 
"]";
 
 2208     tok = tok->
tokAt(2);
 
 2210         tok = tok->
tokAt(2);
 
 2222         if (tok->
str() == 
"this")
 
 2227             tok = tok->
tokAt(-3);
 
 2230             tok = tok->
tokAt(-2);
 
 2235         } 
else if (tok->
str() == 
"]") {
 
 2236             tok = tok->
link()->previous();
 
 2245         if (var.
name() == tok->
str()) {
 
 2248             const Token* fqTok = tok;
 
 2250                 fqTok = fqTok->
tokAt(-2);
 
 2251             if (fqTok->
strAt(-1) == 
"::")
 
 2253             bool isMember = tok == fqTok;
 
 2254             std::string scopeStr;
 
 2255             const Scope* curScope = scope;
 
 2256             while (!isMember && curScope && curScope->
type != Scope::ScopeType::eGlobal) {
 
 2257                 scopeStr.insert(0, curScope->
className + 
" :: ");
 
 2263                 if (tok->
varId() == 0)
 
 2293             if (func.
name() == tok->
str()) {
 
 2295                 int argsPassed = tok2->
str() == 
")" ? 0 : 1;
 
 2303                 if (argsPassed == func.
argCount() ||
 
 2309     } 
else if (tok->
function()->nestedIn == scope)
 
 2310         return !tok->
function()->isStatic();
 
 2334     if (tok->
function()->nestedIn == scope)
 
 2345             if (derivedFrom && derivedFrom->
classScope) {
 
 2362     auto getFuncTok = [](
const Token* tok) -> 
const Token* {
 
 2365         bool isReturn = 
false;
 
 2366         if ((
Token::Match(tok, 
"%name% (|{") || (isReturn = 
Token::simpleMatch(tok->astParent(), 
"return {"))) && !tok->isStandardType() && !tok->isKeyword()) {
 
 2374     auto checkFuncCall = [
this, &memberAccessed](
const Token* funcTok, 
const Scope* scope, 
const Function* func) {
 
 2376             const bool isSelf = func == funcTok->
function();
 
 2383             const std::vector<const Token*> args = 
getArguments(funcTok);
 
 2384             const auto argMax = std::min<nonneg int>(args.size(), f->argCount());
 
 2386             for (
nonneg int argIndex = 0; argIndex < argMax; ++argIndex) {
 
 2387                 const Variable* 
const argVar = f->getArgumentVar(argIndex);
 
 2390                     const Token* arg = args[argIndex];
 
 2395                     varTok = varTok->
next();
 
 2409             lpar = lpar->
tokAt(2);
 
 2410         for (
const Token* tok = lpar->
next(); tok && tok != funcTok->
next()->
link(); tok = tok->next()) {
 
 2411             if (tok->str() == 
"(")
 
 2413             else if ((tok->isName() && 
isMemberVar(scope, tok)) || (tok->isUnaryOp(
"&") && (tok = tok->astOperand1()) && 
isMemberVar(scope, tok))) {
 
 2414                 const Variable* var = tok->variable();
 
 2427             const Variable* v = tok1->variable();
 
 2431             if (tok1->str() == 
"this") {
 
 2432                 if (tok1->previous()->isAssignmentOp())
 
 2434                 if (
Token::Match(tok1->previous(), 
"( this . * %var% )")) 
 
 2436                 if (
Token::simpleMatch(tok1->astParent(), 
"*") && tok1->astParent()->astParent() && tok1->astParent()->astParent()->isIncDecOp())
 
 2441             if (tok1->valueType() && tok1->valueType()->pointer > 0 && tok1->astParent() && tok1->astParent()->isCast() &&
 
 2442                 !(tok1->astParent()->valueType() &&
 
 2443                   (tok1->astParent()->valueType()->pointer == 0 || tok1->astParent()->valueType()->isConst(tok1->astParent()->valueType()->pointer))))
 
 2447             if (lhs->
str() == 
"(" && tok1->astParent() && tok1->astParent()->astParent())
 
 2453             if (lhs->
str() == 
"&") {
 
 2465                 if (lhs->
astParent()->strAt(1) != 
"const")
 
 2475             const Token* jumpBackToken = 
nullptr;
 
 2476             const Token *lastVarTok = tok1;
 
 2477             const Token *end = tok1;
 
 2480                     end = end->
tokAt(2);
 
 2483                 } 
else if (end->
strAt(1) == 
"[") {
 
 2495                                 if (std::none_of(funcMap.cbegin(), funcMap.cend(), [](
const std::pair<std::string, const Function*>& fm) {
 
 2496                                     return fm.second->isConst() && fm.first == 
"operator[]" && !Function::returnsConst(fm.second);
 
 2503                         jumpBackToken = end->
next(); 
 
 2505                 } 
else if (end->
strAt(1) == 
")")
 
 2511             auto hasOverloadedMemberAccess = [](
const Token* end, 
const Scope* scope) -> 
bool {
 
 2514                 const std::string op = 
"operator" + end->
astParent()->originalName();
 
 2516                     return f.isConst() && f.name() == op;
 
 2518                 if (it == scope->
functionList.end() || !it->retType || !it->retType->classScope)
 
 2521                 return func && func->
isConst();
 
 2524             if (end->
strAt(1) == 
"(") {
 
 2529                      && (
Token::Match(end, 
"size|empty|cend|crend|cbegin|crbegin|max_size|length|count|capacity|get_allocator|c_str|str ( )") || 
Token::Match(end, 
"rfind|copy"))) ||
 
 2534                      && (tok1->previous()->isComparisonOp() ||
 
 2535                          (tok1->previous()->isAssignmentOp() && tok1->tokAt(-2)->variable() && 
Token::Match(tok1->tokAt(-2)->variable()->typeEndToken(), 
"const_iterator|const_reverse_iterator"))))) {
 
 2542                 } 
else if (hasOverloadedMemberAccess(end, var->
typeScope())) {
 
 2555             else if (end->
strAt(1) == 
"<<" && tok1->strAt(-1) != 
"<<")
 
 2565             const Token* start = tok1;
 
 2566             while (tok1->strAt(-1) == 
")")
 
 2569             if (start->
strAt(-1) == 
"delete")
 
 2572             tok1 = jumpBackToken?jumpBackToken:end; 
 
 2573             if (tok1 == end && 
Token::Match(end->
previous(), 
". %name% ( !!)") && !checkFuncCall(tok1, scope, func)) 
 
 2580             const Variable* var = tok1->tokAt(-2)->variable();
 
 2591         else if (
const Token* funcTok = getFuncTok(tok1)) {
 
 2592             if (!checkFuncCall(funcTok, scope, func))
 
 2594         } 
else if (
Token::simpleMatch(tok1, 
"> (") && (!tok1->link() || !
Token::Match(tok1->link()->previous(), 
"static_cast|const_cast|dynamic_cast|reinterpret_cast"))) {
 
 2609     std::list<const Token *> toks{ tok1 };
 
 2611         toks.push_back(tok2);
 
 2614                     "$symbol:" + classname + 
"::" + funcname +
"\n" 
 2615                     "Technically the member function '$symbol' can be const.\n" 
 2616                     "The member function '$symbol' can be made a const " 
 2617                     "function. Making this function 'const' should not cause compiler errors. " 
 2618                     "Even though the function can be made const function technically it may not make " 
 2619                     "sense conceptually. Think about your design and the task of the function first - is " 
 2623                     "$symbol:" + classname + 
"::" + funcname +
"\n" 
 2624                     "Technically the member function '$symbol' can be static (but you may consider moving to unnamed namespace).\n" 
 2625                     "The member function '$symbol' can be made a static " 
 2626                     "function. Making a function static can bring a performance benefit since no 'this' instance is " 
 2627                     "passed to the function. This change should not cause compiler errors but it does not " 
 2628                     "necessarily make sense conceptually. Think about your design and the task of the function first - " 
 2629                     "is it a function that must not access members of class instances? And maybe it is more appropriate " 
 2640             : var(_var), tok(_tok) {}
 
 2644         std::vector<const Variable*> initArgs;
 
 2660     logChecker(
"CheckClass::initializerListOrder"); 
 
 2665         for (std::list<Function>::const_iterator func = scope->
functionList.cbegin(); func != scope->
functionList.cend(); ++func) {
 
 2666             if (func->isConstructor() && func->hasBody()) {
 
 2668                 const Token *tok = func->arg->
link()->next();
 
 2670                 if (tok->
str() == 
":") {
 
 2671                     std::vector<VarInfo> vars;
 
 2675                     for (; tok && tok != func->functionScope->bodyStart; tok = tok->
next()) {
 
 2680                                 vars.emplace_back(var, tok);
 
 2684                             for (; tok != end; tok = tok->
next()) {
 
 2686                                     if (scope != argVar->scope())
 
 2688                                     if (argVar->isStatic())
 
 2698                                     vars.back().initArgs.emplace_back(argVar);
 
 2704                     for (
int j = 0; j < vars.size(); j++) {
 
 2706                         for (
const auto& arg : vars[j].initArgs)
 
 2707                             if (vars[j].var->index() < arg->index())
 
 2714                         if (vars[j].var->index() < vars[j - 1].var->index())
 
 2725     std::list<const Token *> toks = { tok1, tok2 };
 
 2726     const std::string msg = argname.empty() ?
 
 2727                             "Member variable '$symbol' is in the wrong place in the initializer list." :
 
 2728                             "Member variable '$symbol' uses an uninitialized argument '" + argname + 
"' due to the order of declarations.";
 
 2730                 "$symbol:" + classname + 
"::" + varname + 
'\n' +
 
 2733                 "Members are initialized in the order they are declared, not in the " 
 2734                 "order they are in the initializer list. Keeping the initializer list " 
 2735                 "in the same order that the members were declared prevents order dependent " 
 2746     logChecker(
"CheckClass::checkSelfInitialization");
 
 2750         if (!
function || !function->isConstructor())
 
 2753         const Token* tok = 
function->arg->
link()->next();
 
 2754         if (tok->
str() != 
":")
 
 2762                         if (initTok->varId() == varTok->
varId())
 
 2764                         else if (initTok->isCast() && ((initTok->astOperand1() && initTok->astOperand1()->varId() == varTok->
varId()) || (initTok->astOperand2() && initTok->astOperand2()->varId() == varTok->
varId())))
 
 2787     logChecker(
"CheckClass::checkVirtualFunctionCallInConstructor"); 
 
 2788     std::map<const Function *, std::list<const Token *>> virtualFunctionCallsMap;
 
 2796         for (
const Token *callToken : virtualFunctionCalls) {
 
 2797             std::list<const Token *> callstack(1, callToken);
 
 2799             if (callstack.empty())
 
 2801             const Function* 
const func = callstack.back()->function();
 
 2814                                                                      std::map<
const Function *, std::list<const Token *>> & virtualFunctionCallsMap)
 
 2816     const std::map<const Function *, std::list<const Token *>>::const_iterator found = virtualFunctionCallsMap.find(&
function);
 
 2817     if (found != virtualFunctionCallsMap.end())
 
 2818         return found->second;
 
 2820     virtualFunctionCallsMap[&
function] = std::list<const Token *>();
 
 2821     std::list<const Token *> & virtualFunctionCalls = virtualFunctionCallsMap.find(&
function)->second;
 
 2823     if (!
function.hasBody() || !
function.functionScope)
 
 2824         return virtualFunctionCalls;
 
 2826     for (
const Token *tok = 
function.arg->
link(); tok != 
function.functionScope->bodyEnd; tok = tok->next()) {
 
 2834                 tok = tok->linkAt(1);
 
 2839             tok = tok->scope()->bodyEnd->next();
 
 2841         const Function * callFunction = tok->function();
 
 2842         if (!callFunction ||
 
 2843             function.nestedIn != callFunction->
nestedIn ||
 
 2845             !(tok->astParent() && (tok->astParent()->str() == 
"(" || (tok->astParent()->str() == 
"::" && 
Token::simpleMatch(tok->astParent()->astParent(), 
"(")))))
 
 2848         if (tok->previous() &&
 
 2849             tok->previous()->str() == 
"(") {
 
 2860             virtualFunctionCalls.push_back(tok);
 
 2864         const std::list<const Token *> & virtualFunctionCallsOfTok = 
getVirtualFunctionCalls(*callFunction, virtualFunctionCallsMap);
 
 2865         if (!virtualFunctionCallsOfTok.empty())
 
 2866             virtualFunctionCalls.push_back(tok);
 
 2868     return virtualFunctionCalls;
 
 2872     std::map<
const Function *, std::list<const Token *>> & virtualFunctionCallsMap,
 
 2873     const Token * callToken,
 
 2874     std::list<const Token *> & pureFuncStack)
 
 2878         pureFuncStack.push_back(callFunction->
tokenDef);
 
 2881     std::map<const Function *, std::list<const Token *>>::const_iterator found = virtualFunctionCallsMap.find(callFunction);
 
 2882     if (found == virtualFunctionCallsMap.cend() || found->second.empty()) {
 
 2883         pureFuncStack.clear();
 
 2886     const Token * firstCall = *found->second.cbegin();
 
 2887     pureFuncStack.push_back(firstCall);
 
 2893     const std::list<const Token *> & tokStack,
 
 2894     const std::string &funcname)
 
 2899     const char * scopeFunctionTypeName = scopeFunction ? 
getFunctionTypeName(scopeFunction->
type) : 
"constructor";
 
 2902     std::transform(tokStack.cbegin(), tokStack.cend(), std::back_inserter(errorPath), [](
const Token* tok) {
 
 2903         return ErrorPathItem(tok, 
"Calling " + tok->str());
 
 2906     if (!errorPath.empty()) {
 
 2907         lineNumber = errorPath.front().first->linenr();
 
 2908         errorPath.back().second = funcname + 
" is a virtual function";
 
 2911     std::string constructorName;
 
 2912     if (scopeFunction) {
 
 2914         if (scopeFunction->
type == Function::Type::eDestructor)
 
 2915             constructorName = 
"~";
 
 2916         for (
const Token *tok = scopeFunction->
tokenDef; tok != endToken; tok = tok->
next()) {
 
 2918                 constructorName += 
' ';
 
 2919             constructorName += tok->
str();
 
 2920             if (tok->
str() == 
")")
 
 2926                 "Virtual function '" + funcname + 
"' is called from " + scopeFunctionTypeName + 
" '" + constructorName + 
"' at line " + std::to_string(lineNumber) + 
". Dynamic binding is not used.", 
CWE(0U), 
Certainty::normal);
 
 2931     const std::list<const Token *> & tokStack,
 
 2932     const std::string &purefuncname)
 
 2934     const char * scopeFunctionTypeName = scopeFunction ? 
getFunctionTypeName(scopeFunction->
type) : 
"constructor";
 
 2937     std::transform(tokStack.cbegin(), tokStack.cend(), std::back_inserter(errorPath), [](
const Token* tok) {
 
 2938         return ErrorPathItem(tok, 
"Calling " + tok->str());
 
 2940     if (!errorPath.empty())
 
 2941         errorPath.back().second = purefuncname + 
" is a pure virtual function without body";
 
 2944                 "$symbol:" + purefuncname +
"\n" 
 2945                 "Call of pure virtual function '$symbol' in " + scopeFunctionTypeName + 
".\n" 
 2946                 "Call of pure virtual function '$symbol' in " + scopeFunctionTypeName + 
". The call will fail during runtime.", 
CWE(0U), 
Certainty::normal);
 
 2959     logChecker(
"CheckClass::checkDuplInheritedMembers"); 
 
 2969     struct DuplMemberInfo {
 
 2975     struct DuplMemberFuncInfo {
 
 2985     std::vector<DuplMemberInfo> results;
 
 2991         if (parentClassIt.
type == typeBase)
 
 2996                 if (classVarIt.
name() == parentClassVarIt.
name() && (!parentClassVarIt.
isPrivate() || !skipPrivate)) 
 
 2997                     results.emplace_back(&classVarIt, &parentClassVarIt, &parentClassIt);
 
 3000         if (typeCurrent != parentClassIt.
type) {
 
 3002             results.insert(results.end(), recursive.begin(), recursive.end());
 
 3010     std::vector<DuplMemberFuncInfo> results;
 
 3016         if (parentClassIt.
type == typeBase)
 
 3022                 if (classFuncIt.
name() == parentClassFuncIt.
name() &&
 
 3028                     results.emplace_back(&classFuncIt, &parentClassFuncIt, &parentClassIt);
 
 3031         if (typeCurrent != parentClassIt.
type) {
 
 3033             results.insert(results.end(), recursive.begin(), recursive.end());
 
 3042     for (
const auto& r : resultsVar) {
 
 3044                                   typeCurrent->
name(), r.parentClass->type->name(), r.classVar->name(),
 
 3050     for (
const auto& r : resultsFunc) {
 
 3052                                   typeCurrent->
name(), r.parentClass->type->name(), r.classFunc->name(),
 
 3059                                            const std::string &derivedName, 
const std::string &baseName,
 
 3060                                            const std::string &memberName, 
bool derivedIsStruct, 
bool baseIsStruct, 
bool isFunction)
 
 3063     const std::string member = isFunction ? 
"function" : 
"variable";
 
 3064     errorPath.emplace_back(tok2, 
"Parent " + member + 
" '" + baseName + 
"::" + memberName + 
"'");
 
 3065     errorPath.emplace_back(tok1, 
"Derived " + member + 
" '" + derivedName + 
"::" + memberName + 
"'");
 
 3067     const std::string symbols = 
"$symbol:" + derivedName + 
"\n$symbol:" + memberName + 
"\n$symbol:" + baseName;
 
 3069     const std::string message = 
"The " + std::string(derivedIsStruct ? 
"struct" : 
"class") + 
" '" + derivedName +
 
 3070                                 "' defines member " + member + 
" with name '" + memberName + 
"' also defined in its parent " +
 
 3071                                 std::string(baseIsStruct ? 
"struct" : 
"class") + 
" '" + baseName + 
"'.";
 
 3098         const bool hasNonStaticVars = std::any_of(scope->
varlist.begin(), scope->
varlist.end(), [](
const Variable& var) {
 
 3099             return !var.isStatic();
 
 3101         if (!hasNonStaticVars)
 
 3105         bool moveCtor = 
false;
 
 3141     const std::string message = 
"$symbol:" + classname + 
"\n" 
 3142                                 "The " + std::string(isStruct ? 
"struct" : 
"class") + 
" '$symbol' has '" +
 
 3155     logChecker(
"CheckClass::checkMissingOverride"); 
 
 3171     const std::string functionName = funcInDerived ? ((funcInDerived->
isDestructor() ? 
"~" : 
"") + funcInDerived->
name()) : 
"";
 
 3172     const std::string funcType = (funcInDerived && funcInDerived->
isDestructor()) ? 
"destructor" : 
"function";
 
 3175     if (funcInBase && funcInDerived) {
 
 3176         errorPath.emplace_back(funcInBase->
tokenDef, 
"Virtual " + funcType + 
" in base class");
 
 3177         errorPath.emplace_back(funcInDerived->
tokenDef, 
char(std::toupper(funcType[0])) + funcType.substr(1) + 
" in derived class");
 
 3181                 "$symbol:" + functionName + 
"\n" 
 3182                 "The " + funcType + 
" '$symbol' overrides a " + funcType + 
" in a base class but is not marked with a 'override' specifier.",
 
 3189     const std::string functionName = funcInDerived ? ((funcInDerived->
isDestructor() ? 
"~" : 
"") + funcInDerived->
name()) : 
"";
 
 3190     const std::string funcType = (funcInDerived && funcInDerived->
isDestructor()) ? 
"destructor" : 
"function";
 
 3193     if (funcInBase && funcInDerived) {
 
 3194         errorPath.emplace_back(funcInBase->
tokenDef, 
"Virtual " + funcType + 
" in base class");
 
 3195         errorPath.emplace_back(funcInDerived->
tokenDef, 
char(std::toupper(funcType[0])) + funcType.substr(1) + 
" in derived class");
 
 3198     std::string errStr = 
"\nThe " + funcType + 
" '$symbol' overrides a " + funcType + 
" in a base class but ";
 
 3200         errStr += 
"is identical to the overridden function";
 
 3203         errStr += 
"just delegates back to the base class.";
 
 3205                 "$symbol:" + functionName +
 
 3216     const Token* ftok = start;
 
 3217     if (ftok->
str() == 
"return")
 
 3221             ftok = ftok->
next();
 
 3229     const Token* tok1 = start1;
 
 3230     const Token* tok2 = start2;
 
 3232     while (tok1 && tok2) {
 
 3235         if (tok1->
str() != tok2->
str())
 
 3237         if (tok1->
str() == 
"this")
 
 3241         if (tok1 == end1 && tok2 == end2) {
 
 3245         tok1 = tok1->
next();
 
 3246         tok2 = tok2->
next();
 
 3256     logChecker(
"CheckClass::checkUselessOverride"); 
 
 3272                 return f.name() == func.name();
 
 3295                 if (call->function() != baseFunc)
 
 3298                 std::vector<const Token*> callArgs = 
getArguments(call);
 
 3299                 if (funcArgs.size() != callArgs.size() ||
 
 3300                     !std::equal(funcArgs.begin(), funcArgs.end(), callArgs.begin(), [](
const Token* t1, 
const Token* t2) {
 
 3301                     return t1->str() == t2->str();
 
 3327     logChecker(
"CheckClass::checkReturnByReference"); 
 
 3338                 if (container->view)
 
 3341                 if (!var->valueType())
 
 3343                 if (var->isArgument())
 
 3345                 const bool isContainer = var->valueType()->type == ValueType::Type::CONTAINER && var->valueType()->container;
 
 3346                 const bool isView = isContainer && var->valueType()->container->view;
 
 3347                 bool warn = isContainer && !isView;
 
 3348                 if (!warn && !isView) {
 
 3363     const std::string message = 
"Function '" + (func ? func->
name() : 
"func") + 
"()' should return member '" + (var ? var->
name() : 
"var") + 
"' by const reference.";
 
 3372     logChecker(
"CheckClass::checkThisUseAfterFree"); 
 
 3386                 bool hasAssign = 
false;
 
 3388                     if (func.
type != Function::Type::eFunction || !func.
hasBody())
 
 3405                 if (func.
type != Function::Type::eFunction || !func.
hasBody())
 
 3408                 const Token * freeToken = 
nullptr;
 
 3409                 std::set<const Function *> callstack;
 
 3422     if (callstack.count(func))
 
 3424     callstack.insert(func);
 
 3428     for (
const Token *tok = bodyStart; tok != bodyEnd; tok = tok->
next()) {
 
 3429         const bool isDestroyed = freeToken != 
nullptr && !func->
isStatic();
 
 3430         if (
Token::Match(tok, 
"delete %var% ;") && selfPointer == tok->next()->variable()) {
 
 3432             tok = tok->
tokAt(2);
 
 3433         } 
else if (
Token::Match(tok, 
"%var% . reset ( )") && selfPointer == tok->variable())
 
 3435         else if (
Token::Match(tok->previous(), 
"!!. %name% (") && tok->function() && tok->function()->nestedIn == classScope) {
 
 3442         } 
else if (isDestroyed && 
Token::Match(tok->previous(), 
"!!. %name%") && tok->variable() && tok->variable()->scope() == classScope && !tok->variable()->isStatic() && !tok->variable()->isArgument()) {
 
 3445         } 
else if (freeToken && 
Token::Match(tok, 
"return|throw")) {
 
 3447             return tok->str() == 
"throw";
 
 3448         } 
else if (tok->str() == 
"{" && tok->scope()->type == Scope::ScopeType::eLambda) {
 
 3457     std::string selfPointer = 
self ? 
self->str() : 
"ptr";
 
 3458     const ErrorPath errorPath = { 
ErrorPathItem(
self, 
"Assuming '" + selfPointer + 
"' is used as 'this'"), 
ErrorPathItem(free, 
"Delete '" + selfPointer + 
"', invalidating 'this'"), 
ErrorPathItem(use, 
"Call method when 'this' is invalid") };
 
 3459     const std::string usestr = use ? use->
str() : 
"x";
 
 3460     const std::string usemsg = use && use->
function() ? (
"Calling method '" + usestr + 
"()'") : (
"Using member '" + usestr + 
"'");
 
 3462                 "$symbol:" + selfPointer + 
"\n" +
 
 3463                 usemsg + 
" when 'this' might be invalid",
 
 3471     logChecker(
"CheckClass::checkUnsafeClassRefMember"); 
 
 3494                 "$symbol:" + varname + 
"\n" 
 3495                 "Unsafe class: The const reference member '$symbol' is initialized by a const reference constructor argument. You need to be careful about lifetime issues.\n" 
 3496                 "Unsafe class checking: The const reference member '$symbol' is initialized by a const reference constructor argument. You need to be careful about lifetime issues. If you pass a local variable or temporary value in this constructor argument, be extra careful. If the argument is always some global object that is never destroyed then this is safe usage. However it would be defensive to make the member '$symbol' a non-reference variable or a smart pointer.",
 
 3503 inline namespace CheckClass_internal
 
 3512             std::string className;
 
 3513             std::string fileName;
 
 3518             bool isSameLocation(
const NameLoc& other)
 const {
 
 3519                 return fileName == other.fileName &&
 
 3520                        lineNumber == other.lineNumber &&
 
 3521                        column == other.column;
 
 3524         std::vector<NameLoc> classDefinitions;
 
 3527         std::string 
toString()
 const override 
 3530             for (
const NameLoc &nameLoc: classDefinitions) {
 
 3533                        "\" line=\"" + std::to_string(nameLoc.lineNumber) +
 
 3534                        "\" col=\"" + std::to_string(nameLoc.column) +
 
 3535                        "\" hash=\"" + std::to_string(nameLoc.hash) +
 
 3545     if (!tokenizer.
isCPP())
 
 3549     std::vector<MyFileInfo::NameLoc> classDefinitions;
 
 3551         if (classScope->isAnonymous())
 
 3554         if (classScope->classDef && 
Token::simpleMatch(classScope->classDef->previous(), 
">"))
 
 3558         const bool fullDefinition = std::all_of(classScope->functionList.cbegin(),
 
 3559                                                 classScope->functionList.cend(),
 
 3563         if (!fullDefinition)
 
 3567         const Scope *scope = classScope;
 
 3580         if (scope->
type != Scope::ScopeType::eGlobal)
 
 3583         MyFileInfo::NameLoc nameLoc;
 
 3584         nameLoc.className = std::move(
name);
 
 3585         nameLoc.fileName = tokenizer.
list.
file(classScope->classDef);
 
 3586         nameLoc.lineNumber = classScope->classDef->linenr();
 
 3587         nameLoc.column = classScope->classDef->column();
 
 3591         for (
const Token *tok = classScope->classDef; tok != classScope->bodyEnd; tok = tok->
next())
 
 3593         for (
const Function &f: classScope->functionList) {
 
 3599         nameLoc.hash = std::hash<std::string> {}(def);
 
 3601         classDefinitions.push_back(std::move(nameLoc));
 
 3604     if (classDefinitions.empty())
 
 3607     auto *fileInfo = 
new MyFileInfo;
 
 3608     fileInfo->classDefinitions.swap(classDefinitions);
 
 3614     auto *fileInfo = 
new MyFileInfo;
 
 3615     for (
const tinyxml2::XMLElement *e = xmlElement->FirstChildElement(); e; e = e->NextSiblingElement()) {
 
 3616         if (std::strcmp(e->Name(), 
"class") != 0)
 
 3618         const char *
name = e->Attribute(
"name");
 
 3619         const char *file = e->Attribute(
"file");
 
 3620         const char *line = e->Attribute(
"line");
 
 3621         const char *col = e->Attribute(
"col");
 
 3622         const char *hash = e->Attribute(
"hash");
 
 3623         if (
name && file && line && col && hash) {
 
 3624             MyFileInfo::NameLoc nameLoc;
 
 3625             nameLoc.className = 
name;
 
 3626             nameLoc.fileName = file;
 
 3627             nameLoc.lineNumber = strToInt<int>(line);
 
 3628             nameLoc.column = strToInt<int>(col);
 
 3629             nameLoc.hash = strToInt<std::size_t>(hash);
 
 3630             fileInfo->classDefinitions.push_back(std::move(nameLoc));
 
 3633     if (fileInfo->classDefinitions.empty()) {
 
 3642     bool foundErrors = 
false;
 
 3646     std::unordered_map<std::string, MyFileInfo::NameLoc> all;
 
 3648     CheckClass dummy(
nullptr, &settings, &errorLogger);
 
 3650     logChecker(
"CheckClass::analyseWholeProgram");
 
 3653         const MyFileInfo *fi = 
dynamic_cast<const MyFileInfo*
>(fi1);
 
 3656         for (
const MyFileInfo::NameLoc &nameLoc : fi->classDefinitions) {
 
 3657             auto it = all.find(nameLoc.className);
 
 3658             if (it == all.end()) {
 
 3659                 all[nameLoc.className] = nameLoc;
 
 3662             if (it->second.hash == nameLoc.hash)
 
 3665             if (it->second.isSameLocation(nameLoc))
 
 3668             std::list<ErrorMessage::FileLocation> locationList;
 
 3669             locationList.emplace_back(nameLoc.fileName, nameLoc.lineNumber, nameLoc.column);
 
 3670             locationList.emplace_back(it->second.fileName, it->second.lineNumber, it->second.column);
 
 3675                                       "$symbol:" + nameLoc.className +
 
 3676                                       "\nThe one definition rule is violated, different classes/structs have the same name '$symbol'",
 
 3677                                       "ctuOneDefinitionRuleViolation",
 
std::vector< const Token * > getArguments(const Token *ftok)
Get arguments (AST)
 
bool astIsRangeBasedForDecl(const Token *tok)
Is given token a range-declaration in a range-based for loop.
 
bool precedes(const Token *tok1, const Token *tok2)
If tok2 comes after tok1.
 
bool isLikelyStreamRead(const Token *op)
do we see a likely write of rhs through overloaded operator s >> x; a & x;
 
const Token * findLambdaEndToken(const Token *first)
find lambda function end token
 
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)
 
void visitAstNodes(T *ast, const TFunc &visitor)
Visit AST nodes recursively.
 
#define WRONG_DATA(COND, TOK)
Use WRONG_DATA in checkers to mark conditions that check that data is correct.
 
static bool isVclTypeInit(const Type *type)
 
static std::vector< DuplMemberFuncInfo > getDuplInheritedMemberFunctionsRecursive(const Type *typeCurrent, const Type *typeBase, bool skipPrivate=true)
 
static const Token * getFuncTokFromThis(const Token *tok)
 
static const CWE CWE398(398U)
 
static const CWE CWE762(762U)
 
static const CWE CWE_ONE_DEFINITION_RULE(758U)
 
static std::vector< DuplMemberInfo > getDuplInheritedMembersRecursive(const Type *typeCurrent, const Type *typeBase, bool skipPrivate=true)
 
static const Token * getSingleFunctionCall(const Scope *scope)
 
static const CWE CWE758(758U)
 
static const CWE CWE665(665U)
 
static bool isTrueKeyword(const Token *tok)
 
static std::string noMemberErrorMessage(const Scope *scope, const char function[], bool isdefault)
 
static const Variable * getSingleReturnVar(const Scope *scope)
 
static bool checkFunctionUsage(const Function *privfunc, const Scope *scope)
 
static const Scope * findFunctionOf(const Scope *scope)
 
static bool isVariableCopyNeeded(const Variable &var, Function::Type type)
 
static const CWE CWE404(404U)
 
static bool hasNonCopyableBase(const Scope *scope, bool *unknown)
 
static const char * getFunctionTypeName(Function::Type type)
 
static bool compareTokenRanges(const Token *start1, const Token *end1, const Token *start2, const Token *end2)
 
static void getAllVariableMembers(const Scope *scope, std::vector< const Variable * > &varList)
 
static bool isFalseKeyword(const Token *tok)
 
static bool isConstMemberFunc(const Scope *scope, const Token *tok)
 
bool checkThisUseAfterFreeRecursive(const Scope *classScope, const Function *func, const Variable *selfPointer, std::set< const Function * > callstack, const Token *&freeToken)
Helper for checkThisUseAfterFree.
 
bool analyseWholeProgram(const CTU::FileInfo *ctu, const std::list< Check::FileInfo * > &fileInfo, const Settings &settings, ErrorLogger &errorLogger) override
Analyse all file infos for all TU.
 
void operatorEqMissingReturnStatementError(const Token *tok, bool error)
 
static void getFirstVirtualFunctionCallStack(std::map< const Function *, std::list< const Token * >> &virtualFunctionCallsMap, const Token *callToken, std::list< const Token * > &pureFuncStack)
looks for the first virtual function call stack
 
bool checkConstFunc(const Scope *scope, const Function *func, MemberAccess &memberAccessed) const
 
void overrideError(const Function *funcInBase, const Function *funcInDerived)
 
const SymbolDatabase * mSymbolDatabase
 
Check::FileInfo * getFileInfo(const Tokenizer &tokenizer, const Settings &settings) const override
Parse current TU and extract file info.
 
bool hasAllocation(const Function *func, const Scope *scope) const
 
void checkCopyCtorAndEqOperator()
Check that copy constructor and operator defined together.
 
void checkOverride()
Check that the override keyword is used when overriding virtual functions.
 
void uninitVarError(const Token *tok, bool isprivate, Function::Type functionType, const std::string &classname, const std::string &varname, bool derived, bool inconclusive)
 
void thisSubtraction()
warn for "this-x".
 
void checkThisUseAfterFree()
When "self pointer" is destroyed, 'this' might become invalid.
 
void initializerListError(const Token *tok1, const Token *tok2, const std::string &classname, const std::string &varname, const std::string &argname={})
 
void checkReturnPtrThis(const Scope *scope, const Function *func, const Token *tok, const Token *last)
 
void noExplicitConstructorError(const Token *tok, const std::string &classname, bool isStruct)
 
void operatorEqRetRefThis()
'operator=' should return reference to *this
 
void operatorEqToSelfError(const Token *tok)
 
void operatorEqVarError(const Token *tok, const std::string &classname, const std::string &varname, bool inconclusive)
 
void duplInheritedMembersError(const Token *tok1, const Token *tok2, const std::string &derivedName, const std::string &baseName, const std::string &memberName, bool derivedIsStruct, bool baseIsStruct, bool isFunction=false)
 
void uselessOverrideError(const Function *funcInBase, const Function *funcInDerived, bool isSameCode=false)
 
static void initVar(std::vector< Usage > &usageList, nonneg int varid)
initialize a variable in the varlist
 
static bool canNotCopy(const Scope *scope)
 
void mallocOnClassWarning(const Token *tok, const std::string &memfunc, const Token *classTok)
 
void copyConstructorShallowCopyError(const Token *tok, const std::string &varname)
 
void unusedPrivateFunctionError(const Token *tok, const std::string &classname, const std::string &funcname)
 
void checkUnsafeClassRefMember()
Unsafe class check - const reference member.
 
void virtualFunctionCallInConstructorError(const Function *scopeFunction, const std::list< const Token * > &tokStack, const std::string &funcname)
 
CheckClass()
This constructor is used when registering the CheckClass.
 
static bool hasAssignSelf(const Function *func, const Token *rhs, const Token *&out_ifStatementScopeStart)
 
void thisSubtractionError(const Token *tok)
 
void checkReturnByReference()
Check that large members are returned by reference from getter function.
 
void checkDuplInheritedMembers()
Check duplicated inherited members.
 
void operatorEqToSelf()
'operator=' should check for assignment to self
 
static void assignAllVar(std::vector< Usage > &usageList)
set all variables in list assigned
 
static bool isBaseClassMutableMemberFunc(const Token *tok, const Scope *scope)
 
void selfInitializationError(const Token *tok, const std::string &varname)
 
bool isMemberVar(const Scope *scope, const Token *tok) const
 
void operatorEqShouldBeLeftUnimplementedError(const Token *tok)
 
const std::list< const Token * > & getVirtualFunctionCalls(const Function &function, std::map< const Function *, std::list< const Token * >> &virtualFunctionCallsMap)
gives a list of tokens where virtual functions are called directly or indirectly
 
void mallocOnClassError(const Token *tok, const std::string &memfunc, const Token *classTok, const std::string &classname)
 
static bool canNotMove(const Scope *scope)
 
void noConstructorError(const Token *tok, const std::string &classname, bool isStruct)
 
void privateFunctions()
Check that all private functions are called
 
void virtualDestructorError(const Token *tok, const std::string &Base, const std::string &Derived, bool inconclusive)
 
void checkUselessOverride()
Check that the overriden function is not identical to the base function.
 
static void clearAllVar(std::vector< Usage > &usageList)
set all variables in list not assigned and not initialized
 
static bool isMemberFunc(const Scope *scope, const Token *tok)
 
void initializerListOrder()
Check initializer list order.
 
void initializationListUsage()
Suggest using initialization list.
 
static void assignAllVarsVisibleFromScope(std::vector< Usage > &usageList, const Scope *scope)
set all variable in list assigned, if visible from given scope
 
void checkDuplInheritedMembersRecursive(const Type *typeCurrent, const Type *typeBase)
 
void initializeVarList(const Function &func, std::list< const Function * > &callstack, const Scope *scope, std::vector< Usage > &usage) const
parse a scope for a constructor or member function and set the "init" flags in the provided varlist
 
void checkMemset()
Check that the memsets are valid.
 
void noDestructorError(const Scope *scope, bool isdefault, const Token *alloc)
 
void missingMemberCopyError(const Token *tok, Function::Type functionType, const std::string &classname, const std::string &varname)
 
void checkVirtualFunctionCallInConstructor()
call of virtual function in constructor/destructor
 
static std::vector< Usage > createUsageList(const Scope *scope)
Create usage list that contains all scope members and also members of base classes without constructo...
 
void memsetErrorFloat(const Token *tok, const std::string &type)
 
void noCopyConstructorError(const Scope *scope, bool isdefault, const Token *alloc, bool inconclusive)
 
void checkConstError(const Token *tok, const std::string &classname, const std::string &funcname, bool suggestStatic)
 
void constructors()
Check that all class constructors are ok
 
void checkSelfInitialization()
Check for initialization of a member with itself.
 
static void assignVar(std::vector< Usage > &usageList, nonneg int varid)
assign a variable in the varlist
 
void checkConstError2(const Token *tok1, const Token *tok2, const std::string &classname, const std::string &funcname, bool suggestStatic)
 
static Bool isInverted(const Token *tok, const Token *rhs)
 
void operatorEqRetRefThisError(const Token *tok)
 
void checkMemsetType(const Scope *start, const Token *tok, const Scope *type, bool allocation, std::set< const Scope * > parsedTypes)
 
static const Token * getIfStmtBodyStart(const Token *tok, const Token *rhs)
 
void noOperatorEqError(const Scope *scope, bool isdefault, const Token *alloc, bool inconclusive)
 
static const std::set< std::string > stl_containers_not_const
Set of the STL types whose operator[] is not const.
 
Check::FileInfo * loadFileInfoFromXml(const tinyxml2::XMLElement *xmlElement) const override
 
void virtualDestructor()
The destructor in a base class should be virtual.
 
void suggestInitializationList(const Token *tok, const std::string &varname)
 
void returnByReferenceError(const Function *func, const Variable *var)
 
void memsetErrorReference(const Token *tok, const std::string &memfunc, const std::string &type)
 
void pureVirtualFunctionCallInConstructorError(const Function *scopeFunction, const std::list< const Token * > &tokStack, const std::string &purefuncname)
 
void unsafeClassRefMemberError(const Token *tok, const std::string &varname)
 
void memsetError(const Token *tok, const std::string &memfunc, const std::string &classname, const std::string &type, bool isContainer=false)
 
void checkConst()
can member function be const?
 
void thisUseAfterFree(const Token *self, const Token *free, const Token *use)
 
void checkExplicitConstructors()
Check that constructors with single parameter are explicit, if they has to be.
 
void copyCtorAndEqOperatorError(const Token *tok, const std::string &classname, bool isStruct, bool hasCopyCtor)
 
bool hasAllocationInIfScope(const Function *func, const Scope *scope, const Token *ifStatementScopeStart) const
 
Base class used for whole-program analysis.
 
Interface class that cppcheck uses to communicate with the checks.
 
void reportError(const Token *tok, const Severity severity, const std::string &id, const std::string &msg)
report an error
 
const Settings *const mSettings
 
const Tokenizer *const mTokenizer
 
void logChecker(const char id[])
log checker
 
const std::string & name() const
class name, used to generate documentation
 
This is an interface, which the class responsible of error logging should implement.
 
virtual void reportErr(const ErrorMessage &msg)=0
Information about found errors and warnings is directed here.
 
static std::string toxml(const std::string &str)
Convert XML-sensitive characters into XML entities.
 
Wrapper for error messages, provided by reportErr()
 
AccessControl access
public/protected/private
 
nonneg int minArgCount() const
 
bool hasFinalSpecifier() const
 
const std::string & name() const
 
const Token * argDef
function argument start '(' in class definition
 
const Scope * functionScope
scope of function body
 
const Function * getOverriddenFunction(bool *foundAllBaseClasses=nullptr) const
get function in base class that is overridden
 
static bool returnsConst(const Function *function, bool unknown=false)
 
Type type
constructor, destructor, ...
 
static bool returnsPointer(const Function *function, bool unknown=false)
 
static bool returnsReference(const Function *function, bool unknown=false, bool includeRValueRef=false)
 
bool argsMatch(const Scope *scope, const Token *first, const Token *second, const std::string &path, nonneg int path_length) const
 
const Variable * getArgumentVar(nonneg int num) const
 
nonneg int argCount() const
 
const Token * retDef
function return type token
 
bool isImplicitlyVirtual(bool defaultVal=false) const
check if this function is virtual in the base classes
 
static bool returnsStandardType(const Function *function, bool unknown=false)
 
const Token * constructorMemberInitialization() const
 
const Token * token
function name token in implementation
 
const ::Type * retType
function return type
 
const Token * arg
function argument start '('
 
const Scope * nestedIn
Scope the function is declared in.
 
bool hasOverrideSpecifier() const
 
bool hasVirtualSpecifier() const
 
const Token * tokenDef
function name token in class definition
 
const Token * templateDef
points to 'template <' before function
 
std::list< Variable > argumentList
argument list, must remain list due to clangimport usage!
 
bool isDestructor() const
 
bool isConstructor() const
 
Yield getYield(const std::string &function) const
 
const Container * detectContainerOrIterator(const Token *typeStart, bool *isIterator=nullptr, bool withoutStd=false) const
 
bool isSmartPointer(const Token *tok) const
 
const AllocFunc * getAllocFuncInfo(const Token *tok) const
get allocation info for function
 
bool isScopeNoReturn(const Token *end, std::string *unknownFunc) const
 
TypeCheck getTypeCheck(std::string check, std::string typeName) const
 
const AllocFunc * getReallocFuncInfo(const Token *tok) const
get reallocation info for function
 
const PodType * podtype(const std::string &name) const
 
const AllocFunc * getDeallocFuncInfo(const Token *tok) const
get deallocation info for function
 
const Container * detectContainer(const Token *typeStart) const
 
bool isFunctionConst(const std::string &functionName, bool pure) const
 
bool ignorefunction(const std::string &functionName) const
 
std::list< Function > functionList
 
std::map< std::string, Type * > definedTypesMap
 
std::list< Variable > varlist
 
nonneg int numCopyOrMoveConstructors
 
std::multimap< std::string, const Function * > functionMap
 
std::vector< Scope * > nestedList
 
const Function * getDestructor() const
 
Function * function
function info for this function
 
const Function * findFunction(const Token *tok, bool requireConst=false) const
find a function
 
const Token * classDef
class/struct/union/namespace token
 
const Token * bodyStart
'{' token
 
const Token * bodyEnd
'}' token
 
nonneg int numConstructors
 
const Scope * functionOf
scope this function belongs to
 
const Variable * getVariable(const std::string &varname) const
get variable from name
 
bool isClassOrStruct() const
 
This is just a container for general settings so that we don't need to pass individual values to func...
 
bool hasLib(const std::string &lib) const
Is library specified?
 
bool isPremiumEnabled(const char id[]) const
Is checker id enabled by premiumArgs.
 
SimpleEnableGroup< Certainty > certainty
 
SimpleEnableGroup< Severity > severity
 
Standards standards
Struct contains standards settings.
 
bool isEnabled(T flag) const
 
const std::vector< const Variable * > & variableList() const
 
void debugMessage(const Token *tok, const std::string &type, const std::string &msg) const
output a debug message
 
std::list< Type > typeList
Fast access to types.
 
std::vector< const Scope * > functionScopes
Fast access to function scopes.
 
std::list< Scope > scopeList
Information about all namespaces/classes/structures.
 
std::vector< const Scope * > classAndStructScopes
Fast access to class and struct scopes.
 
const std::string & file(const Token *tok) const
get filename for given token
 
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.
 
static const Token * findmatch(const Token *const startTok, const char pattern[], const nonneg int varId=0)
 
bool hasKnownIntValue() const
 
MathLib::bigint getKnownIntValue() const
 
bool isExpandedMacro() const
 
bool isUpperCaseName() const
 
const ValueType * valueType() const
 
const std::string & strAt(int index) const
 
void astOperand1(Token *tok)
 
void function(const Function *f)
Associate this token with given function.
 
std::pair< const Token *, const Token * > findExpressionStartEndTokens() const
 
bool isUnaryOp(const std::string &s) 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 isStandardType() const
 
void variable(const Variable *v)
Associate this token with given variable.
 
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.
 
void astParent(Token *tok)
 
The main purpose is to tokenize the source code.
 
const Token * tokens() const
 
TokenList list
Token list: stores all tokens.
 
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.
 
const Scope * enclosingScope
 
const Token * classDef
Points to "class" token.
 
std::vector< BaseInfo > derivedFrom
 
std::vector< FriendInfo > friendList
 
enum Type::NeedInitialization needInitialization
 
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 pointer
0=>not pointer, 1=>*, 2=>**, 3=>***, etc
 
const Token * containerTypeToken
The container type token.
 
const Scope * typeScope
if the type definition is seen this point out the type scope
 
static ValueType parseDecl(const Token *type, const Settings &settings)
 
const ::Type * smartPointerType
Smart pointer type.
 
Information about a member variable.
 
bool hasDefault() const
Does variable have a default value.
 
bool isArgument() const
Is variable a function argument.
 
bool isEnumType() const
Determine whether it's an enumeration type.
 
bool isClass() const
Is variable a user defined (or unknown) type.
 
bool isArrayOrPointer() const
Is array or pointer variable.
 
const Type * smartPointerType() const
 
bool isReference() const
Is reference variable.
 
bool isFloatingType() const
Determine whether it's a floating number type.
 
std::string getTypeName() const
 
bool isStlType() const
Checks if the variable is an STL type ('std::') E.g.
 
bool isSmartPointer() const
 
const Type * type() const
Get Type pointer of known type.
 
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.
 
bool isPointerArray() const
Is variable an array of pointers.
 
bool isArray() const
Is variable an array.
 
const Token * nameToken() const
Get name token.
 
bool isPrivate() const
Is variable private.
 
nonneg int declarationId() const
Get declaration ID (varId used for variable in its declaration).
 
bool isMutable() const
Is variable mutable.
 
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
 
std::string toString(Color c)
 
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.
 
Whole program analysis (ctu=Cross Translation Unit)
 
size_t getSizeOf(const ValueType &vt, const Settings &settings, int maxRecursion=0)
 
static constexpr char CWE[]
 
Information about a member variable.
 
bool classes
Public interface of classes.
 
enum Standards::cppstd_t cpp
 
const Token * isLambdaCaptureList(const Token *tok)
 
bool endsWith(const std::string &str, char c)
 
#define bailout(tokenlist, errorLogger, tok, what)