PageRenderTime 748ms CodeModel.GetById 36ms RepoModel.GetById 18ms app.codeStats 1ms

/lib/checkclass.cpp

https://github.com/toralf/cppcheck
C++ | 2176 lines | 1606 code | 284 blank | 286 comment | 895 complexity | 13d8f48107fe58632eb3097737fd9d82 MD5 | raw file
Possible License(s): GPL-3.0
  1. /*
  2. * Cppcheck - A tool for static C/C++ code analysis
  3. * Copyright (C) 2007-2014 Daniel Marjam채ki and Cppcheck team.
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. //---------------------------------------------------------------------------
  19. #include "checkclass.h"
  20. #include "tokenize.h"
  21. #include "token.h"
  22. #include "errorlogger.h"
  23. #include "symboldatabase.h"
  24. #include <string>
  25. #include <algorithm>
  26. #include <cctype>
  27. //---------------------------------------------------------------------------
  28. // Register CheckClass..
  29. namespace {
  30. CheckClass instance;
  31. const char * getFunctionTypeName(
  32. Function::Type type)
  33. {
  34. switch (type) {
  35. case Function::eConstructor:
  36. return "constructor";
  37. case Function::eCopyConstructor:
  38. return "copy constructor";
  39. case Function::eMoveConstructor:
  40. return "move constructor";
  41. case Function::eDestructor:
  42. return "destructor";
  43. case Function::eFunction:
  44. return "function";
  45. case Function::eOperatorEqual:
  46. return "operator=";
  47. }
  48. return "";
  49. }
  50. inline bool isPureWithoutBody(Function const & func)
  51. {
  52. return func.isPure && !func.hasBody;
  53. }
  54. }
  55. //---------------------------------------------------------------------------
  56. CheckClass::CheckClass(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
  57. : Check(myName(), tokenizer, settings, errorLogger),
  58. symbolDatabase(tokenizer?tokenizer->getSymbolDatabase():nullptr)
  59. {
  60. }
  61. //---------------------------------------------------------------------------
  62. // ClassCheck: Check that all class constructors are ok.
  63. //---------------------------------------------------------------------------
  64. void CheckClass::constructors()
  65. {
  66. const bool style = _settings->isEnabled("style");
  67. const bool warnings = _settings->isEnabled("warning");
  68. if (!style && !warnings)
  69. return;
  70. const std::size_t classes = symbolDatabase->classAndStructScopes.size();
  71. for (std::size_t i = 0; i < classes; ++i) {
  72. const Scope * scope = symbolDatabase->classAndStructScopes[i];
  73. // There are no constructors.
  74. if (scope->numConstructors == 0 && style) {
  75. // If there is a private variable, there should be a constructor..
  76. std::list<Variable>::const_iterator var;
  77. for (var = scope->varlist.begin(); var != scope->varlist.end(); ++var) {
  78. if (var->isPrivate() && !var->isStatic() && !Token::Match(var->nameToken(), "%varid% ; %varid% =", var->declarationId()) &&
  79. (!var->isClass() || (var->type() && var->type()->needInitialization == Type::True))) {
  80. noConstructorError(scope->classDef, scope->className, scope->classDef->str() == "struct");
  81. break;
  82. }
  83. }
  84. }
  85. if (!warnings)
  86. continue;
  87. // #3196 => bailout if there are nested unions
  88. // TODO: handle union variables better
  89. {
  90. bool bailout = false;
  91. for (std::list<Scope *>::const_iterator it = scope->nestedList.begin(); it != scope->nestedList.end(); ++it) {
  92. const Scope * const nestedScope = *it;
  93. if (nestedScope->type == Scope::eUnion) {
  94. bailout = true;
  95. break;
  96. }
  97. }
  98. if (bailout)
  99. continue;
  100. }
  101. std::list<Function>::const_iterator func;
  102. std::vector<Usage> usage(scope->varlist.size());
  103. for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
  104. if (!func->hasBody || !(func->isConstructor() ||
  105. func->type == Function::eOperatorEqual))
  106. continue;
  107. // Mark all variables not used
  108. clearAllVar(usage);
  109. std::list<const Function *> callstack;
  110. initializeVarList(*func, callstack, &(*scope), usage);
  111. // Check if any variables are uninitialized
  112. std::list<Variable>::const_iterator var;
  113. unsigned int count = 0;
  114. for (var = scope->varlist.begin(); var != scope->varlist.end(); ++var, ++count) {
  115. // check for C++11 initializer
  116. if (var->hasDefault()) {
  117. usage[count].init = true;
  118. continue;
  119. }
  120. if (usage[count].assign || usage[count].init || var->isStatic())
  121. continue;
  122. if (var->isConst() && func->isOperator) // We can't set const members in assignment operator
  123. continue;
  124. // Check if this is a class constructor
  125. if (!var->isPointer() && var->isClass() && func->type == Function::eConstructor) {
  126. // Unknown type so assume it is initialized
  127. if (!var->type())
  128. continue;
  129. // Known type that doesn't need initialization or
  130. // known type that has member variables of an unknown type
  131. else if (var->type()->needInitialization != Type::True)
  132. continue;
  133. }
  134. // Check if type can't be copied
  135. if (!var->isPointer() && var->typeScope()) {
  136. if (func->type == Function::eMoveConstructor) {
  137. if (canNotMove(var->typeScope()))
  138. continue;
  139. } else {
  140. if (canNotCopy(var->typeScope()))
  141. continue;
  142. }
  143. }
  144. bool inconclusive = false;
  145. // Don't warn about unknown types in copy constructors since we
  146. // don't know if they can be copied or not..
  147. if (!var->isPointer() &&
  148. !(var->type() && var->type()->needInitialization != Type::True) &&
  149. (func->type == Function::eCopyConstructor || func->type == Function::eOperatorEqual)) {
  150. if (!var->typeStartToken()->isStandardType()) {
  151. if (_settings->inconclusive)
  152. inconclusive = true;
  153. else
  154. continue;
  155. }
  156. }
  157. // It's non-static and it's not initialized => error
  158. if (func->type == Function::eOperatorEqual) {
  159. const Token *operStart = func->arg;
  160. bool classNameUsed = false;
  161. for (const Token *operTok = operStart; operTok != operStart->link(); operTok = operTok->next()) {
  162. if (operTok->str() == scope->className) {
  163. classNameUsed = true;
  164. break;
  165. }
  166. }
  167. if (classNameUsed)
  168. operatorEqVarError(func->token, scope->className, var->name(), inconclusive);
  169. } else if (func->access != Private) {
  170. const Scope *varType = var->typeScope();
  171. if (!varType || varType->type != Scope::eUnion) {
  172. if (func->type == Function::eConstructor &&
  173. func->nestedIn && (func->nestedIn->numConstructors - func->nestedIn->numCopyOrMoveConstructors) > 1 &&
  174. func->argCount() == 0 && func->functionScope &&
  175. func->arg && func->arg->link()->next() == func->functionScope->classStart &&
  176. func->functionScope->classStart->link() == func->functionScope->classStart->next()) {
  177. // don't warn about user defined default constructor when there are other constructors
  178. if (_settings->inconclusive)
  179. uninitVarError(func->token, scope->className, var->name(), true);
  180. } else
  181. uninitVarError(func->token, scope->className, var->name(), inconclusive);
  182. }
  183. }
  184. }
  185. }
  186. }
  187. }
  188. void CheckClass::copyconstructors()
  189. {
  190. if (!_settings->isEnabled("style"))
  191. return;
  192. const std::size_t classes = symbolDatabase->classAndStructScopes.size();
  193. for (std::size_t i = 0; i < classes; ++i) {
  194. const Scope * scope = symbolDatabase->classAndStructScopes[i];
  195. std::map<unsigned int, const Token*> allocatedVars;
  196. for (std::list<Function>::const_iterator func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
  197. if (func->type == Function::eConstructor && func->functionScope) {
  198. const Token* tok = func->functionScope->classDef->linkAt(1);
  199. for (const Token* const end = func->functionScope->classStart; tok != end; tok = tok->next()) {
  200. if (Token::Match(tok, "%var% ( new|malloc|g_malloc|g_try_malloc|realloc|g_realloc|g_try_realloc")) {
  201. const Variable* var = tok->variable();
  202. if (var && var->isPointer() && var->scope() == &*scope)
  203. allocatedVars[tok->varId()] = tok;
  204. }
  205. }
  206. for (const Token* const end = func->functionScope->classEnd; tok != end; tok = tok->next()) {
  207. if (Token::Match(tok, "%var% = new|malloc|g_malloc|g_try_malloc|realloc|g_realloc|g_try_realloc")) {
  208. const Variable* var = tok->variable();
  209. if (var && var->isPointer() && var->scope() == &*scope)
  210. allocatedVars[tok->varId()] = tok;
  211. }
  212. }
  213. }
  214. }
  215. std::set<const Token*> copiedVars;
  216. const Token* copyCtor = 0;
  217. for (std::list<Function>::const_iterator func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
  218. if (func->type == Function::eCopyConstructor) {
  219. copyCtor = func->tokenDef;
  220. if (func->functionScope) {
  221. const Token* tok = func->tokenDef->linkAt(1)->next();
  222. if (tok->str()==":") {
  223. tok=tok->next();
  224. while (Token::Match(tok, "%var% (")) {
  225. if (allocatedVars.find(tok->varId()) != allocatedVars.end()) {
  226. if (tok->varId() && Token::Match(tok->tokAt(2), "%var% . %var% )"))
  227. copiedVars.insert(tok);
  228. else if (!Token::Match(tok->tokAt(2), "%any% )"))
  229. allocatedVars.erase(tok->varId()); // Assume memory is allocated
  230. }
  231. tok = tok->linkAt(1)->tokAt(2);
  232. }
  233. }
  234. for (tok=func->functionScope->classStart; tok!=func->functionScope->classEnd; tok=tok->next()) {
  235. if (Token::Match(tok, "%var% = new|malloc|g_malloc|g_try_malloc|realloc|g_realloc|g_try_realloc")) {
  236. allocatedVars.erase(tok->varId());
  237. } else if (Token::Match(tok, "%var% = %var% . %var% ;") && allocatedVars.find(tok->varId()) != allocatedVars.end()) {
  238. copiedVars.insert(tok);
  239. }
  240. }
  241. } else // non-copyable or implementation not seen
  242. allocatedVars.clear();
  243. break;
  244. }
  245. }
  246. if (!copyCtor) {
  247. if (!allocatedVars.empty() && scope->definedType->derivedFrom.empty()) // TODO: Check if base class is non-copyable
  248. noCopyConstructorError(scope->classDef, scope->className, scope->type == Scope::eStruct);
  249. } else {
  250. if (!copiedVars.empty()) {
  251. for (std::set<const Token*>::const_iterator it = copiedVars.begin(); it != copiedVars.end(); ++it) {
  252. copyConstructorShallowCopyError(*it, (*it)->str());
  253. }
  254. }
  255. // throw error if count mismatch
  256. /* FIXME: This doesn't work. See #4154
  257. for (std::map<unsigned int, const Token*>::const_iterator i = allocatedVars.begin(); i != allocatedVars.end(); ++i) {
  258. copyConstructorMallocError(copyCtor, i->second, i->second->str());
  259. }
  260. */
  261. }
  262. }
  263. }
  264. /* This doesn't work. See #4154
  265. void CheckClass::copyConstructorMallocError(const Token *cctor, const Token *alloc, const std::string& varname)
  266. {
  267. std::list<const Token*> callstack;
  268. callstack.push_back(cctor);
  269. callstack.push_back(alloc);
  270. reportError(callstack, Severity::warning, "copyCtorNoAllocation", "Copy constructor does not allocate memory for member '" + varname + "' although memory has been allocated in other constructors.");
  271. }
  272. */
  273. void CheckClass::copyConstructorShallowCopyError(const Token *tok, const std::string& varname)
  274. {
  275. reportError(tok, Severity::style, "copyCtorPointerCopying", "Value of pointer '" + varname + "', which points to allocated memory, is copied in copy constructor instead of allocating new memory.");
  276. }
  277. void CheckClass::noCopyConstructorError(const Token *tok, const std::string &classname, bool isStruct)
  278. {
  279. // The constructor might be intentionally missing. Therefore this is not a "warning"
  280. reportError(tok, Severity::style, "noCopyConstructor",
  281. "'" + std::string(isStruct ? "struct" : "class") + " " + classname +
  282. "' does not have a copy constructor which is recommended since the class contains a pointer to allocated memory.");
  283. }
  284. bool CheckClass::canNotCopy(const Scope *scope)
  285. {
  286. std::list<Function>::const_iterator func;
  287. bool constructor = false;
  288. bool publicAssign = false;
  289. bool publicCopy = false;
  290. for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
  291. if (func->isConstructor())
  292. constructor = true;
  293. if ((func->type == Function::eCopyConstructor) &&
  294. func->access == Public)
  295. publicCopy = true;
  296. else if (func->type == Function::eOperatorEqual && func->access == Public)
  297. publicAssign = true;
  298. }
  299. return constructor && !(publicAssign || publicCopy);
  300. }
  301. bool CheckClass::canNotMove(const Scope *scope)
  302. {
  303. std::list<Function>::const_iterator func;
  304. bool constructor = false;
  305. bool publicAssign = false;
  306. bool publicCopy = false;
  307. bool publicMove = false;
  308. for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
  309. if (func->isConstructor())
  310. constructor = true;
  311. if ((func->type == Function::eCopyConstructor) &&
  312. func->access == Public)
  313. publicCopy = true;
  314. else if ((func->type == Function::eMoveConstructor) &&
  315. func->access == Public)
  316. publicMove = true;
  317. else if (func->type == Function::eOperatorEqual && func->access == Public)
  318. publicAssign = true;
  319. }
  320. return constructor && !(publicAssign || publicCopy || publicMove);
  321. }
  322. void CheckClass::assignVar(const std::string &varname, const Scope *scope, std::vector<Usage> &usage)
  323. {
  324. std::list<Variable>::const_iterator var;
  325. unsigned int count = 0;
  326. for (var = scope->varlist.begin(); var != scope->varlist.end(); ++var, ++count) {
  327. if (var->name() == varname) {
  328. usage[count].assign = true;
  329. return;
  330. }
  331. }
  332. }
  333. void CheckClass::initVar(const std::string &varname, const Scope *scope, std::vector<Usage> &usage)
  334. {
  335. std::list<Variable>::const_iterator var;
  336. unsigned int count = 0;
  337. for (var = scope->varlist.begin(); var != scope->varlist.end(); ++var, ++count) {
  338. if (var->name() == varname) {
  339. usage[count].init = true;
  340. return;
  341. }
  342. }
  343. }
  344. void CheckClass::assignAllVar(std::vector<Usage> &usage)
  345. {
  346. for (std::size_t i = 0; i < usage.size(); ++i)
  347. usage[i].assign = true;
  348. }
  349. void CheckClass::clearAllVar(std::vector<Usage> &usage)
  350. {
  351. for (std::size_t i = 0; i < usage.size(); ++i) {
  352. usage[i].assign = false;
  353. usage[i].init = false;
  354. }
  355. }
  356. bool CheckClass::isBaseClassFunc(const Token *tok, const Scope *scope)
  357. {
  358. // Iterate through each base class...
  359. for (std::size_t i = 0; i < scope->definedType->derivedFrom.size(); ++i) {
  360. const Type *derivedFrom = scope->definedType->derivedFrom[i].type;
  361. // Check if base class exists in database
  362. if (derivedFrom && derivedFrom->classScope) {
  363. const std::list<Function>& functionList = derivedFrom->classScope->functionList;
  364. std::list<Function>::const_iterator func;
  365. for (func = functionList.begin(); func != functionList.end(); ++func) {
  366. if (func->tokenDef->str() == tok->str())
  367. return true;
  368. }
  369. }
  370. // Base class not found so assume it is in it.
  371. else
  372. return true;
  373. }
  374. return false;
  375. }
  376. void CheckClass::initializeVarList(const Function &func, std::list<const Function *> &callstack, const Scope *scope, std::vector<Usage> &usage)
  377. {
  378. if (!func.functionScope)
  379. throw InternalError(0, "Internal Error: Invalid syntax"); // #5702
  380. bool initList = func.isConstructor();
  381. const Token *ftok = func.arg->link()->next();
  382. int level = 0;
  383. for (; ftok && ftok != func.functionScope->classEnd; ftok = ftok->next()) {
  384. // Class constructor.. initializing variables like this
  385. // clKalle::clKalle() : var(value) { }
  386. if (initList) {
  387. if (level == 0 && Token::Match(ftok, "%var% {|(")) {
  388. if (ftok->str() != func.name()) {
  389. initVar(ftok->str(), scope, usage);
  390. } else { // c++11 delegate constructor
  391. const Function *member = ftok->function();
  392. // member function found
  393. if (member) {
  394. // recursive call
  395. // assume that all variables are initialized
  396. if (std::find(callstack.begin(), callstack.end(), member) != callstack.end()) {
  397. /** @todo false negative: just bail */
  398. assignAllVar(usage);
  399. return;
  400. }
  401. // member function has implementation
  402. if (member->hasBody) {
  403. // initialize variable use list using member function
  404. callstack.push_back(member);
  405. initializeVarList(*member, callstack, scope, usage);
  406. callstack.pop_back();
  407. }
  408. // there is a called member function, but it has no implementation, so we assume it initializes everything
  409. else {
  410. assignAllVar(usage);
  411. }
  412. }
  413. }
  414. ftok = ftok->next();
  415. level++;
  416. } else if (level != 0 && Token::Match(ftok, "%var% =")) // assignment in the initializer: var(value = x)
  417. assignVar(ftok->str(), scope, usage);
  418. else if (ftok->str() == "(")
  419. level++;
  420. else if (ftok->str() == ")" || ftok->str() == "}")
  421. level--;
  422. else if (ftok->str() == "{") {
  423. if (level == 0)
  424. initList = false;
  425. else
  426. ftok = ftok->link();
  427. }
  428. }
  429. if (initList)
  430. continue;
  431. // Variable getting value from stream?
  432. if (Token::Match(ftok, ">> %var%")) {
  433. assignVar(ftok->strAt(1), scope, usage);
  434. }
  435. // Before a new statement there is "[{};()=[]"
  436. if (! Token::Match(ftok, "[{};()=[]"))
  437. continue;
  438. if (Token::simpleMatch(ftok, "( !"))
  439. ftok = ftok->next();
  440. // Using the operator= function to initialize all variables..
  441. if (Token::Match(ftok->next(), "return| (| * this )| =")) {
  442. assignAllVar(usage);
  443. break;
  444. }
  445. // Using swap to assign all variables..
  446. if (func.type == Function::eOperatorEqual && Token::Match(ftok, "[;{}] %var% (") && Token::Match(ftok->linkAt(2), ") . %var% ( *| this ) ;")) {
  447. assignAllVar(usage);
  448. break;
  449. }
  450. // Calling member variable function?
  451. if (Token::Match(ftok->next(), "%var% . %var% (")) {
  452. std::list<Variable>::const_iterator var;
  453. for (var = scope->varlist.begin(); var != scope->varlist.end(); ++var) {
  454. if (var->declarationId() == ftok->next()->varId()) {
  455. /** @todo false negative: we assume function changes variable state */
  456. assignVar(ftok->next()->str(), scope, usage);
  457. break;
  458. }
  459. }
  460. ftok = ftok->tokAt(2);
  461. }
  462. if (!Token::Match(ftok->next(), "::| %var%") &&
  463. !Token::Match(ftok->next(), "*| this . %var%") &&
  464. !Token::Match(ftok->next(), "* %var% =") &&
  465. !Token::Match(ftok->next(), "( * this ) . %var%"))
  466. continue;
  467. // Goto the first token in this statement..
  468. ftok = ftok->next();
  469. // skip "return"
  470. if (ftok->str() == "return")
  471. ftok = ftok->next();
  472. // Skip "( * this )"
  473. if (Token::simpleMatch(ftok, "( * this ) .")) {
  474. ftok = ftok->tokAt(5);
  475. }
  476. // Skip "this->"
  477. if (Token::simpleMatch(ftok, "this ."))
  478. ftok = ftok->tokAt(2);
  479. // Skip "classname :: "
  480. if (Token::Match(ftok, ":: %var%"))
  481. ftok = ftok->next();
  482. while (Token::Match(ftok, "%var% ::"))
  483. ftok = ftok->tokAt(2);
  484. // Clearing all variables..
  485. if (Token::Match(ftok, "::| memset ( this ,")) {
  486. assignAllVar(usage);
  487. return;
  488. }
  489. // Clearing array..
  490. else if (Token::Match(ftok, "::| memset ( %var% ,")) {
  491. if (ftok->str() == "::")
  492. ftok = ftok->next();
  493. assignVar(ftok->strAt(2), scope, usage);
  494. ftok = ftok->linkAt(1);
  495. continue;
  496. }
  497. // Calling member function?
  498. else if (Token::simpleMatch(ftok, "operator= (") &&
  499. ftok->previous()->str() != "::") {
  500. if (ftok->function() && ftok->function()->nestedIn == scope) {
  501. const Function *member = ftok->function();
  502. // recursive call
  503. // assume that all variables are initialized
  504. if (std::find(callstack.begin(), callstack.end(), member) != callstack.end()) {
  505. /** @todo false negative: just bail */
  506. assignAllVar(usage);
  507. return;
  508. }
  509. // member function has implementation
  510. if (member->hasBody) {
  511. // initialize variable use list using member function
  512. callstack.push_back(member);
  513. initializeVarList(*member, callstack, scope, usage);
  514. callstack.pop_back();
  515. }
  516. // there is a called member function, but it has no implementation, so we assume it initializes everything
  517. else {
  518. assignAllVar(usage);
  519. }
  520. }
  521. // using default operator =, assume everything initialized
  522. else {
  523. assignAllVar(usage);
  524. }
  525. } else if (Token::Match(ftok, "::| %var% (") && ftok->str() != "if") {
  526. if (ftok->str() == "::")
  527. ftok = ftok->next();
  528. // Passing "this" => assume that everything is initialized
  529. for (const Token *tok2 = ftok->next()->link(); tok2 && tok2 != ftok; tok2 = tok2->previous()) {
  530. if (tok2->str() == "this") {
  531. assignAllVar(usage);
  532. return;
  533. }
  534. }
  535. // check if member function
  536. if (ftok->function() && ftok->function()->nestedIn == scope &&
  537. !ftok->function()->isConstructor()) {
  538. const Function *member = ftok->function();
  539. // recursive call
  540. // assume that all variables are initialized
  541. if (std::find(callstack.begin(), callstack.end(), member) != callstack.end()) {
  542. assignAllVar(usage);
  543. return;
  544. }
  545. // member function has implementation
  546. if (member->hasBody) {
  547. // initialize variable use list using member function
  548. callstack.push_back(member);
  549. initializeVarList(*member, callstack, scope, usage);
  550. callstack.pop_back();
  551. // Assume that variables that are passed to it are initialized..
  552. for (const Token *tok2 = ftok; tok2; tok2 = tok2->next()) {
  553. if (Token::Match(tok2, "[;{}]"))
  554. break;
  555. if (Token::Match(tok2, "[(,] &| %var% [,)]")) {
  556. tok2 = tok2->next();
  557. if (tok2->str() == "&")
  558. tok2 = tok2->next();
  559. assignVar(tok2->str(), scope, usage);
  560. }
  561. }
  562. }
  563. // there is a called member function, but it has no implementation, so we assume it initializes everything
  564. else {
  565. assignAllVar(usage);
  566. }
  567. }
  568. // not member function
  569. else {
  570. // could be a base class virtual function, so we assume it initializes everything
  571. if (!func.isConstructor() && isBaseClassFunc(ftok, scope)) {
  572. /** @todo False Negative: we should look at the base class functions to see if they
  573. * call any derived class virtual functions that change the derived class state
  574. */
  575. assignAllVar(usage);
  576. }
  577. // has friends, so we assume it initializes everything
  578. if (!scope->definedType->friendList.empty())
  579. assignAllVar(usage);
  580. // the function is external and it's neither friend nor inherited virtual function.
  581. // assume all variables that are passed to it are initialized..
  582. else {
  583. for (const Token *tok = ftok->tokAt(2); tok && tok != ftok->next()->link(); tok = tok->next()) {
  584. if (tok->isName()) {
  585. assignVar(tok->str(), scope, usage);
  586. }
  587. }
  588. }
  589. }
  590. }
  591. // Assignment of member variable?
  592. else if (Token::Match(ftok, "%var% =")) {
  593. assignVar(ftok->str(), scope, usage);
  594. }
  595. // Assignment of array item of member variable?
  596. else if (Token::Match(ftok, "%var% [|.")) {
  597. const Token *tok2 = ftok;
  598. while (tok2) {
  599. if (tok2->strAt(1) == "[")
  600. tok2 = tok2->next()->link();
  601. else if (Token::Match(tok2->next(), ". %var%"))
  602. tok2 = tok2->tokAt(2);
  603. else
  604. break;
  605. }
  606. if (tok2 && tok2->strAt(1) == "=")
  607. assignVar(ftok->str(), scope, usage);
  608. }
  609. // Assignment of array item of member variable?
  610. else if (Token::Match(ftok, "* %var% =")) {
  611. assignVar(ftok->next()->str(), scope, usage);
  612. } else if (Token::Match(ftok, "* this . %var% =")) {
  613. assignVar(ftok->strAt(3), scope, usage);
  614. }
  615. // The functions 'clear' and 'Clear' are supposed to initialize variable.
  616. if (Token::Match(ftok, "%var% . clear|Clear (")) {
  617. assignVar(ftok->str(), scope, usage);
  618. }
  619. }
  620. }
  621. void CheckClass::noConstructorError(const Token *tok, const std::string &classname, bool isStruct)
  622. {
  623. // For performance reasons the constructor might be intentionally missing. Therefore this is not a "warning"
  624. reportError(tok, Severity::style, "noConstructor",
  625. "The " + std::string(isStruct ? "struct" : "class") + " '" + classname +
  626. "' does not have a constructor.\n"
  627. "The " + std::string(isStruct ? "struct" : "class") + " '" + classname +
  628. "' does not have a constructor although it has private member variables. "
  629. "Member variables of builtin types are left uninitialized when the class is "
  630. "instantiated. That may cause bugs or undefined behavior.");
  631. }
  632. void CheckClass::uninitVarError(const Token *tok, const std::string &classname, const std::string &varname, bool inconclusive)
  633. {
  634. reportError(tok, Severity::warning, "uninitMemberVar", "Member variable '" + classname + "::" + varname + "' is not initialized in the constructor.", inconclusive);
  635. }
  636. void CheckClass::operatorEqVarError(const Token *tok, const std::string &classname, const std::string &varname, bool inconclusive)
  637. {
  638. reportError(tok, Severity::warning, "operatorEqVarError", "Member variable '" + classname + "::" + varname + "' is not assigned a value in '" + classname + "::operator='.", inconclusive);
  639. }
  640. //---------------------------------------------------------------------------
  641. // ClassCheck: Use initialization list instead of assignment
  642. //---------------------------------------------------------------------------
  643. void CheckClass::initializationListUsage()
  644. {
  645. if (!_settings->isEnabled("performance"))
  646. return;
  647. const std::size_t functions = symbolDatabase->functionScopes.size();
  648. for (std::size_t i = 0; i < functions; ++i) {
  649. const Scope * scope = symbolDatabase->functionScopes[i];
  650. // Check every constructor
  651. if (!scope->function || (!scope->function->isConstructor()))
  652. continue;
  653. const Scope* owner = scope->functionOf;
  654. for (const Token* tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) {
  655. if (Token::Match(tok, "%var% (")) // Assignments might depend on this function call or if/for/while/switch statement from now on.
  656. break;
  657. if (Token::Match(tok, "try|do {"))
  658. break;
  659. if (tok->varId() && Token::Match(tok, "%var% = %any%")) {
  660. const Variable* var = tok->variable();
  661. if (var && var->scope() == owner && !var->isStatic()) {
  662. bool allowed = true;
  663. for (const Token* tok2 = tok->tokAt(2); tok2->str() != ";"; tok2 = tok2->next()) {
  664. if (tok2->varId()) {
  665. const Variable* var2 = tok2->variable();
  666. if (var2 && var2->scope() == owner &&
  667. tok2->strAt(-1)!=".") { // Is there a dependency between two member variables?
  668. allowed = false;
  669. break;
  670. } else if (var2 && (var2->isArray() && var2->isLocal())) { // Can't initialize with a local array
  671. allowed = false;
  672. break;
  673. }
  674. } else if (tok2->str() == "this") { // 'this' instance is not completely constructed in initialization list
  675. allowed = false;
  676. break;
  677. } else if (Token::Match(tok2, "%var% (") && tok2->strAt(-1) != "." && isMemberFunc(owner, tok2)) { // Member function called?
  678. allowed = false;
  679. break;
  680. }
  681. }
  682. if (!allowed)
  683. continue;
  684. if (!var->isPointer() && !var->isReference() && (var->type() || var->isStlStringType() || (Token::Match(var->typeStartToken(), "std :: %type% <") && !Token::simpleMatch(var->typeStartToken()->linkAt(3), "> ::"))))
  685. suggestInitializationList(tok, tok->str());
  686. }
  687. }
  688. }
  689. }
  690. }
  691. void CheckClass::suggestInitializationList(const Token* tok, const std::string& varname)
  692. {
  693. reportError(tok, Severity::performance, "useInitializationList", "Variable '" + varname + "' is assigned in constructor body. Consider performing initialization in initialization list.\n"
  694. "When an object of a class is created, the constructors of all member variables are called consecutively "
  695. "in the order the variables are declared, even if you don't explicitly write them to the initialization list. You "
  696. "could avoid assigning '" + varname + "' a value by passing the value to the constructor in the initialization list.");
  697. }
  698. //---------------------------------------------------------------------------
  699. // ClassCheck: Unused private functions
  700. //---------------------------------------------------------------------------
  701. static bool checkFunctionUsage(const std::string& name, const Scope* scope)
  702. {
  703. if (!scope)
  704. return true; // Assume it is used, if scope is not seen
  705. for (std::list<Function>::const_iterator func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
  706. if (func->functionScope) {
  707. if (Token::Match(func->tokenDef, "%var% (")) {
  708. for (const Token *ftok = func->tokenDef->tokAt(2); ftok && ftok->str() != ")"; ftok = ftok->next()) {
  709. if (Token::Match(ftok, "= %var% [(,)]") && ftok->strAt(1) == name)
  710. return true;
  711. if (ftok->str() == "(")
  712. ftok = ftok->link();
  713. }
  714. }
  715. for (const Token *ftok = func->functionScope->classDef->linkAt(1); ftok != func->functionScope->classEnd; ftok = ftok->next()) {
  716. if (ftok->str() == name) // Function used. TODO: Handle overloads
  717. return true;
  718. }
  719. } else if ((func->type != Function::eCopyConstructor &&
  720. func->type != Function::eOperatorEqual) ||
  721. func->access != Private) // Assume it is used, if a function implementation isn't seen, but empty private copy constructors and assignment operators are OK
  722. return true;
  723. }
  724. for (std::list<Scope*>::const_iterator i = scope->nestedList.begin(); i != scope->nestedList.end(); ++i) {
  725. if ((*i)->isClassOrStruct())
  726. if (checkFunctionUsage(name, *i)) // Check nested classes, which can access private functions of their base
  727. return true;
  728. }
  729. for (std::list<Variable>::const_iterator i = scope->varlist.begin(); i != scope->varlist.end(); ++i) {
  730. if (i->isStatic()) {
  731. const Token* tok = Token::findmatch(scope->classEnd, "%varid% =|(|{", i->declarationId());
  732. if (tok)
  733. tok = tok->tokAt(2);
  734. while (tok && tok->str() != ";") {
  735. if (tok->str() == name && (tok->strAt(-1) == "." || tok->strAt(-2) == scope->className))
  736. return true;
  737. tok = tok->next();
  738. }
  739. }
  740. }
  741. return false; // Unused in this scope
  742. }
  743. void CheckClass::privateFunctions()
  744. {
  745. if (!_settings->isEnabled("style"))
  746. return;
  747. const std::size_t classes = symbolDatabase->classAndStructScopes.size();
  748. for (std::size_t i = 0; i < classes; ++i) {
  749. const Scope * scope = symbolDatabase->classAndStructScopes[i];
  750. // do not check borland classes with properties..
  751. if (Token::findsimplematch(scope->classStart, "; __property ;", scope->classEnd))
  752. continue;
  753. std::list<const Function*> privateFuncs;
  754. for (std::list<Function>::const_iterator func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
  755. // Get private functions..
  756. if (func->type == Function::eFunction && func->access == Private && !func->isOperator) // TODO: There are smarter ways to check private operator usage
  757. privateFuncs.push_back(&*func);
  758. }
  759. // Bailout for overridden virtual functions of base classes
  760. if (!scope->definedType->derivedFrom.empty()) {
  761. // Check virtual functions
  762. for (std::list<const Function*>::iterator it = privateFuncs.begin(); it != privateFuncs.end();) {
  763. if ((*it)->isImplicitlyVirtual(true)) // Give true as default value to be returned if we don't see all base classes
  764. privateFuncs.erase(it++);
  765. else
  766. ++it;
  767. }
  768. }
  769. while (!privateFuncs.empty()) {
  770. const std::string& funcName = privateFuncs.front()->tokenDef->str();
  771. // Check that all private functions are used
  772. bool used = checkFunctionUsage(funcName, &*scope); // Usage in this class
  773. // Check in friend classes
  774. const std::list<Type::FriendInfo>& friendList = scope->definedType->friendList;
  775. for (std::list<Type::FriendInfo>::const_iterator it = friendList.begin(); !used && it != friendList.end(); ++it) {
  776. if (it->type)
  777. used = checkFunctionUsage(funcName, it->type->classScope);
  778. else
  779. used = true; // Assume, it is used if we do not see friend class
  780. }
  781. if (!used)
  782. unusedPrivateFunctionError(privateFuncs.front()->tokenDef, scope->className, funcName);
  783. privateFuncs.pop_front();
  784. }
  785. }
  786. }
  787. void CheckClass::unusedPrivateFunctionError(const Token *tok, const std::string &classname, const std::string &funcname)
  788. {
  789. reportError(tok, Severity::style, "unusedPrivateFunction", "Unused private function: '" + classname + "::" + funcname + "'");
  790. }
  791. //---------------------------------------------------------------------------
  792. // ClassCheck: Check that memset is not used on classes
  793. //---------------------------------------------------------------------------
  794. static const Scope* findFunctionOf(const Scope* scope)
  795. {
  796. while (scope) {
  797. if (scope->type == Scope::eFunction)
  798. return scope->functionOf;
  799. scope = scope->nestedIn;
  800. }
  801. return 0;
  802. }
  803. void CheckClass::checkMemset()
  804. {
  805. const std::size_t functions = symbolDatabase->functionScopes.size();
  806. for (std::size_t i = 0; i < functions; ++i) {
  807. const Scope * scope = symbolDatabase->functionScopes[i];
  808. for (const Token *tok = scope->classStart; tok && tok != scope->classEnd; tok = tok->next()) {
  809. if (Token::Match(tok, "memset|memcpy|memmove ( %any%")) {
  810. const Token* arg1 = tok->tokAt(2);
  811. const Token* arg3 = arg1->nextArgument();
  812. if (arg3)
  813. arg3 = arg3->nextArgument();
  814. if (!arg3)
  815. // weird, shouldn't happen: memset etc should have
  816. // 3 arguments.
  817. continue;
  818. const Token *typeTok = nullptr;
  819. const Scope *type = nullptr;
  820. if (Token::Match(arg3, "sizeof ( %type% ) )"))
  821. typeTok = arg3->tokAt(2);
  822. else if (Token::Match(arg3, "sizeof ( %type% :: %type% ) )"))
  823. typeTok = arg3->tokAt(4);
  824. else if (Token::Match(arg3, "sizeof ( struct %type% ) )"))
  825. typeTok = arg3->tokAt(3);
  826. else if (Token::simpleMatch(arg3, "sizeof ( * this ) )") || Token::simpleMatch(arg1, "this ,")) {
  827. type = findFunctionOf(arg3->scope());
  828. } else if (Token::Match(arg1, "&|*|%var%")) {
  829. int derefs = 1;
  830. for (;; arg1 = arg1->next()) {
  831. if (arg1->str() == "&")
  832. derefs--;
  833. else if (arg1->str() == "*")
  834. derefs++;
  835. else
  836. break;
  837. }
  838. const Variable *var = arg1->variable();
  839. if (var && arg1->strAt(1) == ",") {
  840. if (var->isPointer()) {
  841. derefs--;
  842. if (var->typeEndToken() && Token::simpleMatch(var->typeEndToken()->previous(), "* *")) // Check if it's a pointer to pointer
  843. derefs--;
  844. }
  845. if (var->isArray())
  846. derefs -= (int)var->dimensions().size();
  847. if (derefs == 0)
  848. type = var->typeScope();
  849. }
  850. }
  851. // No type defined => The tokens didn't match
  852. if (!typeTok && !type)
  853. continue;
  854. if (typeTok && typeTok->str() == "(")
  855. typeTok = typeTok->next();
  856. if (!type) {
  857. const Type* t = symbolDatabase->findVariableType(&(*scope), typeTok);
  858. if (t)
  859. type = t->classScope;
  860. }
  861. if (type) {
  862. std::list<const Scope *> parsedTypes;
  863. checkMemsetType(&(*scope), tok, type, false, parsedTypes);
  864. }
  865. } else if (tok->variable() && tok->variable()->typeScope() && Token::Match(tok, "%var% = calloc|malloc|realloc|g_malloc|g_try_malloc|g_realloc|g_try_realloc (")) {
  866. std::list<const Scope *> parsedTypes;
  867. checkMemsetType(&(*scope), tok->tokAt(2), tok->variable()->typeScope(), true, parsedTypes);
  868. if (tok->variable()->typeScope()->numConstructors > 0 && _settings->isEnabled("warning"))
  869. mallocOnClassWarning(tok, tok->strAt(2), tok->variable()->typeScope()->classDef);
  870. }
  871. }
  872. }
  873. }
  874. void CheckClass::checkMemsetType(const Scope *start, const Token *tok, const Scope *type, bool allocation, std::list<const Scope *> parsedTypes)
  875. {
  876. // If type has been checked there is no need to check it again
  877. if (std::find(parsedTypes.begin(), parsedTypes.end(), type) != parsedTypes.end())
  878. return;
  879. parsedTypes.push_back(type);
  880. // recursively check all parent classes
  881. for (std::size_t i = 0; i < type->definedType->derivedFrom.size(); i++) {
  882. const Type* derivedFrom = type->definedType->derivedFrom[i].type;
  883. if (derivedFrom && derivedFrom->classScope)
  884. checkMemsetType(start, tok, derivedFrom->classScope, allocation, parsedTypes);
  885. }
  886. // Warn if type is a class that contains any virtual functions
  887. std::list<Function>::const_iterator func;
  888. for (func = type->functionList.begin(); func != type->functionList.end(); ++func) {
  889. if (func->isVirtual) {
  890. if (allocation)
  891. mallocOnClassError(tok, tok->str(), type->classDef, "virtual method");
  892. else
  893. memsetError(tok, tok->str(), "virtual method", type->classDef->str());
  894. }
  895. }
  896. // Warn if type is a class or struct that contains any std::* variables
  897. std::list<Variable>::const_iterator var;
  898. for (var = type->varlist.begin(); var != type->varlist.end(); ++var) {
  899. if (var->isReference() && !var->isStatic()) {
  900. memsetErrorReference(tok, tok->str(), type->classDef->str());
  901. continue;
  902. }
  903. // don't warn if variable static or const, pointer or reference
  904. if (!var->isStatic() && !var->isConst() && !var->isPointer()) {
  905. const Token *tok1 = var->typeStartToken();
  906. const Scope *typeScope = var->typeScope();
  907. // check for std:: type
  908. if (var->isStlType() && tok1->strAt(2) != "array" && !_settings->library.podtype(tok1->strAt(2)))
  909. if (allocation)
  910. mallocOnClassError(tok, tok->str(), type->classDef, "'std::" + tok1->strAt(2) + "'");
  911. else
  912. memsetError(tok, tok->str(), "'std::" + tok1->strAt(2) + "'", type->classDef->str());
  913. // check for known type
  914. else if (typeScope && typeScope != type)
  915. checkMemsetType(start, tok, typeScope, allocation, parsedTypes);
  916. // check for float
  917. else if (tok->str() == "memset" && var->isFloatingType() && _settings->isEnabled("portability"))
  918. memsetErrorFloat(tok, type->classDef->str());
  919. }
  920. }
  921. }
  922. void CheckClass::mallocOnClassWarning(const Token* tok, const std::string &memfunc, const Token* classTok)
  923. {
  924. std::list<const Token *> toks;
  925. toks.push_back(tok);
  926. toks.push_back(classTok);
  927. reportError(toks, Severity::warning, "mallocOnClassWarning",
  928. "Memory for class instance allocated with " + memfunc + "(), but class provides constructors.\n"
  929. "Memory for class instance allocated with " + memfunc + "(), but class provides constructors. This is unsafe, "
  930. "since no constructor is called and class members remain uninitialized. Consider using 'new' instead.");
  931. }
  932. void CheckClass::mallocOnClassError(const Token* tok, const std::string &memfunc, const Token* classTok, const std::string &classname)
  933. {
  934. std::list<const Token *> toks;
  935. toks.push_back(tok);
  936. toks.push_back(classTok);
  937. reportError(toks, Severity::error, "mallocOnClassError",
  938. "Memory for class instance allocated with " + memfunc + "(), but class contains a " + classname + ".\n"
  939. "Memory for class instance allocated with " + memfunc + "(), but class a " + classname + ". This is unsafe, "
  940. "since no constructor is called and class members remain uninitialized. Consider using 'new' instead.");
  941. }
  942. void CheckClass::memsetError(const Token *tok, const std::string &memfunc, const std::string &classname, const std::string &type)
  943. {
  944. reportError(tok, Severity::error, "memsetClass",
  945. "Using '" + memfunc + "' on " + type + " that contains a " + classname + ".\n"
  946. "Using '" + memfunc + "' on " + type + " that contains a " + classname + " is unsafe, because constructor, destructor "
  947. "and copy operator calls are omitted. These are necessary for this non-POD type to ensure that a valid object "
  948. "is created.");
  949. }
  950. void CheckClass::memsetErrorReference(const Token *tok, const std::string &memfunc, const std::string &type)
  951. {
  952. reportError(tok, Severity::error, "memsetClassReference", "Using '" + memfunc + "' on " + type + " that contains a reference.");
  953. }
  954. void CheckClass::memsetErrorFloat(const Token *tok, const std::string &type)
  955. {
  956. reportError(tok, Severity::portability, "memsetClassFloat", "Using memset() on " + type + " which contains a floating point number.\n"
  957. "Using memset() on " + type + " which contains a floating point number. This is not portable because memset() sets each byte of a block of memory to a specific value and"
  958. " the actual representation of a floating-point value is implementation defined.");
  959. }
  960. //---------------------------------------------------------------------------
  961. // ClassCheck: "void operator=(" and "const type & operator=("
  962. //---------------------------------------------------------------------------
  963. void CheckClass::operatorEq()
  964. {
  965. if (!_settings->isEnabled("style"))
  966. return;
  967. const std::size_t classes = symbolDatabase->classAndStructScopes.size();
  968. for (std::size_t i = 0; i < classes; ++i) {
  969. const Scope * scope = symbolDatabase->classAndStructScopes[i];
  970. std::list<Function>::const_iterator func;
  971. for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
  972. if (func->type == Function::eOperatorEqual && func->access != Private) {
  973. // skip "deleted" functions - cannot be called anyway
  974. if (func->isDelete)
  975. continue;
  976. // use definition for check so we don't have to deal with qualification
  977. if (!(Token::Match(func->retDef, "%type% &") && func->retDef->str() == scope->className)) {
  978. // make sure we really have a copy assignment operator
  979. if (Token::Match(func->tokenDef->tokAt(2), "const| %var% &")) {
  980. if (func->tokenDef->strAt(2) == "const" &&
  981. func->tokenDef->strAt(3) == scope->className)
  982. operatorEqReturnError(func->retDef, scope->className);
  983. else if (func->tokenDef->strAt(2) == scope->className)
  984. operatorEqReturnError(func->retDef, scope->className);
  985. }
  986. }
  987. }
  988. }
  989. }
  990. }
  991. void CheckClass::operatorEqReturnError(const Token *tok, const std::string &className)
  992. {
  993. reportError(tok, Severity::style, "operatorEq", "'" + className + "::operator=' should return '" + className + " &'.\n"
  994. "The "+className+"::operator= does not conform to standard C/C++ behaviour. To conform to standard C/C++ behaviour, return a reference to self (such as: '"+className+" &"+className+"::operator=(..) { .. return *this; }'. For safety reasons it might be better to not fix this message. If you think that safety is always more important than conformance then please ignore/suppress this message. For more details about this topic, see the book \"Effective C++\" by Scott Meyers."
  995. );
  996. }
  997. //---------------------------------------------------------------------------
  998. // ClassCheck: "C& operator=(const C&) { ... return *this; }"
  999. // operator= should return a reference to *this
  1000. //---------------------------------------------------------------------------
  1001. void CheckClass::operatorEqRetRefThis()
  1002. {
  1003. if (!_settings->isEnabled("style"))
  1004. return;
  1005. const std::size_t classes = symbolDatabase->classAndStructScopes.size();
  1006. for (std::size_t i = 0; i < classes; ++i) {
  1007. const Scope * scope = symbolDatabase->classAndStructScopes[i];
  1008. std::list<Function>::const_iterator func;
  1009. for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
  1010. if (func->type == Function::eOperatorEqual && func->hasBody) {
  1011. // make sure return signature is correct
  1012. if (Token::Match(func->retDef, "%type% &") && func->retDef->str() == scope->className) {
  1013. checkReturnPtrThis(&(*scope), &(*func), func->functionScope->classStart, func->functionScope->classEnd);
  1014. }
  1015. }
  1016. }
  1017. }
  1018. }
  1019. void CheckClass::checkReturnPtrThis(const Scope *scope, const Function *func, const Token *tok, const Token *last)
  1020. {
  1021. std::set<const Function*> analyzedFunctions;
  1022. checkReturnPtrThis(scope, func, tok, last, analyzedFunctions);
  1023. }
  1024. void CheckClass::checkReturnPtrThis(const Scope *scope, const Function *func, const Token *tok, const Token *last, std::set<const Function*>& analyzedFunctions)
  1025. {
  1026. bool foundReturn = false;
  1027. for (; tok && tok != last; tok = tok->next()) {
  1028. // check for return of reference to this
  1029. if (tok->str() == "return") {
  1030. foundReturn = true;
  1031. std::string cast("( " + scope->className + " & )");
  1032. if (Token::simpleMatch(tok->next(), cast.c_str()))
  1033. tok = tok->tokAt(4);
  1034. // check if a function is called
  1035. if (tok->strAt(2) == "(" &&
  1036. tok->linkAt(2)->next()->str() == ";") {
  1037. std::list<Function>::const_iterator it;
  1038. // check if it is a member function
  1039. for (it = scope->functionList.begin(); it != scope->functionList.end(); ++it) {
  1040. // check for a regular function with the same name and a body
  1041. if (it->type == Function::eFunction && it->hasBody &&
  1042. it->token->str() == tok->next()->str()) {
  1043. // check for the proper return type
  1044. if (it->tokenDef->previous()->str() == "&" &&
  1045. it->tokenDef->strAt(-2) == scope->className) {
  1046. // make sure it's not a const function
  1047. if (!it->isConst) {
  1048. /** @todo make sure argument types match */
  1049. // avoid endless recursions
  1050. if (analyzedFunctions.find(&*it) == analyzedFunctions.end()) {
  1051. analyzedFunctions.insert(&*it);
  1052. checkReturnPtrThis(scope, &*it, it->arg->link()->next(), it->arg->link()->next()->link(),
  1053. analyzedFunctions);
  1054. }
  1055. // just bail for now
  1056. else
  1057. return;
  1058. }
  1059. }
  1060. }
  1061. }
  1062. }
  1063. // check if *this is returned
  1064. else if (!(Token::Match(tok->next(), "(| * this ;|=") ||
  1065. Token::simpleMatch(tok->next(), "operator= (") ||
  1066. Token::simpleMatch(tok->next(), "this . operator= (") ||
  1067. (Token::Match(tok->next(), "%type% :: operator= (") &&
  1068. tok->next()->str() == scope->className)))
  1069. operatorEqRetRefThisError(func->token);
  1070. }
  1071. }
  1072. if (!foundReturn)
  1073. operatorEqRetRefThisError(func->token);
  1074. }
  1075. void CheckClass::operatorEqRetRefThisError(const Token *tok)
  1076. {
  1077. reportError(tok, Severity::style, "operatorEqRetRefThis", "'operator=' should return reference to 'this' instance.");
  1078. }
  1079. //---------------------------------------------------------------------------
  1080. // ClassCheck: "C& operator=(const C& rhs) { if (this == &rhs) ... }"
  1081. // operator= should check for assignment to self
  1082. //
  1083. // For simple classes, an assignment to self check is only a potential optimization.
  1084. //
  1085. // For classes that allocate dynamic memory, assignment to self can be a real error
  1086. // if it is deallocated and allocated again without being checked for.
  1087. //
  1088. // This check is not valid for classes with multiple inheritance because a
  1089. // class can have multiple addresses so there is no trivial way to check for
  1090. // assignment to self.
  1091. //---------------------------------------------------------------------------
  1092. void CheckClass::operatorEqToSelf()
  1093. {
  1094. if (!_settings->isEnabled("warning"))
  1095. return;
  1096. const std::size_t classes = symbolDatabase->classAndStructScopes.size();
  1097. for (std::size_t i = 0; i < classes; ++i) {
  1098. const Scope * scope = symbolDatabase->classAndStructScopes[i];
  1099. // skip classes with multiple inheritance
  1100. if (scope->definedType->derivedFrom.size() > 1)
  1101. continue;
  1102. std::list<Function>::const_iterator func;
  1103. for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
  1104. if (func->type == Function::eOperatorEqual && func->hasBody) {
  1105. // make sure that the operator takes an object of the same type as *this, otherwise we can't detect self-assignment checks
  1106. if (func->argumentList.empty())
  1107. continue;
  1108. const Token* typeTok = func->argumentList.front().typeEndToken();
  1109. while (typeTok->str() == "const" || typeTok->str() == "&" || typeTok->str() == "*")
  1110. typeTok = typeTok->previous();
  1111. if (typeTok->str() != scope->className)
  1112. continue;
  1113. // make sure return signature is correct
  1114. if (Token::Match(func->retDef, "%type% &") && func->retDef->str() == scope->className) {
  1115. // find the parameter name
  1116. const Token *rhs = func->argumentList.begin()->nameToken();
  1117. if (!hasAssignSelf(&(*func), rhs)) {
  1118. if (hasAllocation(&(*func), &*scope))
  1119. operatorEqToSelfError(func->token);
  1120. }
  1121. }
  1122. }
  1123. }
  1124. }
  1125. }
  1126. bool CheckClass::hasAllocation(const Function *func, const Scope* scope) const
  1127. {
  1128. // This function is called when no simple check was found for assignment
  1129. // to self. We are currently looking for:
  1130. // - deallocate member ; ... member =
  1131. // - alloc member
  1132. // That is not ideal because it can cause false negatives but its currently
  1133. // necessary to prevent false positives.
  1134. const Token *last = func->functionScope->classEnd;
  1135. for (const Token *tok = func->functionScope->classStart; tok && (tok != last); tok = tok->next()) {
  1136. if (Token::Match(tok, "%var% = malloc|realloc|calloc|new") && isMemberVar(scope, tok))
  1137. return true;
  1138. // check for deallocating memory
  1139. const Token *var = nullptr;
  1140. if (Token::Match(tok, "free ( %var%"))
  1141. var = tok->tokAt(2);
  1142. else if (Token::Match(tok, "delete [ ] %var%"))
  1143. var = tok->tokAt(3);
  1144. else if (Token::Match(tok, "delete %var%"))
  1145. var = tok->next();
  1146. // Check for assignment to the deleted pointer (only if its a member of the class)
  1147. if (var && isMemberVar(scope, var)) {
  1148. for (const Token *tok1 = var->next(); tok1 && (tok1 != last); tok1 = tok1->next()) {
  1149. if (Token::Match(tok1, "%var% =")) {
  1150. if (tok1->str() == var->str())
  1151. return true;
  1152. }
  1153. }
  1154. }
  1155. }
  1156. return false;
  1157. }
  1158. bool CheckClass::hasAssignSelf(const Function *func, const Token *rhs)
  1159. {
  1160. const Token *last = func->functionScope->classEnd;
  1161. for (const Token *tok = func->functionScope->classStart; tok && tok != last; tok = tok->next()) {
  1162. if (Token::simpleMatch(tok, "if (")) {
  1163. const Token *tok1 = tok->tokAt(2);
  1164. const Token *tok2 = tok->next()->link();
  1165. if (tok1 && tok2) {
  1166. for (; tok1 && tok1 != tok2; tok1 = tok1->next()) {
  1167. if (Token::Match(tok1, "this ==|!= & %var%")) {
  1168. if (tok1->strAt(3) == rhs->str())
  1169. return true;
  1170. } else if (Token::Match(tok1, "& %var% ==|!= this")) {
  1171. if (tok1->strAt(1) == rhs->str())
  1172. return true;
  1173. }
  1174. }
  1175. }
  1176. }
  1177. }
  1178. return false;
  1179. }
  1180. void CheckClass::operatorEqToSelfError(const Token *tok)
  1181. {
  1182. reportError(tok, Severity::warning, "operatorEqToSelf",
  1183. "'operator=' should check for assignment to self to avoid problems with dynamic memory.\n"
  1184. "'operator=' should check for assignment to self to ensure that each block of dynamically "
  1185. "allocated memory is owned and managed by only one instance of the class.");
  1186. }
  1187. //---------------------------------------------------------------------------
  1188. // A destructor in a base class should be virtual
  1189. //---------------------------------------------------------------------------
  1190. void CheckClass::virtualDestructor()
  1191. {
  1192. // This error should only be given if:
  1193. // * base class doesn't have virtual destructor
  1194. // * derived class has non-empty destructor
  1195. // * base class is deleted
  1196. // unless inconclusive in which case:
  1197. // * base class has virtual members but doesn't have virtual destructor
  1198. std::list<const Function *> inconclusive_errors;
  1199. const std::size_t classes = symbolDatabase->classAndStructScopes.size();
  1200. for (std::size_t i = 0; i < classes; ++i) {
  1201. const Scope * scope = symbolDatabase->classAndStructScopes[i];
  1202. // Skip base classes (unless inconclusive)
  1203. if (scope->definedType->derivedFrom.empty()) {
  1204. if (_settings->inconclusive) {
  1205. const Function *destructor = scope->getDestructor();
  1206. if (destructor && !destructor->isVirtual) {
  1207. std::list<Function>::const_iterator func;
  1208. for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
  1209. if (func->isVirtual) {
  1210. inconclusive_errors.push_back(destructor);
  1211. break;
  1212. }
  1213. }
  1214. }
  1215. }
  1216. continue;
  1217. }
  1218. // Find the destructor
  1219. const Function *destructor = scope->getDestructor();
  1220. // Check for destructor with implementation
  1221. if (!destructor || !destructor->hasBody)
  1222. continue;
  1223. // Empty destructor
  1224. if (destructor->token->linkAt(3) == destructor->token->tokAt(4))
  1225. continue;
  1226. const Token *derived = scope->classDef;
  1227. const Token *derivedClass = derived->next();
  1228. // Iterate through each base class...
  1229. for (std::size_t j = 0; j < scope->definedType->derivedFrom.size(); ++j) {
  1230. // Check if base class is public and exists in database
  1231. if (scope->definedType->derivedFrom[j].access != Private && scope->definedType->derivedFrom[j].type) {
  1232. const Type *derivedFrom = scope->definedType->derivedFrom[j].type;
  1233. const Scope *derivedFromScope = derivedFrom->classScope;
  1234. if (!derivedFromScope)
  1235. continue;
  1236. // Check for this pattern:
  1237. // 1. Base class pointer is given the address of derived class instance
  1238. // 2. Base class pointer is deleted
  1239. //
  1240. // If this pattern is not seen then bailout the checking of these base/derived classes
  1241. {
  1242. // pointer variables of type 'Base *'
  1243. std::set<unsigned int> basepointer;
  1244. for (std::size_t k = 1; k < symbolDatabase->getVariableListSize(); k++) {
  1245. const Variable* var = symbolDatabase->getVariableFromVarId(k);
  1246. if (var && var->isPointer() && var->type() == derivedFrom)
  1247. basepointer.insert(var->declarationId());
  1248. }
  1249. // pointer variables of type 'Base *' that should not be deleted
  1250. std::set<unsigned int> dontDelete;
  1251. // No deletion of derived class instance through base class pointer found => the code is ok
  1252. bool ok = true;
  1253. for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
  1254. if (Token::Match(tok, "[;{}] %var% =") &&
  1255. tok->next()->varId() > 0 &&
  1256. basepointer.find(tok->next()->varId()) != basepointer.end()) {
  1257. // new derived class..
  1258. if (Token::simpleMatch(tok->tokAt(3), ("new " + derivedClass->str()).c_str())) {
  1259. dontDelete.insert(tok->next()->varId());
  1260. }
  1261. }
  1262. // Delete base class pointer that might point at derived class
  1263. else if (Token::Match(tok, "delete %var% ;") &&
  1264. tok->next()->varId() &&
  1265. dontDelete.find(tok->next()->varId()) != dontDelete.end()) {
  1266. ok = false;
  1267. break;
  1268. }
  1269. }
  1270. // No base class pointer that points at a derived class is deleted
  1271. if (ok)
  1272. continue;
  1273. }
  1274. // Find the destructor declaration for the base class.
  1275. const Function *base_destructor = derivedFromScope->getDestructor();
  1276. const Token *base = nullptr;
  1277. if (base_destructor)
  1278. base = base_destructor->token;
  1279. // Check that there is a destructor..
  1280. if (!base_destructor) {
  1281. if (derivedFrom->derivedFrom.empty()) {
  1282. virtualDestructorError(derivedFrom->classDef, derivedFrom->name(), derivedClass->str(), false);
  1283. // check for duplicate error and remove if if found
  1284. std::list<const Function *>::iterator found = find(inconclusive_errors.begin(), inconclusive_errors.end(), base_destructor);
  1285. if (found != inconclusive_errors.end())
  1286. inconclusive_errors.erase(found);
  1287. }
  1288. } else if (!base_destructor->isVirtual) {
  1289. // TODO: This is just a temporary fix, better solution is needed.
  1290. // Skip situations where base class has base classes of its own, because
  1291. // some of the base classes might have virtual destructor.
  1292. // Proper solution is to check all of the base classes. If base class is not
  1293. // found or if one of the base classes has virtual destructor, error should not
  1294. // be printed. See TODO test case "virtualDestructorInherited"
  1295. if (derivedFrom->derivedFrom.empty()) {
  1296. // Make sure that the destructor is public (protected or private
  1297. // would not compile if inheritance is used in a way that would
  1298. // cause the bug we are trying to find here.)
  1299. if (base_destructor->access == Public) {
  1300. virtualDestructorError(base, derivedFrom->name(), derivedClass->str(), false);
  1301. // check for duplicate error and remove if if found
  1302. std::list<const Function *>::iterator found = find(inconclusive_errors.begin(), inconclusive_errors.end(), base_destructor);
  1303. if (found != inconclusive_errors.end())
  1304. inconclusive_errors.erase(found);
  1305. }
  1306. }
  1307. }
  1308. }
  1309. }
  1310. }
  1311. for (std::list<const Function *>::const_iterator i = inconclusive_errors.begin(); i != inconclusive_errors.end(); ++i)
  1312. virtualDestructorError((*i)->tokenDef, (*i)->name(), "", true);
  1313. }
  1314. void CheckClass::virtualDestructorError(const Token *tok, const std::string &Base, const std::string &Derived, bool inconclusive)
  1315. {
  1316. if (inconclusive)
  1317. reportError(tok, Severity::warning, "virtualDestructor", "Class '" + Base + "' which has virtual members does not have a virtual destructor.", true);
  1318. else
  1319. reportError(tok, Severity::error, "virtualDestructor", "Class '" + Base + "' which is inherited by class '" + Derived + "' does not have a virtual destructor.\n"
  1320. "Class '" + Base + "' which is inherited by class '" + Derived + "' does not have a virtual destructor. "
  1321. "If you destroy instances of the derived class by deleting a pointer that points to the base class, only "
  1322. "the destructor of the base class is executed. Thus, dynamic memory that is managed by the derived class "
  1323. "could leak. This can be avoided by adding a virtual destructor to the base class.");
  1324. }
  1325. //---------------------------------------------------------------------------
  1326. // warn for "this-x". The indented code may be "this->x"
  1327. //---------------------------------------------------------------------------
  1328. void CheckClass::thisSubtraction()
  1329. {
  1330. if (!_settings->isEnabled("warning"))
  1331. return;
  1332. const Token *tok = _tokenizer->tokens();
  1333. for (;;) {
  1334. tok = Token::findmatch(tok, "this - %var%");
  1335. if (!tok)
  1336. break;
  1337. if (tok->strAt(-1) != "*")
  1338. thisSubtractionError(tok);
  1339. tok = tok->next();
  1340. }
  1341. }
  1342. void CheckClass::thisSubtractionError(const Token *tok)
  1343. {
  1344. reportError(tok, Severity::warning, "thisSubtraction", "Suspicious pointer subtraction. Did you intend to write '->'?");
  1345. }
  1346. //---------------------------------------------------------------------------
  1347. // can member function be const?
  1348. //---------------------------------------------------------------------------
  1349. void CheckClass::checkConst()
  1350. {
  1351. // This is an inconclusive check. False positives: #3322.
  1352. if (!_settings->inconclusive)
  1353. return;
  1354. if (!_settings->isEnabled("style"))
  1355. return;
  1356. const std::size_t classes = symbolDatabase->classAndStructScopes.size();
  1357. for (std::size_t i = 0; i < classes; ++i) {
  1358. const Scope * scope = symbolDatabase->classAndStructScopes[i];
  1359. std::list<Function>::const_iterator func;
  1360. for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
  1361. // does the function have a body?
  1362. if (func->type == Function::eFunction && func->hasBody && !func->isFriend && !func->isStatic && !func->isVirtual) {
  1363. // get last token of return type
  1364. const Token *previous = func->tokenDef->previous();
  1365. // does the function return a pointer or reference?
  1366. if (Token::Match(previous, "*|&")) {
  1367. if (func->retDef->str() != "const")
  1368. continue;
  1369. } else if (Token::Match(previous->previous(), "*|& >")) {
  1370. const Token *temp = previous;
  1371. bool foundConst = false;
  1372. while (!Token::Match(temp->previous(), ";|}|{|public:|protected:|private:")) {
  1373. temp = temp->previous();
  1374. if (temp->str() == "const") {
  1375. foundConst = true;
  1376. break;
  1377. }
  1378. }
  1379. if (!foundConst)
  1380. continue;
  1381. } else if (func->isOperator && Token::Match(previous, ";|{|}|public:|private:|protected:")) { // Operator without return type: conversion operator
  1382. const std::string& opName = func->tokenDef->str();
  1383. if (opName.compare(8, 5, "const") != 0 && opName[opName.size()-1] == '&')
  1384. continue;
  1385. } else {
  1386. // don't warn for unknown types..
  1387. // LPVOID, HDC, etc
  1388. if (previous->isUpperCaseName() && previous->str().size() > 2 && !symbolDatabase->isClassOrStruct(previous->str()))
  1389. continue;
  1390. }
  1391. // check if base class function is virtual
  1392. if (!scope->definedType->derivedFrom.empty()) {
  1393. if (func->isImplicitlyVirtual(true))
  1394. continue;
  1395. }
  1396. bool memberAccessed = false;
  1397. // if nothing non-const was found. write error..
  1398. if (checkConstFunc(&(*scope), &*func, memberAccessed)) {
  1399. std::string classname = scope->className;
  1400. const Scope *nest = scope->nestedIn;
  1401. while (nest && nest->type != Scope::eGlobal) {
  1402. classname = std::string(nest->className + "::" + classname);
  1403. nest = nest->nestedIn;
  1404. }
  1405. // get function name
  1406. std::string functionName = (func->tokenDef->isName() ? "" : "operator") + func->tokenDef->str();
  1407. if (func->tokenDef->str() == "(")
  1408. functionName += ")";
  1409. else if (func->tokenDef->str() == "[")
  1410. functionName += "]";
  1411. if (!func->isConst || (!memberAccessed && !func->isOperator)) {
  1412. if (func->isInline)
  1413. checkConstError(func->token, classname, functionName, !memberAccessed && !func->isOperator);
  1414. else // not inline
  1415. checkConstError2(func->token, func->tokenDef, classname, functionName, !memberAccessed && !func->isOperator);
  1416. }
  1417. }
  1418. }
  1419. }
  1420. }
  1421. }
  1422. bool CheckClass::isMemberVar(const Scope *scope, const Token *tok) const
  1423. {
  1424. bool again = false;
  1425. // try to find the member variable
  1426. do {
  1427. again = false;
  1428. if (tok->str() == "this") {
  1429. return true;
  1430. } else if (Token::simpleMatch(tok->tokAt(-3), "( * this )")) {
  1431. return true;
  1432. } else if (Token::Match(tok->tokAt(-2), "%var% . %var%")) {
  1433. tok = tok->tokAt(-2);
  1434. again = true;
  1435. } else if (Token::Match(tok->tokAt(-2), "] . %var%")) {
  1436. tok = tok->linkAt(-2)->previous();
  1437. again = true;
  1438. } else if (tok->str() == "]") {
  1439. tok = tok->link()->previous();
  1440. again = true;
  1441. }
  1442. } while (again);
  1443. std::list<Variable>::const_iterator var;
  1444. for (var = scope->varlist.begin(); var != scope->varlist.end(); ++var) {
  1445. if (var->name() == tok->str()) {
  1446. if (tok->varId() == 0)
  1447. symbolDatabase->debugMessage(tok, "CheckClass::isMemberVar found used member variable \'" + tok->str() + "\' with varid 0");
  1448. return !var->isStatic();
  1449. }
  1450. }
  1451. // not found in this class
  1452. if (!scope->definedType->derivedFrom.empty() && !scope->definedType->hasCircularDependencies()) {
  1453. // check each base class
  1454. for (std::size_t i = 0; i < scope->definedType->derivedFrom.size(); ++i) {
  1455. // find the base class
  1456. const Type *derivedFrom = scope->definedType->derivedFrom[i].type;
  1457. // find the function in the base class
  1458. if (derivedFrom && derivedFrom->classScope) {
  1459. if (isMemberVar(derivedFrom->classScope, tok))
  1460. return true;
  1461. }
  1462. }
  1463. }
  1464. return false;
  1465. }
  1466. bool CheckClass::isMemberFunc(const Scope *scope, const Token *tok) const
  1467. {
  1468. if (tok->function() && tok->function()->nestedIn == scope)
  1469. return !tok->function()->isStatic;
  1470. // not found in this class
  1471. if (!scope->definedType->derivedFrom.empty()) {
  1472. // check each base class
  1473. for (std::size_t i = 0; i < scope->definedType->derivedFrom.size(); ++i) {
  1474. // find the base class
  1475. const Type *derivedFrom = scope->definedType->derivedFrom[i].type;
  1476. // find the function in the base class
  1477. if (derivedFrom && derivedFrom->classScope && !derivedFrom->hasCircularDependencies()) {
  1478. if (isMemberFunc(derivedFrom->classScope, tok))
  1479. return true;
  1480. }
  1481. }
  1482. }
  1483. return false;
  1484. }
  1485. bool CheckClass::isConstMemberFunc(const Scope *scope, const Token *tok) const
  1486. {
  1487. if (tok->function() && tok->function()->nestedIn == scope)
  1488. return tok->function()->isConst;
  1489. // not found in this class
  1490. if (!scope->definedType->derivedFrom.empty()) {
  1491. // check each base class
  1492. for (std::size_t i = 0; i < scope->definedType->derivedFrom.size(); ++i) {
  1493. // find the base class
  1494. const Type *derivedFrom = scope->definedType->derivedFrom[i].type;
  1495. // find the function in the base class
  1496. if (derivedFrom && derivedFrom->classScope && !derivedFrom->hasCircularDependencies()) {
  1497. if (isConstMemberFunc(derivedFrom->classScope, tok))
  1498. return true;
  1499. }
  1500. }
  1501. }
  1502. return false;
  1503. }
  1504. bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, bool& memberAccessed) const
  1505. {
  1506. // if the function doesn't have any assignment nor function call,
  1507. // it can be a const function..
  1508. for (const Token *tok1 = func->functionScope->classStart; tok1 && tok1 != func->functionScope->classEnd; tok1 = tok1->next()) {
  1509. if (tok1->isName() && isMemberVar(scope, tok1)) {
  1510. memberAccessed = true;
  1511. const Variable* v = tok1->variable();
  1512. if (v && v->isMutable())
  1513. continue;
  1514. if (tok1->str() == "this" && tok1->previous()->isAssignmentOp())
  1515. return (false);
  1516. const Token* lhs = tok1->tokAt(-1);
  1517. if (lhs->str() == "&") {
  1518. lhs = lhs->previous();
  1519. if (lhs->type() == Token::eAssignmentOp && lhs->previous()->variable()) {
  1520. if (lhs->previous()->variable()->typeStartToken()->strAt(-1) != "const" && lhs->previous()->variable()->isPointer())
  1521. return false;
  1522. }
  1523. } else {
  1524. const Variable* v2 = lhs->previous()->variable();
  1525. if (lhs->type() == Token::eAssignmentOp && v2)
  1526. if (!v2->isConst() && v2->isReference() && lhs == v2->nameToken()->next())
  1527. return false;
  1528. }
  1529. const Token* jumpBackToken = 0;
  1530. const Token *lastVarTok = tok1;
  1531. const Token *end = tok1;
  1532. for (;;) {
  1533. if (Token::Match(end->next(), ". %var%")) {
  1534. end = end->tokAt(2);
  1535. if (end->varId())
  1536. lastVarTok = end;
  1537. } else if (end->strAt(1) == "[") {
  1538. if (end->varId()) {
  1539. const Variable *var = end->variable();
  1540. // The container contains the STL types whose operator[] is not a const.
  1541. // THIS ARRAY MUST BE ORDERED ALPHABETICALLY
  1542. static const char* const stl_containers [] = {
  1543. "map", "unordered_map"
  1544. };
  1545. if (var && var->isStlType(stl_containers))
  1546. return false;
  1547. }
  1548. if (!jumpBackToken)
  1549. jumpBackToken = end->next(); // Check inside the [] brackets
  1550. end = end->linkAt(1);
  1551. } else if (end->strAt(1) == ")")
  1552. end = end->next();
  1553. else
  1554. break;
  1555. }
  1556. if (end->strAt(1) == "(") {
  1557. const Variable *var = lastVarTok->variable();
  1558. if (!var)
  1559. return false;
  1560. if (var->isStlType() // assume all std::*::size() and std::*::empty() are const
  1561. && (Token::Match(end, "size|empty|cend|crend|cbegin|crbegin|max_size|length|count|capacity|get_allocator|c_str|str ( )") || Token::Match(end, "rfind|copy")))
  1562. ;
  1563. else if (!var->typeScope() || !isConstMemberFunc(var->typeScope(), end))
  1564. return (false);
  1565. }
  1566. // Assignment
  1567. else if (end->next()->type() == Token::eAssignmentOp)
  1568. return (false);
  1569. // Streaming
  1570. else if (end->strAt(1) == "<<" && tok1->strAt(-1) != "<<")
  1571. return (false);
  1572. else if (tok1->strAt(-1) == ">>")
  1573. return (false);
  1574. // ++/--
  1575. else if (end->next()->type() == Token::eIncDecOp || tok1->previous()->type() == Token::eIncDecOp)
  1576. return (false);
  1577. const Token* start = tok1;
  1578. while (tok1->strAt(-1) == ")")
  1579. tok1 = tok1->linkAt(-1);
  1580. if (start->strAt(-1) == "delete")
  1581. return (false);
  1582. tok1 = jumpBackToken?jumpBackToken:end; // Jump back to first [ to check inside, or jump to end of expression
  1583. }
  1584. // streaming: <<
  1585. else if (Token::simpleMatch(tok1->previous(), ") <<") &&
  1586. isMemberVar(scope, tok1->tokAt(-2))) {
  1587. const Variable* var = tok1->tokAt(-2)->variable();
  1588. if (!var || !var->isMutable())
  1589. return (false);
  1590. }
  1591. // function call..
  1592. else if (Token::Match(tok1, "%var% (") && !tok1->isStandardType() &&
  1593. !Token::Match(tok1, "return|if|string|switch|while|catch|for")) {
  1594. if (isMemberFunc(scope, tok1) && tok1->strAt(-1) != ".") {
  1595. if (!isConstMemberFunc(scope, tok1))
  1596. return (false);
  1597. memberAccessed = true;
  1598. }
  1599. // Member variable given as parameter
  1600. for (const Token* tok2 = tok1->tokAt(2); tok2 && tok2 != tok1->next()->link(); tok2 = tok2->next()) {
  1601. if (tok2->str() == "(")
  1602. tok2 = tok2->link();
  1603. else if (tok2->isName() && isMemberVar(scope, tok2)) {
  1604. const Variable* var = tok2->variable();
  1605. if (!var || !var->isMutable())
  1606. return (false); // TODO: Only bailout if function takes argument as non-const reference
  1607. }
  1608. }
  1609. } else if (Token::simpleMatch(tok1, "> (") && (!tok1->link() || !Token::Match(tok1->link()->previous(), "static_cast|const_cast|dynamic_cast|reinterpret_cast"))) {
  1610. return (false);
  1611. }
  1612. }
  1613. return (true);
  1614. }
  1615. void CheckClass::checkConstError(const Token *tok, const std::string &classname, const std::string &funcname, bool suggestStatic)
  1616. {
  1617. checkConstError2(tok, 0, classname, funcname, suggestStatic);
  1618. }
  1619. void CheckClass::checkConstError2(const Token *tok1, const Token *tok2, const std::string &classname, const std::string &funcname, bool suggestStatic)
  1620. {
  1621. std::list<const Token *> toks;
  1622. toks.push_back(tok1);
  1623. if (tok2)
  1624. toks.push_back(tok2);
  1625. if (!suggestStatic)
  1626. reportError(toks, Severity::style, "functionConst",
  1627. "Technically the member function '" + classname + "::" + funcname + "' can be const.\n"
  1628. "The member function '" + classname + "::" + funcname + "' can be made a const "
  1629. "function. Making this function 'const' should not cause compiler errors. "
  1630. "Even though the function can be made const function technically it may not make "
  1631. "sense conceptually. Think about your design and the task of the function first - is "
  1632. "it a function that must not change object internal state?", true);
  1633. else
  1634. reportError(toks, Severity::performance, "functionStatic",
  1635. "Technically the member function '" + classname + "::" + funcname + "' can be static.\n"
  1636. "The member function '" + classname + "::" + funcname + "' can be made a static "
  1637. "function. Making a function static can bring a performance benefit since no 'this' instance is "
  1638. "passed to the function. This change should not cause compiler errors but it does not "
  1639. "necessarily make sense conceptually. Think about your design and the task of the function first - "
  1640. "is it a function that must not access members of class instances?", true);
  1641. }
  1642. //---------------------------------------------------------------------------
  1643. // ClassCheck: Check that initializer list is in declared order.
  1644. //---------------------------------------------------------------------------
  1645. struct VarInfo {
  1646. VarInfo(const Variable *_var, const Token *_tok)
  1647. : var(_var), tok(_tok) { }
  1648. const Variable *var;
  1649. const Token *tok;
  1650. };
  1651. void CheckClass::initializerListOrder()
  1652. {
  1653. if (!_settings->isEnabled("style"))
  1654. return;
  1655. // This check is not inconclusive. However it only determines if the initialization
  1656. // order is incorrect. It does not determine if being out of order causes
  1657. // a real error. Out of order is not necessarily an error but you can never
  1658. // have an error if the list is in order so this enforces defensive programming.
  1659. if (!_settings->inconclusive)
  1660. return;
  1661. const std::size_t classes = symbolDatabase->classAndStructScopes.size();
  1662. for (std::size_t i = 0; i < classes; ++i) {
  1663. const Scope * info = symbolDatabase->classAndStructScopes[i];
  1664. std::list<Function>::const_iterator func;
  1665. // iterate through all member functions looking for constructors
  1666. for (func = info->functionList.begin(); func != info->functionList.end(); ++func) {
  1667. if ((func->isConstructor()) && func->hasBody) {
  1668. // check for initializer list
  1669. const Token *tok = func->arg->link()->next();
  1670. if (tok->str() == ":") {
  1671. std::vector<VarInfo> vars;
  1672. tok = tok->next();
  1673. // find all variable initializations in list
  1674. while (tok && tok != func->functionScope->classStart) {
  1675. if (Token::Match(tok, "%var% (|{")) {
  1676. const Variable *var = info->getVariable(tok->str());
  1677. if (var)
  1678. vars.push_back(VarInfo(var, tok));
  1679. if (Token::Match(tok->tokAt(2), "%var% =")) {
  1680. var = info->getVariable(tok->strAt(2));
  1681. if (var)
  1682. vars.push_back(VarInfo(var, tok->tokAt(2)));
  1683. }
  1684. tok = tok->next()->link()->next();
  1685. } else
  1686. tok = tok->next();
  1687. }
  1688. // need at least 2 members to have out of order initialization
  1689. for (std::size_t j = 1; j < vars.size(); j++) {
  1690. // check for out of order initialization
  1691. if (vars[j].var->index() < vars[j - 1].var->index())
  1692. initializerListError(vars[j].tok,vars[j].var->nameToken(), info->className, vars[j].var->name());
  1693. }
  1694. }
  1695. }
  1696. }
  1697. }
  1698. }
  1699. void CheckClass::initializerListError(const Token *tok1, const Token *tok2, const std::string &classname, const std::string &varname)
  1700. {
  1701. std::list<const Token *> toks;
  1702. toks.push_back(tok1);
  1703. toks.push_back(tok2);
  1704. reportError(toks, Severity::style, "initializerList",
  1705. "Member variable '" + classname + "::" +
  1706. varname + "' is in the wrong place in the initializer list.\n"
  1707. "Member variable '" + classname + "::" +
  1708. varname + "' is in the wrong place in the initializer list. "
  1709. "Members are initialized in the order they are declared, not in the "
  1710. "order they are in the initializer list. Keeping the initializer list "
  1711. "in the same order that the members were declared prevents order dependent "
  1712. "initialization errors.", true);
  1713. }
  1714. //---------------------------------------------------------------------------
  1715. // Check for self initialization in initialization list
  1716. //---------------------------------------------------------------------------
  1717. void CheckClass::checkSelfInitialization()
  1718. {
  1719. for (std::size_t i = 0; i < symbolDatabase->functionScopes.size(); ++i) {
  1720. const Scope* scope = symbolDatabase->functionScopes[i];
  1721. const Function* function = scope->function;
  1722. if (!function || !function->isConstructor())
  1723. continue;
  1724. const Token* tok = function->arg->link()->next();
  1725. if (tok->str() != ":")
  1726. continue;
  1727. for (; tok != scope->classStart; tok = tok->next()) {
  1728. if (Token::Match(tok, "[:,] %var% (|{ %var% )|}") && tok->next()->varId() && tok->next()->varId() == tok->tokAt(3)->varId()) {
  1729. selfInitializationError(tok, tok->strAt(1));
  1730. }
  1731. }
  1732. }
  1733. }
  1734. void CheckClass::selfInitializationError(const Token* tok, const std::string& varname)
  1735. {
  1736. reportError(tok, Severity::error, "selfInitialization", "Member variable '" + varname + "' is initialized by itself.");
  1737. }
  1738. //---------------------------------------------------------------------------
  1739. // Check for pure virtual function calls
  1740. //---------------------------------------------------------------------------
  1741. void CheckClass::checkPureVirtualFunctionCall()
  1742. {
  1743. const std::size_t functions = symbolDatabase->functionScopes.size();
  1744. std::map<const Function *, std::list<const Token *> > callsPureVirtualFunctionMap;
  1745. for (std::size_t i = 0; i < functions; ++i) {
  1746. const Scope * scope = symbolDatabase->functionScopes[i];
  1747. if (scope->function == 0 || !scope->function->hasBody ||
  1748. !(scope->function->isConstructor() ||
  1749. scope->function->isDestructor()))
  1750. continue;
  1751. const std::list<const Token *> & pureVirtualFunctionCalls=callsPureVirtualFunction(*scope->function,callsPureVirtualFunctionMap);
  1752. for (std::list<const Token *>::const_iterator pureCallIter=pureVirtualFunctionCalls.begin();
  1753. pureCallIter!=pureVirtualFunctionCalls.end();
  1754. ++pureCallIter) {
  1755. const Token & pureCall=**pureCallIter;
  1756. std::list<const Token *> pureFuncStack;
  1757. pureFuncStack.push_back(&pureCall);
  1758. getFirstPureVirtualFunctionCallStack(callsPureVirtualFunctionMap, pureCall, pureFuncStack);
  1759. if (!pureFuncStack.empty())
  1760. callsPureVirtualFunctionError(*scope->function, pureFuncStack, pureFuncStack.back()->str());
  1761. }
  1762. }
  1763. }
  1764. const std::list<const Token *> & CheckClass::callsPureVirtualFunction(const Function & function,
  1765. std::map<const Function *, std::list<const Token *> > & callsPureVirtualFunctionMap)
  1766. {
  1767. std::pair<std::map<const Function *, std::list<const Token *> >::iterator, bool > found =
  1768. callsPureVirtualFunctionMap.insert(std::pair<const Function *, std::list< const Token *> >(&function, std::list<const Token *>()));
  1769. std::list<const Token *> & pureFunctionCalls = found.first->second;
  1770. if (found.second) {
  1771. if (function.hasBody) {
  1772. for (const Token *tok = function.arg->link();
  1773. tok && tok != function.functionScope->classEnd;
  1774. tok = tok->next()) {
  1775. if (function.type != Function::eConstructor &&
  1776. function.type != Function::eCopyConstructor &&
  1777. function.type != Function::eMoveConstructor &&
  1778. function.type != Function::eDestructor) {
  1779. if ((Token::simpleMatch(tok, ") {") &&
  1780. tok->link() &&
  1781. Token::Match(tok->link()->previous(), "if|switch")) ||
  1782. Token::simpleMatch(tok, "else {")
  1783. ) {
  1784. // Assume pure virtual function call is prevented by "if|else|switch" condition
  1785. tok = tok->linkAt(1);
  1786. continue;
  1787. }
  1788. }
  1789. const Function * callFunction = tok->function();
  1790. if (!callFunction ||
  1791. function.nestedIn != callFunction->nestedIn ||
  1792. (tok->previous() && tok->previous()->str() == "."))
  1793. continue;
  1794. if (tok->previous() &&
  1795. tok->previous()->str() == "(") {
  1796. const Token * prev = tok->previous();
  1797. if (prev->previous() &&
  1798. (_settings->library.ignorefunction(tok->str())
  1799. || _settings->library.ignorefunction(prev->previous()->str())))
  1800. continue;
  1801. }
  1802. if (isPureWithoutBody(*callFunction)) {
  1803. pureFunctionCalls.push_back(tok);
  1804. continue;
  1805. }
  1806. const std::list<const Token *> & pureFunctionCallsOfTok = callsPureVirtualFunction(*callFunction,
  1807. callsPureVirtualFunctionMap);
  1808. if (!pureFunctionCallsOfTok.empty()) {
  1809. pureFunctionCalls.push_back(tok);
  1810. continue;
  1811. }
  1812. }
  1813. }
  1814. }
  1815. return pureFunctionCalls;
  1816. }
  1817. void CheckClass::getFirstPureVirtualFunctionCallStack(
  1818. std::map<const Function *, std::list<const Token *> > & callsPureVirtualFunctionMap,
  1819. const Token & pureCall,
  1820. std::list<const Token *> & pureFuncStack)
  1821. {
  1822. if (isPureWithoutBody(*pureCall.function())) {
  1823. pureFuncStack.push_back(pureCall.function()->token);
  1824. return;
  1825. }
  1826. std::map<const Function *, std::list<const Token *> >::const_iterator found = callsPureVirtualFunctionMap.find(pureCall.function());
  1827. if (found == callsPureVirtualFunctionMap.end() ||
  1828. found->second.empty()) {
  1829. pureFuncStack.clear();
  1830. return;
  1831. }
  1832. const Token & firstPureCall = **found->second.begin();
  1833. pureFuncStack.push_back(&firstPureCall);
  1834. getFirstPureVirtualFunctionCallStack(callsPureVirtualFunctionMap, firstPureCall, pureFuncStack);
  1835. }
  1836. void CheckClass::callsPureVirtualFunctionError(
  1837. const Function & scopeFunction,
  1838. const std::list<const Token *> & tokStack,
  1839. const std::string &purefuncname)
  1840. {
  1841. const char * scopeFunctionTypeName = getFunctionTypeName(scopeFunction.type);
  1842. reportError(tokStack, Severity::warning, "pureVirtualCall", "Call of pure virtual function '" + purefuncname + "' in " + scopeFunctionTypeName + ".\n"
  1843. "Call of pure virtual function '" + purefuncname + "' in " + scopeFunctionTypeName + ". The call will fail during runtime.");
  1844. }
  1845. //---------------------------------------------------------------------------
  1846. // Check for members hiding inherited members with the same name
  1847. //---------------------------------------------------------------------------
  1848. void CheckClass::checkDuplInheritedMembers()
  1849. {
  1850. if (!_settings->isEnabled("warning"))
  1851. return;
  1852. // Iterate over all classes
  1853. for (std::list<Type>::const_iterator classIt = symbolDatabase->typeList.begin();
  1854. classIt != symbolDatabase->typeList.end();
  1855. ++classIt) {
  1856. // Iterate over the parent classes
  1857. for (std::vector<Type::BaseInfo>::const_iterator parentClassIt = classIt->derivedFrom.begin();
  1858. parentClassIt != classIt->derivedFrom.end();
  1859. ++parentClassIt) {
  1860. // Check if there is info about the 'Base' class
  1861. if (!parentClassIt->type || !parentClassIt->type->classScope)
  1862. continue;
  1863. // Check if they have a member variable in common
  1864. for (std::list<Variable>::const_iterator classVarIt = classIt->classScope->varlist.begin();
  1865. classVarIt != classIt->classScope->varlist.end();
  1866. ++classVarIt) {
  1867. for (std::list<Variable>::const_iterator parentClassVarIt = parentClassIt->type->classScope->varlist.begin();
  1868. parentClassVarIt != parentClassIt->type->classScope->varlist.end();
  1869. ++parentClassVarIt) {
  1870. if (classVarIt->name() == parentClassVarIt->name() && !parentClassVarIt->isPrivate()) { // Check if the class and its parent have a common variable
  1871. duplInheritedMembersError(classVarIt->nameToken(), parentClassVarIt->nameToken(),
  1872. classIt->name(), parentClassIt->type->name(), classVarIt->name(),
  1873. classIt->classScope->type == Scope::eStruct,
  1874. parentClassIt->type->classScope->type == Scope::eStruct);
  1875. }
  1876. }
  1877. }
  1878. }
  1879. }
  1880. }
  1881. void CheckClass::duplInheritedMembersError(const Token *tok1, const Token* tok2,
  1882. const std::string &derivedname, const std::string &basename,
  1883. const std::string &variablename, bool derivedIsStruct, bool baseIsStruct)
  1884. {
  1885. std::list<const Token *> toks;
  1886. toks.push_back(tok1);
  1887. toks.push_back(tok2);
  1888. const std::string message = "The " + std::string(derivedIsStruct ? "struct" : "class") + " '" + derivedname +
  1889. "' defines member variable with name '" + variablename + "' also defined in its parent " +
  1890. std::string(baseIsStruct ? "struct" : "class") + " '" + basename + "'.";
  1891. reportError(toks, Severity::warning, "duplInheritedMember", message);
  1892. }