PageRenderTime 37ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 1ms

/test/testclass.cpp

https://github.com/toralf/cppcheck
C++ | 6139 lines | 5314 code | 632 blank | 193 comment | 7 complexity | 9088e92ec4301a522b70a4bef6cb00a0 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. #include "tokenize.h"
  19. #include "checkclass.h"
  20. #include "testsuite.h"
  21. #include <sstream>
  22. extern std::ostringstream errout;
  23. class TestClass : public TestFixture {
  24. public:
  25. TestClass() : TestFixture("TestClass") {
  26. }
  27. private:
  28. void run() {
  29. TEST_CASE(virtualDestructor1); // Base class not found => no error
  30. TEST_CASE(virtualDestructor2); // Base class doesn't have a destructor
  31. TEST_CASE(virtualDestructor3); // Base class has a destructor, but it's not virtual
  32. TEST_CASE(virtualDestructor4); // Derived class doesn't have a destructor => no error
  33. TEST_CASE(virtualDestructor5); // Derived class has empty destructor => no error
  34. TEST_CASE(virtualDestructor6); // only report error if base class pointer that points at derived class is deleted
  35. TEST_CASE(virtualDestructorProtected);
  36. TEST_CASE(virtualDestructorInherited);
  37. TEST_CASE(virtualDestructorTemplate);
  38. TEST_CASE(virtualDestructorInconclusive); // ticket # 5807
  39. TEST_CASE(copyConstructor1);
  40. TEST_CASE(copyConstructor2); // ticket #4458
  41. TEST_CASE(operatorEq1);
  42. TEST_CASE(operatorEq2);
  43. TEST_CASE(operatorEq3); // ticket #3051
  44. TEST_CASE(operatorEq4); // ticket #3114
  45. TEST_CASE(operatorEq5); // ticket #3296
  46. TEST_CASE(operatorEqRetRefThis1);
  47. TEST_CASE(operatorEqRetRefThis2); // ticket #1323
  48. TEST_CASE(operatorEqRetRefThis3); // ticket #1405
  49. TEST_CASE(operatorEqRetRefThis4); // ticket #1451
  50. TEST_CASE(operatorEqRetRefThis5); // ticket #1550
  51. TEST_CASE(operatorEqRetRefThis6); // ticket #2479
  52. TEST_CASE(operatorEqRetRefThis7); // ticket #5782 endless recursion
  53. TEST_CASE(operatorEqToSelf1); // single class
  54. TEST_CASE(operatorEqToSelf2); // nested class
  55. TEST_CASE(operatorEqToSelf3); // multiple inheritance
  56. TEST_CASE(operatorEqToSelf4); // nested class with multiple inheritance
  57. TEST_CASE(operatorEqToSelf5); // ticket # 1233
  58. TEST_CASE(operatorEqToSelf6); // ticket # 1550
  59. TEST_CASE(operatorEqToSelf7);
  60. TEST_CASE(operatorEqToSelf8); // ticket #2179
  61. TEST_CASE(operatorEqToSelf9); // ticket #2592
  62. TEST_CASE(memsetOnStruct);
  63. TEST_CASE(memsetVector);
  64. TEST_CASE(memsetOnClass);
  65. TEST_CASE(memsetOnInvalid); // Ticket #5425: Crash upon invalid
  66. TEST_CASE(memsetOnStdPodType); // Ticket #5901 - std::uint8_t
  67. TEST_CASE(memsetOnFloat); // Ticket #5421
  68. TEST_CASE(mallocOnClass);
  69. TEST_CASE(this_subtraction); // warn about "this-x"
  70. // can member function be made const
  71. TEST_CASE(const1);
  72. TEST_CASE(const2);
  73. TEST_CASE(const3);
  74. TEST_CASE(const4);
  75. TEST_CASE(const5); // ticket #1482
  76. TEST_CASE(const6); // ticket #1491
  77. TEST_CASE(const7);
  78. TEST_CASE(const8); // ticket #1517
  79. TEST_CASE(const9); // ticket #1515
  80. TEST_CASE(const10); // ticket #1522
  81. TEST_CASE(const11); // ticket #1529
  82. TEST_CASE(const12); // ticket #1552
  83. TEST_CASE(const13); // ticket #1519
  84. TEST_CASE(const14);
  85. TEST_CASE(const15);
  86. TEST_CASE(const16); // ticket #1551
  87. TEST_CASE(const17); // ticket #1552
  88. TEST_CASE(const18);
  89. TEST_CASE(const19); // ticket #1612
  90. TEST_CASE(const20); // ticket #1602
  91. TEST_CASE(const21); // ticket #1683
  92. TEST_CASE(const22);
  93. TEST_CASE(const23); // ticket #1699
  94. TEST_CASE(const24); // ticket #1708
  95. TEST_CASE(const25); // ticket #1724
  96. TEST_CASE(const26); // ticket #1847
  97. TEST_CASE(const27); // ticket #1882
  98. TEST_CASE(const28); // ticket #1883
  99. TEST_CASE(const29); // ticket #1922
  100. TEST_CASE(const30);
  101. TEST_CASE(const31);
  102. TEST_CASE(const32); // ticket #1905 - member array is assigned
  103. TEST_CASE(const33);
  104. TEST_CASE(const34); // ticket #1964
  105. TEST_CASE(const35); // ticket #2001
  106. TEST_CASE(const36); // ticket #2003
  107. TEST_CASE(const37); // ticket #2081 and #2085
  108. TEST_CASE(const38); // ticket #2135
  109. TEST_CASE(const39);
  110. TEST_CASE(const40); // ticket #2228
  111. TEST_CASE(const41); // ticket #2255
  112. TEST_CASE(const42); // ticket #2282
  113. TEST_CASE(const43); // ticket #2377
  114. TEST_CASE(const44); // ticket #2595
  115. TEST_CASE(const45); // ticket #2664
  116. TEST_CASE(const46); // ticket #2636
  117. TEST_CASE(const47); // ticket #2670
  118. TEST_CASE(const48); // ticket #2672
  119. TEST_CASE(const49); // ticket #2795
  120. TEST_CASE(const50); // ticket #2943
  121. TEST_CASE(const51); // ticket #3040
  122. TEST_CASE(const52); // ticket #3048
  123. TEST_CASE(const53); // ticket #3049
  124. TEST_CASE(const54); // ticket #3052
  125. TEST_CASE(const55);
  126. TEST_CASE(const56); // ticket #3149
  127. TEST_CASE(const57); // tickets #2669 and #2477
  128. TEST_CASE(const58); // ticket #2698
  129. TEST_CASE(const59); // ticket #4646
  130. TEST_CASE(const60); // ticket #3322
  131. TEST_CASE(const61); // ticket #5606
  132. TEST_CASE(const62); // ticket #5701
  133. TEST_CASE(const63); // ticket #5983
  134. TEST_CASE(const64); // ticket #6268
  135. TEST_CASE(const_handleDefaultParameters);
  136. TEST_CASE(const_passThisToMemberOfOtherClass);
  137. TEST_CASE(assigningPointerToPointerIsNotAConstOperation);
  138. TEST_CASE(assigningArrayElementIsNotAConstOperation);
  139. TEST_CASE(constoperator1); // operator< can often be const
  140. TEST_CASE(constoperator2); // operator<<
  141. TEST_CASE(constoperator3);
  142. TEST_CASE(constoperator4);
  143. TEST_CASE(constoperator5); // ticket #3252
  144. TEST_CASE(constincdec); // increment/decrement => non-const
  145. TEST_CASE(constassign1);
  146. TEST_CASE(constassign2);
  147. TEST_CASE(constincdecarray); // increment/decrement array element => non-const
  148. TEST_CASE(constassignarray);
  149. TEST_CASE(constReturnReference);
  150. TEST_CASE(constDelete); // delete member variable => not const
  151. TEST_CASE(constLPVOID); // a function that returns LPVOID can't be const
  152. TEST_CASE(constFunc); // a function that calls const functions can be const
  153. TEST_CASE(constVirtualFunc);
  154. TEST_CASE(constIfCfg); // ticket #1881 - fp when there are #if
  155. TEST_CASE(constFriend); // ticket #1921 - fp for friend function
  156. TEST_CASE(constUnion); // ticket #2111 - fp when there is a union
  157. TEST_CASE(constArrayOperator); // #4406
  158. TEST_CASE(initializerListOrder);
  159. TEST_CASE(initializerListUsage);
  160. TEST_CASE(selfInitialization);
  161. TEST_CASE(pureVirtualFunctionCall);
  162. TEST_CASE(pureVirtualFunctionCallOtherClass);
  163. TEST_CASE(pureVirtualFunctionCallWithBody);
  164. TEST_CASE(pureVirtualFunctionCallPrevented);
  165. TEST_CASE(duplInheritedMembers);
  166. }
  167. void checkDuplInheritedMembers(const char code[]) {
  168. // Clear the error log
  169. errout.str("");
  170. Settings settings;
  171. settings.addEnabled("warning");
  172. // Tokenize..
  173. Tokenizer tokenizer(&settings, this);
  174. std::istringstream istr(code);
  175. tokenizer.tokenize(istr, "test.cpp");
  176. tokenizer.simplifyTokenList2();
  177. // Check..
  178. CheckClass checkClass(&tokenizer, &settings, this);
  179. checkClass.checkDuplInheritedMembers();
  180. }
  181. void duplInheritedMembers() {
  182. checkDuplInheritedMembers("class Base {\n"
  183. " int x;\n"
  184. "};\n"
  185. "struct Derived : Base {\n"
  186. " int x;\n"
  187. "};");
  188. ASSERT_EQUALS("", errout.str());
  189. checkDuplInheritedMembers("class Base {\n"
  190. " protected:\n"
  191. " int x;\n"
  192. "};\n"
  193. "struct Derived : Base {\n"
  194. " int x;\n"
  195. "};");
  196. ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:3]: (warning) The struct 'Derived' defines member variable with name 'x' also defined in its parent class 'Base'.\n", errout.str());
  197. checkDuplInheritedMembers("class Base {\n"
  198. " protected:\n"
  199. " int x;\n"
  200. "};\n"
  201. "struct Derived : public Base {\n"
  202. " int x;\n"
  203. "};");
  204. ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:3]: (warning) The struct 'Derived' defines member variable with name 'x' also defined in its parent class 'Base'.\n", errout.str());
  205. checkDuplInheritedMembers("class Base0 {\n"
  206. " int x;\n"
  207. "};\n"
  208. "class Base1 {\n"
  209. " int x;\n"
  210. "};\n"
  211. "struct Derived : Base0, Base1 {\n"
  212. " int x;\n"
  213. "};");
  214. ASSERT_EQUALS("", errout.str());
  215. checkDuplInheritedMembers("class Base0 {\n"
  216. " protected:\n"
  217. " int x;\n"
  218. "};\n"
  219. "class Base1 {\n"
  220. " int x;\n"
  221. "};\n"
  222. "struct Derived : Base0, Base1 {\n"
  223. " int x;\n"
  224. "};");
  225. ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:3]: (warning) The struct 'Derived' defines member variable with name 'x' also defined in its parent class 'Base0'.\n", errout.str());
  226. checkDuplInheritedMembers("class Base0 {\n"
  227. " protected:\n"
  228. " int x;\n"
  229. "};\n"
  230. "class Base1 {\n"
  231. " public:\n"
  232. " int x;\n"
  233. "};\n"
  234. "struct Derived : Base0, Base1 {\n"
  235. " int x;\n"
  236. "};");
  237. ASSERT_EQUALS("[test.cpp:10] -> [test.cpp:3]: (warning) The struct 'Derived' defines member variable with name 'x' also defined in its parent class 'Base0'.\n"
  238. "[test.cpp:10] -> [test.cpp:7]: (warning) The struct 'Derived' defines member variable with name 'x' also defined in its parent class 'Base1'.\n", errout.str());
  239. checkDuplInheritedMembers("class Base {\n"
  240. " int x;\n"
  241. "};\n"
  242. "struct Derived : Base {\n"
  243. " int y;\n"
  244. "};");
  245. ASSERT_EQUALS("", errout.str());
  246. checkDuplInheritedMembers("class A {\n"
  247. " int x;\n"
  248. "};\n"
  249. "struct B {\n"
  250. " int x;\n"
  251. "};");
  252. ASSERT_EQUALS("", errout.str());
  253. // Unknown 'Base' class
  254. checkDuplInheritedMembers("class Derived : public UnknownBase {\n"
  255. " int x;\n"
  256. "};");
  257. ASSERT_EQUALS("", errout.str());
  258. checkDuplInheritedMembers("class Base {\n"
  259. " int x;\n"
  260. "};\n"
  261. "class Derived : public Base {\n"
  262. "};");
  263. ASSERT_EQUALS("", errout.str());
  264. }
  265. void checkCopyConstructor(const char code[]) {
  266. // Clear the error log
  267. errout.str("");
  268. Settings settings;
  269. settings.addEnabled("style");
  270. // Tokenize..
  271. Tokenizer tokenizer(&settings, this);
  272. std::istringstream istr(code);
  273. tokenizer.tokenize(istr, "test.cpp");
  274. tokenizer.simplifyTokenList2();
  275. // Check..
  276. CheckClass checkClass(&tokenizer, &settings, this);
  277. checkClass.copyconstructors();
  278. }
  279. void copyConstructor1() {
  280. checkCopyConstructor("class F\n"
  281. "{\n"
  282. " public:\n"
  283. " char *c,*p,*d;\n"
  284. " F(const F &f) : p(f.p), c(f.c)\n"
  285. " {\n"
  286. " p=(char *)malloc(strlen(f.p)+1);\n"
  287. " strcpy(p,f.p);\n"
  288. " }\n"
  289. " F(char *str)\n"
  290. " {\n"
  291. " p=(char *)malloc(strlen(str)+1);\n"
  292. " strcpy(p,str);\n"
  293. " }\n"
  294. "};");
  295. ASSERT_EQUALS("[test.cpp:5]: (style) Value of pointer 'p', which points to allocated memory, is copied in copy constructor instead of allocating new memory.\n", errout.str());
  296. checkCopyConstructor("class F {\n"
  297. " char *p;\n"
  298. " F(const F &f) {\n"
  299. " p = f.p;\n"
  300. " }\n"
  301. " F(char *str) {\n"
  302. " p = malloc(strlen(str)+1);\n"
  303. " }\n"
  304. "};");
  305. TODO_ASSERT_EQUALS("[test.cpp:4]: (style) Value of pointer 'p', which points to allocated memory, is copied in copy constructor instead of allocating new memory.\n"
  306. "[test.cpp:3] -> [test.cpp:7]: (warning) Copy constructor does not allocate memory for member 'p' although memory has been allocated in other constructors.\n",
  307. "[test.cpp:4]: (style) Value of pointer 'p', which points to allocated memory, is copied in copy constructor instead of allocating new memory.\n"
  308. , errout.str());
  309. checkCopyConstructor("class F\n"
  310. "{\n"
  311. " public:\n"
  312. " char *c,*p,*d;\n"
  313. " F(const F &f) :p(f.p)\n"
  314. " {\n"
  315. " }\n"
  316. " F(char *str)\n"
  317. " {\n"
  318. " p=(char *)malloc(strlen(str)+1);\n"
  319. " strcpy(p,str);\n"
  320. " }\n"
  321. "};");
  322. TODO_ASSERT_EQUALS("[test.cpp:5]: (style) Value of pointer 'p', which points to allocated memory, is copied in copy constructor instead of allocating new memory.\n"
  323. "[test.cpp:5] -> [test.cpp:10]: (warning) Copy constructor does not allocate memory for member 'p' although memory has been allocated in other constructors.\n",
  324. "[test.cpp:5]: (style) Value of pointer 'p', which points to allocated memory, is copied in copy constructor instead of allocating new memory.\n"
  325. , errout.str());
  326. checkCopyConstructor("class kalci\n"
  327. "{\n"
  328. " public:\n"
  329. " char *c,*p,*d;\n"
  330. " kalci()\n"
  331. " {\n"
  332. " p=(char *)malloc(100);\n"
  333. " strcpy(p,\"hello\");\n"
  334. " c=(char *)malloc(100);\n"
  335. " strcpy(p,\"hello\");\n"
  336. " d=(char *)malloc(100);\n"
  337. " strcpy(p,\"hello\");\n"
  338. " }\n"
  339. " kalci(const kalci &f)\n"
  340. " {\n"
  341. " p=(char *)malloc(strlen(str)+1);\n"
  342. " strcpy(p,f.p);\n"
  343. " c=(char *)malloc(strlen(str)+1);\n"
  344. " strcpy(p,f.p);\n"
  345. " d=(char *)malloc(strlen(str)+1);\n"
  346. " strcpy(p,f.p);\n"
  347. " }\n"
  348. "};");
  349. ASSERT_EQUALS("", errout.str());
  350. checkCopyConstructor("class F\n"
  351. "{\n"
  352. " public:\n"
  353. " char *c,*p,*d;\n"
  354. " F(char *str,char *st,char *string)\n"
  355. " {\n"
  356. " p=(char *)malloc(100);\n"
  357. " strcpy(p,str);\n"
  358. " c=(char *)malloc(100);\n"
  359. " strcpy(p,st);\n"
  360. " d=(char *)malloc(100);\n"
  361. " strcpy(p,string);\n"
  362. " }\n"
  363. " F(const F &f)\n"
  364. " {\n"
  365. " p=(char *)malloc(strlen(str)+1);\n"
  366. " strcpy(p,f.p);\n"
  367. " c=(char *)malloc(strlen(str)+1);\n"
  368. " strcpy(p,f.p);\n"
  369. " }\n"
  370. "};");
  371. TODO_ASSERT_EQUALS("[test.cpp:14] -> [test.cpp:11]: (warning) Copy constructor does not allocate memory for member 'd' although memory has been allocated in other constructors.\n", "", errout.str());
  372. checkCopyConstructor("class F {\n"
  373. " char *c;\n"
  374. " F(char *str,char *st,char *string) {\n"
  375. " p=(char *)malloc(100);\n"
  376. " }\n"
  377. " F(const F &f)\n"
  378. " : p(malloc(size))\n"
  379. " {\n"
  380. " }\n"
  381. "};");
  382. ASSERT_EQUALS("", errout.str());
  383. checkCopyConstructor("class F {\n"
  384. " char *c;\n"
  385. " F(char *str,char *st,char *string)\n"
  386. " : p(malloc(size))\n"
  387. " {\n"
  388. " }\n"
  389. " F(const F &f)\n"
  390. " {\n"
  391. " }\n"
  392. "};");
  393. TODO_ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:4]: (warning) Copy constructor does not allocate memory for member 'd' although memory has been allocated in other constructors.\n", "", errout.str());
  394. checkCopyConstructor("class F\n"
  395. "{\n"
  396. " public:\n"
  397. " char *c,*p,*d;\n"
  398. " F()\n"
  399. " {\n"
  400. " p=(char *)malloc(100);\n"
  401. " c=(char *)malloc(100);\n"
  402. " d=(char*)malloc(100);\n"
  403. " }\n"
  404. "};");
  405. ASSERT_EQUALS("[test.cpp:1]: (style) 'class F' does not have a copy constructor which is recommended since the class contains a pointer to allocated memory.\n", errout.str());
  406. checkCopyConstructor("class F\n"
  407. "{\n"
  408. " public:\n"
  409. " char *c;\n"
  410. " const char *p,*d;\n"
  411. " F(char *str,char *st,char *string)\n"
  412. " {\n"
  413. " p=str;\n"
  414. " d=st;\n"
  415. " c=(char *)malloc(strlen(string)+1);\n"
  416. " strcpy(d,string);\n"
  417. " }\n"
  418. " F(const F &f)\n"
  419. " {\n"
  420. " p=f.p;\n"
  421. " d=f.d;\n"
  422. " c=(char *)malloc(strlen(str)+1);\n"
  423. " strcpy(d,f.p);\n"
  424. " }\n"
  425. "};");
  426. ASSERT_EQUALS("", errout.str());
  427. checkCopyConstructor("class F : E\n"
  428. "{\n"
  429. " char *p;\n"
  430. " F() {\n"
  431. " p = malloc(100);\n"
  432. " }\n"
  433. "};");
  434. ASSERT_EQUALS("", errout.str());
  435. checkCopyConstructor("class E { E(E&); };\n" // non-copyable
  436. "class F : E\n"
  437. "{\n"
  438. " char *p;\n"
  439. " F() {\n"
  440. " p = malloc(100);\n"
  441. " }\n"
  442. "};");
  443. ASSERT_EQUALS("", errout.str());
  444. checkCopyConstructor("class E {};\n"
  445. "class F : E {\n"
  446. " char *p;\n"
  447. " F() {\n"
  448. " p = malloc(100);\n"
  449. " }\n"
  450. "};");
  451. TODO_ASSERT_EQUALS("[test.cpp:2]: (style) 'class F' does not have a copy constructor which is recommended since the class contains a pointer to allocated memory.\n", "", errout.str());
  452. checkCopyConstructor("class F {\n"
  453. " char *p;\n"
  454. " F() {\n"
  455. " p = malloc(100);\n"
  456. " }\n"
  457. " F(F& f);\n" // non-copyable
  458. "};");
  459. ASSERT_EQUALS("", errout.str());
  460. checkCopyConstructor("class F {\n"
  461. " char *p;\n"
  462. " F() : p(malloc(100)) {}\n"
  463. "};");
  464. ASSERT_EQUALS("[test.cpp:1]: (style) 'class F' does not have a copy constructor which is recommended since the class contains a pointer to allocated memory.\n", errout.str());
  465. }
  466. void copyConstructor2() { // ticket #4458
  467. checkCopyConstructor("template <class _Tp>\n"
  468. "class Vector\n"
  469. "{\n"
  470. "public:\n"
  471. " Vector() {\n"
  472. " _M_finish = new _Tp[ 42 ];\n"
  473. " }\n"
  474. " Vector( const Vector<_Tp>& v ) {\n"
  475. " }\n"
  476. " _Tp* _M_finish;\n"
  477. "};");
  478. ASSERT_EQUALS("", errout.str());
  479. }
  480. // Check the operator Equal
  481. void checkOpertorEq(const char code[]) {
  482. // Clear the error log
  483. errout.str("");
  484. Settings settings;
  485. settings.addEnabled("style");
  486. settings.inconclusive = true;
  487. // Tokenize..
  488. Tokenizer tokenizer(&settings, this);
  489. std::istringstream istr(code);
  490. tokenizer.tokenize(istr, "test.cpp");
  491. tokenizer.simplifyTokenList2();
  492. // Check..
  493. CheckClass checkClass(&tokenizer, &settings, this);
  494. checkClass.operatorEq();
  495. }
  496. void operatorEq1() {
  497. checkOpertorEq("class A\n"
  498. "{\n"
  499. "public:\n"
  500. " void goo() {}"
  501. " void operator=(const A&);\n"
  502. "};");
  503. ASSERT_EQUALS("[test.cpp:4]: (style) 'A::operator=' should return 'A &'.\n", errout.str());
  504. checkOpertorEq("class A\n"
  505. "{\n"
  506. "public:\n"
  507. " void goo() {}"
  508. " void operator=(const A&)=delete;\n"
  509. "};");
  510. ASSERT_EQUALS("", errout.str());
  511. checkOpertorEq("class A\n"
  512. "{\n"
  513. "private:\n"
  514. " void operator=(const A&);\n"
  515. "};");
  516. ASSERT_EQUALS("", errout.str());
  517. checkOpertorEq("class A\n"
  518. "{\n"
  519. "private:\n"
  520. " void operator=(const A&)=delete;\n"
  521. "};");
  522. ASSERT_EQUALS("", errout.str());
  523. checkOpertorEq("class A\n"
  524. "{\n"
  525. " void operator=(const A&);\n"
  526. "};");
  527. ASSERT_EQUALS("", errout.str());
  528. checkOpertorEq("class A\n"
  529. "{\n"
  530. "public:\n"
  531. " void goo() {}\n"
  532. "private:\n"
  533. " void operator=(const A&);\n"
  534. "};");
  535. ASSERT_EQUALS("", errout.str());
  536. checkOpertorEq("class A\n"
  537. "{\n"
  538. "public:\n"
  539. " void operator=(const A&);\n"
  540. "};\n"
  541. "class B\n"
  542. "{\n"
  543. "public:\n"
  544. " void operator=(const B&);\n"
  545. "};");
  546. ASSERT_EQUALS("[test.cpp:4]: (style) 'A::operator=' should return 'A &'.\n"
  547. "[test.cpp:9]: (style) 'B::operator=' should return 'B &'.\n", errout.str());
  548. checkOpertorEq("struct A\n"
  549. "{\n"
  550. " void operator=(const A&);\n"
  551. "};");
  552. ASSERT_EQUALS("[test.cpp:3]: (style) 'A::operator=' should return 'A &'.\n", errout.str());
  553. checkOpertorEq("struct A\n"
  554. "{\n"
  555. " void operator=(const A&)=delete;\n"
  556. "};");
  557. ASSERT_EQUALS("", errout.str());
  558. }
  559. void operatorEq2() {
  560. checkOpertorEq("class A\n"
  561. "{\n"
  562. "public:\n"
  563. " void * operator=(const A&);\n"
  564. "};");
  565. ASSERT_EQUALS("[test.cpp:4]: (style) 'A::operator=' should return 'A &'.\n", errout.str());
  566. checkOpertorEq("class A\n"
  567. "{\n"
  568. "public:\n"
  569. " A * operator=(const A&);\n"
  570. "};");
  571. ASSERT_EQUALS("[test.cpp:4]: (style) 'A::operator=' should return 'A &'.\n", errout.str());
  572. checkOpertorEq("class A\n"
  573. "{\n"
  574. "public:\n"
  575. " const A & operator=(const A&);\n"
  576. "};");
  577. ASSERT_EQUALS("[test.cpp:4]: (style) 'A::operator=' should return 'A &'.\n", errout.str());
  578. checkOpertorEq("class A\n"
  579. "{\n"
  580. "public:\n"
  581. " B & operator=(const A&);\n"
  582. "};");
  583. ASSERT_EQUALS("[test.cpp:4]: (style) 'A::operator=' should return 'A &'.\n", errout.str());
  584. }
  585. void operatorEq3() { // ticket #3051
  586. checkOpertorEq("class A\n"
  587. "{\n"
  588. "public:\n"
  589. " A * operator=(const A*);\n"
  590. "};");
  591. ASSERT_EQUALS("", errout.str());
  592. }
  593. void operatorEq4() { // ticket #3114 (infinite loop)
  594. checkOpertorEq("struct A {\n"
  595. " A& operator=(A const& a) { return operator=(&a); }\n"
  596. " A& operator=(const A*) { return *this; }\n"
  597. "};");
  598. ASSERT_EQUALS("", errout.str());
  599. }
  600. void operatorEq5() { // ticket #3296 (virtual operator)
  601. checkOpertorEq(
  602. "class A {\n"
  603. " virtual A& operator=(const A &a) {return *this};\n"
  604. "};");
  605. ASSERT_EQUALS("", errout.str());
  606. }
  607. // Check that operator Equal returns reference to this
  608. void checkOpertorEqRetRefThis(const char code[]) {
  609. // Clear the error log
  610. errout.str("");
  611. Settings settings;
  612. settings.addEnabled("style");
  613. // Tokenize..
  614. Tokenizer tokenizer(&settings, this);
  615. std::istringstream istr(code);
  616. tokenizer.tokenize(istr, "test.cpp");
  617. tokenizer.simplifyTokenList2();
  618. // Check..
  619. CheckClass checkClass(&tokenizer, &settings, this);
  620. checkClass.operatorEqRetRefThis();
  621. }
  622. void operatorEqRetRefThis1() {
  623. checkOpertorEqRetRefThis(
  624. "class A\n"
  625. "{\n"
  626. "public:\n"
  627. " A & operator=(const A &a) { return *this; }\n"
  628. "};");
  629. ASSERT_EQUALS("", errout.str());
  630. checkOpertorEqRetRefThis(
  631. "class A\n"
  632. "{\n"
  633. "public:\n"
  634. " A & operator=(const A &a) { return a; }\n"
  635. "};");
  636. ASSERT_EQUALS("[test.cpp:4]: (style) 'operator=' should return reference to 'this' instance.\n", errout.str());
  637. checkOpertorEqRetRefThis(
  638. "class A\n"
  639. "{\n"
  640. "public:\n"
  641. " A & operator=(const A &);\n"
  642. "};\n"
  643. "A & A::operator=(const A &a) { return *this; }");
  644. ASSERT_EQUALS("", errout.str());
  645. checkOpertorEqRetRefThis(
  646. "class A\n"
  647. "{\n"
  648. "public:\n"
  649. " A & operator=(const A &a);\n"
  650. "};\n"
  651. "A & A::operator=(const A &a) { return *this; }");
  652. ASSERT_EQUALS("", errout.str());
  653. checkOpertorEqRetRefThis(
  654. "class A\n"
  655. "{\n"
  656. "public:\n"
  657. " A & operator=(const A &);\n"
  658. "};\n"
  659. "A & A::operator=(const A &a) { return a; }");
  660. ASSERT_EQUALS("[test.cpp:6]: (style) 'operator=' should return reference to 'this' instance.\n", errout.str());
  661. checkOpertorEqRetRefThis(
  662. "class A\n"
  663. "{\n"
  664. "public:\n"
  665. " A & operator=(const A &a);\n"
  666. "};\n"
  667. "A & A::operator=(const A &a) { return a; }");
  668. ASSERT_EQUALS("[test.cpp:6]: (style) 'operator=' should return reference to 'this' instance.\n", errout.str());
  669. checkOpertorEqRetRefThis(
  670. "class A\n"
  671. "{\n"
  672. "public:\n"
  673. " class B\n"
  674. " {\n"
  675. " public:\n"
  676. " B & operator=(const B &b) { return *this; }\n"
  677. " };\n"
  678. "};");
  679. ASSERT_EQUALS("", errout.str());
  680. checkOpertorEqRetRefThis(
  681. "class A\n"
  682. "{\n"
  683. "public:\n"
  684. " class B\n"
  685. " {\n"
  686. " public:\n"
  687. " B & operator=(const B &b) { return b; }\n"
  688. " };\n"
  689. "};");
  690. ASSERT_EQUALS("[test.cpp:7]: (style) 'operator=' should return reference to 'this' instance.\n", errout.str());
  691. checkOpertorEqRetRefThis(
  692. "class A\n"
  693. "{\n"
  694. "public:\n"
  695. " class B\n"
  696. " {\n"
  697. " public:\n"
  698. " B & operator=(const B &);\n"
  699. " };\n"
  700. "};\n"
  701. "A::B & A::B::operator=(const A::B &b) { return *this; }");
  702. ASSERT_EQUALS("", errout.str());
  703. checkOpertorEqRetRefThis(
  704. "class A\n"
  705. "{\n"
  706. "public:\n"
  707. " class B\n"
  708. " {\n"
  709. " public:\n"
  710. " B & operator=(const B &);\n"
  711. " };\n"
  712. "};\n"
  713. "A::B & A::B::operator=(const A::B &b) { return b; }");
  714. ASSERT_EQUALS("[test.cpp:10]: (style) 'operator=' should return reference to 'this' instance.\n", errout.str());
  715. }
  716. void operatorEqRetRefThis2() {
  717. // ticket # 1323
  718. checkOpertorEqRetRefThis(
  719. "class szp\n"
  720. "{\n"
  721. " szp &operator =(int *other) {};\n"
  722. "};");
  723. ASSERT_EQUALS("[test.cpp:3]: (style) 'operator=' should return reference to 'this' instance.\n", errout.str());
  724. checkOpertorEqRetRefThis(
  725. "class szp\n"
  726. "{\n"
  727. " szp &operator =(int *other);\n"
  728. "};\n"
  729. "szp &szp::operator =(int *other) {}");
  730. ASSERT_EQUALS("[test.cpp:5]: (style) 'operator=' should return reference to 'this' instance.\n", errout.str());
  731. }
  732. void operatorEqRetRefThis3() {
  733. // ticket # 1405
  734. checkOpertorEqRetRefThis(
  735. "class A {\n"
  736. "public:\n"
  737. " inline A &operator =(int *other) { return (*this); };\n"
  738. " inline A &operator =(long *other) { return (*this = 0); };\n"
  739. "};");
  740. ASSERT_EQUALS("", errout.str());
  741. checkOpertorEqRetRefThis(
  742. "class A {\n"
  743. "public:\n"
  744. " A &operator =(int *other);\n"
  745. " A &operator =(long *other);\n"
  746. "};\n"
  747. "A &A::operator =(int *other) { return (*this); };\n"
  748. "A &A::operator =(long *other) { return (*this = 0); };");
  749. ASSERT_EQUALS("", errout.str());
  750. checkOpertorEqRetRefThis(
  751. "class A {\n"
  752. "public:\n"
  753. " inline A &operator =(int *other) { return (*this); };\n"
  754. " inline A &operator =(long *other) { return operator = (*(int *)other); };\n"
  755. "};");
  756. ASSERT_EQUALS("", errout.str());
  757. checkOpertorEqRetRefThis(
  758. "class A {\n"
  759. "public:\n"
  760. " A &operator =(int *other);\n"
  761. " A &operator =(long *other);\n"
  762. "};\n"
  763. "A &A::operator =(int *other) { return (*this); };\n"
  764. "A &A::operator =(long *other) { return operator = (*(int *)other); };");
  765. ASSERT_EQUALS("", errout.str());
  766. checkOpertorEqRetRefThis(
  767. "class A {\n"
  768. "public:\n"
  769. " A &operator =(int *other);\n"
  770. " A &operator =(long *other);\n"
  771. "};\n"
  772. "A &A::operator =(int *other) { return (*this); };\n"
  773. "A &A::operator =(long *other) { return this->operator = (*(int *)other); };");
  774. ASSERT_EQUALS("", errout.str());
  775. }
  776. void operatorEqRetRefThis4() {
  777. // ticket # 1451
  778. checkOpertorEqRetRefThis(
  779. "P& P::operator = (const P& pc)\n"
  780. "{\n"
  781. " return (P&)(*this += pc);\n"
  782. "}");
  783. ASSERT_EQUALS("", errout.str());
  784. }
  785. void operatorEqRetRefThis5() {
  786. // ticket # 1550
  787. checkOpertorEqRetRefThis(
  788. "class A {\n"
  789. "public:\n"
  790. " A & operator=(const A &a) { }\n"
  791. "};");
  792. ASSERT_EQUALS("[test.cpp:3]: (style) 'operator=' should return reference to 'this' instance.\n", errout.str());
  793. checkOpertorEqRetRefThis(
  794. "class A {\n"
  795. "public:\n"
  796. " A & operator=(const A &a);\n"
  797. "};\n"
  798. "A & A :: operator=(const A &a) { }");
  799. ASSERT_EQUALS("[test.cpp:5]: (style) 'operator=' should return reference to 'this' instance.\n", errout.str());
  800. }
  801. void operatorEqRetRefThis6() { // ticket #2478 (segmentation fault)
  802. checkOpertorEqRetRefThis(
  803. "class UString {\n"
  804. "public:\n"
  805. " UString& assign( const char* c_str );\n"
  806. " UString& operator=( const UString& s );\n"
  807. "};\n"
  808. "UString& UString::assign( const char* c_str ) {\n"
  809. " std::string tmp( c_str );\n"
  810. " return assign( tmp );\n"
  811. "}\n"
  812. "UString& UString::operator=( const UString& s ) {\n"
  813. " return assign( s );\n"
  814. "}");
  815. }
  816. void operatorEqRetRefThis7() { // ticket #5782 Endless recursion in CheckClass::checkReturnPtrThis()
  817. checkOpertorEqRetRefThis(
  818. "class basic_fbstring {\n"
  819. " basic_fbstring& operator=(int il) {\n"
  820. " return assign();\n"
  821. " }\n"
  822. " basic_fbstring& assign() {\n"
  823. " return replace();\n"
  824. " }\n"
  825. " basic_fbstring& replaceImplDiscr() {\n"
  826. " return replace();\n"
  827. " }\n"
  828. " basic_fbstring& replace() {\n"
  829. " return replaceImplDiscr();\n"
  830. " }\n"
  831. "};\n");
  832. ASSERT_EQUALS("", errout.str());
  833. }
  834. // Check that operator Equal checks for assignment to self
  835. void checkOpertorEqToSelf(const char code[]) {
  836. // Clear the error log
  837. errout.str("");
  838. Settings settings;
  839. settings.addEnabled("warning");
  840. // Tokenize..
  841. Tokenizer tokenizer(&settings, this);
  842. std::istringstream istr(code);
  843. tokenizer.tokenize(istr, "test.cpp");
  844. tokenizer.simplifyTokenList2();
  845. // Check..
  846. CheckClass checkClass(&tokenizer, &settings, this);
  847. checkClass.operatorEqToSelf();
  848. }
  849. void operatorEqToSelf1() {
  850. // this test has an assignment test but it is not needed
  851. checkOpertorEqToSelf(
  852. "class A\n"
  853. "{\n"
  854. "public:\n"
  855. " A & operator=(const A &a) { if (&a != this) { } return *this; }\n"
  856. "};");
  857. ASSERT_EQUALS("", errout.str());
  858. // this test doesn't have an assignment test but it is not needed
  859. checkOpertorEqToSelf(
  860. "class A\n"
  861. "{\n"
  862. "public:\n"
  863. " A & operator=(const A &a) { return *this; }\n"
  864. "};");
  865. ASSERT_EQUALS("", errout.str());
  866. // this test needs an assignment test and has it
  867. checkOpertorEqToSelf(
  868. "class A\n"
  869. "{\n"
  870. "public:\n"
  871. " char *s;\n"
  872. " A & operator=(const A &a)\n"
  873. " {\n"
  874. " if (&a != this)\n"
  875. " {\n"
  876. " free(s);\n"
  877. " s = strdup(a.s);\n"
  878. " }\n"
  879. " return *this;\n"
  880. " }\n"
  881. "};");
  882. ASSERT_EQUALS("", errout.str());
  883. // this class needs an assignment test but doesn't have it
  884. checkOpertorEqToSelf(
  885. "class A\n"
  886. "{\n"
  887. "public:\n"
  888. " char *s;\n"
  889. " A & operator=(const A &a)\n"
  890. " {\n"
  891. " free(s);\n"
  892. " s = strdup(a.s);\n"
  893. " return *this;\n"
  894. " }\n"
  895. "};");
  896. ASSERT_EQUALS("[test.cpp:5]: (warning) 'operator=' should check for assignment to self to avoid problems with dynamic memory.\n", errout.str());
  897. // this test has an assignment test but doesn't need it
  898. checkOpertorEqToSelf(
  899. "class A\n"
  900. "{\n"
  901. "public:\n"
  902. " A & operator=(const A &);\n"
  903. "};\n"
  904. "A & A::operator=(const A &a) { if (&a != this) { } return *this; }");
  905. ASSERT_EQUALS("", errout.str());
  906. // this test doesn't have an assignment test but doesn't need it
  907. checkOpertorEqToSelf(
  908. "class A\n"
  909. "{\n"
  910. "public:\n"
  911. " A & operator=(const A &);\n"
  912. "};\n"
  913. "A & A::operator=(const A &a) { return *this; }");
  914. ASSERT_EQUALS("", errout.str());
  915. // this test needs an assignment test and has it
  916. checkOpertorEqToSelf(
  917. "class A\n"
  918. "{\n"
  919. "public:\n"
  920. " char *s;\n"
  921. " A & operator=(const A &);\n"
  922. "};\n"
  923. "A & A::operator=(const A &a)\n"
  924. "{\n"
  925. " if (&a != this)\n"
  926. " {\n"
  927. " free(s);\n"
  928. " s = strdup(a.s);\n"
  929. " }\n"
  930. " return *this;\n"
  931. "}");
  932. ASSERT_EQUALS("", errout.str());
  933. // this test needs an assignment test but doesn’t have it
  934. checkOpertorEqToSelf(
  935. "class A\n"
  936. "{\n"
  937. "public:\n"
  938. " char *s;\n"
  939. " A & operator=(const A &);\n"
  940. "};\n"
  941. "A & A::operator=(const A &a)\n"
  942. "{\n"
  943. " free(s);\n"
  944. " s = strdup(a.s);\n"
  945. " return *this;\n"
  946. "}");
  947. ASSERT_EQUALS("[test.cpp:7]: (warning) 'operator=' should check for assignment to self to avoid problems with dynamic memory.\n", errout.str());
  948. // ticket #1224
  949. checkOpertorEqToSelf(
  950. "const SubTree &SubTree::operator= (const SubTree &b)\n"
  951. "{\n"
  952. " CodeTree *oldtree = tree;\n"
  953. " tree = new CodeTree(*b.tree);\n"
  954. " delete oldtree;\n"
  955. " return *this;\n"
  956. "}\n"
  957. "const SubTree &SubTree::operator= (const CodeTree &b)\n"
  958. "{\n"
  959. " CodeTree *oldtree = tree;\n"
  960. " tree = new CodeTree(b);\n"
  961. " delete oldtree;\n"
  962. " return *this;\n"
  963. "}");
  964. ASSERT_EQUALS("", errout.str());
  965. }
  966. void operatorEqToSelf2() {
  967. // this test has an assignment test but doesn't need it
  968. checkOpertorEqToSelf(
  969. "class A\n"
  970. "{\n"
  971. "public:\n"
  972. " class B\n"
  973. " {\n"
  974. " public:\n"
  975. " B & operator=(const B &b) { if (&b != this) { } return *this; }\n"
  976. " };\n"
  977. "};");
  978. ASSERT_EQUALS("", errout.str());
  979. // this test doesn't have an assignment test but doesn't need it
  980. checkOpertorEqToSelf(
  981. "class A\n"
  982. "{\n"
  983. "public:\n"
  984. " class B\n"
  985. " {\n"
  986. " public:\n"
  987. " B & operator=(const B &b) { return *this; }\n"
  988. " };\n"
  989. "};");
  990. ASSERT_EQUALS("", errout.str());
  991. // this test needs an assignment test but has it
  992. checkOpertorEqToSelf(
  993. "class A\n"
  994. "{\n"
  995. "public:\n"
  996. " class B\n"
  997. " {\n"
  998. " public:\n"
  999. " char *s;\n"
  1000. " B & operator=(const B &b)\n"
  1001. " {\n"
  1002. " if (&b != this)\n"
  1003. " {\n"
  1004. " }\n"
  1005. " return *this;\n"
  1006. " }\n"
  1007. " };\n"
  1008. "};");
  1009. ASSERT_EQUALS("", errout.str());
  1010. // this test needs an assignment test but doesn't have it
  1011. checkOpertorEqToSelf(
  1012. "class A\n"
  1013. "{\n"
  1014. "public:\n"
  1015. " class B\n"
  1016. " {\n"
  1017. " public:\n"
  1018. " char *s;\n"
  1019. " B & operator=(const B &b)\n"
  1020. " {\n"
  1021. " free(s);\n"
  1022. " s = strdup(b.s);\n"
  1023. " return *this;\n"
  1024. " }\n"
  1025. " };\n"
  1026. "};");
  1027. ASSERT_EQUALS("[test.cpp:8]: (warning) 'operator=' should check for assignment to self to avoid problems with dynamic memory.\n", errout.str());
  1028. // this test has an assignment test but doesn't need it
  1029. checkOpertorEqToSelf(
  1030. "class A\n"
  1031. "{\n"
  1032. "public:\n"
  1033. " class B\n"
  1034. " {\n"
  1035. " public:\n"
  1036. " B & operator=(const B &);\n"
  1037. " };\n"
  1038. "};\n"
  1039. "A::B & A::B::operator=(const A::B &b) { if (&b != this) { } return *this; }");
  1040. ASSERT_EQUALS("", errout.str());
  1041. // this test doesn't have an assignment test but doesn't need it
  1042. checkOpertorEqToSelf(
  1043. "class A\n"
  1044. "{\n"
  1045. "public:\n"
  1046. " class B\n"
  1047. " {\n"
  1048. " public:\n"
  1049. " B & operator=(const B &);\n"
  1050. " };\n"
  1051. "};\n"
  1052. "A::B & A::B::operator=(const A::B &b) { return *this; }");
  1053. ASSERT_EQUALS("", errout.str());
  1054. // this test needs an assignment test and has it
  1055. checkOpertorEqToSelf(
  1056. "class A\n"
  1057. "{\n"
  1058. "public:\n"
  1059. " class B\n"
  1060. " {\n"
  1061. " public:\n"
  1062. " char * s;\n"
  1063. " B & operator=(const B &);\n"
  1064. " };\n"
  1065. "};\n"
  1066. "A::B & A::B::operator=(const A::B &b)\n"
  1067. "{\n"
  1068. " if (&b != this)\n"
  1069. " {\n"
  1070. " free(s);\n"
  1071. " s = strdup(b.s);\n"
  1072. " }\n"
  1073. " return *this;\n"
  1074. " }");
  1075. ASSERT_EQUALS("", errout.str());
  1076. // this test needs an assignment test but doesn't have it
  1077. checkOpertorEqToSelf(
  1078. "class A\n"
  1079. "{\n"
  1080. "public:\n"
  1081. " class B\n"
  1082. " {\n"
  1083. " public:\n"
  1084. " char * s;\n"
  1085. " B & operator=(const B &);\n"
  1086. " };\n"
  1087. "};\n"
  1088. "A::B & A::B::operator=(const A::B &b)\n"
  1089. "{\n"
  1090. " free(s);\n"
  1091. " s = strdup(b.s);\n"
  1092. " return *this;\n"
  1093. " }");
  1094. ASSERT_EQUALS("[test.cpp:11]: (warning) 'operator=' should check for assignment to self to avoid problems with dynamic memory.\n", errout.str());
  1095. }
  1096. void operatorEqToSelf3() {
  1097. // this test has multiple inheritance so there is no trivial way to test for self assignment but doesn't need it
  1098. checkOpertorEqToSelf(
  1099. "class A : public B, public C\n"
  1100. "{\n"
  1101. "public:\n"
  1102. " A & operator=(const A &a) { return *this; }\n"
  1103. "};");
  1104. ASSERT_EQUALS("", errout.str());
  1105. // this test has multiple inheritance and needs an assignment test but there is no trivial way to test for it
  1106. checkOpertorEqToSelf(
  1107. "class A : public B, public C\n"
  1108. "{\n"
  1109. "public:\n"
  1110. " char *s;\n"
  1111. " A & operator=(const A &a)\n"
  1112. " {\n"
  1113. " free(s);\n"
  1114. " s = strdup(a.s);\n"
  1115. " return *this;\n"
  1116. " }\n"
  1117. "};");
  1118. ASSERT_EQUALS("", errout.str());
  1119. // this test has multiple inheritance so there is no trivial way to test for self assignment but doesn't need it
  1120. checkOpertorEqToSelf(
  1121. "class A : public B, public C\n"
  1122. "{\n"
  1123. "public:\n"
  1124. " A & operator=(const A &);\n"
  1125. "};\n"
  1126. "A & A::operator=(const A &a) { return *this; }");
  1127. ASSERT_EQUALS("", errout.str());
  1128. // this test has multiple inheritance and needs an assignment test but there is no trivial way to test for it
  1129. checkOpertorEqToSelf(
  1130. "class A : public B, public C\n"
  1131. "{\n"
  1132. "public:\n"
  1133. " char *s;\n"
  1134. " A & operator=(const A &);\n"
  1135. "};\n"
  1136. "A & A::operator=(const A &a)\n"
  1137. "{\n"
  1138. " free(s);\n"
  1139. " s = strdup(a.s);\n"
  1140. " return *this;\n"
  1141. "}");
  1142. ASSERT_EQUALS("", errout.str());
  1143. }
  1144. void operatorEqToSelf4() {
  1145. // this test has multiple inheritance so there is no trivial way to test for self assignment but doesn't need it
  1146. checkOpertorEqToSelf(
  1147. "class A\n"
  1148. "{\n"
  1149. "public:\n"
  1150. " class B : public C, public D\n"
  1151. " {\n"
  1152. " public:\n"
  1153. " B & operator=(const B &b) { return *this; }\n"
  1154. " };\n"
  1155. "};");
  1156. ASSERT_EQUALS("", errout.str());
  1157. // this test has multiple inheritance and needs an assignment test but there is no trivial way to test for it
  1158. checkOpertorEqToSelf(
  1159. "class A\n"
  1160. "{\n"
  1161. "public:\n"
  1162. " class B : public C, public D\n"
  1163. " {\n"
  1164. " public:\n"
  1165. " char * s;\n"
  1166. " B & operator=(const B &b)\n"
  1167. " {\n"
  1168. " free(s);\n"
  1169. " s = strdup(b.s);\n"
  1170. " return *this;\n"
  1171. " }\n"
  1172. " };\n"
  1173. "};");
  1174. ASSERT_EQUALS("", errout.str());
  1175. // this test has multiple inheritance so there is no trivial way to test for self assignment but doesn't need it
  1176. checkOpertorEqToSelf(
  1177. "class A\n"
  1178. "{\n"
  1179. "public:\n"
  1180. " class B : public C, public D\n"
  1181. " {\n"
  1182. " public:\n"
  1183. " B & operator=(const B &);\n"
  1184. " };\n"
  1185. "};\n"
  1186. "A::B & A::B::operator=(const A::B &b) { return *this; }");
  1187. ASSERT_EQUALS("", errout.str());
  1188. // this test has multiple inheritance and needs an assignment test but there is no trivial way to test for it
  1189. checkOpertorEqToSelf(
  1190. "class A\n"
  1191. "{\n"
  1192. "public:\n"
  1193. " class B : public C, public D\n"
  1194. " {\n"
  1195. " public:\n"
  1196. " char * s;\n"
  1197. " B & operator=(const B &);\n"
  1198. " };\n"
  1199. "};\n"
  1200. "A::B & A::B::operator=(const A::B &b)\n"
  1201. "{\n"
  1202. " free(s);\n"
  1203. " s = strdup(b.s);\n"
  1204. " return *this;\n"
  1205. "}");
  1206. ASSERT_EQUALS("", errout.str());
  1207. }
  1208. void operatorEqToSelf5() {
  1209. // ticket # 1233
  1210. checkOpertorEqToSelf(
  1211. "class A\n"
  1212. "{\n"
  1213. "public:\n"
  1214. " char *s;\n"
  1215. " A & operator=(const A &a)\n"
  1216. " {\n"
  1217. " if((&a!=this))\n"
  1218. " {\n"
  1219. " free(s);\n"
  1220. " s = strdup(a.s);\n"
  1221. " }\n"
  1222. " return *this;\n"
  1223. " }\n"
  1224. "};");
  1225. ASSERT_EQUALS("", errout.str());
  1226. checkOpertorEqToSelf(
  1227. "class A\n"
  1228. "{\n"
  1229. "public:\n"
  1230. " char *s;\n"
  1231. " A & operator=(const A &a)\n"
  1232. " {\n"
  1233. " if((this!=&a))\n"
  1234. " {\n"
  1235. " free(s);\n"
  1236. " s = strdup(a.s);\n"
  1237. " }\n"
  1238. " return *this;\n"
  1239. " }\n"
  1240. "};");
  1241. ASSERT_EQUALS("", errout.str());
  1242. checkOpertorEqToSelf(
  1243. "class A\n"
  1244. "{\n"
  1245. "public:\n"
  1246. " char *s;\n"
  1247. " A & operator=(const A &a)\n"
  1248. " {\n"
  1249. " if(!(&a==this))\n"
  1250. " {\n"
  1251. " free(s);\n"
  1252. " s = strdup(a.s);\n"
  1253. " }\n"
  1254. " return *this;\n"
  1255. " }\n"
  1256. "};");
  1257. ASSERT_EQUALS("", errout.str());
  1258. checkOpertorEqToSelf(
  1259. "class A\n"
  1260. "{\n"
  1261. "public:\n"
  1262. " char *s;\n"
  1263. " A & operator=(const A &a)\n"
  1264. " {\n"
  1265. " if(!(this==&a))\n"
  1266. " {\n"
  1267. " free(s);\n"
  1268. " s = strdup(a.s);\n"
  1269. " }\n"
  1270. " return *this;\n"
  1271. " }\n"
  1272. "};");
  1273. ASSERT_EQUALS("", errout.str());
  1274. checkOpertorEqToSelf(
  1275. "class A\n"
  1276. "{\n"
  1277. "public:\n"
  1278. " char *s;\n"
  1279. " A & operator=(const A &a)\n"
  1280. " {\n"
  1281. " if(false==(&a==this))\n"
  1282. " {\n"
  1283. " free(s);\n"
  1284. " s = strdup(a.s);\n"
  1285. " }\n"
  1286. " return *this;\n"
  1287. " }\n"
  1288. "};");
  1289. ASSERT_EQUALS("", errout.str());
  1290. checkOpertorEqToSelf(
  1291. "class A\n"
  1292. "{\n"
  1293. "public:\n"
  1294. " char *s;\n"
  1295. " A & operator=(const A &a)\n"
  1296. " {\n"
  1297. " if(false==(this==&a))\n"
  1298. " {\n"
  1299. " free(s);\n"
  1300. " s = strdup(a.s);\n"
  1301. " }\n"
  1302. " return *this;\n"
  1303. " }\n"
  1304. "};");
  1305. ASSERT_EQUALS("", errout.str());
  1306. checkOpertorEqToSelf(
  1307. "class A\n"
  1308. "{\n"
  1309. "public:\n"
  1310. " char *s;\n"
  1311. " A & operator=(const A &a)\n"
  1312. " {\n"
  1313. " if(true!=(&a==this))\n"
  1314. " {\n"
  1315. " free(s);\n"
  1316. " s = strdup(a.s);\n"
  1317. " }\n"
  1318. " return *this;\n"
  1319. " }\n"
  1320. "};");
  1321. ASSERT_EQUALS("", errout.str());
  1322. checkOpertorEqToSelf(
  1323. "class A\n"
  1324. "{\n"
  1325. "public:\n"
  1326. " char *s;\n"
  1327. " A & operator=(const A &a)\n"
  1328. " {\n"
  1329. " if(true!=(this==&a))\n"
  1330. " {\n"
  1331. " free(s);\n"
  1332. " s = strdup(a.s);\n"
  1333. " }\n"
  1334. " return *this;\n"
  1335. " }\n"
  1336. "};");
  1337. ASSERT_EQUALS("", errout.str());
  1338. checkOpertorEqToSelf(
  1339. "class A\n"
  1340. "{\n"
  1341. "public:\n"
  1342. " char *s;\n"
  1343. " A & operator=(const A &a);\n"
  1344. "};\n"
  1345. "A & A::operator=(const A &a)\n"
  1346. "{\n"
  1347. " if((&a!=this))\n"
  1348. " {\n"
  1349. " free(s);\n"
  1350. " s = strdup(a.s);\n"
  1351. " }\n"
  1352. " return *this;\n"
  1353. "};");
  1354. ASSERT_EQUALS("", errout.str());
  1355. checkOpertorEqToSelf(
  1356. "class A\n"
  1357. "{\n"
  1358. "public:\n"
  1359. " char *s;\n"
  1360. " A & operator=(const A &a);\n"
  1361. "};\n"
  1362. "A & A::operator=(const A &a)\n"
  1363. "{\n"
  1364. " if((this!=&a))\n"
  1365. " {\n"
  1366. " free(s);\n"
  1367. " s = strdup(a.s);\n"
  1368. " }\n"
  1369. " return *this;\n"
  1370. "};");
  1371. ASSERT_EQUALS("", errout.str());
  1372. checkOpertorEqToSelf(
  1373. "class A\n"
  1374. "{\n"
  1375. "public:\n"
  1376. " char *s;\n"
  1377. " A & operator=(const A &a);\n"
  1378. "};\n"
  1379. "A & A::operator=(const A &a)\n"
  1380. "{\n"
  1381. " if(!(&a==this))\n"
  1382. " {\n"
  1383. " free(s);\n"
  1384. " s = strdup(a.s);\n"
  1385. " }\n"
  1386. " return *this;\n"
  1387. "};");
  1388. ASSERT_EQUALS("", errout.str());
  1389. checkOpertorEqToSelf(
  1390. "class A\n"
  1391. "{\n"
  1392. "public:\n"
  1393. " char *s;\n"
  1394. " A & operator=(const A &a);\n"
  1395. "};\n"
  1396. "A & A::operator=(const A &a)\n"
  1397. "{\n"
  1398. " if(!(this==&a))\n"
  1399. " {\n"
  1400. " free(s);\n"
  1401. " s = strdup(a.s);\n"
  1402. " }\n"
  1403. " return *this;\n"
  1404. "};");
  1405. ASSERT_EQUALS("", errout.str());
  1406. checkOpertorEqToSelf(
  1407. "class A\n"
  1408. "{\n"
  1409. "public:\n"
  1410. " char *s;\n"
  1411. " A & operator=(const A &a);\n"
  1412. "};\n"
  1413. "A & A::operator=(const A &a)\n"
  1414. "{\n"
  1415. " if(false==(&a==this))\n"
  1416. " {\n"
  1417. " free(s);\n"
  1418. " s = strdup(a.s);\n"
  1419. " }\n"
  1420. " return *this;\n"
  1421. "};");
  1422. ASSERT_EQUALS("", errout.str());
  1423. checkOpertorEqToSelf(
  1424. "class A\n"
  1425. "{\n"
  1426. "public:\n"
  1427. " char *s;\n"
  1428. " A & operator=(const A &a);\n"
  1429. "};\n"
  1430. "A & A::operator=(const A &a)\n"
  1431. "{\n"
  1432. " if(false==(this==&a))\n"
  1433. " {\n"
  1434. " free(s);\n"
  1435. " s = strdup(a.s);\n"
  1436. " }\n"
  1437. " return *this;\n"
  1438. "};");
  1439. ASSERT_EQUALS("", errout.str());
  1440. checkOpertorEqToSelf(
  1441. "class A\n"
  1442. "{\n"
  1443. "public:\n"
  1444. " char *s;\n"
  1445. " A & operator=(const A &a);\n"
  1446. "};\n"
  1447. "A & A::operator=(const A &a)\n"
  1448. "{\n"
  1449. " if(true!=(&a==this))\n"
  1450. " {\n"
  1451. " free(s);\n"
  1452. " s = strdup(a.s);\n"
  1453. " }\n"
  1454. " return *this;\n"
  1455. "};");
  1456. ASSERT_EQUALS("", errout.str());
  1457. checkOpertorEqToSelf(
  1458. "class A\n"
  1459. "{\n"
  1460. "public:\n"
  1461. " char *s;\n"
  1462. " A & operator=(const A &a);\n"
  1463. "};\n"
  1464. "A & A::operator=(const A &a)\n"
  1465. "{\n"
  1466. " if(true!=(this==&a))\n"
  1467. " {\n"
  1468. " free(s);\n"
  1469. " s = strdup(a.s);\n"
  1470. " }\n"
  1471. " return *this;\n"
  1472. "};");
  1473. ASSERT_EQUALS("", errout.str());
  1474. checkOpertorEqToSelf(
  1475. "struct A {\n"
  1476. " char *s;\n"
  1477. " A& operator=(const B &b);\n"
  1478. "};\n"
  1479. "A& A::operator=(const B &b) {\n"
  1480. " free(s);\n"
  1481. " s = strdup(a.s);\n"
  1482. " return *this;\n"
  1483. "};");
  1484. ASSERT_EQUALS("", errout.str());
  1485. }
  1486. void operatorEqToSelf6() {
  1487. // ticket # 1550
  1488. checkOpertorEqToSelf(
  1489. "class A\n"
  1490. "{\n"
  1491. "public:\n"
  1492. " A & operator=(const A &a)\n"
  1493. " {\n"
  1494. " delete [] data;\n"
  1495. " data = new char[strlen(a.data) + 1];\n"
  1496. " strcpy(data, a.data);\n"
  1497. " return *this;\n"
  1498. " }\n"
  1499. "private:\n"
  1500. " char * data;\n"
  1501. "};");
  1502. ASSERT_EQUALS("[test.cpp:4]: (warning) 'operator=' should check for assignment to self to avoid problems with dynamic memory.\n", errout.str());
  1503. checkOpertorEqToSelf(
  1504. "class A\n"
  1505. "{\n"
  1506. "public:\n"
  1507. " A & operator=(const A &a);\n"
  1508. "private:\n"
  1509. " char * data;\n"
  1510. "};\n"
  1511. "A & A::operator=(const A &a)\n"
  1512. "{\n"
  1513. " delete [] data;\n"
  1514. " data = new char[strlen(a.data) + 1];\n"
  1515. " strcpy(data, a.data);\n"
  1516. " return *this;\n"
  1517. "};");
  1518. ASSERT_EQUALS("[test.cpp:8]: (warning) 'operator=' should check for assignment to self to avoid problems with dynamic memory.\n", errout.str());
  1519. checkOpertorEqToSelf(
  1520. "class A\n"
  1521. "{\n"
  1522. "public:\n"
  1523. " A & operator=(const A &a)\n"
  1524. " {\n"
  1525. " delete data;\n"
  1526. " data = new char;\n"
  1527. " *data = *a.data;\n"
  1528. " return *this;\n"
  1529. " }\n"
  1530. "private:\n"
  1531. " char * data;\n"
  1532. "};");
  1533. ASSERT_EQUALS("[test.cpp:4]: (warning) 'operator=' should check for assignment to self to avoid problems with dynamic memory.\n", errout.str());
  1534. checkOpertorEqToSelf(
  1535. "class A\n"
  1536. "{\n"
  1537. "public:\n"
  1538. " A & operator=(const A &a);\n"
  1539. "private:\n"
  1540. " char * data;\n"
  1541. "};\n"
  1542. "A & A::operator=(const A &a)\n"
  1543. "{\n"
  1544. " delete data;\n"
  1545. " data = new char;\n"
  1546. " *data = *a.data;\n"
  1547. " return *this;\n"
  1548. "};");
  1549. ASSERT_EQUALS("[test.cpp:8]: (warning) 'operator=' should check for assignment to self to avoid problems with dynamic memory.\n", errout.str());
  1550. }
  1551. void operatorEqToSelf7() {
  1552. checkOpertorEqToSelf(
  1553. "class A\n"
  1554. "{\n"
  1555. "public:\n"
  1556. " A & assign(const A & a)\n"
  1557. " {\n"
  1558. " return *this;\n"
  1559. " }\n"
  1560. " A & operator=(const A &a)\n"
  1561. " {\n"
  1562. " return assign(a);\n"
  1563. " }\n"
  1564. "};");
  1565. ASSERT_EQUALS("", errout.str());
  1566. }
  1567. void operatorEqToSelf8() {
  1568. checkOpertorEqToSelf(
  1569. "class FMat\n"
  1570. "{\n"
  1571. "public:\n"
  1572. " FMat& copy(const FMat& rhs);\n"
  1573. " FMat& operator=(const FMat& in);\n"
  1574. "};\n"
  1575. "FMat& FMat::copy(const FMat& rhs)\n"
  1576. "{\n"
  1577. " return *this;\n"
  1578. "}\n"
  1579. "FMat& FMat::operator=(const FMat& in)\n"
  1580. "{\n"
  1581. " return copy(in);\n"
  1582. "}");
  1583. ASSERT_EQUALS("", errout.str());
  1584. }
  1585. void operatorEqToSelf9() {
  1586. checkOpertorEqToSelf(
  1587. "class Foo\n"
  1588. "{\n"
  1589. "public:\n"
  1590. " Foo& operator=(Foo* pOther);\n"
  1591. " Foo& operator=(Foo& other);\n"
  1592. "};\n"
  1593. "Foo& Foo::operator=(Foo* pOther)\n"
  1594. "{\n"
  1595. " return *this;\n"
  1596. "}\n"
  1597. "Foo& Foo::operator=(Foo& other)\n"
  1598. "{\n"
  1599. " return Foo::operator=(&other);\n"
  1600. "}");
  1601. ASSERT_EQUALS("", errout.str());
  1602. }
  1603. // Check that base classes have virtual destructors
  1604. void checkVirtualDestructor(const char code[], bool inconclusive = false) {
  1605. // Clear the error log
  1606. errout.str("");
  1607. Settings settings;
  1608. settings.inconclusive = inconclusive;
  1609. // Tokenize..
  1610. Tokenizer tokenizer(&settings, this);
  1611. std::istringstream istr(code);
  1612. tokenizer.tokenize(istr, "test.cpp");
  1613. tokenizer.simplifyTokenList2();
  1614. // Check..
  1615. CheckClass checkClass(&tokenizer, &settings, this);
  1616. checkClass.virtualDestructor();
  1617. }
  1618. void virtualDestructor1() {
  1619. // Base class not found
  1620. checkVirtualDestructor("class Derived : public Base { };\n"
  1621. "Base *base = new Derived;\n"
  1622. "delete base;");
  1623. ASSERT_EQUALS("", errout.str());
  1624. checkVirtualDestructor("class Derived : Base { };\n"
  1625. "Base *base = new Derived;\n"
  1626. "delete base;");
  1627. ASSERT_EQUALS("", errout.str());
  1628. }
  1629. void virtualDestructor2() {
  1630. // Base class doesn't have a destructor
  1631. checkVirtualDestructor("class Base { };\n"
  1632. "class Derived : public Base { public: ~Derived() { (void)11; } };"
  1633. "Base *base = new Derived;\n"
  1634. "delete base;");
  1635. ASSERT_EQUALS("[test.cpp:1]: (error) Class 'Base' which is inherited by class 'Derived' does not have a virtual destructor.\n", errout.str());
  1636. checkVirtualDestructor("class Base { };\n"
  1637. "class Derived : protected Base { public: ~Derived() { (void)11; } };"
  1638. "Base *base = new Derived;\n"
  1639. "delete base;");
  1640. ASSERT_EQUALS("[test.cpp:1]: (error) Class 'Base' which is inherited by class 'Derived' does not have a virtual destructor.\n", errout.str());
  1641. checkVirtualDestructor("class Base { };\n"
  1642. "class Derived : private Base { public: ~Derived() { (void)11; } };"
  1643. "Base *base = new Derived;\n"
  1644. "delete base;");
  1645. ASSERT_EQUALS("", errout.str());
  1646. checkVirtualDestructor("class Base { };\n"
  1647. "class Derived : Base { public: ~Derived() { (void)11; } };"
  1648. "Base *base = new Derived;\n"
  1649. "delete base;");
  1650. ASSERT_EQUALS("", errout.str());
  1651. }
  1652. void virtualDestructor3() {
  1653. // Base class has a destructor, but it's not virtual
  1654. checkVirtualDestructor("class Base { public: ~Base(); };\n"
  1655. "class Derived : public Base { public: ~Derived() { (void)11; } };"
  1656. "Base *base = new Derived;\n"
  1657. "delete base;");
  1658. ASSERT_EQUALS("[test.cpp:1]: (error) Class 'Base' which is inherited by class 'Derived' does not have a virtual destructor.\n", errout.str());
  1659. checkVirtualDestructor("class Base { public: ~Base(); };\n"
  1660. "class Derived : protected Base { public: ~Derived() { (void)11; } };"
  1661. "Base *base = new Derived;\n"
  1662. "delete base;");
  1663. ASSERT_EQUALS("[test.cpp:1]: (error) Class 'Base' which is inherited by class 'Derived' does not have a virtual destructor.\n", errout.str());
  1664. checkVirtualDestructor("class Base { public: ~Base(); };\n"
  1665. "class Derived : private Fred, public Base { public: ~Derived() { (void)11; } };"
  1666. "Base *base = new Derived;\n"
  1667. "delete base;");
  1668. ASSERT_EQUALS("[test.cpp:1]: (error) Class 'Base' which is inherited by class 'Derived' does not have a virtual destructor.\n", errout.str());
  1669. }
  1670. void virtualDestructor4() {
  1671. // Derived class doesn't have a destructor => no error
  1672. checkVirtualDestructor("class Base { public: ~Base(); };\n"
  1673. "class Derived : public Base { };"
  1674. "Base *base = new Derived;\n"
  1675. "delete base;");
  1676. ASSERT_EQUALS("", errout.str());
  1677. checkVirtualDestructor("class Base { public: ~Base(); };\n"
  1678. "class Derived : private Fred, public Base { };"
  1679. "Base *base = new Derived;\n"
  1680. "delete base;");
  1681. ASSERT_EQUALS("", errout.str());
  1682. }
  1683. void virtualDestructor5() {
  1684. // Derived class has empty destructor => no error
  1685. checkVirtualDestructor("class Base { public: ~Base(); };\n"
  1686. "class Derived : public Base { public: ~Derived() {} };"
  1687. "Base *base = new Derived;\n"
  1688. "delete base;");
  1689. ASSERT_EQUALS("", errout.str());
  1690. checkVirtualDestructor("class Base { public: ~Base(); };\n"
  1691. "class Derived : public Base { public: ~Derived(); }; Derived::~Derived() {}"
  1692. "Base *base = new Derived;\n"
  1693. "delete base;");
  1694. ASSERT_EQUALS("", errout.str());
  1695. }
  1696. void virtualDestructor6() {
  1697. // Only report error if base class pointer is deleted that
  1698. // points at derived class
  1699. checkVirtualDestructor("class Base { public: ~Base(); };\n"
  1700. "class Derived : public Base { public: ~Derived() { (void)11; } };");
  1701. ASSERT_EQUALS("", errout.str());
  1702. }
  1703. void virtualDestructorProtected() {
  1704. // Base class has protected destructor, it makes Base *p = new Derived(); fail
  1705. // during compilation time, so error is not possible. => no error
  1706. checkVirtualDestructor("class A\n"
  1707. "{\n"
  1708. "protected:\n"
  1709. " ~A() { }\n"
  1710. "};\n"
  1711. "\n"
  1712. "class B : public A\n"
  1713. "{\n"
  1714. "public:\n"
  1715. " ~B() { int a; }\n"
  1716. "};");
  1717. ASSERT_EQUALS("", errout.str());
  1718. }
  1719. void virtualDestructorInherited() {
  1720. // class A inherits virtual destructor from class Base -> no error
  1721. checkVirtualDestructor("class Base\n"
  1722. "{\n"
  1723. "public:\n"
  1724. "virtual ~Base() {}\n"
  1725. "};\n"
  1726. "class A : private Base\n"
  1727. "{\n"
  1728. "public:\n"
  1729. " ~A() { }\n"
  1730. "};\n"
  1731. "\n"
  1732. "class B : public A\n"
  1733. "{\n"
  1734. "public:\n"
  1735. " ~B() { int a; }\n"
  1736. "};");
  1737. ASSERT_EQUALS("", errout.str());
  1738. // class A inherits virtual destructor from struct Base -> no error
  1739. // also notice that public is not given, but destructor is public, because
  1740. // we are using struct instead of class
  1741. checkVirtualDestructor("struct Base\n"
  1742. "{\n"
  1743. "virtual ~Base() {}\n"
  1744. "};\n"
  1745. "class A : public Base\n"
  1746. "{\n"
  1747. "};\n"
  1748. "\n"
  1749. "class B : public A\n"
  1750. "{\n"
  1751. "public:\n"
  1752. " ~B() { int a; }\n"
  1753. "};");
  1754. ASSERT_EQUALS("", errout.str());
  1755. // Unknown Base class -> it could have virtual destructor, so ignore
  1756. checkVirtualDestructor("class A : private Base\n"
  1757. "{\n"
  1758. "public:\n"
  1759. " ~A() { }\n"
  1760. "};\n"
  1761. "\n"
  1762. "class B : public A\n"
  1763. "{\n"
  1764. "public:\n"
  1765. " ~B() { int a; }\n"
  1766. "};");
  1767. ASSERT_EQUALS("", errout.str());
  1768. // Virtual destructor is inherited -> no error
  1769. checkVirtualDestructor("class Base2\n"
  1770. "{\n"
  1771. "virtual ~Base2() {}\n"
  1772. "};\n"
  1773. "class Base : public Base2\n"
  1774. "{\n"
  1775. "};\n"
  1776. "class A : private Base\n"
  1777. "{\n"
  1778. "public:\n"
  1779. " ~A() { }\n"
  1780. "};\n"
  1781. "\n"
  1782. "class B : public A\n"
  1783. "{\n"
  1784. "public:\n"
  1785. " ~B() { int a; }\n"
  1786. "};");
  1787. ASSERT_EQUALS("", errout.str());
  1788. // class A doesn't inherit virtual destructor from class Base -> error
  1789. checkVirtualDestructor("class Base\n"
  1790. "{\n"
  1791. "public:\n"
  1792. " ~Base() {}\n"
  1793. "};\n"
  1794. "class A : private Base\n"
  1795. "{\n"
  1796. "public:\n"
  1797. " ~A() { }\n"
  1798. "};\n"
  1799. "\n"
  1800. "class B : public A\n"
  1801. "{\n"
  1802. "public:\n"
  1803. " ~B() { int a; }\n"
  1804. "};");
  1805. TODO_ASSERT_EQUALS("[test.cpp:7]: (error) Class 'Base' which is inherited by class 'B' does not have a virtual destructor.\n",
  1806. "", errout.str());
  1807. }
  1808. void virtualDestructorTemplate() {
  1809. checkVirtualDestructor("template <typename T> class A\n"
  1810. "{\n"
  1811. " public:\n"
  1812. " virtual ~A(){}\n"
  1813. "};\n"
  1814. "template <typename T> class AA\n"
  1815. "{\n"
  1816. " public:\n"
  1817. " ~AA(){}\n"
  1818. "};\n"
  1819. "class B : public A<int>, public AA<double>\n"
  1820. "{\n"
  1821. " public:\n"
  1822. " ~B(){int a;}\n"
  1823. "};\n"
  1824. "\n"
  1825. "AA<double> *p = new B; delete p;");
  1826. ASSERT_EQUALS("[test.cpp:9]: (error) Class 'AA<double>' which is inherited by class 'B' does not have a virtual destructor.\n", errout.str());
  1827. }
  1828. void virtualDestructorInconclusive() {
  1829. checkVirtualDestructor("class Base {\n"
  1830. "public:\n"
  1831. " ~Base(){}\n"
  1832. " virtual void foo(){}\n"
  1833. "};\n", true);
  1834. ASSERT_EQUALS("[test.cpp:3]: (warning, inconclusive) Class 'Base' which has virtual members does not have a virtual destructor.\n", errout.str());
  1835. checkVirtualDestructor("class Base {\n"
  1836. "public:\n"
  1837. " ~Base(){}\n"
  1838. " virtual void foo(){}\n"
  1839. "};\n"
  1840. "class Derived : public Base {\n"
  1841. "public:\n"
  1842. " ~Derived() { bar(); }\n"
  1843. "};\n"
  1844. "void foo() {\n"
  1845. " Base * base = new Derived();\n"
  1846. " delete base;\n"
  1847. "}\n", true);
  1848. ASSERT_EQUALS("[test.cpp:3]: (error) Class 'Base' which is inherited by class 'Derived' does not have a virtual destructor.\n", errout.str());
  1849. }
  1850. void checkNoMemset(const char code[], bool load_std_cfg = false, bool portability = false) {
  1851. // Clear the error log
  1852. errout.str("");
  1853. Settings settings;
  1854. settings.addEnabled("warning");
  1855. if (portability)
  1856. settings.addEnabled("portability");
  1857. if (load_std_cfg) {
  1858. LOAD_LIB_2(settings.library, "std.cfg");
  1859. }
  1860. // Tokenize..
  1861. Tokenizer tokenizer(&settings, this);
  1862. std::istringstream istr(code);
  1863. tokenizer.tokenize(istr, "test.cpp");
  1864. // Check..
  1865. CheckClass checkClass(&tokenizer, &settings, this);
  1866. checkClass.checkMemset();
  1867. }
  1868. void memsetOnClass() {
  1869. checkNoMemset("class Fred\n"
  1870. "{\n"
  1871. "};\n"
  1872. "void f()\n"
  1873. "{\n"
  1874. " Fred fred;\n"
  1875. " memset(&fred, 0, sizeof(Fred));\n"
  1876. "}");
  1877. ASSERT_EQUALS("", errout.str());
  1878. checkNoMemset("class Fred\n"
  1879. "{\n"
  1880. " static std::string b;\n"
  1881. "};\n"
  1882. "void f()\n"
  1883. "{\n"
  1884. " Fred fred;\n"
  1885. " memset(&fred, 0, sizeof(Fred));\n"
  1886. "}");
  1887. ASSERT_EQUALS("", errout.str());
  1888. checkNoMemset("class Fred\n"
  1889. "{\n"
  1890. " std::string * b;\n"
  1891. "};\n"
  1892. "void f()\n"
  1893. "{\n"
  1894. " Fred fred;\n"
  1895. " memset(&fred, 0, sizeof(Fred));\n"
  1896. "}");
  1897. ASSERT_EQUALS("", errout.str());
  1898. checkNoMemset("class Fred\n"
  1899. "{\n"
  1900. " std::string b;\n"
  1901. "};\n"
  1902. "void f()\n"
  1903. "{\n"
  1904. " Fred fred;\n"
  1905. " memset(&fred, 0, sizeof(Fred));\n"
  1906. "}");
  1907. ASSERT_EQUALS("[test.cpp:8]: (error) Using 'memset' on class that contains a 'std::string'.\n", errout.str());
  1908. checkNoMemset("class Fred\n"
  1909. "{\n"
  1910. " mutable std::string b;\n"
  1911. "};\n"
  1912. "void f()\n"
  1913. "{\n"
  1914. " Fred fred;\n"
  1915. " memset(&fred, 0, sizeof(Fred));\n"
  1916. "}");
  1917. ASSERT_EQUALS("[test.cpp:8]: (error) Using 'memset' on class that contains a 'std::string'.\n", errout.str());
  1918. checkNoMemset("class Fred {\n"
  1919. " std::string b;\n"
  1920. " void f();\n"
  1921. "};\n"
  1922. "void Fred::f() {\n"
  1923. " memset(this, 0, sizeof(*this));\n"
  1924. "}");
  1925. ASSERT_EQUALS("[test.cpp:6]: (error) Using 'memset' on class that contains a 'std::string'.\n", errout.str());
  1926. checkNoMemset("class Fred\n"
  1927. "{\n"
  1928. "};\n"
  1929. "void f()\n"
  1930. "{\n"
  1931. " Fred fred;\n"
  1932. " memset(&fred, 0, sizeof(fred));\n"
  1933. "}");
  1934. ASSERT_EQUALS("", errout.str());
  1935. checkNoMemset("class Fred\n"
  1936. "{\n"
  1937. " std::string s;\n"
  1938. "};\n"
  1939. "void f()\n"
  1940. "{\n"
  1941. " Fred fred;\n"
  1942. " memset(&fred, 0, sizeof(fred));\n"
  1943. "}");
  1944. ASSERT_EQUALS("[test.cpp:8]: (error) Using 'memset' on class that contains a 'std::string'.\n", errout.str());
  1945. checkNoMemset("class Fred\n"
  1946. "{\n"
  1947. " std::string s;\n"
  1948. "};\n"
  1949. "class Pebbles: public Fred {};\n"
  1950. "void f()\n"
  1951. "{\n"
  1952. " Pebbles pebbles;\n"
  1953. " memset(&pebbles, 0, sizeof(pebbles));\n"
  1954. "}");
  1955. ASSERT_EQUALS("[test.cpp:9]: (error) Using 'memset' on class that contains a 'std::string'.\n", errout.str());
  1956. checkNoMemset("class Fred\n"
  1957. "{\n"
  1958. " virtual ~Fred();\n"
  1959. "};\n"
  1960. "void f()\n"
  1961. "{\n"
  1962. " Fred fred;\n"
  1963. " memset(&fred, 0, sizeof(fred));\n"
  1964. "}");
  1965. ASSERT_EQUALS("[test.cpp:8]: (error) Using 'memset' on class that contains a virtual method.\n", errout.str());
  1966. checkNoMemset("class Fred\n"
  1967. "{\n"
  1968. " virtual ~Fred();\n"
  1969. "};\n"
  1970. "void f()\n"
  1971. "{\n"
  1972. " static Fred fred;\n"
  1973. " memset(&fred, 0, sizeof(fred));\n"
  1974. "}");
  1975. ASSERT_EQUALS("[test.cpp:8]: (error) Using 'memset' on class that contains a virtual method.\n", errout.str());
  1976. checkNoMemset("class Fred\n"
  1977. "{\n"
  1978. "};\n"
  1979. "class Wilma\n"
  1980. "{\n"
  1981. " virtual ~Wilma();\n"
  1982. "};\n"
  1983. "class Pebbles: public Fred, Wilma {};\n"
  1984. "void f()\n"
  1985. "{\n"
  1986. " Pebbles pebbles;\n"
  1987. " memset(&pebbles, 0, sizeof(pebbles));\n"
  1988. "}");
  1989. ASSERT_EQUALS("[test.cpp:12]: (error) Using 'memset' on class that contains a virtual method.\n", errout.str());
  1990. // Fred not defined in scope
  1991. checkNoMemset("namespace n1 {\n"
  1992. " class Fred\n"
  1993. " {\n"
  1994. " std::string b;\n"
  1995. " };\n"
  1996. "}\n"
  1997. "void f()\n"
  1998. "{\n"
  1999. " Fred fred;\n"
  2000. " memset(&fred, 0, sizeof(Fred));\n"
  2001. "}");
  2002. ASSERT_EQUALS("", errout.str());
  2003. // Fred with namespace qualifier
  2004. checkNoMemset("namespace n1 {\n"
  2005. " class Fred\n"
  2006. " {\n"
  2007. " std::string b;\n"
  2008. " };\n"
  2009. "}\n"
  2010. "void f()\n"
  2011. "{\n"
  2012. " n1::Fred fred;\n"
  2013. " memset(&fred, 0, sizeof(n1::Fred));\n"
  2014. "}");
  2015. ASSERT_EQUALS("[test.cpp:10]: (error) Using 'memset' on class that contains a 'std::string'.\n", errout.str());
  2016. // Fred with namespace qualifier
  2017. checkNoMemset("namespace n1 {\n"
  2018. " class Fred\n"
  2019. " {\n"
  2020. " std::string b;\n"
  2021. " };\n"
  2022. "}\n"
  2023. "void f()\n"
  2024. "{\n"
  2025. " n1::Fred fred;\n"
  2026. " memset(&fred, 0, sizeof(fred));\n"
  2027. "}");
  2028. ASSERT_EQUALS("[test.cpp:10]: (error) Using 'memset' on class that contains a 'std::string'.\n", errout.str());
  2029. checkNoMemset("class A {\n"
  2030. " virtual ~A() { }\n"
  2031. " std::string s;\n"
  2032. "};\n"
  2033. "int f() {\n"
  2034. " const int N = 10;\n"
  2035. " A** arr = new A*[N];\n"
  2036. " memset(arr, 0, N * sizeof(A*));\n"
  2037. "}");
  2038. ASSERT_EQUALS("", errout.str());
  2039. checkNoMemset("class A {\n" // #5116 - nested class data is mixed in the SymbolDatabase
  2040. " std::string s;\n"
  2041. " struct B { int x; };\n"
  2042. "};\n"
  2043. "void f(A::B *b) {\n"
  2044. " memset(b,0,4);\n"
  2045. "}");
  2046. ASSERT_EQUALS("", errout.str());
  2047. // #4461 Warn about memset/memcpy on class with references as members
  2048. checkNoMemset("class A {\n"
  2049. " std::string &s;\n"
  2050. "};\n"
  2051. "void f() {\n"
  2052. " A a;\n"
  2053. " memset(&a, 0, sizeof(a)); \n"
  2054. "}");
  2055. ASSERT_EQUALS("[test.cpp:6]: (error) Using 'memset' on class that contains a reference.\n", errout.str());
  2056. checkNoMemset("class A {\n"
  2057. " const B&b;\n"
  2058. "};\n"
  2059. "void f() {\n"
  2060. " A a;\n"
  2061. " memset(&a, 0, sizeof(a)); \n"
  2062. "}");
  2063. ASSERT_EQUALS("[test.cpp:6]: (error) Using 'memset' on class that contains a reference.\n", errout.str());
  2064. }
  2065. void memsetOnInvalid() { // Ticket #5425
  2066. checkNoMemset("union ASFStreamHeader {\n"
  2067. " struct AVMPACKED {\n"
  2068. " union {\n"
  2069. " struct AVMPACKED {\n"
  2070. " int width;\n"
  2071. " } vid;\n"
  2072. " };\n"
  2073. " } hdr;\n"
  2074. "};"
  2075. "void parseHeader() {\n"
  2076. " ASFStreamHeader strhdr;\n"
  2077. " memset(&strhdr, 0, sizeof(strhdr));\n"
  2078. "}");
  2079. }
  2080. void memsetOnStruct() {
  2081. checkNoMemset("struct A\n"
  2082. "{\n"
  2083. "};\n"
  2084. "void f()\n"
  2085. "{\n"
  2086. " A a;\n"
  2087. " memset(&a, 0, sizeof(A));\n"
  2088. "}");
  2089. ASSERT_EQUALS("", errout.str());
  2090. checkNoMemset("struct A\n"
  2091. "{\n"
  2092. "};\n"
  2093. "void f()\n"
  2094. "{\n"
  2095. " struct A a;\n"
  2096. " memset(&a, 0, sizeof(struct A));\n"
  2097. "}");
  2098. ASSERT_EQUALS("", errout.str());
  2099. checkNoMemset("struct A\n"
  2100. "{\n"
  2101. "};\n"
  2102. "void f()\n"
  2103. "{\n"
  2104. " struct A a;\n"
  2105. " memset(&a, 0, sizeof(A));\n"
  2106. "}");
  2107. ASSERT_EQUALS("", errout.str());
  2108. checkNoMemset("void f()\n"
  2109. "{\n"
  2110. " struct sockaddr_in6 fail;\n"
  2111. " memset(&fail, 0, sizeof(struct sockaddr_in6));\n"
  2112. "}");
  2113. ASSERT_EQUALS("", errout.str());
  2114. checkNoMemset("struct A\n"
  2115. "{\n"
  2116. " void g( struct sockaddr_in6& a);\n"
  2117. "private:\n"
  2118. " std::string b;\n"
  2119. "};\n"
  2120. "void f()\n"
  2121. "{\n"
  2122. " struct A fail;\n"
  2123. " memset(&fail, 0, sizeof(struct A));\n"
  2124. "}");
  2125. ASSERT_EQUALS("[test.cpp:10]: (error) Using 'memset' on struct that contains a 'std::string'.\n", errout.str());
  2126. checkNoMemset("struct Fred\n"
  2127. "{\n"
  2128. " std::string s;\n"
  2129. "};\n"
  2130. "void f()\n"
  2131. "{\n"
  2132. " Fred fred;\n"
  2133. " memset(&fred, 0, sizeof(fred));\n"
  2134. "}");
  2135. ASSERT_EQUALS("[test.cpp:8]: (error) Using 'memset' on struct that contains a 'std::string'.\n", errout.str());
  2136. checkNoMemset("struct Stringy {\n"
  2137. " std::string inner;\n"
  2138. "};\n"
  2139. "struct Foo {\n"
  2140. " Stringy s;\n"
  2141. "};\n"
  2142. "int main() {\n"
  2143. " Foo foo;\n"
  2144. " memset(&foo, 0, sizeof(Foo));\n"
  2145. "}");
  2146. ASSERT_EQUALS("[test.cpp:9]: (error) Using 'memset' on struct that contains a 'std::string'.\n", errout.str());
  2147. }
  2148. void memsetVector() {
  2149. checkNoMemset("class A\n"
  2150. "{ std::vector<int> ints; };\n"
  2151. "\n"
  2152. "void f()\n"
  2153. "{\n"
  2154. " A a;\n"
  2155. " memset(&a, 0, sizeof(A));\n"
  2156. "}");
  2157. ASSERT_EQUALS("[test.cpp:7]: (error) Using 'memset' on class that contains a 'std::vector'.\n", errout.str());
  2158. checkNoMemset("struct A\n"
  2159. "{ std::vector<int> ints; };\n"
  2160. "\n"
  2161. "void f()\n"
  2162. "{\n"
  2163. " A a;\n"
  2164. " memset(&a, 0, sizeof(A));\n"
  2165. "}");
  2166. ASSERT_EQUALS("[test.cpp:7]: (error) Using 'memset' on struct that contains a 'std::vector'.\n", errout.str());
  2167. checkNoMemset("struct A\n"
  2168. "{ std::vector<int> ints; };\n"
  2169. "\n"
  2170. "void f()\n"
  2171. "{\n"
  2172. " A a;\n"
  2173. " memset(&a, 0, sizeof(struct A));\n"
  2174. "}");
  2175. ASSERT_EQUALS("[test.cpp:7]: (error) Using 'memset' on struct that contains a 'std::vector'.\n", errout.str());
  2176. checkNoMemset("struct A\n"
  2177. "{ std::vector<int> ints; };\n"
  2178. "\n"
  2179. "void f()\n"
  2180. "{\n"
  2181. " A a;\n"
  2182. " memset(&a, 0, sizeof(a));\n"
  2183. "}");
  2184. ASSERT_EQUALS("[test.cpp:7]: (error) Using 'memset' on struct that contains a 'std::vector'.\n", errout.str());
  2185. checkNoMemset("class A\n"
  2186. "{ std::vector< std::vector<int> > ints; };\n"
  2187. "\n"
  2188. "void f()\n"
  2189. "{\n"
  2190. " A a;\n"
  2191. " memset(&a, 0, sizeof(A));\n"
  2192. "}");
  2193. ASSERT_EQUALS("[test.cpp:7]: (error) Using 'memset' on class that contains a 'std::vector'.\n", errout.str());
  2194. checkNoMemset("struct A\n"
  2195. "{ std::vector< std::vector<int> > ints; };\n"
  2196. "\n"
  2197. "void f()\n"
  2198. "{\n"
  2199. " A a;\n"
  2200. " memset(&a, 0, sizeof(A));\n"
  2201. "}");
  2202. ASSERT_EQUALS("[test.cpp:7]: (error) Using 'memset' on struct that contains a 'std::vector'.\n", errout.str());
  2203. checkNoMemset("struct A\n"
  2204. "{ std::vector< std::vector<int> > ints; };\n"
  2205. "\n"
  2206. "void f()\n"
  2207. "{\n"
  2208. " A a;\n"
  2209. " memset(&a, 0, sizeof(a));\n"
  2210. "}");
  2211. ASSERT_EQUALS("[test.cpp:7]: (error) Using 'memset' on struct that contains a 'std::vector'.\n", errout.str());
  2212. checkNoMemset("struct A\n"
  2213. "{ std::vector<int *> ints; };\n"
  2214. "\n"
  2215. "void f()\n"
  2216. "{\n"
  2217. " A a;\n"
  2218. " memset(&a, 0, sizeof(A));\n"
  2219. "}");
  2220. ASSERT_EQUALS("[test.cpp:7]: (error) Using 'memset' on struct that contains a 'std::vector'.\n", errout.str());
  2221. checkNoMemset("struct A {\n"
  2222. " std::vector<int *> buf;\n"
  2223. " operator int*() {return &buf[0];}\n"
  2224. "};\n"
  2225. "void f() {\n"
  2226. " A a;\n"
  2227. " memset(a, 0, 100);\n"
  2228. "}");
  2229. ASSERT_EQUALS("", errout.str()); // #4460
  2230. checkNoMemset("struct C {\n"
  2231. " std::string s;\n"
  2232. "};\n"
  2233. "int foo() {\n"
  2234. " C* c1[10][10];\n"
  2235. " C* c2[10];\n"
  2236. " C c3[10][10];\n"
  2237. " C** c4 = new C*[10];\n"
  2238. " memset(**c1, 0, 10);\n"
  2239. " memset(*c1, 0, 10);\n"
  2240. " memset(*c2, 0, 10);\n"
  2241. " memset(*c3, 0, 10);\n"
  2242. " memset(*c4, 0, 10);\n"
  2243. " memset(c2, 0, 10);\n"
  2244. " memset(c3, 0, 10);\n"
  2245. "}");
  2246. ASSERT_EQUALS("[test.cpp:9]: (error) Using 'memset' on struct that contains a 'std::string'.\n"
  2247. "[test.cpp:11]: (error) Using 'memset' on struct that contains a 'std::string'.\n"
  2248. "[test.cpp:12]: (error) Using 'memset' on struct that contains a 'std::string'.\n"
  2249. "[test.cpp:13]: (error) Using 'memset' on struct that contains a 'std::string'.\n", errout.str());
  2250. checkNoMemset("class A {\n"
  2251. " std::array<int, 10> ints;\n"
  2252. "};\n"
  2253. "void f() {\n"
  2254. " A a;\n"
  2255. " memset(&a, 0, sizeof(A));\n"
  2256. "}", true);
  2257. ASSERT_EQUALS("", errout.str()); // std::array is POD (#5481)
  2258. }
  2259. void memsetOnStdPodType() { // Ticket #5901
  2260. checkNoMemset("struct st {\n"
  2261. " std::uint8_t a;\n"
  2262. " std::uint8_t b;\n"
  2263. " std::uint8_t c;\n"
  2264. "};\n"
  2265. "\n"
  2266. "void f() {\n"
  2267. " st s;\n"
  2268. " std::memset(&s, 0, sizeof(st));\n"
  2269. "}", true);
  2270. ASSERT_EQUALS("", errout.str());
  2271. }
  2272. void memsetOnFloat() {
  2273. checkNoMemset("struct A {\n"
  2274. " float f;\n"
  2275. "};\n"
  2276. "void f() {\n"
  2277. " A a;\n"
  2278. " memset(&a, 0, sizeof(A));\n"
  2279. "}", false, true);
  2280. ASSERT_EQUALS("[test.cpp:6]: (portability) Using memset() on struct which contains a floating point number.\n", errout.str());
  2281. checkNoMemset("struct A {\n"
  2282. " float f[4];\n"
  2283. "};\n"
  2284. "void f() {\n"
  2285. " A a;\n"
  2286. " memset(&a, 0, sizeof(A));\n"
  2287. "}", false, true);
  2288. ASSERT_EQUALS("[test.cpp:6]: (portability) Using memset() on struct which contains a floating point number.\n", errout.str());
  2289. checkNoMemset("struct A {\n"
  2290. " float f[4];\n"
  2291. "};\n"
  2292. "void f(const A& b) {\n"
  2293. " A a;\n"
  2294. " memcpy(&a, &b, sizeof(A));\n"
  2295. "}", false, true);
  2296. ASSERT_EQUALS("", errout.str());
  2297. checkNoMemset("struct A {\n"
  2298. " float* f;\n"
  2299. "};\n"
  2300. "void f() {\n"
  2301. " A a;\n"
  2302. " memset(&a, 0, sizeof(A));\n"
  2303. "}", false, true);
  2304. ASSERT_EQUALS("", errout.str());
  2305. checkNoMemset("struct A {\n"
  2306. " float f;\n"
  2307. "};\n"
  2308. "void f() {\n"
  2309. " A a;\n"
  2310. " memset(&a, 0, sizeof(A));\n"
  2311. "}", false, false);
  2312. ASSERT_EQUALS("", errout.str());
  2313. }
  2314. void mallocOnClass() {
  2315. checkNoMemset("class C { C() {} };\n"
  2316. "void foo(C*& p) {\n"
  2317. " p = malloc(sizeof(C));\n"
  2318. "}");
  2319. ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:1]: (warning) Memory for class instance allocated with malloc(), but class provides constructors.\n", errout.str());
  2320. checkNoMemset("class C { C(int z, Foo bar) { bar(); } };\n"
  2321. "void foo(C*& p) {\n"
  2322. " p = malloc(sizeof(C));\n"
  2323. "}");
  2324. ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:1]: (warning) Memory for class instance allocated with malloc(), but class provides constructors.\n", errout.str());
  2325. checkNoMemset("struct C { C() {} };\n"
  2326. "void foo(C*& p) {\n"
  2327. " p = realloc(p, sizeof(C));\n"
  2328. "}");
  2329. ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:1]: (warning) Memory for class instance allocated with realloc(), but class provides constructors.\n", errout.str());
  2330. checkNoMemset("struct C { virtual void bar(); };\n"
  2331. "void foo(C*& p) {\n"
  2332. " p = malloc(sizeof(C));\n"
  2333. "}");
  2334. ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:1]: (error) Memory for class instance allocated with malloc(), but class contains a virtual method.\n", errout.str());
  2335. checkNoMemset("struct C { std::string s; };\n"
  2336. "void foo(C*& p) {\n"
  2337. " p = malloc(sizeof(C));\n"
  2338. "}");
  2339. ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:1]: (error) Memory for class instance allocated with malloc(), but class contains a 'std::string'.\n", errout.str());
  2340. checkNoMemset("class C { };\n" // C-Style class/struct
  2341. "void foo(C*& p) {\n"
  2342. " p = malloc(sizeof(C));\n"
  2343. "}");
  2344. ASSERT_EQUALS("", errout.str());
  2345. checkNoMemset("struct C { C() {} };\n"
  2346. "void foo(C*& p) {\n"
  2347. " p = new C();\n"
  2348. "}");
  2349. ASSERT_EQUALS("", errout.str());
  2350. checkNoMemset("class C { C() {} };\n"
  2351. "void foo(D*& p) {\n" // Unknown type
  2352. " p = malloc(sizeof(C));\n"
  2353. "}");
  2354. ASSERT_EQUALS("", errout.str());
  2355. }
  2356. void checkThisSubtraction(const char code[]) {
  2357. // Clear the error log
  2358. errout.str("");
  2359. Settings settings;
  2360. settings.addEnabled("warning");
  2361. // Tokenize..
  2362. Tokenizer tokenizer(&settings, this);
  2363. std::istringstream istr(code);
  2364. tokenizer.tokenize(istr, "test.cpp");
  2365. tokenizer.simplifyTokenList2();
  2366. // Check..
  2367. CheckClass checkClass(&tokenizer, &settings, this);
  2368. checkClass.thisSubtraction();
  2369. }
  2370. void this_subtraction() {
  2371. checkThisSubtraction("; this-x ;");
  2372. ASSERT_EQUALS("[test.cpp:1]: (warning) Suspicious pointer subtraction. Did you intend to write '->'?\n", errout.str());
  2373. checkThisSubtraction("; *this = *this-x ;");
  2374. ASSERT_EQUALS("", errout.str());
  2375. checkThisSubtraction("; *this = *this-x ;\n"
  2376. "this-x ;");
  2377. ASSERT_EQUALS("[test.cpp:2]: (warning) Suspicious pointer subtraction. Did you intend to write '->'?\n", errout.str());
  2378. checkThisSubtraction("; *this = *this-x ;\n"
  2379. "this-x ;\n"
  2380. "this-x ;\n");
  2381. ASSERT_EQUALS("[test.cpp:2]: (warning) Suspicious pointer subtraction. Did you intend to write '->'?\n"
  2382. "[test.cpp:3]: (warning) Suspicious pointer subtraction. Did you intend to write '->'?\n", errout.str());
  2383. }
  2384. void checkConst(const char code[], const Settings *s = 0, bool inconclusive = true, bool verify = true) {
  2385. // Clear the error log
  2386. errout.str("");
  2387. // Check..
  2388. Settings settings;
  2389. if (s)
  2390. settings = *s;
  2391. else
  2392. settings.addEnabled("style");
  2393. settings.inconclusive = inconclusive;
  2394. // Tokenize..
  2395. Tokenizer tokenizer(&settings, this);
  2396. std::istringstream istr(code);
  2397. tokenizer.tokenize(istr, "test.cpp");
  2398. const std::string str1(tokenizer.tokens()->stringifyList(0,true));
  2399. tokenizer.simplifyTokenList2();
  2400. const std::string str2(tokenizer.tokens()->stringifyList(0,true));
  2401. if (verify && str1 != str2)
  2402. warnUnsimplified(str1, str2);
  2403. CheckClass checkClass(&tokenizer, &settings, this);
  2404. checkClass.checkConst();
  2405. }
  2406. void const1() {
  2407. checkConst("class Fred {\n"
  2408. " int a;\n"
  2409. " int getA() { return a; }\n"
  2410. "};");
  2411. ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::getA' can be const.\n", errout.str());
  2412. checkConst("class Fred {\n"
  2413. " const std::string foo() { return \"\"; }\n"
  2414. "};");
  2415. ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Technically the member function 'Fred::foo' can be static.\n", errout.str());
  2416. checkConst("class Fred {\n"
  2417. " std::string s;\n"
  2418. " const std::string & foo() { return \"\"; }\n"
  2419. "};");
  2420. ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::foo' can be static.\n", errout.str());
  2421. // constructors can't be const..
  2422. checkConst("class Fred {\n"
  2423. " int a;\n"
  2424. "public:\n"
  2425. " Fred() { }\n"
  2426. "};");
  2427. ASSERT_EQUALS("", errout.str());
  2428. // assignment through |=..
  2429. checkConst("class Fred {\n"
  2430. " int a;\n"
  2431. " int setA() { a |= true; }\n"
  2432. "};");
  2433. ASSERT_EQUALS("", errout.str());
  2434. // functions with a call to a member function can only be const, if that member function is const, too.. (#1305)
  2435. checkConst("class foo {\n"
  2436. "public:\n"
  2437. " int x;\n"
  2438. " void a() { x = 1; }\n"
  2439. " void b() { a(); }\n"
  2440. "};");
  2441. ASSERT_EQUALS("", errout.str());
  2442. checkConst("class Fred {\n"
  2443. "public:\n"
  2444. " int x;\n"
  2445. " int a() const { return x; }\n"
  2446. " void b() { a(); }\n"
  2447. "};");
  2448. ASSERT_EQUALS("[test.cpp:5]: (style, inconclusive) Technically the member function 'Fred::b' can be const.\n", errout.str());
  2449. checkConst("class Fred {\n"
  2450. "public:\n"
  2451. " int x;\n"
  2452. " void b() { a(); }\n"
  2453. "};");
  2454. ASSERT_EQUALS("[test.cpp:4]: (performance, inconclusive) Technically the member function 'Fred::b' can be static.\n", errout.str());
  2455. // static functions can't be const..
  2456. checkConst("class foo\n"
  2457. "{\n"
  2458. "public:\n"
  2459. " static unsigned get()\n"
  2460. " { return 0; }\n"
  2461. "};");
  2462. ASSERT_EQUALS("", errout.str());
  2463. checkConst("class Fred {\n"
  2464. " const std::string foo() const throw() { return \"\"; }\n"
  2465. "};");
  2466. ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Technically the member function 'Fred::foo' can be static.\n", errout.str());
  2467. }
  2468. void const2() {
  2469. // ticket 1344
  2470. // assignment to variable can't be const
  2471. checkConst("class Fred {\n"
  2472. " std::string s;\n"
  2473. " void foo() { s = \"\"; }\n"
  2474. "};");
  2475. ASSERT_EQUALS("", errout.str());
  2476. // assignment to function argument reference can be const
  2477. checkConst("class Fred {\n"
  2478. " std::string s;\n"
  2479. " void foo(std::string & a) { a = s; }\n"
  2480. "};");
  2481. ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::foo' can be const.\n", errout.str());
  2482. // assignment to variable can't be const
  2483. checkConst("class Fred {\n"
  2484. " std::string s;\n"
  2485. " void foo(std::string & a) { s = a; }\n"
  2486. "};");
  2487. ASSERT_EQUALS("", errout.str());
  2488. // assignment to function argument references can be const
  2489. checkConst("class Fred {\n"
  2490. " std::string s;\n"
  2491. " void foo(std::string & a, std::string & b) { a = s; b = s; }\n"
  2492. "};");
  2493. ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::foo' can be const.\n", errout.str());
  2494. // assignment to variable, can't be const
  2495. checkConst("class Fred {\n"
  2496. " std::string s;\n"
  2497. " void foo(std::string & a, std::string & b) { s = a; s = b; }\n"
  2498. "};");
  2499. ASSERT_EQUALS("", errout.str());
  2500. // assignment to variable, can't be const
  2501. checkConst("class Fred {\n"
  2502. " std::string s;\n"
  2503. " void foo(std::string & a, std::string & b) { s = a; b = a; }\n"
  2504. "};");
  2505. ASSERT_EQUALS("", errout.str());
  2506. // assignment to variable, can't be const
  2507. checkConst("class Fred {\n"
  2508. " std::string s;\n"
  2509. " void foo(std::string & a, std::string & b) { a = s; s = b; }\n"
  2510. "};");
  2511. ASSERT_EQUALS("", errout.str());
  2512. }
  2513. void const3() {
  2514. // assignment to function argument pointer can be const
  2515. checkConst("class Fred {\n"
  2516. " int s;\n"
  2517. " void foo(int * a) { *a = s; }\n"
  2518. "};");
  2519. ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::foo' can be const.\n", errout.str());
  2520. // assignment to variable, can't be const
  2521. checkConst("class Fred {\n"
  2522. " int s;\n"
  2523. " void foo(int * a) { s = *a; }\n"
  2524. "};");
  2525. ASSERT_EQUALS("", errout.str());
  2526. // assignment to function argument pointers can be const
  2527. checkConst("class Fred {\n"
  2528. " std::string s;\n"
  2529. " void foo(std::string * a, std::string * b) { *a = s; *b = s; }\n"
  2530. "};");
  2531. ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::foo' can be const.\n", errout.str());
  2532. // assignment to variable, can't be const
  2533. checkConst("class Fred {\n"
  2534. " std::string s;\n"
  2535. " void foo(std::string * a, std::string * b) { s = *a; s = *b; }\n"
  2536. "};");
  2537. ASSERT_EQUALS("", errout.str());
  2538. // assignment to variable, can't be const
  2539. checkConst("class Fred {\n"
  2540. " std::string s;\n"
  2541. " void foo(std::string * a, std::string * b) { s = *a; *b = s; }\n"
  2542. "};");
  2543. ASSERT_EQUALS("", errout.str());
  2544. // assignment to variable, can't be const
  2545. checkConst("class Fred {\n"
  2546. " std::string s;\n"
  2547. " void foo(std::string * a, std::string * b) { *a = s; s = b; }\n"
  2548. "};");
  2549. ASSERT_EQUALS("", errout.str());
  2550. }
  2551. void const4() {
  2552. checkConst("class Fred {\n"
  2553. " int a;\n"
  2554. " int getA();\n"
  2555. "};\n"
  2556. "int Fred::getA() { return a; }");
  2557. ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::getA' can be const.\n", errout.str());
  2558. checkConst("class Fred {\n"
  2559. " std::string s;\n"
  2560. " const std::string & foo();\n"
  2561. "};\n"
  2562. "const std::string & Fred::foo() { return \"\"; }");
  2563. ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::foo' can be static.\n", errout.str());
  2564. // functions with a function call to a non-const member can't be const.. (#1305)
  2565. checkConst("class Fred\n"
  2566. "{\n"
  2567. "public:\n"
  2568. " int x;\n"
  2569. " void a() { x = 1; }\n"
  2570. " void b();\n"
  2571. "};\n"
  2572. "void Fred::b() { a(); }");
  2573. ASSERT_EQUALS("", errout.str());
  2574. // static functions can't be const..
  2575. checkConst("class Fred\n"
  2576. "{\n"
  2577. "public:\n"
  2578. " static unsigned get();\n"
  2579. "};\n"
  2580. "static unsigned Fred::get() { return 0; }");
  2581. ASSERT_EQUALS("", errout.str());
  2582. // assignment to variable can't be const
  2583. checkConst("class Fred {\n"
  2584. " std::string s;\n"
  2585. " void foo();\n"
  2586. "};\n"
  2587. "void Fred::foo() { s = \"\"; }");
  2588. ASSERT_EQUALS("", errout.str());
  2589. // assignment to function argument reference can be const
  2590. checkConst("class Fred {\n"
  2591. " std::string s;\n"
  2592. " void foo(std::string & a);\n"
  2593. "};\n"
  2594. "void Fred::foo(std::string & a) { a = s; }");
  2595. ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::foo' can be const.\n", errout.str());
  2596. // assignment to variable can't be const
  2597. checkConst("class Fred {\n"
  2598. " std::string s;\n"
  2599. " void foo(std::string & a);\n"
  2600. "};\n"
  2601. "void Fred::foo(std::string & a) { s = a; }");
  2602. ASSERT_EQUALS("", errout.str());
  2603. // assignment to function argument references can be const
  2604. checkConst("class Fred {\n"
  2605. " std::string s;\n"
  2606. " void foo(std::string & a, std::string & b);\n"
  2607. "};\n"
  2608. "void Fred::foo(std::string & a, std::string & b) { a = s; b = s; }");
  2609. ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::foo' can be const.\n", errout.str());
  2610. // assignment to variable, can't be const
  2611. checkConst("class Fred {\n"
  2612. " std::string s;\n"
  2613. " void foo(std::string & a, std::string & b);\n"
  2614. "};\n"
  2615. "void Fred::foo(std::string & a, std::string & b) { s = a; s = b; }");
  2616. ASSERT_EQUALS("", errout.str());
  2617. // assignment to variable, can't be const
  2618. checkConst("class Fred {\n"
  2619. " std::string s;\n"
  2620. " void foo(std::string & a, std::string & b);\n"
  2621. "};\n"
  2622. "void Fred::foo(std::string & a, std::string & b) { s = a; b = a; }");
  2623. ASSERT_EQUALS("", errout.str());
  2624. // assignment to variable, can't be const
  2625. checkConst("class Fred {\n"
  2626. " std::string s;\n"
  2627. " void foo(std::string & a, std::string & b);\n"
  2628. "};\n"
  2629. "void Fred::foo(std::string & a, std::string & b) { a = s; s = b; }");
  2630. ASSERT_EQUALS("", errout.str());
  2631. // assignment to function argument pointer can be const
  2632. checkConst("class Fred {\n"
  2633. " int s;\n"
  2634. " void foo(int * a);\n"
  2635. "};\n"
  2636. "void Fred::foo(int * a) { *a = s; }");
  2637. ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::foo' can be const.\n", errout.str());
  2638. // assignment to variable, can't be const
  2639. checkConst("class Fred {\n"
  2640. " int s;\n"
  2641. " void foo(int * a);\n"
  2642. "};\n"
  2643. "void Fred::foo(int * a) { s = *a; }");
  2644. ASSERT_EQUALS("", errout.str());
  2645. // assignment to function argument pointers can be const
  2646. checkConst("class Fred {\n"
  2647. " std::string s;\n"
  2648. " void foo(std::string * a, std::string * b);\n"
  2649. "};\n"
  2650. "void Fred::foo(std::string * a, std::string * b) { *a = s; *b = s; }");
  2651. ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::foo' can be const.\n", errout.str());
  2652. // assignment to variable, can't be const
  2653. checkConst("class Fred {\n"
  2654. " std::string s;\n"
  2655. " void foo(std::string * a, std::string * b);\n"
  2656. "};\n"
  2657. "void Fred::foo(std::string * a, std::string * b) { s = *a; s = *b; }");
  2658. ASSERT_EQUALS("", errout.str());
  2659. // assignment to variable, can't be const
  2660. checkConst("class Fred {\n"
  2661. " std::string s;\n"
  2662. " void foo(std::string * a, std::string * b);\n"
  2663. "};\n"
  2664. "void Fred::foo(std::string * a, std::string * b) { s = *a; *b = s; }");
  2665. ASSERT_EQUALS("", errout.str());
  2666. // assignment to variable, can't be const
  2667. checkConst("class Fred {\n"
  2668. " std::string s;\n"
  2669. " void foo(std::string * a, std::string * b);\n"
  2670. "};\n"
  2671. "void Fred::foo(std::string * a, std::string * b) { *a = s; s = b; }");
  2672. ASSERT_EQUALS("", errout.str());
  2673. // check functions with same name
  2674. checkConst("class Fred {\n"
  2675. " std::string s;\n"
  2676. " void foo();\n"
  2677. " void foo(std::string & a);\n"
  2678. " void foo(const std::string & a);\n"
  2679. "};\n"
  2680. "void Fred::foo() { }"
  2681. "void Fred::foo(std::string & a) { a = s; }"
  2682. "void Fred::foo(const std::string & a) { s = a; }");
  2683. ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::foo' can be static.\n"
  2684. "[test.cpp:7] -> [test.cpp:4]: (style, inconclusive) Technically the member function 'Fred::foo' can be const.\n", errout.str());
  2685. // check functions with different or missing parameter names
  2686. checkConst("class Fred {\n"
  2687. " std::string s;\n"
  2688. " void foo1(int, int);\n"
  2689. " void foo2(int a, int b);\n"
  2690. " void foo3(int, int b);\n"
  2691. " void foo4(int a, int);\n"
  2692. " void foo5(int a, int b);\n"
  2693. "};\n"
  2694. "void Fred::foo1(int a, int b) { }\n"
  2695. "void Fred::foo2(int c, int d) { }\n"
  2696. "void Fred::foo3(int a, int b) { }\n"
  2697. "void Fred::foo4(int a, int b) { }\n"
  2698. "void Fred::foo5(int, int) { }");
  2699. ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::foo1' can be static.\n"
  2700. "[test.cpp:10] -> [test.cpp:4]: (performance, inconclusive) Technically the member function 'Fred::foo2' can be static.\n"
  2701. "[test.cpp:11] -> [test.cpp:5]: (performance, inconclusive) Technically the member function 'Fred::foo3' can be static.\n"
  2702. "[test.cpp:12] -> [test.cpp:6]: (performance, inconclusive) Technically the member function 'Fred::foo4' can be static.\n"
  2703. "[test.cpp:13] -> [test.cpp:7]: (performance, inconclusive) Technically the member function 'Fred::foo5' can be static.\n", errout.str());
  2704. // check nested classes
  2705. checkConst("class Fred {\n"
  2706. " class A {\n"
  2707. " int a;\n"
  2708. " int getA() { return a; }\n"
  2709. " };\n"
  2710. "};");
  2711. ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'Fred::A::getA' can be const.\n", errout.str());
  2712. checkConst("class Fred {\n"
  2713. " class A {\n"
  2714. " int a;\n"
  2715. " int getA();\n"
  2716. " };\n"
  2717. " int A::getA() { return a; }\n"
  2718. "};");
  2719. ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:4]: (style, inconclusive) Technically the member function 'Fred::A::getA' can be const.\n", errout.str());
  2720. checkConst("class Fred {\n"
  2721. " class A {\n"
  2722. " int a;\n"
  2723. " int getA();\n"
  2724. " };\n"
  2725. "};\n"
  2726. "int Fred::A::getA() { return a; }");
  2727. ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:4]: (style, inconclusive) Technically the member function 'Fred::A::getA' can be const.\n", errout.str());
  2728. // check deeply nested classes
  2729. checkConst("class Fred {\n"
  2730. " class B {\n"
  2731. " int b;\n"
  2732. " int getB() { return b; }\n"
  2733. " class A {\n"
  2734. " int a;\n"
  2735. " int getA() { return a; }\n"
  2736. " };\n"
  2737. " };\n"
  2738. "};");
  2739. ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'Fred::B::getB' can be const.\n"
  2740. "[test.cpp:7]: (style, inconclusive) Technically the member function 'Fred::B::A::getA' can be const.\n"
  2741. , errout.str());
  2742. checkConst("class Fred {\n"
  2743. " class B {\n"
  2744. " int b;\n"
  2745. " int getB();\n"
  2746. " class A {\n"
  2747. " int a;\n"
  2748. " int getA();\n"
  2749. " };\n"
  2750. " int A::getA() { return a; }\n"
  2751. " };\n"
  2752. " int B::getB() { return b; }\n"
  2753. "};");
  2754. ASSERT_EQUALS("[test.cpp:11] -> [test.cpp:4]: (style, inconclusive) Technically the member function 'Fred::B::getB' can be const.\n"
  2755. "[test.cpp:9] -> [test.cpp:7]: (style, inconclusive) Technically the member function 'Fred::B::A::getA' can be const.\n" , errout.str());
  2756. checkConst("class Fred {\n"
  2757. " class B {\n"
  2758. " int b;\n"
  2759. " int getB();\n"
  2760. " class A {\n"
  2761. " int a;\n"
  2762. " int getA();\n"
  2763. " };\n"
  2764. " };\n"
  2765. " int B::A::getA() { return a; }\n"
  2766. " int B::getB() { return b; }\n"
  2767. "};");
  2768. ASSERT_EQUALS("[test.cpp:11] -> [test.cpp:4]: (style, inconclusive) Technically the member function 'Fred::B::getB' can be const.\n"
  2769. "[test.cpp:10] -> [test.cpp:7]: (style, inconclusive) Technically the member function 'Fred::B::A::getA' can be const.\n" , errout.str());
  2770. checkConst("class Fred {\n"
  2771. " class B {\n"
  2772. " int b;\n"
  2773. " int getB();\n"
  2774. " class A {\n"
  2775. " int a;\n"
  2776. " int getA();\n"
  2777. " };\n"
  2778. " };\n"
  2779. "};\n"
  2780. "int Fred::B::A::getA() { return a; }\n"
  2781. "int Fred::B::getB() { return b; }");
  2782. ASSERT_EQUALS("[test.cpp:12] -> [test.cpp:4]: (style, inconclusive) Technically the member function 'Fred::B::getB' can be const.\n"
  2783. "[test.cpp:11] -> [test.cpp:7]: (style, inconclusive) Technically the member function 'Fred::B::A::getA' can be const.\n" , errout.str());
  2784. }
  2785. // operator< can often be const
  2786. void constoperator1() {
  2787. checkConst("struct Fred {\n"
  2788. " int a;\n"
  2789. " bool operator<(const Fred &f) { return a < f.a; }\n"
  2790. "};");
  2791. ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::operator<' can be const.\n", errout.str());
  2792. }
  2793. // operator<<
  2794. void constoperator2() {
  2795. checkConst("struct Foo {\n"
  2796. " void operator<<(int);\n"
  2797. "};\n"
  2798. "struct Fred {\n"
  2799. " Foo foo;\n"
  2800. " void x()\n"
  2801. " {\n"
  2802. " foo << 123;\n"
  2803. " }\n"
  2804. "};");
  2805. ASSERT_EQUALS("", errout.str());
  2806. checkConst("struct Foo {\n"
  2807. " void operator<<(int);\n"
  2808. "};\n"
  2809. "struct Fred {\n"
  2810. " Foo foo;\n"
  2811. " void x()\n"
  2812. " {\n"
  2813. " std::cout << foo << 123;\n"
  2814. " }\n"
  2815. "};");
  2816. ASSERT_EQUALS("[test.cpp:6]: (style, inconclusive) Technically the member function 'Fred::x' can be const.\n", errout.str());
  2817. }
  2818. void constoperator3() {
  2819. checkConst("struct Fred {\n"
  2820. " int array[10];\n"
  2821. " int const & operator [] (unsigned int index) const { return array[index]; }\n"
  2822. " int & operator [] (unsigned int index) { return array[index]; }\n"
  2823. "};");
  2824. ASSERT_EQUALS("", errout.str());
  2825. checkConst("struct Fred {\n"
  2826. " int array[10];\n"
  2827. " int const & operator [] (unsigned int index) { return array[index]; }\n"
  2828. "};");
  2829. ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::operator[]' can be const.\n", errout.str());
  2830. }
  2831. void constoperator4() {
  2832. checkConst("struct Fred {\n"
  2833. " int array[10];\n"
  2834. " typedef int* (Fred::*UnspecifiedBoolType);\n"
  2835. " operator UnspecifiedBoolType() { };\n"
  2836. "};");
  2837. ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'Fred::operatorint**' can be const.\n", errout.str());
  2838. checkConst("struct Fred {\n"
  2839. " int array[10];\n"
  2840. " typedef int* (Fred::*UnspecifiedBoolType);\n"
  2841. " operator UnspecifiedBoolType() { array[0] = 0; };\n"
  2842. "};");
  2843. ASSERT_EQUALS("", errout.str());
  2844. }
  2845. void constoperator5() { // ticket #3252
  2846. checkConst("class A {\n"
  2847. " int c;\n"
  2848. "public:\n"
  2849. " operator int& () {return c}\n"
  2850. "};");
  2851. ASSERT_EQUALS("", errout.str());
  2852. checkConst("class A {\n"
  2853. " int c;\n"
  2854. "public:\n"
  2855. " operator const int& () {return c}\n"
  2856. "};");
  2857. ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'A::operatorconstint&' can be const.\n", errout.str());
  2858. checkConst("class A {\n"
  2859. " int c;\n"
  2860. "public:\n"
  2861. " operator int () {return c}\n"
  2862. "};");
  2863. ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'A::operatorint' can be const.\n", errout.str());
  2864. }
  2865. void const5() {
  2866. // ticket #1482
  2867. checkConst("class A {\n"
  2868. " int a;\n"
  2869. " bool foo(int i)\n"
  2870. " {\n"
  2871. " bool same;\n"
  2872. " same = (i == a);\n"
  2873. " return same;\n"
  2874. " }\n"
  2875. "};");
  2876. ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'A::foo' can be const.\n", errout.str());
  2877. }
  2878. void const6() {
  2879. // ticket #1491
  2880. checkConst("class foo {\n"
  2881. "public:\n"
  2882. "};\n"
  2883. "void bar() {}");
  2884. ASSERT_EQUALS("", errout.str());
  2885. checkConst("class Fred\n"
  2886. "{\n"
  2887. "public:\n"
  2888. " void foo() { }\n"
  2889. "};");
  2890. ASSERT_EQUALS("[test.cpp:4]: (performance, inconclusive) Technically the member function 'Fred::foo' can be static.\n", errout.str());
  2891. checkConst("struct fast_string\n"
  2892. "{\n"
  2893. " union\n"
  2894. " {\n"
  2895. " char buff[100];\n"
  2896. " };\n"
  2897. " void set_type(char t);\n"
  2898. "};\n"
  2899. "inline void fast_string::set_type(char t)\n"
  2900. "{\n"
  2901. " buff[10] = t;\n"
  2902. "}");
  2903. ASSERT_EQUALS("", errout.str());
  2904. }
  2905. void const7() {
  2906. checkConst("class foo {\n"
  2907. " int a;\n"
  2908. "public:\n"
  2909. " void set(int i) { a = i; }\n"
  2910. " void set(const foo & f) { *this = f; }\n"
  2911. "};\n"
  2912. "void bar() {}");
  2913. ASSERT_EQUALS("", errout.str());
  2914. }
  2915. void const8() {
  2916. // ticket #1517
  2917. checkConst("class A {\n"
  2918. "public:\n"
  2919. " A():m_strValue(\"\"){}\n"
  2920. " std::string strGetString() { return m_strValue; }\n"
  2921. "private:\n"
  2922. " std::string m_strValue;\n"
  2923. "};");
  2924. ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'A::strGetString' can be const.\n", errout.str());
  2925. }
  2926. void const9() {
  2927. // ticket #1515
  2928. checkConst("class wxThreadInternal {\n"
  2929. "public:\n"
  2930. " void SetExitCode(wxThread::ExitCode exitcode) { m_exitcode = exitcode; }\n"
  2931. "private:\n"
  2932. " wxThread::ExitCode m_exitcode;\n"
  2933. "};");
  2934. ASSERT_EQUALS("", errout.str());
  2935. }
  2936. void const10() {
  2937. // ticket #1522
  2938. checkConst("class A {\n"
  2939. "public:\n"
  2940. " int foo() { return x = 0; }\n"
  2941. "private:\n"
  2942. " int x;\n"
  2943. "};");
  2944. ASSERT_EQUALS("", errout.str());
  2945. checkConst("class A {\n"
  2946. "public:\n"
  2947. " int foo() { return x ? x : x = 0; }\n"
  2948. "private:\n"
  2949. " int x;\n"
  2950. "};");
  2951. ASSERT_EQUALS("", errout.str());
  2952. checkConst("class A {\n"
  2953. "public:\n"
  2954. " int foo() { return x ? x = 0 : x; }\n"
  2955. "private:\n"
  2956. " int x;\n"
  2957. "};");
  2958. ASSERT_EQUALS("", errout.str());
  2959. }
  2960. void const11() {
  2961. // ticket #1529
  2962. checkConst("class A {\n"
  2963. "public:\n"
  2964. " void set(struct tm time) { m_time = time; }\n"
  2965. "private:\n"
  2966. " struct tm m_time;\n"
  2967. "};");
  2968. ASSERT_EQUALS("", errout.str());
  2969. }
  2970. void const12() {
  2971. // ticket #1525
  2972. checkConst("class A {\n"
  2973. "public:\n"
  2974. " int foo() { x = 0; }\n"
  2975. "private:\n"
  2976. " mutable int x;\n"
  2977. "};");
  2978. ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'A::foo' can be const.\n", errout.str());
  2979. }
  2980. void const13() {
  2981. // ticket #1519
  2982. checkConst("class A {\n"
  2983. "public:\n"
  2984. " A(){}\n"
  2985. " std::vector<int> GetVec() {return m_vec;}\n"
  2986. " std::pair<int,double> GetPair() {return m_pair;}\n"
  2987. "private:\n"
  2988. " std::vector<int> m_vec;\n"
  2989. " std::pair<int,double> m_pair;\n"
  2990. "};");
  2991. ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'A::GetVec' can be const.\n"
  2992. "[test.cpp:5]: (style, inconclusive) Technically the member function 'A::GetPair' can be const.\n", errout.str());
  2993. checkConst("class A {\n"
  2994. "public:\n"
  2995. " A(){}\n"
  2996. " const std::vector<int> & GetVec() {return m_vec;}\n"
  2997. " const std::pair<int,double> & GetPair() {return m_pair;}\n"
  2998. "private:\n"
  2999. " std::vector<int> m_vec;\n"
  3000. " std::pair<int,double> m_pair;\n"
  3001. "};");
  3002. ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'A::GetVec' can be const.\n"
  3003. "[test.cpp:5]: (style, inconclusive) Technically the member function 'A::GetPair' can be const.\n", errout.str());
  3004. }
  3005. void const14() {
  3006. // extends ticket 1519
  3007. checkConst("class A {\n"
  3008. "public:\n"
  3009. " A(){}\n"
  3010. " std::pair<std::vector<int>,double> GetPair() {return m_pair;}\n"
  3011. "private:\n"
  3012. " std::pair<std::vector<int>,double> m_pair;\n"
  3013. "};");
  3014. ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'A::GetPair' can be const.\n", errout.str());
  3015. checkConst("class A {\n"
  3016. "public:\n"
  3017. " A(){}\n"
  3018. " const std::pair<std::vector<int>,double>& GetPair() {return m_pair;}\n"
  3019. "private:\n"
  3020. " std::pair<std::vector<int>,double> m_pair;\n"
  3021. "};");
  3022. ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'A::GetPair' can be const.\n", errout.str());
  3023. checkConst("class A {\n"
  3024. "public:\n"
  3025. " A(){}\n"
  3026. " std::pair<std::vector<int>,double>& GetPair() {return m_pair;}\n"
  3027. "private:\n"
  3028. " std::pair<std::vector<int>,double> m_pair;\n"
  3029. "};");
  3030. ASSERT_EQUALS("", errout.str());
  3031. checkConst("using namespace std;"
  3032. "class A {\n"
  3033. "public:\n"
  3034. " A(){}\n"
  3035. " pair<int ,double> GetPair() {return m_pair;}\n"
  3036. "private:\n"
  3037. " pair<int ,double> m_pair;\n"
  3038. "};");
  3039. ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'A::GetPair' can be const.\n", errout.str());
  3040. checkConst("using namespace std;"
  3041. "class A {\n"
  3042. "public:\n"
  3043. " A(){}\n"
  3044. " const pair<int ,double> & GetPair() {return m_pair;}\n"
  3045. "private:\n"
  3046. " pair<int ,double> m_pair;\n"
  3047. "};");
  3048. ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'A::GetPair' can be const.\n", errout.str());
  3049. checkConst("using namespace std;"
  3050. "class A {\n"
  3051. "public:\n"
  3052. " A(){}\n"
  3053. " pair<int ,double> & GetPair() {return m_pair;}\n"
  3054. "private:\n"
  3055. " pair<int ,double> m_pair;\n"
  3056. "};");
  3057. ASSERT_EQUALS("", errout.str());
  3058. checkConst("class A {\n"
  3059. "public:\n"
  3060. " A(){}\n"
  3061. " std::pair< int,std::vector<int> > GetPair() {return m_pair;}\n"
  3062. "private:\n"
  3063. " std::pair< int,std::vector<int> > m_pair;\n"
  3064. "};");
  3065. ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'A::GetPair' can be const.\n", errout.str());
  3066. checkConst("class A {\n"
  3067. "public:\n"
  3068. " A(){}\n"
  3069. " const std::pair< int,std::vector<int> >& GetPair() {return m_pair;}\n"
  3070. "private:\n"
  3071. " std::pair< int,std::vector<int> > m_pair;\n"
  3072. "};");
  3073. ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'A::GetPair' can be const.\n", errout.str());
  3074. checkConst("class A {\n"
  3075. "public:\n"
  3076. " A(){}\n"
  3077. " std::pair< int,std::vector<int> >& GetPair() {return m_pair;}\n"
  3078. "private:\n"
  3079. " std::pair< int,std::vector<int> > m_pair;\n"
  3080. "};");
  3081. ASSERT_EQUALS("", errout.str());
  3082. checkConst("using namespace std;"
  3083. "class A {\n"
  3084. "public:\n"
  3085. " A(){}\n"
  3086. " pair< vector<int>, int > GetPair() {return m_pair;}\n"
  3087. "private:\n"
  3088. " pair< vector<int>, int > m_pair;\n"
  3089. "};");
  3090. ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'A::GetPair' can be const.\n", errout.str());
  3091. checkConst("using namespace std;"
  3092. "class A {\n"
  3093. "public:\n"
  3094. " A(){}\n"
  3095. " const pair< vector<int>, int >& GetPair() {return m_pair;}\n"
  3096. "private:\n"
  3097. " pair< vector<int>, int > m_pair;\n"
  3098. "};");
  3099. ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'A::GetPair' can be const.\n", errout.str());
  3100. checkConst("using namespace std;"
  3101. "class A {\n"
  3102. "public:\n"
  3103. " A(){}\n"
  3104. " pair< vector<int>, int >& GetPair() {return m_pair;}\n"
  3105. "private:\n"
  3106. " pair< vector<int>, int > m_pair;\n"
  3107. "};");
  3108. ASSERT_EQUALS("", errout.str());
  3109. checkConst("class A {\n"
  3110. "public:\n"
  3111. " A(){}\n"
  3112. " std::pair< std::vector<int>,std::vector<int> > GetPair() {return m_pair;}\n"
  3113. "private:\n"
  3114. " std::pair< std::vector<int>,std::vector<int> > m_pair;\n"
  3115. "};");
  3116. ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'A::GetPair' can be const.\n", errout.str());
  3117. checkConst("class A {\n"
  3118. "public:\n"
  3119. " A(){}\n"
  3120. " const std::pair< std::vector<int>,std::vector<int> >& GetPair() {return m_pair;}\n"
  3121. "private:\n"
  3122. " std::pair< std::vector<int>,std::vector<int> > m_pair;\n"
  3123. "};");
  3124. ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'A::GetPair' can be const.\n", errout.str());
  3125. checkConst("class A {\n"
  3126. "public:\n"
  3127. " A(){}\n"
  3128. " std::pair< std::vector<int>,std::vector<int> >& GetPair() {return m_pair;}\n"
  3129. "private:\n"
  3130. " std::pair< std::vector<int>,std::vector<int> > m_pair;\n"
  3131. "};");
  3132. ASSERT_EQUALS("", errout.str());
  3133. checkConst("class A {\n"
  3134. "public:\n"
  3135. " A(){}\n"
  3136. " std::pair< std::pair < int, char > , int > GetPair() {return m_pair;}\n"
  3137. "private:\n"
  3138. " std::pair< std::pair < int, char > , int > m_pair;\n"
  3139. "};");
  3140. ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'A::GetPair' can be const.\n", errout.str());
  3141. checkConst("class A {\n"
  3142. "public:\n"
  3143. " A(){}\n"
  3144. " const std::pair< std::pair < int, char > , int > & GetPair() {return m_pair;}\n"
  3145. "private:\n"
  3146. " std::pair< std::pair < int, char > , int > m_pair;\n"
  3147. "};");
  3148. ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'A::GetPair' can be const.\n", errout.str());
  3149. checkConst("class A {\n"
  3150. "public:\n"
  3151. " A(){}\n"
  3152. " std::pair< std::pair < int, char > , int > & GetPair() {return m_pair;}\n"
  3153. "private:\n"
  3154. " std::pair< std::pair < int, char > , int > m_pair;\n"
  3155. "};");
  3156. ASSERT_EQUALS("", errout.str());
  3157. checkConst("class A {\n"
  3158. "public:\n"
  3159. " A(){}\n"
  3160. " std::pair< int , std::pair < int, char > > GetPair() {return m_pair;}\n"
  3161. "private:\n"
  3162. " std::pair< int , std::pair < int, char > > m_pair;\n"
  3163. "};");
  3164. ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'A::GetPair' can be const.\n", errout.str());
  3165. checkConst("class A {\n"
  3166. "public:\n"
  3167. " A(){}\n"
  3168. " const std::pair< int , std::pair < int, char > >& GetPair() {return m_pair;}\n"
  3169. "private:\n"
  3170. " std::pair< int , std::pair < int, char > > m_pair;\n"
  3171. "};");
  3172. ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'A::GetPair' can be const.\n", errout.str());
  3173. checkConst("class A {\n"
  3174. "public:\n"
  3175. " A(){}\n"
  3176. " std::pair< int , std::pair < int, char > >& GetPair() {return m_pair;}\n"
  3177. "private:\n"
  3178. " std::pair< int , std::pair < int, char > > m_pair;\n"
  3179. "};");
  3180. ASSERT_EQUALS("", errout.str());
  3181. checkConst("using namespace std;"
  3182. "class A {\n"
  3183. "public:\n"
  3184. " A(){}\n"
  3185. " vector<int> GetVec() {return m_Vec;}\n"
  3186. "private:\n"
  3187. " vector<int> m_Vec;\n"
  3188. "};");
  3189. ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'A::GetVec' can be const.\n", errout.str());
  3190. checkConst("using namespace std;"
  3191. "class A {\n"
  3192. "public:\n"
  3193. " A(){}\n"
  3194. " const vector<int>& GetVec() {return m_Vec;}\n"
  3195. "private:\n"
  3196. " vector<int> m_Vec;\n"
  3197. "};");
  3198. ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'A::GetVec' can be const.\n", errout.str());
  3199. checkConst("using namespace std;"
  3200. "class A {\n"
  3201. "public:\n"
  3202. " A(){}\n"
  3203. " vector<int>& GetVec() {return m_Vec;}\n"
  3204. "private:\n"
  3205. " vector<int> m_Vec;\n"
  3206. "};");
  3207. ASSERT_EQUALS("", errout.str());
  3208. checkConst("class A {\n"
  3209. "public:\n"
  3210. " int * * foo() { return &x; }\n"
  3211. "private:\n"
  3212. " const int * x;\n"
  3213. "};");
  3214. ASSERT_EQUALS("", errout.str());
  3215. checkConst("class A {\n"
  3216. "public:\n"
  3217. " const int ** foo() { return &x; }\n"
  3218. "private:\n"
  3219. " const int * x;\n"
  3220. "};");
  3221. ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'A::foo' can be const.\n", errout.str());
  3222. }
  3223. void const15() {
  3224. checkConst("class Fred {\n"
  3225. " unsigned long long int a;\n"
  3226. " unsigned long long int getA() { return a; }\n"
  3227. "};");
  3228. ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::getA' can be const.\n", errout.str());
  3229. // constructors can't be const..
  3230. checkConst("class Fred {\n"
  3231. " unsigned long long int a;\n"
  3232. "public:\n"
  3233. " Fred() { }\n"
  3234. "};");
  3235. ASSERT_EQUALS("", errout.str());
  3236. // assignment through |=..
  3237. checkConst("class Fred {\n"
  3238. " unsigned long long int a;\n"
  3239. " unsigned long long int setA() { a |= true; }\n"
  3240. "};");
  3241. ASSERT_EQUALS("", errout.str());
  3242. // static functions can't be const..
  3243. checkConst("class foo\n"
  3244. "{\n"
  3245. "public:\n"
  3246. " static unsigned long long int get()\n"
  3247. " { return 0; }\n"
  3248. "};");
  3249. ASSERT_EQUALS("", errout.str());
  3250. }
  3251. void const16() {
  3252. // ticket #1551
  3253. checkConst("class Fred {\n"
  3254. " int a;\n"
  3255. " void set(int i) { Fred::a = i; }\n"
  3256. "};");
  3257. ASSERT_EQUALS("", errout.str());
  3258. }
  3259. void const17() {
  3260. // ticket #1552
  3261. checkConst("class Fred {\n"
  3262. "public:\n"
  3263. " void set(int i, int j) { a[i].k = i; }\n"
  3264. "private:\n"
  3265. " struct { int k; } a[4];\n"
  3266. "};");
  3267. ASSERT_EQUALS("", errout.str());
  3268. }
  3269. void const18() {
  3270. checkConst("class Fred {\n"
  3271. "static int x;\n"
  3272. "public:\n"
  3273. " void set(int i) { x = i; }\n"
  3274. "};");
  3275. ASSERT_EQUALS("[test.cpp:4]: (performance, inconclusive) Technically the member function 'Fred::set' can be static.\n", errout.str());
  3276. }
  3277. void const19() {
  3278. // ticket #1612
  3279. checkConst("using namespace std;\n"
  3280. "class Fred {\n"
  3281. "private:\n"
  3282. " std::string s;\n"
  3283. "public:\n"
  3284. " void set(std::string ss) { s = ss; }\n"
  3285. "};");
  3286. ASSERT_EQUALS("", errout.str());
  3287. }
  3288. void const20() {
  3289. // ticket #1602
  3290. checkConst("class Fred {\n"
  3291. " int x : 3;\n"
  3292. "public:\n"
  3293. " void set(int i) { x = i; }\n"
  3294. "};");
  3295. ASSERT_EQUALS("", errout.str());
  3296. checkConst("class Fred {\n"
  3297. " list<int *> x;\n"
  3298. "public:\n"
  3299. " list<int *> get() { return x; }\n"
  3300. "};");
  3301. ASSERT_EQUALS("", errout.str());
  3302. checkConst("class Fred {\n"
  3303. " list<const int *> x;\n"
  3304. "public:\n"
  3305. " list<const int *> get() { return x; }\n"
  3306. "};");
  3307. ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'Fred::get' can be const.\n", errout.str());
  3308. checkConst("class Fred {\n"
  3309. " std::list<std::string &> x;\n"
  3310. "public:\n"
  3311. " std::list<std::string &> get() { return x; }\n"
  3312. "};");
  3313. ASSERT_EQUALS("", errout.str());
  3314. checkConst("class Fred {\n"
  3315. " std::list<const std::string &> x;\n"
  3316. "public:\n"
  3317. " std::list<const std::string &> get() { return x; }\n"
  3318. "};");
  3319. ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'Fred::get' can be const.\n", errout.str());
  3320. }
  3321. void const21() {
  3322. // ticket #1683
  3323. checkConst("class A\n"
  3324. "{\n"
  3325. "private:\n"
  3326. " const char * l1[10];\n"
  3327. "public:\n"
  3328. " A()\n"
  3329. " {\n"
  3330. " for (int i = 0 ; i < 10; l1[i] = NULL, i++);\n"
  3331. " }\n"
  3332. " void f1() { l1[0] = \"Hello\"; }\n"
  3333. "};");
  3334. ASSERT_EQUALS("", errout.str());
  3335. }
  3336. void const22() {
  3337. checkConst("class A\n"
  3338. "{\n"
  3339. "private:\n"
  3340. " B::C * v1;\n"
  3341. "public:\n"
  3342. " void f1() { v1 = 0; }\n"
  3343. "};");
  3344. ASSERT_EQUALS("", errout.str());
  3345. checkConst("class A\n"
  3346. "{\n"
  3347. "private:\n"
  3348. " B::C * v1[0];\n"
  3349. "public:\n"
  3350. " void f1() { v1[0] = 0; }\n"
  3351. "};");
  3352. ASSERT_EQUALS("", errout.str());
  3353. }
  3354. void const23() {
  3355. checkConst("class Class {\n"
  3356. "public:\n"
  3357. " typedef Template<double> Type;\n"
  3358. " typedef Template2<Type> Type2;\n"
  3359. " void set_member(Type2 m) { _m = m; }\n"
  3360. "private:\n"
  3361. " Type2 _m;\n"
  3362. "};");
  3363. ASSERT_EQUALS("", errout.str());
  3364. }
  3365. void const24() {
  3366. checkConst("class Class {\n"
  3367. "public:\n"
  3368. "void Settings::SetSetting(QString strSetting, QString strNewVal)\n"
  3369. "{\n"
  3370. " (*m_pSettings)[strSetting] = strNewVal;\n"
  3371. "}\n"
  3372. "private:\n"
  3373. " std::map<QString, QString> *m_pSettings;\n"
  3374. "};");
  3375. ASSERT_EQUALS("", errout.str());
  3376. }
  3377. void const25() { // ticket #1724
  3378. checkConst("class A{\n"
  3379. "public:\n"
  3380. "A(){m_strVal=\"\";}\n"
  3381. "std::string strGetString() const\n"
  3382. "{return m_strVal.c_str();}\n"
  3383. "const std::string strGetString1() const\n"
  3384. "{return m_strVal.c_str();}\n"
  3385. "private:\n"
  3386. "std::string m_strVal;\n"
  3387. "};\n"
  3388. );
  3389. ASSERT_EQUALS("", errout.str());
  3390. checkConst("class A{\n"
  3391. "public:\n"
  3392. "A(){m_strVal=\"\";}\n"
  3393. "std::string strGetString()\n"
  3394. "{return m_strVal.c_str();}\n"
  3395. "private:\n"
  3396. "std::string m_strVal;\n"
  3397. "};\n"
  3398. );
  3399. ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'A::strGetString' can be const.\n", errout.str());
  3400. checkConst("class A{\n"
  3401. "public:\n"
  3402. "A(){m_strVal=\"\";}\n"
  3403. "const std::string strGetString1()\n"
  3404. "{return m_strVal.c_str();}\n"
  3405. "private:\n"
  3406. "std::string m_strVal;\n"
  3407. "};\n"
  3408. );
  3409. ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'A::strGetString1' can be const.\n", errout.str());
  3410. checkConst("class A{\n"
  3411. "public:\n"
  3412. "A(){m_strVec.push_back(\"\");}\n"
  3413. "size_t strGetSize()\n"
  3414. "{return m_strVec.size();}\n"
  3415. "private:\n"
  3416. "std::vector<std::string> m_strVec;\n"
  3417. "};\n"
  3418. );
  3419. ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'A::strGetSize' can be const.\n", errout.str());
  3420. checkConst("class A{\n"
  3421. "public:\n"
  3422. "A(){m_strVec.push_back(\"\");}\n"
  3423. "bool strGetEmpty()\n"
  3424. "{return m_strVec.empty();}\n"
  3425. "private:\n"
  3426. "std::vector<std::string> m_strVec;\n"
  3427. "};\n"
  3428. );
  3429. ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'A::strGetEmpty' can be const.\n", errout.str());
  3430. }
  3431. void const26() { // ticket #1847
  3432. checkConst("class DelayBase {\n"
  3433. "public:\n"
  3434. "void swapSpecificDelays(int index1, int index2) {\n"
  3435. " std::swap<float>(delays_[index1], delays_[index2]);\n"
  3436. "}\n"
  3437. "float delays_[4];\n"
  3438. "};\n"
  3439. );
  3440. ASSERT_EQUALS("", errout.str());
  3441. checkConst("struct DelayBase {\n"
  3442. " float swapSpecificDelays(int index1) {\n"
  3443. " return delays_[index1];\n"
  3444. " }\n"
  3445. " float delays_[4];\n"
  3446. "};");
  3447. ASSERT_EQUALS("[test.cpp:2]: (style, inconclusive) Technically the member function 'DelayBase::swapSpecificDelays' can be const.\n", errout.str());
  3448. }
  3449. void const27() { // ticket #1882
  3450. checkConst("class A {\n"
  3451. "public:\n"
  3452. " A(){m_d=1.0; m_iRealVal=2.0;}\n"
  3453. " double dGetValue();\n"
  3454. "private:\n"
  3455. " double m_d;\n"
  3456. " double m_iRealVal;\n"
  3457. "};\n"
  3458. "double A::dGetValue() {\n"
  3459. " double dRet = m_iRealVal;\n"
  3460. " if( m_d != 0 )\n"
  3461. " return m_iRealVal / m_d;\n"
  3462. " return dRet;\n"
  3463. "};\n"
  3464. );
  3465. ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:4]: (style, inconclusive) Technically the member function 'A::dGetValue' can be const.\n", errout.str());
  3466. }
  3467. void const28() { // ticket #1883
  3468. checkConst("class P {\n"
  3469. "public:\n"
  3470. " P() { x=0.0; y=0.0; }\n"
  3471. " double x,y;\n"
  3472. "};\n"
  3473. "class A : public P {\n"
  3474. "public:\n"
  3475. " A():P(){}\n"
  3476. " void SetPos(double xPos, double yPos) {\n"
  3477. " x=xPos;\n"
  3478. " y=yPos;\n"
  3479. " }\n"
  3480. "};\n"
  3481. );
  3482. ASSERT_EQUALS("", errout.str());
  3483. checkConst("class AA : public P {\n"
  3484. "public:\n"
  3485. " AA():P(){}\n"
  3486. " inline void vSetXPos(int x_)\n"
  3487. " {\n"
  3488. " UnknownScope::x = x_;\n"
  3489. " }\n"
  3490. "};");
  3491. ASSERT_EQUALS("", errout.str());
  3492. checkConst("class AA {\n"
  3493. "public:\n"
  3494. " AA():P(){}\n"
  3495. " inline void vSetXPos(int x_)\n"
  3496. " {\n"
  3497. " UnknownScope::x = x_;\n"
  3498. " }\n"
  3499. "};");
  3500. ASSERT_EQUALS("[test.cpp:4]: (performance, inconclusive) Technically the member function 'AA::vSetXPos' can be static.\n", errout.str());
  3501. }
  3502. void const29() { // ticket #1922
  3503. checkConst("class test {\n"
  3504. " public:\n"
  3505. " test();\n"
  3506. " const char* get() const;\n"
  3507. " char* get();\n"
  3508. " private:\n"
  3509. " char* value_;\n"
  3510. "};\n"
  3511. "test::test()\n"
  3512. "{\n"
  3513. " value_ = 0;\n"
  3514. "}\n"
  3515. "const char* test::get() const\n"
  3516. "{\n"
  3517. " return value_;\n"
  3518. "}\n"
  3519. "char* test::get()\n"
  3520. "{\n"
  3521. " return value_;\n"
  3522. "}");
  3523. ASSERT_EQUALS("", errout.str());
  3524. }
  3525. void const30() {
  3526. // check for false negatives
  3527. checkConst("class Base {\n"
  3528. "public:\n"
  3529. " int a;\n"
  3530. "};\n"
  3531. "class Derived : public Base {\n"
  3532. "public:\n"
  3533. " int get() {\n"
  3534. " return a;\n"
  3535. " }\n"
  3536. "};");
  3537. ASSERT_EQUALS("[test.cpp:7]: (style, inconclusive) Technically the member function 'Derived::get' can be const.\n", errout.str());
  3538. checkConst("class Base1 {\n"
  3539. "public:\n"
  3540. " int a;\n"
  3541. "};\n"
  3542. "class Base2 {\n"
  3543. "public:\n"
  3544. " int b;\n"
  3545. "};\n"
  3546. "class Derived : public Base1, public Base2 {\n"
  3547. "public:\n"
  3548. " int getA() {\n"
  3549. " return a;\n"
  3550. " }\n"
  3551. " int getB() {\n"
  3552. " return b;\n"
  3553. " }\n"
  3554. "};");
  3555. ASSERT_EQUALS("[test.cpp:11]: (style, inconclusive) Technically the member function 'Derived::getA' can be const.\n"
  3556. "[test.cpp:14]: (style, inconclusive) Technically the member function 'Derived::getB' can be const.\n", errout.str());
  3557. checkConst("class Base {\n"
  3558. "public:\n"
  3559. " int a;\n"
  3560. "};\n"
  3561. "class Derived1 : public Base { };\n"
  3562. "class Derived2 : public Derived1 {\n"
  3563. "public:\n"
  3564. " int get() {\n"
  3565. " return a;\n"
  3566. " }\n"
  3567. "};");
  3568. ASSERT_EQUALS("[test.cpp:8]: (style, inconclusive) Technically the member function 'Derived2::get' can be const.\n", errout.str());
  3569. checkConst("class Base {\n"
  3570. "public:\n"
  3571. " int a;\n"
  3572. "};\n"
  3573. "class Derived1 : public Base { };\n"
  3574. "class Derived2 : public Derived1 { };\n"
  3575. "class Derived3 : public Derived2 { };\n"
  3576. "class Derived4 : public Derived3 {\n"
  3577. "public:\n"
  3578. " int get() {\n"
  3579. " return a;\n"
  3580. " }\n"
  3581. "};");
  3582. ASSERT_EQUALS("[test.cpp:10]: (style, inconclusive) Technically the member function 'Derived4::get' can be const.\n", errout.str());
  3583. // check for false positives
  3584. checkConst("class Base {\n"
  3585. "public:\n"
  3586. " int a;\n"
  3587. "};\n"
  3588. "class Derived : public Base {\n"
  3589. "public:\n"
  3590. " int get() const {\n"
  3591. " return a;\n"
  3592. " }\n"
  3593. "};");
  3594. ASSERT_EQUALS("", errout.str());
  3595. checkConst("class Base1 {\n"
  3596. "public:\n"
  3597. " int a;\n"
  3598. "};\n"
  3599. "class Base2 {\n"
  3600. "public:\n"
  3601. " int b;\n"
  3602. "};\n"
  3603. "class Derived : public Base1, public Base2 {\n"
  3604. "public:\n"
  3605. " int getA() const {\n"
  3606. " return a;\n"
  3607. " }\n"
  3608. " int getB() const {\n"
  3609. " return b;\n"
  3610. " }\n"
  3611. "};");
  3612. ASSERT_EQUALS("", errout.str());
  3613. checkConst("class Base {\n"
  3614. "public:\n"
  3615. " int a;\n"
  3616. "};\n"
  3617. "class Derived1 : public Base { };\n"
  3618. "class Derived2 : public Derived1 {\n"
  3619. "public:\n"
  3620. " int get() const {\n"
  3621. " return a;\n"
  3622. " }\n"
  3623. "};");
  3624. ASSERT_EQUALS("", errout.str());
  3625. checkConst("class Base {\n"
  3626. "public:\n"
  3627. " int a;\n"
  3628. "};\n"
  3629. "class Derived1 : public Base { };\n"
  3630. "class Derived2 : public Derived1 { };\n"
  3631. "class Derived3 : public Derived2 { };\n"
  3632. "class Derived4 : public Derived3 {\n"
  3633. "public:\n"
  3634. " int get() const {\n"
  3635. " return a;\n"
  3636. " }\n"
  3637. "};");
  3638. ASSERT_EQUALS("", errout.str());
  3639. }
  3640. void const31() {
  3641. checkConst("namespace std { }\n"
  3642. "class Fred {\n"
  3643. "public:\n"
  3644. " int a;\n"
  3645. " int get() { return a; }\n"
  3646. "};");
  3647. ASSERT_EQUALS("[test.cpp:5]: (style, inconclusive) Technically the member function 'Fred::get' can be const.\n", errout.str());
  3648. }
  3649. void const32() {
  3650. checkConst("class Fred {\n"
  3651. "public:\n"
  3652. " std::string a[10];\n"
  3653. " void seta() { a[0] = \"\"; }\n"
  3654. "};");
  3655. ASSERT_EQUALS("", errout.str());
  3656. }
  3657. void const33() {
  3658. checkConst("class derived : public base {\n"
  3659. "public:\n"
  3660. " void f(){}\n"
  3661. "};");
  3662. ASSERT_EQUALS("", errout.str());
  3663. }
  3664. void const34() { // ticket #1964
  3665. checkConst("class Bar {\n"
  3666. " void init(Foo * foo) {\n"
  3667. " foo.bar = this;\n"
  3668. " }\n"
  3669. "};");
  3670. ASSERT_EQUALS("", errout.str());
  3671. }
  3672. void const35() { // ticket #2001
  3673. checkConst("namespace N\n"
  3674. "{\n"
  3675. " class Base\n"
  3676. " {\n"
  3677. " };\n"
  3678. "}\n"
  3679. "namespace N\n"
  3680. "{\n"
  3681. " class Derived : public Base\n"
  3682. " {\n"
  3683. " public:\n"
  3684. " int getResourceName() { return var; }\n"
  3685. " int var;\n"
  3686. " };\n"
  3687. "}");
  3688. ASSERT_EQUALS("[test.cpp:12]: (style, inconclusive) Technically the member function 'N::Derived::getResourceName' can be const.\n", errout.str());
  3689. checkConst("namespace N\n"
  3690. "{\n"
  3691. " class Base\n"
  3692. " {\n"
  3693. " public:\n"
  3694. " int getResourceName();\n"
  3695. " int var;\n"
  3696. " };\n"
  3697. "}\n"
  3698. "int N::Base::getResourceName() { return var; }");
  3699. ASSERT_EQUALS("[test.cpp:10] -> [test.cpp:6]: (style, inconclusive) Technically the member function 'N::Base::getResourceName' can be const.\n", errout.str());
  3700. checkConst("namespace N\n"
  3701. "{\n"
  3702. " class Base\n"
  3703. " {\n"
  3704. " public:\n"
  3705. " int getResourceName();\n"
  3706. " int var;\n"
  3707. " };\n"
  3708. "}\n"
  3709. "namespace N\n"
  3710. "{\n"
  3711. " int Base::getResourceName() { return var; }\n"
  3712. "}");
  3713. ASSERT_EQUALS("[test.cpp:12] -> [test.cpp:6]: (style, inconclusive) Technically the member function 'N::Base::getResourceName' can be const.\n", errout.str());
  3714. checkConst("namespace N\n"
  3715. "{\n"
  3716. " class Base\n"
  3717. " {\n"
  3718. " public:\n"
  3719. " int getResourceName();\n"
  3720. " int var;\n"
  3721. " };\n"
  3722. "}\n"
  3723. "using namespace N;\n"
  3724. "int Base::getResourceName() { return var; }");
  3725. ASSERT_EQUALS("[test.cpp:11] -> [test.cpp:6]: (style, inconclusive) Technically the member function 'N::Base::getResourceName' can be const.\n", errout.str());
  3726. }
  3727. void const36() { // ticket #2003
  3728. checkConst("class Foo {\n"
  3729. "public:\n"
  3730. " Blue::Utility::Size m_MaxQueueSize;\n"
  3731. " void SetMaxQueueSize(Blue::Utility::Size a_MaxQueueSize)\n"
  3732. " {\n"
  3733. " m_MaxQueueSize = a_MaxQueueSize;\n"
  3734. " }\n"
  3735. "};");
  3736. ASSERT_EQUALS("", errout.str());
  3737. }
  3738. void const37() { // ticket #2081 and #2085
  3739. checkConst("class A\n"
  3740. "{\n"
  3741. "public:\n"
  3742. " A(){};\n"
  3743. " std::string operator+(const char *c)\n"
  3744. " {\n"
  3745. " return m_str+std::string(c);\n"
  3746. " }\n"
  3747. "private:\n"
  3748. " std::string m_str;\n"
  3749. "};");
  3750. ASSERT_EQUALS("[test.cpp:5]: (style, inconclusive) Technically the member function 'A::operator+' can be const.\n", errout.str());
  3751. checkConst("class Fred\n"
  3752. "{\n"
  3753. "private:\n"
  3754. " long x;\n"
  3755. "public:\n"
  3756. " Fred() {\n"
  3757. " x = 0;\n"
  3758. " }\n"
  3759. " bool isValid() {\n"
  3760. " return bool(x == 0x11224488);\n"
  3761. " }\n"
  3762. "};");
  3763. ASSERT_EQUALS("[test.cpp:9]: (style, inconclusive) Technically the member function 'Fred::isValid' can be const.\n", errout.str());
  3764. }
  3765. void const38() { // ticket #2135
  3766. checkConst("class Foo {\n"
  3767. "public:\n"
  3768. " ~Foo() { delete oArq; }\n"
  3769. " Foo(): oArq(new std::ofstream(\"...\")) {}\n"
  3770. " void MyMethod();\n"
  3771. "private:\n"
  3772. " std::ofstream *oArq;\n"
  3773. "};\n"
  3774. "void Foo::MyMethod()\n"
  3775. "{\n"
  3776. " (*oArq) << \"</table>\";\n"
  3777. "}");
  3778. ASSERT_EQUALS("", errout.str());
  3779. }
  3780. void const39() {
  3781. checkConst("class Foo\n"
  3782. "{\n"
  3783. " int * p;\n"
  3784. "public:\n"
  3785. " Foo () : p(0) { }\n"
  3786. " int * f();\n"
  3787. " const int * f() const;\n"
  3788. "};\n"
  3789. "const int * Foo::f() const\n"
  3790. "{\n"
  3791. " return p;\n"
  3792. "}\n"
  3793. "int * Foo::f()\n"
  3794. "{\n"
  3795. " return p;\n"
  3796. "}");
  3797. ASSERT_EQUALS("", errout.str());
  3798. }
  3799. void const40() { // ticket #2228
  3800. checkConst("class SharedPtrHolder\n"
  3801. "{\n"
  3802. " private:\n"
  3803. " std::tr1::shared_ptr<int> pView;\n"
  3804. " public:\n"
  3805. " SharedPtrHolder()\n"
  3806. " { }\n"
  3807. " void SetView(const std::shared_ptr<int> & aView)\n"
  3808. " {\n"
  3809. " pView = aView;\n"
  3810. " }\n"
  3811. "};");
  3812. ASSERT_EQUALS("", errout.str());
  3813. }
  3814. void const41() { // ticket #2255
  3815. checkConst("class Fred\n"
  3816. "{\n"
  3817. " ::std::string m_name;\n"
  3818. "public:\n"
  3819. " void SetName(const ::std::string & name)\n"
  3820. " {\n"
  3821. " m_name = name;\n"
  3822. " }\n"
  3823. "};");
  3824. ASSERT_EQUALS("", errout.str());
  3825. checkConst("class SharedPtrHolder\n"
  3826. "{\n"
  3827. " ::std::tr1::shared_ptr<int> pNum;\n"
  3828. " public :\n"
  3829. " void SetNum(const ::std::tr1::shared_ptr<int> & apNum)\n"
  3830. " {\n"
  3831. " pNum = apNum;\n"
  3832. " }\n"
  3833. "};");
  3834. ASSERT_EQUALS("", errout.str());
  3835. checkConst("class SharedPtrHolder2\n"
  3836. "{\n"
  3837. " public:\n"
  3838. " typedef ::std::tr1::shared_ptr<int> IntSharedPtr;\n"
  3839. " private:\n"
  3840. " IntSharedPtr pNum;\n"
  3841. " public :\n"
  3842. " void SetNum(const IntSharedPtr & apNum)\n"
  3843. " {\n"
  3844. " pNum = apNum;\n"
  3845. " }\n"
  3846. "};");
  3847. ASSERT_EQUALS("", errout.str());
  3848. checkConst("struct IntPtrTypes\n"
  3849. "{\n"
  3850. " typedef ::std::tr1::shared_ptr<int> Shared;\n"
  3851. "};\n"
  3852. "class SharedPtrHolder3\n"
  3853. "{\n"
  3854. " private:\n"
  3855. " IntPtrTypes::Shared pNum;\n"
  3856. " public :\n"
  3857. " void SetNum(const IntPtrTypes::Shared & apNum)\n"
  3858. " {\n"
  3859. " pNum = apNum;\n"
  3860. " }\n"
  3861. "};");
  3862. ASSERT_EQUALS("", errout.str());
  3863. checkConst("template <typename T>\n"
  3864. "struct PtrTypes\n"
  3865. "{\n"
  3866. " typedef ::std::tr1::shared_ptr<T> Shared;\n"
  3867. "};\n"
  3868. "class SharedPtrHolder4\n"
  3869. "{\n"
  3870. " private:\n"
  3871. " PtrTypes<int>::Shared pNum;\n"
  3872. " public :\n"
  3873. " void SetNum(const PtrTypes<int>::Shared & apNum)\n"
  3874. " {\n"
  3875. " pNum = apNum;\n"
  3876. " }\n"
  3877. "};");
  3878. ASSERT_EQUALS("", errout.str());
  3879. }
  3880. void const42() { // ticket #2282
  3881. checkConst("class Fred\n"
  3882. "{\n"
  3883. "public:\n"
  3884. " struct AB { };\n"
  3885. " bool f(AB * ab);\n"
  3886. "};\n"
  3887. "bool Fred::f(Fred::AB * ab)\n"
  3888. "{\n"
  3889. "}");
  3890. ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:5]: (performance, inconclusive) Technically the member function 'Fred::f' can be static.\n", errout.str());
  3891. checkConst("class Fred\n"
  3892. "{\n"
  3893. "public:\n"
  3894. " struct AB {\n"
  3895. " struct CD { };\n"
  3896. " };\n"
  3897. " bool f(AB::CD * cd);\n"
  3898. "};\n"
  3899. "bool Fred::f(Fred::AB::CD * cd)\n"
  3900. "{\n"
  3901. "}");
  3902. ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:7]: (performance, inconclusive) Technically the member function 'Fred::f' can be static.\n", errout.str());
  3903. checkConst("namespace NS {\n"
  3904. " class Fred\n"
  3905. " {\n"
  3906. " public:\n"
  3907. " struct AB {\n"
  3908. " struct CD { };\n"
  3909. " };\n"
  3910. " bool f(AB::CD * cd);\n"
  3911. " };\n"
  3912. " bool Fred::f(Fred::AB::CD * cd)\n"
  3913. " {\n"
  3914. " }\n"
  3915. "}");
  3916. ASSERT_EQUALS("[test.cpp:10] -> [test.cpp:8]: (performance, inconclusive) Technically the member function 'NS::Fred::f' can be static.\n", errout.str());
  3917. checkConst("namespace NS {\n"
  3918. " class Fred\n"
  3919. " {\n"
  3920. " public:\n"
  3921. " struct AB {\n"
  3922. " struct CD { };\n"
  3923. " };\n"
  3924. " bool f(AB::CD * cd);\n"
  3925. " };\n"
  3926. "}\n"
  3927. "bool NS::Fred::f(NS::Fred::AB::CD * cd)\n"
  3928. "{\n"
  3929. "}");
  3930. ASSERT_EQUALS("[test.cpp:11] -> [test.cpp:8]: (performance, inconclusive) Technically the member function 'NS::Fred::f' can be static.\n", errout.str());
  3931. checkConst("class Foo {\n"
  3932. " class Fred\n"
  3933. " {\n"
  3934. " public:\n"
  3935. " struct AB {\n"
  3936. " struct CD { };\n"
  3937. " };\n"
  3938. " bool f(AB::CD * cd);\n"
  3939. " };\n"
  3940. "};\n"
  3941. "bool Foo::Fred::f(Foo::Fred::AB::CD * cd)\n"
  3942. "{\n"
  3943. "}");
  3944. ASSERT_EQUALS("[test.cpp:11] -> [test.cpp:8]: (performance, inconclusive) Technically the member function 'Foo::Fred::f' can be static.\n", errout.str());
  3945. }
  3946. void const43() { // ticket 2377
  3947. checkConst("class A\n"
  3948. "{\n"
  3949. "public:\n"
  3950. " void foo( AA::BB::CC::DD b );\n"
  3951. " AA::BB::CC::DD a;\n"
  3952. "};\n"
  3953. "void A::foo( AA::BB::CC::DD b )\n"
  3954. "{\n"
  3955. " a = b;\n"
  3956. "}");
  3957. ASSERT_EQUALS("", errout.str());
  3958. checkConst("namespace AA\n"
  3959. "{\n"
  3960. " namespace BB\n"
  3961. " {\n"
  3962. " namespace CC\n"
  3963. " {\n"
  3964. " struct DD\n"
  3965. " {};\n"
  3966. " }\n"
  3967. " }\n"
  3968. "}\n"
  3969. "class A\n"
  3970. "{\n"
  3971. " public:\n"
  3972. "\n"
  3973. " AA::BB::CC::DD a;\n"
  3974. " void foo(AA::BB::CC::DD b)\n"
  3975. " {\n"
  3976. " a = b;\n"
  3977. " }\n"
  3978. "};");
  3979. ASSERT_EQUALS("", errout.str());
  3980. checkConst("namespace ZZ\n"
  3981. "{\n"
  3982. " namespace YY\n"
  3983. " {\n"
  3984. " struct XX\n"
  3985. " {};\n"
  3986. " }\n"
  3987. "}\n"
  3988. "class B\n"
  3989. "{\n"
  3990. " public:\n"
  3991. " ZZ::YY::XX a;\n"
  3992. " void foo(ZZ::YY::XX b)\n"
  3993. " {\n"
  3994. " a = b;\n"
  3995. " }\n"
  3996. "};");
  3997. ASSERT_EQUALS("", errout.str());
  3998. }
  3999. void const44() { // ticket 2595
  4000. checkConst("class A\n"
  4001. "{\n"
  4002. "public:\n"
  4003. " bool bOn;\n"
  4004. " bool foo()\n"
  4005. " {\n"
  4006. " return 0 != (bOn = bOn);\n"
  4007. " }\n"
  4008. "};");
  4009. ASSERT_EQUALS("", errout.str());
  4010. }
  4011. void const45() { // ticket 2664
  4012. checkConst("namespace wraps {\n"
  4013. " class BaseLayout {};\n"
  4014. "}\n"
  4015. "namespace tools {\n"
  4016. " class WorkspaceControl :\n"
  4017. " public wraps::BaseLayout\n"
  4018. " {\n"
  4019. " int toGrid(int _value)\n"
  4020. " {\n"
  4021. " }\n"
  4022. " };\n"
  4023. "}");
  4024. ASSERT_EQUALS("[test.cpp:8]: (performance, inconclusive) Technically the member function 'tools::WorkspaceControl::toGrid' can be static.\n", errout.str());
  4025. }
  4026. void const46() { // ticket 2663
  4027. checkConst("class Altren {\n"
  4028. "public:\n"
  4029. " int fun1() {\n"
  4030. " int a;\n"
  4031. " a++;\n"
  4032. " }\n"
  4033. " int fun2() {\n"
  4034. " b++;\n"
  4035. " }\n"
  4036. "};");
  4037. ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Altren::fun1' can be static.\n"
  4038. "[test.cpp:7]: (performance, inconclusive) Technically the member function 'Altren::fun2' can be static.\n", errout.str());
  4039. }
  4040. void const47() { // ticket 2670
  4041. checkConst("class Altren {\n"
  4042. "public:\n"
  4043. " void foo() { delete this; }\n"
  4044. " void foo(int i) const { }\n"
  4045. " void bar() { foo(); }\n"
  4046. "};");
  4047. ASSERT_EQUALS("[test.cpp:4]: (performance, inconclusive) Technically the member function 'Altren::foo' can be static.\n", errout.str());
  4048. checkConst("class Altren {\n"
  4049. "public:\n"
  4050. " void foo() { delete this; }\n"
  4051. " void foo(int i) const { }\n"
  4052. " void bar() { foo(1); }\n"
  4053. "};");
  4054. ASSERT_EQUALS("[test.cpp:4]: (performance, inconclusive) Technically the member function 'Altren::foo' can be static.\n"
  4055. "[test.cpp:5]: (style, inconclusive) Technically the member function 'Altren::bar' can be const.\n", errout.str());
  4056. }
  4057. void const48() { // ticket 2672
  4058. checkConst("class S0 {\n"
  4059. " class S1 {\n"
  4060. " class S2 {\n"
  4061. " class S3 {\n"
  4062. " class S4 { };\n"
  4063. " };\n"
  4064. " };\n"
  4065. " };\n"
  4066. "};\n"
  4067. "class TextIterator {\n"
  4068. " S0::S1::S2::S3::S4 mCurrent, mSave;\n"
  4069. "public:\n"
  4070. " bool setTagColour();\n"
  4071. "};\n"
  4072. "bool TextIterator::setTagColour() {\n"
  4073. " mSave = mCurrent;\n"
  4074. "}");
  4075. ASSERT_EQUALS("", errout.str());
  4076. }
  4077. void const49() { // ticket 2795
  4078. checkConst("class A {\n"
  4079. " private:\n"
  4080. " std::map<unsigned int,unsigned int> _hash;\n"
  4081. " public:\n"
  4082. " A() : _hash() {}\n"
  4083. " unsigned int fetch(unsigned int key)\n" // cannot be 'const'
  4084. " {\n"
  4085. " return _hash[key];\n"
  4086. " }\n"
  4087. "};");
  4088. ASSERT_EQUALS("", errout.str());
  4089. }
  4090. void const50() { // ticket 2943
  4091. checkConst("class Altren\n"
  4092. "{\n"
  4093. " class SubClass : public std::vector<int>\n"
  4094. " {\n"
  4095. " };\n"
  4096. "};\n"
  4097. "void _setAlign()\n"
  4098. "{\n"
  4099. " if (mTileSize.height > 0) return;\n"
  4100. " if (mEmptyView) return;\n"
  4101. "}");
  4102. ASSERT_EQUALS("", errout.str());
  4103. }
  4104. void const51() { // ticket 3040
  4105. checkConst("class PSIPTable {\n"
  4106. "public:\n"
  4107. " PSIPTable() : _pesdata(0) { }\n"
  4108. " const unsigned char* pesdata() const { return _pesdata; }\n"
  4109. " unsigned char* pesdata() { return _pesdata; }\n"
  4110. " void SetSection(uint num) { pesdata()[6] = num; }\n"
  4111. "private:\n"
  4112. " unsigned char *_pesdata;\n"
  4113. "};");
  4114. ASSERT_EQUALS("", errout.str());
  4115. checkConst("class PESPacket {\n"
  4116. "public:\n"
  4117. " PESPacket() : _pesdata(0) { }\n"
  4118. " const unsigned char* pesdata() const { return _pesdata; }\n"
  4119. " unsigned char* pesdata() { return _pesdata; }\n"
  4120. "private:\n"
  4121. " unsigned char *_pesdata;\n"
  4122. "};\n"
  4123. "class PSIPTable : public PESPacket\n"
  4124. "{\n"
  4125. "public:\n"
  4126. " void SetSection(uint num) { pesdata()[6] = num; }\n"
  4127. "};");
  4128. ASSERT_EQUALS("", errout.str());
  4129. }
  4130. void const52() { // ticket 3048
  4131. checkConst("class foo {\n"
  4132. " void DoSomething(int &a) const { a = 1; }\n"
  4133. " void DoSomethingElse() { DoSomething(bar); }\n"
  4134. "private:\n"
  4135. " int bar;\n"
  4136. "};");
  4137. ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Technically the member function 'foo::DoSomething' can be static.\n", errout.str());
  4138. }
  4139. void const53() { // ticket 3049
  4140. checkConst("class A {\n"
  4141. " public:\n"
  4142. " A() : foo(false) {};\n"
  4143. " virtual bool One(bool b = false) { foo = b; return false; }\n"
  4144. " private:\n"
  4145. " bool foo;\n"
  4146. "};\n"
  4147. "class B : public A {\n"
  4148. " public:\n"
  4149. " B() {};\n"
  4150. " bool One(bool b = false) { return false; }\n"
  4151. "};");
  4152. ASSERT_EQUALS("", errout.str());
  4153. }
  4154. void const54() { // ticket 3052
  4155. checkConst("class Example {\n"
  4156. " public:\n"
  4157. " void Clear(void) { Example tmp; (*this) = tmp; }\n"
  4158. "};");
  4159. ASSERT_EQUALS("", errout.str());
  4160. }
  4161. void const55() {
  4162. checkConst("class MyObject {\n"
  4163. " int tmp;\n"
  4164. " MyObject() : tmp(0) {}\n"
  4165. "public:\n"
  4166. " void set(std::stringstream &in) { in >> tmp; }\n"
  4167. "};");
  4168. ASSERT_EQUALS("", errout.str());
  4169. }
  4170. void const56() { // ticket #3149
  4171. checkConst("class MyObject {\n"
  4172. "public:\n"
  4173. " void foo(int x) {\n"
  4174. " switch (x) { }\n"
  4175. " }\n"
  4176. "};");
  4177. ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'MyObject::foo' can be static.\n", errout.str());
  4178. checkConst("class A\n"
  4179. "{\n"
  4180. " protected:\n"
  4181. " unsigned short f (unsigned short X);\n"
  4182. " public:\n"
  4183. " A ();\n"
  4184. "};\n"
  4185. "\n"
  4186. "unsigned short A::f (unsigned short X)\n"
  4187. "{\n"
  4188. " enum ERetValues {RET_NOK = 0, RET_OK = 1};\n"
  4189. " enum ETypes {FLOAT_TYPE = 1, INT_TYPE = 2};\n"
  4190. "\n"
  4191. " try\n"
  4192. " {\n"
  4193. " switch (X)\n"
  4194. " {\n"
  4195. " case FLOAT_TYPE:\n"
  4196. " {\n"
  4197. " return RET_OK;\n"
  4198. " }\n"
  4199. " case INT_TYPE:\n"
  4200. " {\n"
  4201. " return RET_OK;\n"
  4202. " }\n"
  4203. " default:\n"
  4204. " {\n"
  4205. " return RET_NOK;\n"
  4206. " }\n"
  4207. " }\n"
  4208. " }\n"
  4209. " catch (...)\n"
  4210. " {\n"
  4211. " return RET_NOK;\n"
  4212. " }\n"
  4213. "\n"
  4214. " return RET_NOK;\n"
  4215. "}");
  4216. ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:4]: (performance, inconclusive) Technically the member function 'A::f' can be static.\n", errout.str());
  4217. checkConst("class MyObject {\n"
  4218. "public:\n"
  4219. " void foo(int x) {\n"
  4220. " for (int i = 0; i < 5; i++) { }\n"
  4221. " }\n"
  4222. "};");
  4223. ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'MyObject::foo' can be static.\n", errout.str());
  4224. }
  4225. void const57() { // tickets #2669 and #2477
  4226. checkConst("namespace MyGUI\n"
  4227. "{\n"
  4228. " namespace types\n"
  4229. " {\n"
  4230. " struct TSize {};\n"
  4231. " struct TCoord {\n"
  4232. " TSize size() const { }\n"
  4233. " };\n"
  4234. " }\n"
  4235. " typedef types::TSize IntSize;\n"
  4236. " typedef types::TCoord IntCoord;\n"
  4237. "}\n"
  4238. "class SelectorControl\n"
  4239. "{\n"
  4240. " MyGUI::IntSize getSize()\n"
  4241. " {\n"
  4242. " return mCoordValue.size();\n"
  4243. " }\n"
  4244. "private:\n"
  4245. " MyGUI::IntCoord mCoordValue;\n"
  4246. "};");
  4247. ASSERT_EQUALS("[test.cpp:7]: (performance, inconclusive) Technically the member function 'MyGUI::types::TCoord::size' can be static.\n"
  4248. "[test.cpp:15]: (style, inconclusive) Technically the member function 'SelectorControl::getSize' can be const.\n", errout.str());
  4249. checkConst("struct Foo {\n"
  4250. " Bar b;\n"
  4251. " void foo(Foo f) {\n"
  4252. " b.run();\n"
  4253. " }\n"
  4254. "};");
  4255. ASSERT_EQUALS("", errout.str());
  4256. checkConst("struct Bar {\n"
  4257. " int i = 0;\n"
  4258. " void run() { i++; }\n"
  4259. "};\n"
  4260. "struct Foo {\n"
  4261. " Bar b;\n"
  4262. " void foo(Foo f) {\n"
  4263. " b.run();\n"
  4264. " }\n"
  4265. "};");
  4266. ASSERT_EQUALS("", errout.str());
  4267. checkConst("struct Bar {\n"
  4268. " void run() const { }\n"
  4269. "};\n"
  4270. "struct Foo {\n"
  4271. " Bar b;\n"
  4272. " void foo(Foo f) {\n"
  4273. " b.run();\n"
  4274. " }\n"
  4275. "};");
  4276. ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Technically the member function 'Bar::run' can be static.\n"
  4277. "[test.cpp:6]: (style, inconclusive) Technically the member function 'Foo::foo' can be const.\n", errout.str());
  4278. }
  4279. void const58() {
  4280. checkConst("struct MyObject {\n"
  4281. " void foo(Foo f) {\n"
  4282. " f.clear();\n"
  4283. " }\n"
  4284. "};");
  4285. ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Technically the member function 'MyObject::foo' can be static.\n", errout.str());
  4286. checkConst("struct MyObject {\n"
  4287. " int foo(Foo f) {\n"
  4288. " return f.length();\n"
  4289. " }\n"
  4290. "};");
  4291. ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Technically the member function 'MyObject::foo' can be static.\n", errout.str());
  4292. checkConst("struct MyObject {\n"
  4293. " Foo f;\n"
  4294. " int foo() {\n"
  4295. " return f.length();\n"
  4296. " }\n"
  4297. "};");
  4298. ASSERT_EQUALS("", errout.str());
  4299. checkConst("struct MyObject {\n"
  4300. " std::string f;\n"
  4301. " int foo() {\n"
  4302. " return f.length();\n"
  4303. " }\n"
  4304. "};");
  4305. ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'MyObject::foo' can be const.\n", errout.str());
  4306. }
  4307. void const59() { // ticket #4646
  4308. checkConst("class C {\n"
  4309. "public:\n"
  4310. " inline void operator += (const int &x ) { re += x; }\n"
  4311. " friend inline void exp(C & c, const C & x) { }\n"
  4312. "protected:\n"
  4313. " int re;\n"
  4314. " int im;\n"
  4315. "};");
  4316. ASSERT_EQUALS("", errout.str());
  4317. }
  4318. void const60() { // ticket #3322
  4319. checkConst("class MyString {\n"
  4320. "public:\n"
  4321. " MyString() : m_ptr(0){}\n"
  4322. " MyString& operator+=( const MyString& rhs ) {\n"
  4323. " delete m_ptr;\n"
  4324. " m_ptr = new char[42];\n"
  4325. " }\n"
  4326. " MyString append( const MyString& str )\n"
  4327. " { return operator+=( str ); } \n"
  4328. " char *m_ptr;\n"
  4329. "};");
  4330. ASSERT_EQUALS("", errout.str());
  4331. checkConst("class MyString {\n"
  4332. "public:\n"
  4333. " MyString() : m_ptr(0){}\n"
  4334. " MyString& operator+=( const MyString& rhs );\n"
  4335. " MyString append( const MyString& str )\n"
  4336. " { return operator+=( str ); } \n"
  4337. " char *m_ptr;\n"
  4338. "};");
  4339. ASSERT_EQUALS("", errout.str());
  4340. }
  4341. void const61() { // ticket #5606 - don't crash
  4342. checkConst("class MixerParticipant : public MixerParticipant {\n"
  4343. " int GetAudioFrame();\n"
  4344. "};\n"
  4345. "int MixerParticipant::GetAudioFrame() {\n"
  4346. " return 0;\n"
  4347. "}");
  4348. ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2]: (performance, inconclusive) Technically the member function 'MixerParticipant::GetAudioFrame' can be static.\n", errout.str());
  4349. checkConst("class MixerParticipant : public MixerParticipant {\n"
  4350. " bool InitializeFileReader() {\n"
  4351. " printf(\"music\");\n"
  4352. " }\n"
  4353. "};");
  4354. ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Technically the member function 'MixerParticipant::InitializeFileReader' can be static.\n", errout.str());
  4355. // Based on an example from SVN source code causing an endless recursion within CheckClass::isConstMemberFunc()
  4356. // A more complete example including a template declaration like
  4357. // template<typename K> class Hash{/* ... */};
  4358. // didn't .
  4359. checkConst("template<>\n"
  4360. "class Hash<void> {\n"
  4361. "protected:\n"
  4362. " typedef Key::key_type key_type;\n"
  4363. " void set(const Key& key);\n"
  4364. "};\n"
  4365. "template<typename K, int KeySize>\n"
  4366. "class Hash : private Hash<void> {\n"
  4367. " typedef Hash<void> inherited;\n"
  4368. " void set(const Key& key) {\n"
  4369. " inherited::set(inherited::Key(key));\n"
  4370. " }\n"
  4371. "};\n", 0, false);
  4372. ASSERT_EQUALS("", errout.str());
  4373. }
  4374. void const62() {
  4375. checkConst("class A {\n"
  4376. " private:\n"
  4377. " std::unordered_map<unsigned int,unsigned int> _hash;\n"
  4378. " public:\n"
  4379. " A() : _hash() {}\n"
  4380. " unsigned int fetch(unsigned int key)\n" // cannot be 'const'
  4381. " {\n"
  4382. " return _hash[key];\n"
  4383. " }\n"
  4384. "};");
  4385. ASSERT_EQUALS("", errout.str());
  4386. }
  4387. void const63() {
  4388. checkConst("struct A {\n"
  4389. " std::string s;\n"
  4390. " void clear() {\n"
  4391. " std::string* p = &s;\n"
  4392. " p->clear();\n"
  4393. " }\n"
  4394. "};");
  4395. ASSERT_EQUALS("", errout.str());
  4396. checkConst("struct A {\n"
  4397. " std::string s;\n"
  4398. " void clear() {\n"
  4399. " std::string& r = s;\n"
  4400. " r.clear();\n"
  4401. " }\n"
  4402. "};");
  4403. ASSERT_EQUALS("", errout.str());
  4404. checkConst("struct A {\n"
  4405. " std::string s;\n"
  4406. " void clear() {\n"
  4407. " std::string& r = sth; r = s;\n"
  4408. " r.clear();\n"
  4409. " }\n"
  4410. "};");
  4411. ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'A::clear' can be const.\n", errout.str());
  4412. checkConst("struct A {\n"
  4413. " std::string s;\n"
  4414. " void clear() {\n"
  4415. " const std::string* p = &s;\n"
  4416. " p->somefunction();\n"
  4417. " }\n"
  4418. "};");
  4419. ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'A::clear' can be const.\n", errout.str());
  4420. checkConst("struct A {\n"
  4421. " std::string s;\n"
  4422. " void clear() {\n"
  4423. " const std::string& r = s;\n"
  4424. " r.somefunction();\n"
  4425. " }\n"
  4426. "};");
  4427. ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'A::clear' can be const.\n", errout.str());
  4428. }
  4429. void const64() {
  4430. checkConst("namespace B {\n"
  4431. " namespace D {\n"
  4432. " typedef int DKIPtr;\n"
  4433. " }\n"
  4434. " class ZClass {\n"
  4435. " void set(const ::B::D::DKIPtr& p) {\n"
  4436. " membervariable = p;\n"
  4437. " }\n"
  4438. " ::B::D::DKIPtr membervariable;\n"
  4439. " };\n"
  4440. "}");
  4441. ASSERT_EQUALS("", errout.str());
  4442. }
  4443. void const_handleDefaultParameters() {
  4444. checkConst("struct Foo {\n"
  4445. " void foo1(int i, int j = 0) {\n"
  4446. " return func(this);\n"
  4447. " }\n"
  4448. " int bar1() {\n"
  4449. " return foo1(1);\n"
  4450. " }\n"
  4451. " int bar2() {\n"
  4452. " return foo1(1, 2);\n"
  4453. " }\n"
  4454. " int bar3() {\n"
  4455. " return foo1(1, 2, 3);\n"
  4456. " }\n"
  4457. " int bar4() {\n"
  4458. " return foo1();\n"
  4459. " }\n"
  4460. " void foo2(int i = 0) {\n"
  4461. " return func(this);\n"
  4462. " }\n"
  4463. " int bar5() {\n"
  4464. " return foo2();\n"
  4465. " }\n"
  4466. " void foo3() {\n"
  4467. " return func(this);\n"
  4468. " }\n"
  4469. " int bar6() {\n"
  4470. " return foo3();\n"
  4471. " }\n"
  4472. "};");
  4473. ASSERT_EQUALS("[test.cpp:11]: (performance, inconclusive) Technically the member function 'Foo::bar3' can be static.\n"
  4474. "[test.cpp:14]: (performance, inconclusive) Technically the member function 'Foo::bar4' can be static.\n", errout.str());
  4475. }
  4476. void const_passThisToMemberOfOtherClass() {
  4477. checkConst("struct Foo {\n"
  4478. " void foo() {\n"
  4479. " Bar b;\n"
  4480. " b.takeFoo(this);\n"
  4481. " }\n"
  4482. "};");
  4483. ASSERT_EQUALS("", errout.str());
  4484. checkConst("struct Foo {\n"
  4485. " void foo() {\n"
  4486. " Foo f;\n"
  4487. " f.foo();\n"
  4488. " }\n"
  4489. "};");
  4490. ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Technically the member function 'Foo::foo' can be static.\n", errout.str());
  4491. }
  4492. void assigningPointerToPointerIsNotAConstOperation() {
  4493. checkConst("struct s\n"
  4494. "{\n"
  4495. " int** v;\n"
  4496. " void f()\n"
  4497. " {\n"
  4498. " v = 0;\n"
  4499. " }\n"
  4500. "};\n"
  4501. );
  4502. ASSERT_EQUALS("", errout.str());
  4503. }
  4504. void assigningArrayElementIsNotAConstOperation() {
  4505. checkConst("struct s\n"
  4506. "{\n"
  4507. " ::std::string v[3];\n"
  4508. " void f()\n"
  4509. " {\n"
  4510. " v[0] = \"Happy new year!\";\n"
  4511. " }\n"
  4512. "};\n"
  4513. );
  4514. ASSERT_EQUALS("", errout.str());
  4515. }
  4516. // increment/decrement => not const
  4517. void constincdec() {
  4518. checkConst("class Fred {\n"
  4519. " int a;\n"
  4520. " void nextA() { return ++a; }\n"
  4521. "};");
  4522. ASSERT_EQUALS("", errout.str());
  4523. checkConst("class Fred {\n"
  4524. " int a;\n"
  4525. " void nextA() { return --a; }\n"
  4526. "};");
  4527. ASSERT_EQUALS("", errout.str());
  4528. checkConst("class Fred {\n"
  4529. " int a;\n"
  4530. " void nextA() { return a++; }\n"
  4531. "};");
  4532. ASSERT_EQUALS("", errout.str());
  4533. checkConst("class Fred {\n"
  4534. " int a;\n"
  4535. " void nextA() { return a--; }\n"
  4536. "};");
  4537. ASSERT_EQUALS("", errout.str());
  4538. checkConst("int a;\n"
  4539. "class Fred {\n"
  4540. " void nextA() { return ++a; }\n"
  4541. "};");
  4542. ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
  4543. checkConst("int a;\n"
  4544. "class Fred {\n"
  4545. " void nextA() { return --a; }\n"
  4546. "};");
  4547. ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
  4548. checkConst("int a;\n"
  4549. "class Fred {\n"
  4550. " void nextA() { return a++; }\n"
  4551. "};");
  4552. ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
  4553. checkConst("int a;\n"
  4554. "class Fred {\n"
  4555. " void nextA() { return a--; }\n"
  4556. "};");
  4557. ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
  4558. }
  4559. void constassign1() {
  4560. checkConst("class Fred {\n"
  4561. " int a;\n"
  4562. " void nextA() { return a=1; }\n"
  4563. "};");
  4564. ASSERT_EQUALS("", errout.str());
  4565. checkConst("class Fred {\n"
  4566. " int a;\n"
  4567. " void nextA() { return a-=1; }\n"
  4568. "};");
  4569. ASSERT_EQUALS("", errout.str());
  4570. checkConst("class Fred {\n"
  4571. " int a;\n"
  4572. " void nextA() { return a+=1; }\n"
  4573. "};");
  4574. ASSERT_EQUALS("", errout.str());
  4575. checkConst("class Fred {\n"
  4576. " int a;\n"
  4577. " void nextA() { return a*=-1; }\n"
  4578. "};");
  4579. ASSERT_EQUALS("", errout.str());
  4580. checkConst("class Fred {\n"
  4581. " int a;\n"
  4582. " void nextA() { return a/=-2; }\n"
  4583. "};");
  4584. ASSERT_EQUALS("", errout.str());
  4585. checkConst("int a;\n"
  4586. "class Fred {\n"
  4587. " void nextA() { return a=1; }\n"
  4588. "};");
  4589. ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
  4590. checkConst("int a;\n"
  4591. "class Fred {\n"
  4592. " void nextA() { return a-=1; }\n"
  4593. "};");
  4594. ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
  4595. checkConst("int a;\n"
  4596. "class Fred {\n"
  4597. " void nextA() { return a+=1; }\n"
  4598. "};");
  4599. ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
  4600. checkConst("int a;\n"
  4601. "class Fred {\n"
  4602. " void nextA() { return a*=-1; }\n"
  4603. "};");
  4604. ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
  4605. checkConst("int a;\n"
  4606. "class Fred {\n"
  4607. " void nextA() { return a/=-2; }\n"
  4608. "};");
  4609. ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
  4610. }
  4611. void constassign2() {
  4612. checkConst("class Fred {\n"
  4613. " struct A { int a; } s;\n"
  4614. " void nextA() { return s.a=1; }\n"
  4615. "};");
  4616. ASSERT_EQUALS("", errout.str());
  4617. checkConst("class Fred {\n"
  4618. " struct A { int a; } s;\n"
  4619. " void nextA() { return s.a-=1; }\n"
  4620. "};");
  4621. ASSERT_EQUALS("", errout.str());
  4622. checkConst("class Fred {\n"
  4623. " struct A { int a; } s;\n"
  4624. " void nextA() { return s.a+=1; }\n"
  4625. "};");
  4626. ASSERT_EQUALS("", errout.str());
  4627. checkConst("class Fred {\n"
  4628. " struct A { int a; } s;\n"
  4629. " void nextA() { return s.a*=-1; }\n"
  4630. "};");
  4631. ASSERT_EQUALS("", errout.str());
  4632. checkConst("struct A { int a; } s;\n"
  4633. "class Fred {\n"
  4634. " void nextA() { return s.a=1; }\n"
  4635. "};");
  4636. ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
  4637. checkConst("struct A { int a; } s;\n"
  4638. "class Fred {\n"
  4639. " void nextA() { return s.a-=1; }\n"
  4640. "};");
  4641. ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
  4642. checkConst("struct A { int a; } s;\n"
  4643. "class Fred {\n"
  4644. " void nextA() { return s.a+=1; }\n"
  4645. "};");
  4646. ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
  4647. checkConst("struct A { int a; } s;\n"
  4648. "class Fred {\n"
  4649. " void nextA() { return s.a*=-1; }\n"
  4650. "};");
  4651. ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
  4652. checkConst("struct A { int a; } s;\n"
  4653. "class Fred {\n"
  4654. " void nextA() { return s.a/=-2; }\n"
  4655. "};");
  4656. ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
  4657. checkConst("struct A { int a; };\n"
  4658. "class Fred {\n"
  4659. " A s;\n"
  4660. " void nextA() { return s.a=1; }\n"
  4661. "};");
  4662. ASSERT_EQUALS("", errout.str());
  4663. checkConst("struct A { int a; };\n"
  4664. "class Fred {\n"
  4665. " A s;\n"
  4666. " void nextA() { return s.a-=1; }\n"
  4667. "};");
  4668. ASSERT_EQUALS("", errout.str());
  4669. checkConst("struct A { int a; };\n"
  4670. "class Fred {\n"
  4671. " A s;\n"
  4672. " void nextA() { return s.a+=1; }\n"
  4673. "};");
  4674. ASSERT_EQUALS("", errout.str());
  4675. checkConst("struct A { int a; };\n"
  4676. "class Fred {\n"
  4677. " A s;\n"
  4678. " void nextA() { return s.a*=-1; }\n"
  4679. "};");
  4680. ASSERT_EQUALS("", errout.str());
  4681. checkConst("struct A { int a; };\n"
  4682. "class Fred {\n"
  4683. " A s;\n"
  4684. " void nextA() { return s.a/=-2; }\n"
  4685. "};");
  4686. ASSERT_EQUALS("", errout.str());
  4687. }
  4688. // increment/decrement array element => not const
  4689. void constincdecarray() {
  4690. checkConst("class Fred {\n"
  4691. " int a[2];\n"
  4692. " void nextA() { return ++a[0]; }\n"
  4693. "};");
  4694. ASSERT_EQUALS("", errout.str());
  4695. checkConst("class Fred {\n"
  4696. " int a[2];\n"
  4697. " void nextA() { return --a[0]; }\n"
  4698. "};");
  4699. ASSERT_EQUALS("", errout.str());
  4700. checkConst("class Fred {\n"
  4701. " int a[2];\n"
  4702. " void nextA() { return a[0]++; }\n"
  4703. "};");
  4704. ASSERT_EQUALS("", errout.str());
  4705. checkConst("class Fred {\n"
  4706. " int a[2];\n"
  4707. " void nextA() { return a[0]--; }\n"
  4708. "};");
  4709. ASSERT_EQUALS("", errout.str());
  4710. checkConst("int a[2];\n"
  4711. "class Fred {\n"
  4712. " void nextA() { return ++a[0]; }\n"
  4713. "};");
  4714. ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
  4715. checkConst("int a[2];\n"
  4716. "class Fred {\n"
  4717. " void nextA() { return --a[0]; }\n"
  4718. "};");
  4719. ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
  4720. checkConst("int a[2];\n"
  4721. "class Fred {\n"
  4722. " void nextA() { return a[0]++; }\n"
  4723. "};");
  4724. ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
  4725. checkConst("int a[2];\n"
  4726. "class Fred {\n"
  4727. " void nextA() { return a[0]--; }\n"
  4728. "};");
  4729. ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
  4730. }
  4731. void constassignarray() {
  4732. checkConst("class Fred {\n"
  4733. " int a[2];\n"
  4734. " void nextA() { return a[0]=1; }\n"
  4735. "};");
  4736. ASSERT_EQUALS("", errout.str());
  4737. checkConst("class Fred {\n"
  4738. " int a[2];\n"
  4739. " void nextA() { return a[0]-=1; }\n"
  4740. "};");
  4741. ASSERT_EQUALS("", errout.str());
  4742. checkConst("class Fred {\n"
  4743. " int a[2];\n"
  4744. " void nextA() { return a[0]+=1; }\n"
  4745. "};");
  4746. ASSERT_EQUALS("", errout.str());
  4747. checkConst("class Fred {\n"
  4748. " int a[2];\n"
  4749. " void nextA() { return a[0]*=-1; }\n"
  4750. "};");
  4751. ASSERT_EQUALS("", errout.str());
  4752. checkConst("class Fred {\n"
  4753. " int a[2];\n"
  4754. " void nextA() { return a[0]/=-2; }\n"
  4755. "};");
  4756. ASSERT_EQUALS("", errout.str());
  4757. checkConst("int a[2];\n"
  4758. "class Fred {\n"
  4759. " void nextA() { return a[0]=1; }\n"
  4760. "};");
  4761. ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
  4762. checkConst("int a[2];\n"
  4763. "class Fred {\n"
  4764. " void nextA() { return a[0]-=1; }\n"
  4765. "};");
  4766. ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
  4767. checkConst("int a[2];\n"
  4768. "class Fred {\n"
  4769. " void nextA() { return a[0]+=1; }\n"
  4770. "};");
  4771. ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
  4772. checkConst("int a[2];\n"
  4773. "class Fred {\n"
  4774. " void nextA() { return a[0]*=-1; }\n"
  4775. "};");
  4776. ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
  4777. checkConst("int a[2];\n"
  4778. "class Fred {\n"
  4779. " void nextA() { return a[0]/=-2; }\n"
  4780. "};");
  4781. ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
  4782. }
  4783. // return pointer/reference => not const
  4784. void constReturnReference() {
  4785. checkConst("class Fred {\n"
  4786. " int a;\n"
  4787. " int &getR() { return a; }\n"
  4788. " int *getP() { return &a; }"
  4789. "};");
  4790. ASSERT_EQUALS("", errout.str());
  4791. }
  4792. // delete member variable => not const (but technically it can, it compiles without errors)
  4793. void constDelete() {
  4794. checkConst("class Fred {\n"
  4795. " int *a;\n"
  4796. " void clean() { delete a; }\n"
  4797. "};");
  4798. ASSERT_EQUALS("", errout.str());
  4799. }
  4800. // A function that returns unknown types can't be const (#1579)
  4801. void constLPVOID() {
  4802. checkConst("class Fred {\n"
  4803. " UNKNOWN a() { return 0; };\n"
  4804. "};");
  4805. TODO_ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Technically the member function 'Fred::a' can be static.\n", "", errout.str());
  4806. // #1579 - HDC
  4807. checkConst("class Fred {\n"
  4808. " foo bar;\n"
  4809. " UNKNOWN a() { return b; };\n"
  4810. "};");
  4811. ASSERT_EQUALS("", errout.str());
  4812. }
  4813. // a function that calls const functions can be const
  4814. void constFunc() {
  4815. checkConst("class Fred {\n"
  4816. " void f() const { };\n"
  4817. " void a() { f(); };\n"
  4818. "};");
  4819. ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Technically the member function 'Fred::f' can be static.\n"
  4820. "[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::a' can be const.\n", errout.str());
  4821. // ticket #1593
  4822. checkConst("class A\n"
  4823. "{\n"
  4824. " std::vector<int> m_v;\n"
  4825. "public:\n"
  4826. " A(){}\n"
  4827. " unsigned int GetVecSize() {return m_v.size();}\n"
  4828. "};");
  4829. ASSERT_EQUALS("[test.cpp:6]: (style, inconclusive) Technically the member function 'A::GetVecSize' can be const.\n", errout.str());
  4830. checkConst("class A\n"
  4831. "{\n"
  4832. " std::vector<int> m_v;\n"
  4833. "public:\n"
  4834. " A(){}\n"
  4835. " bool GetVecEmpty() {return m_v.empty();}\n"
  4836. "};");
  4837. ASSERT_EQUALS("[test.cpp:6]: (style, inconclusive) Technically the member function 'A::GetVecEmpty' can be const.\n", errout.str());
  4838. }
  4839. void constVirtualFunc() {
  4840. // base class has no virtual function
  4841. checkConst("class A { };\n"
  4842. "class B : public A {\n"
  4843. " int b;\n"
  4844. "public:\n"
  4845. " B() : b(0) { }\n"
  4846. " int func() { return b; }\n"
  4847. "};");
  4848. ASSERT_EQUALS("[test.cpp:6]: (style, inconclusive) Technically the member function 'B::func' can be const.\n", errout.str());
  4849. checkConst("class A { };\n"
  4850. "class B : public A {\n"
  4851. " int b;\n"
  4852. "public:\n"
  4853. " B() : b(0) { }\n"
  4854. " int func();\n"
  4855. "};\n"
  4856. "int B::func() { return b; }");
  4857. ASSERT_EQUALS("[test.cpp:8] -> [test.cpp:6]: (style, inconclusive) Technically the member function 'B::func' can be const.\n", errout.str());
  4858. // base class has no virtual function
  4859. checkConst("class A {\n"
  4860. "public:\n"
  4861. " int func();\n"
  4862. "};\n"
  4863. "class B : public A {\n"
  4864. " int b;\n"
  4865. "public:\n"
  4866. " B() : b(0) { }\n"
  4867. " int func() { return b; }\n"
  4868. "};");
  4869. ASSERT_EQUALS("[test.cpp:9]: (style, inconclusive) Technically the member function 'B::func' can be const.\n", errout.str());
  4870. checkConst("class A {\n"
  4871. "public:\n"
  4872. " int func();\n"
  4873. "};\n"
  4874. "class B : public A {\n"
  4875. " int b;\n"
  4876. "public:\n"
  4877. " B() : b(0) { }\n"
  4878. " int func();\n"
  4879. "};\n"
  4880. "int B::func() { return b; }");
  4881. ASSERT_EQUALS("[test.cpp:11] -> [test.cpp:9]: (style, inconclusive) Technically the member function 'B::func' can be const.\n", errout.str());
  4882. // base class has virtual function
  4883. checkConst("class A {\n"
  4884. "public:\n"
  4885. " virtual int func();\n"
  4886. "};\n"
  4887. "class B : public A {\n"
  4888. " int b;\n"
  4889. "public:\n"
  4890. " B() : b(0) { }\n"
  4891. " int func() { return b; }\n"
  4892. "};");
  4893. ASSERT_EQUALS("", errout.str());
  4894. checkConst("class A {\n"
  4895. "public:\n"
  4896. " virtual int func();\n"
  4897. "};\n"
  4898. "class B : public A {\n"
  4899. " int b;\n"
  4900. "public:\n"
  4901. " B() : b(0) { }\n"
  4902. " int func();\n"
  4903. "};\n"
  4904. "int B::func() { return b; }");
  4905. ASSERT_EQUALS("", errout.str());
  4906. checkConst("class A {\n"
  4907. "public:\n"
  4908. " virtual int func() = 0;\n"
  4909. "};\n"
  4910. "class B : public A {\n"
  4911. " int b;\n"
  4912. "public:\n"
  4913. " B() : b(0) { }\n"
  4914. " int func();\n"
  4915. "};\n"
  4916. "int B::func() { return b; }");
  4917. ASSERT_EQUALS("", errout.str());
  4918. // base class has no virtual function
  4919. checkConst("class A {\n"
  4920. " int a;\n"
  4921. "public:\n"
  4922. " A() : a(0) { }\n"
  4923. " int func() { return a; }\n"
  4924. "};\n"
  4925. "class B : public A {\n"
  4926. " int b;\n"
  4927. "public:\n"
  4928. " B() : b(0) { }\n"
  4929. " int func() { return b; }\n"
  4930. "};\n"
  4931. "class C : public B {\n"
  4932. " int c;\n"
  4933. "public:\n"
  4934. " C() : c(0) { }\n"
  4935. " int func() { return c; }\n"
  4936. "};");
  4937. ASSERT_EQUALS("[test.cpp:5]: (style, inconclusive) Technically the member function 'A::func' can be const.\n"
  4938. "[test.cpp:11]: (style, inconclusive) Technically the member function 'B::func' can be const.\n"
  4939. "[test.cpp:17]: (style, inconclusive) Technically the member function 'C::func' can be const.\n", errout.str());
  4940. checkConst("class A {\n"
  4941. " int a;\n"
  4942. "public:\n"
  4943. " A() : a(0) { }\n"
  4944. " int func();\n"
  4945. "};\n"
  4946. "int A::func() { return a; }\n"
  4947. "class B : public A {\n"
  4948. " int b;\n"
  4949. "public:\n"
  4950. " B() : b(0) { }\n"
  4951. " int func();\n"
  4952. "};\n"
  4953. "int B::func() { return b; }\n"
  4954. "class C : public B {\n"
  4955. " int c;\n"
  4956. "public:\n"
  4957. " C() : c(0) { }\n"
  4958. " int func();\n"
  4959. "};\n"
  4960. "int C::func() { return c; }");
  4961. ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:5]: (style, inconclusive) Technically the member function 'A::func' can be const.\n"
  4962. "[test.cpp:14] -> [test.cpp:12]: (style, inconclusive) Technically the member function 'B::func' can be const.\n"
  4963. "[test.cpp:21] -> [test.cpp:19]: (style, inconclusive) Technically the member function 'C::func' can be const.\n", errout.str());
  4964. // base class has virtual function
  4965. checkConst("class A {\n"
  4966. " int a;\n"
  4967. "public:\n"
  4968. " A() : a(0) { }\n"
  4969. " virtual int func() { return a; }\n"
  4970. "};\n"
  4971. "class B : public A {\n"
  4972. " int b;\n"
  4973. "public:\n"
  4974. " B() : b(0) { }\n"
  4975. " int func() { return b; }\n"
  4976. "};\n"
  4977. "class C : public B {\n"
  4978. " int c;\n"
  4979. "public:\n"
  4980. " C() : c(0) { }\n"
  4981. " int func() { return c; }\n"
  4982. "};");
  4983. ASSERT_EQUALS("", errout.str());
  4984. checkConst("class A {\n"
  4985. " int a;\n"
  4986. "public:\n"
  4987. " A() : a(0) { }\n"
  4988. " virtual int func();\n"
  4989. "};\n"
  4990. "int A::func() { return a; }\n"
  4991. "class B : public A {\n"
  4992. " int b;\n"
  4993. "public:\n"
  4994. " B() : b(0) { }\n"
  4995. " int func();\n"
  4996. "};\n"
  4997. "int B::func() { return b; }\n"
  4998. "class C : public B {\n"
  4999. " int c;\n"
  5000. "public:\n"
  5001. " C() : c(0) { }\n"
  5002. " int func();\n"
  5003. "};\n"
  5004. "int C::func() { return c; }");
  5005. ASSERT_EQUALS("", errout.str());
  5006. // ticket #1311
  5007. checkConst("class X {\n"
  5008. " int x;\n"
  5009. "public:\n"
  5010. " X(int x) : x(x) { }\n"
  5011. " int getX() { return x; }\n"
  5012. "};\n"
  5013. "class Y : public X {\n"
  5014. " int y;\n"
  5015. "public:\n"
  5016. " Y(int x, int y) : X(x), y(y) { }\n"
  5017. " int getY() { return y; }\n"
  5018. "};\n"
  5019. "class Z : public Y {\n"
  5020. " int z;\n"
  5021. "public:\n"
  5022. " Z(int x, int y, int z) : Y(x, y), z(z) { }\n"
  5023. " int getZ() { return z; }\n"
  5024. "};");
  5025. ASSERT_EQUALS("[test.cpp:5]: (style, inconclusive) Technically the member function 'X::getX' can be const.\n"
  5026. "[test.cpp:11]: (style, inconclusive) Technically the member function 'Y::getY' can be const.\n"
  5027. "[test.cpp:17]: (style, inconclusive) Technically the member function 'Z::getZ' can be const.\n", errout.str());
  5028. checkConst("class X {\n"
  5029. " int x;\n"
  5030. "public:\n"
  5031. " X(int x) : x(x) { }\n"
  5032. " int getX();\n"
  5033. "};\n"
  5034. "int X::getX() { return x; }\n"
  5035. "class Y : public X {\n"
  5036. " int y;\n"
  5037. "public:\n"
  5038. " Y(int x, int y) : X(x), y(y) { }\n"
  5039. " int getY();\n"
  5040. "};\n"
  5041. "int Y::getY() { return y; }\n"
  5042. "class Z : public Y {\n"
  5043. " int z;\n"
  5044. "public:\n"
  5045. " Z(int x, int y, int z) : Y(x, y), z(z) { }\n"
  5046. " int getZ();\n"
  5047. "};\n"
  5048. "int Z::getZ() { return z; }");
  5049. ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:5]: (style, inconclusive) Technically the member function 'X::getX' can be const.\n"
  5050. "[test.cpp:14] -> [test.cpp:12]: (style, inconclusive) Technically the member function 'Y::getY' can be const.\n"
  5051. "[test.cpp:21] -> [test.cpp:19]: (style, inconclusive) Technically the member function 'Z::getZ' can be const.\n", errout.str());
  5052. }
  5053. void constIfCfg() {
  5054. const char code[] = "struct foo {\n"
  5055. " int i;\n"
  5056. " void f() {\n"
  5057. //"#ifdef ABC\n"
  5058. //" i = 4;\n"
  5059. //"endif\n"
  5060. " }\n"
  5061. "};";
  5062. Settings settings;
  5063. settings.addEnabled("style");
  5064. checkConst(code, &settings, true);
  5065. ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'foo::f' can be static.\n", errout.str());
  5066. checkConst(code, &settings, false); // TODO: Set inconclusive to true (preprocess it)
  5067. ASSERT_EQUALS("", errout.str());
  5068. }
  5069. void constFriend() { // ticket #1921
  5070. const char code[] = "class foo {\n"
  5071. " friend void f() { }\n"
  5072. "};";
  5073. checkConst(code);
  5074. ASSERT_EQUALS("", errout.str());
  5075. }
  5076. void constUnion() { // ticket #2111
  5077. checkConst("class foo {\n"
  5078. "public:\n"
  5079. " union {\n"
  5080. " int i;\n"
  5081. " float f;\n"
  5082. " } d;\n"
  5083. " void setf(float x) {\n"
  5084. " d.f = x;\n"
  5085. " }\n"
  5086. "};");
  5087. ASSERT_EQUALS("", errout.str());
  5088. }
  5089. void constArrayOperator() {
  5090. checkConst("struct foo {\n"
  5091. " int x;\n"
  5092. " int y[5][724];\n"
  5093. " T a() {\n"
  5094. " return y[x++][6];\n"
  5095. " }\n"
  5096. " T b() {\n"
  5097. " return y[1][++x];\n"
  5098. " }\n"
  5099. " T c() {\n"
  5100. " return y[1][6];\n"
  5101. " }\n"
  5102. "};");
  5103. ASSERT_EQUALS("[test.cpp:10]: (style, inconclusive) Technically the member function 'foo::c' can be const.\n", errout.str());
  5104. }
  5105. void checkInitializerListOrder(const char code[]) {
  5106. // Clear the error log
  5107. errout.str("");
  5108. // Check..
  5109. Settings settings;
  5110. settings.addEnabled("style");
  5111. settings.inconclusive = true;
  5112. // Tokenize..
  5113. Tokenizer tokenizer(&settings, this);
  5114. std::istringstream istr(code);
  5115. tokenizer.tokenize(istr, "test.cpp");
  5116. tokenizer.simplifyTokenList2();
  5117. CheckClass checkClass(&tokenizer, &settings, this);
  5118. checkClass.initializerListOrder();
  5119. }
  5120. void initializerListOrder() {
  5121. checkInitializerListOrder("class Fred {\n"
  5122. " int a, b, c;\n"
  5123. "public:\n"
  5124. " Fred() : c(0), b(0), a(0) { }\n"
  5125. "};");
  5126. ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2]: (style, inconclusive) Member variable 'Fred::b' is in the wrong place in the initializer list.\n"
  5127. "[test.cpp:4] -> [test.cpp:2]: (style, inconclusive) Member variable 'Fred::a' is in the wrong place in the initializer list.\n", errout.str());
  5128. checkInitializerListOrder("class Fred {\n"
  5129. " int a, b, c;\n"
  5130. "public:\n"
  5131. " Fred() : c{0}, b{0}, a{0} { }\n"
  5132. "};");
  5133. ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2]: (style, inconclusive) Member variable 'Fred::b' is in the wrong place in the initializer list.\n"
  5134. "[test.cpp:4] -> [test.cpp:2]: (style, inconclusive) Member variable 'Fred::a' is in the wrong place in the initializer list.\n", errout.str());
  5135. }
  5136. void checkInitializationListUsage(const char code[]) {
  5137. // Clear the error log
  5138. errout.str("");
  5139. // Check..
  5140. Settings settings;
  5141. settings.addEnabled("performance");
  5142. // Tokenize..
  5143. Tokenizer tokenizer(&settings, this);
  5144. std::istringstream istr(code);
  5145. tokenizer.tokenize(istr, "test.cpp");
  5146. tokenizer.simplifyTokenList2();
  5147. CheckClass checkClass(&tokenizer, &settings, this);
  5148. checkClass.initializationListUsage();
  5149. }
  5150. void initializerListUsage() {
  5151. checkInitializationListUsage("class Fred {\n"
  5152. " int a;\n" // No message for builtin types: No performance gain
  5153. " int* b;\n" // No message for pointers: No performance gain
  5154. " Fred() { a = 0; b = 0; }\n"
  5155. "};");
  5156. ASSERT_EQUALS("", errout.str());
  5157. checkInitializationListUsage("class Fred {\n"
  5158. " std::string s;\n"
  5159. " Fred() { a = 0; s = \"foo\"; }\n"
  5160. "};");
  5161. ASSERT_EQUALS("[test.cpp:3]: (performance) Variable 's' is assigned in constructor body. Consider performing initialization in initialization list.\n", errout.str());
  5162. checkInitializationListUsage("class Fred {\n"
  5163. " std::string& s;\n" // Message is invalid for references, since their initialization in initializer list is required anyway and behaves different from assignment (#5004)
  5164. " Fred(const std::string& s_) : s(s_) { s = \"foo\"; }\n"
  5165. "};");
  5166. ASSERT_EQUALS("", errout.str());
  5167. checkInitializationListUsage("class Fred {\n"
  5168. " std::vector<int> v;\n"
  5169. " Fred() { v = unknown; }\n"
  5170. "};");
  5171. ASSERT_EQUALS("[test.cpp:3]: (performance) Variable 'v' is assigned in constructor body. Consider performing initialization in initialization list.\n", errout.str());
  5172. checkInitializationListUsage("class C { std::string s; };\n"
  5173. "class Fred {\n"
  5174. " C c;\n"
  5175. " Fred() { c = unknown; }\n"
  5176. "};");
  5177. ASSERT_EQUALS("[test.cpp:4]: (performance) Variable 'c' is assigned in constructor body. Consider performing initialization in initialization list.\n", errout.str());
  5178. checkInitializationListUsage("class C;\n"
  5179. "class Fred {\n"
  5180. " C c;\n"
  5181. " Fred() { c = unknown; }\n"
  5182. "};");
  5183. ASSERT_EQUALS("[test.cpp:4]: (performance) Variable 'c' is assigned in constructor body. Consider performing initialization in initialization list.\n", errout.str());
  5184. checkInitializationListUsage("class C;\n"
  5185. "class Fred {\n"
  5186. " C c;\n"
  5187. " Fred(Fred const & other) { c = other.c; }\n"
  5188. "};");
  5189. ASSERT_EQUALS("[test.cpp:4]: (performance) Variable 'c' is assigned in constructor body. Consider performing initialization in initialization list.\n", errout.str());
  5190. checkInitializationListUsage("class C;\n"
  5191. "class Fred {\n"
  5192. " C c;\n"
  5193. " Fred(Fred && other) { c = other.c; }\n"
  5194. "};");
  5195. ASSERT_EQUALS("[test.cpp:4]: (performance) Variable 'c' is assigned in constructor body. Consider performing initialization in initialization list.\n", errout.str());
  5196. checkInitializationListUsage("class C;\n"
  5197. "class Fred {\n"
  5198. " C a;\n"
  5199. " Fred() { initB(); a = b; }\n"
  5200. "};");
  5201. ASSERT_EQUALS("", errout.str());
  5202. checkInitializationListUsage("class C;\n"
  5203. "class Fred {\n"
  5204. " C a;\n"
  5205. " Fred() : a(0) { if(b) a = 0; }\n"
  5206. "};");
  5207. ASSERT_EQUALS("", errout.str());
  5208. checkInitializationListUsage("class C;\n"
  5209. "class Fred {\n"
  5210. " C a[5];\n"
  5211. " Fred() { for(int i = 0; i < 5; i++) a[i] = 0; }\n"
  5212. "};");
  5213. ASSERT_EQUALS("", errout.str());
  5214. checkInitializationListUsage("class C;\n"
  5215. "class Fred {\n"
  5216. " C a; int b;\n"
  5217. " Fred() : b(5) { a = b; }\n" // Don't issue a message here: You actually could move it to the initialization list, but it would cause problems if you change the order of the variable declarations.
  5218. "};");
  5219. ASSERT_EQUALS("", errout.str());
  5220. checkInitializationListUsage("class C;\n"
  5221. "class Fred {\n"
  5222. " C a;\n"
  5223. " Fred() { try { a = new int; } catch(...) {} }\n"
  5224. "};");
  5225. ASSERT_EQUALS("", errout.str());
  5226. checkInitializationListUsage("class Fred {\n"
  5227. " std::string s;\n"
  5228. " Fred() { s = toString((size_t)this); }\n"
  5229. "};");
  5230. ASSERT_EQUALS("", errout.str());
  5231. checkInitializationListUsage("class Fred {\n"
  5232. " std::string a;\n"
  5233. " std::string foo();\n"
  5234. " Fred() { a = foo(); }\n"
  5235. "};");
  5236. ASSERT_EQUALS("", errout.str());
  5237. checkInitializationListUsage("class Fred {\n"
  5238. " std::string a;\n"
  5239. " Fred() { a = foo(); }\n"
  5240. "};");
  5241. ASSERT_EQUALS("[test.cpp:3]: (performance) Variable 'a' is assigned in constructor body. Consider performing initialization in initialization list.\n", errout.str());
  5242. checkInitializationListUsage("class Fred {\n" // #4332
  5243. " static std::string s;\n"
  5244. " Fred() { s = \"foo\"; }\n"
  5245. "};");
  5246. ASSERT_EQUALS("", errout.str());
  5247. checkInitializationListUsage("class Fred {\n" // #5640
  5248. " std::string s;\n"
  5249. " Fred() {\n"
  5250. " char str[2];\n"
  5251. " str[0] = c;\n"
  5252. " str[1] = 0;\n"
  5253. " s = str;\n"
  5254. " }\n"
  5255. "};");
  5256. ASSERT_EQUALS("", errout.str());
  5257. }
  5258. void checkSelfInitialization(const char code []) {
  5259. // Clear the error log
  5260. errout.str("");
  5261. // Check..
  5262. Settings settings;
  5263. // Tokenize..
  5264. Tokenizer tokenizer(&settings, this);
  5265. std::istringstream istr(code);
  5266. tokenizer.tokenize(istr, "test.cpp");
  5267. tokenizer.simplifyTokenList2();
  5268. CheckClass checkClass(&tokenizer, &settings, this);
  5269. checkClass.checkSelfInitialization();
  5270. }
  5271. void selfInitialization() {
  5272. checkSelfInitialization("class Fred {\n"
  5273. " int i;\n"
  5274. " Fred() : i(i) {\n"
  5275. " }\n"
  5276. "};");
  5277. ASSERT_EQUALS("[test.cpp:3]: (error) Member variable 'i' is initialized by itself.\n", errout.str());
  5278. checkSelfInitialization("class Fred {\n"
  5279. " int i;\n"
  5280. " Fred() : i{i} {\n"
  5281. " }\n"
  5282. "};");
  5283. ASSERT_EQUALS("[test.cpp:3]: (error) Member variable 'i' is initialized by itself.\n", errout.str());
  5284. checkSelfInitialization("class Fred {\n"
  5285. " int i;\n"
  5286. " Fred();\n"
  5287. "};\n"
  5288. "Fred::Fred() : i(i) {\n"
  5289. "}");
  5290. ASSERT_EQUALS("[test.cpp:5]: (error) Member variable 'i' is initialized by itself.\n", errout.str());
  5291. checkSelfInitialization("class Fred {\n"
  5292. " std::string s;\n"
  5293. " Fred() : s(s) {\n"
  5294. " }\n"
  5295. "};");
  5296. ASSERT_EQUALS("[test.cpp:3]: (error) Member variable 's' is initialized by itself.\n", errout.str());
  5297. checkSelfInitialization("class Fred {\n"
  5298. " std::string s;\n"
  5299. " Fred(const std::string& s) : s(s) {\n"
  5300. " }\n"
  5301. "};");
  5302. ASSERT_EQUALS("", errout.str());
  5303. checkSelfInitialization("struct Foo : Bar {\n"
  5304. " int i;\n"
  5305. " Foo(int i)\n"
  5306. " : Bar(""), i(i) {}\n"
  5307. "};");
  5308. ASSERT_EQUALS("", errout.str());
  5309. checkSelfInitialization("struct Foo : std::Bar {\n" // #6073
  5310. " int i;\n"
  5311. " Foo(int i)\n"
  5312. " : std::Bar(""), i(i) {}\n"
  5313. "};");
  5314. ASSERT_EQUALS("", errout.str());
  5315. checkSelfInitialization("struct Foo : std::Bar {\n" // #6073
  5316. " int i;\n"
  5317. " Foo(int i)\n"
  5318. " : std::Bar(""), i{i} {}\n"
  5319. "};");
  5320. ASSERT_EQUALS("", errout.str());
  5321. }
  5322. void checkPureVirtualFunctionCall(const char code[], const Settings *s = 0, bool inconclusive = true) {
  5323. // Clear the error log
  5324. errout.str("");
  5325. // Check..
  5326. Settings settings;
  5327. if (s)
  5328. settings = *s;
  5329. else
  5330. settings.addEnabled("style");
  5331. settings.inconclusive = inconclusive;
  5332. // Tokenize..
  5333. Tokenizer tokenizer(&settings, this);
  5334. std::istringstream istr(code);
  5335. tokenizer.tokenize(istr, "test.cpp");
  5336. tokenizer.simplifyTokenList2();
  5337. CheckClass checkClass(&tokenizer, &settings, this);
  5338. checkClass.checkPureVirtualFunctionCall();
  5339. }
  5340. void pureVirtualFunctionCall() {
  5341. checkPureVirtualFunctionCall("class A\n"
  5342. "{\n"
  5343. " virtual void pure()=0;\n"
  5344. " A();\n"
  5345. "};\n"
  5346. "A::A()\n"
  5347. "{pure();}\n");
  5348. ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:3]: (warning) Call of pure virtual function 'pure' in constructor.\n", errout.str());
  5349. checkPureVirtualFunctionCall("class A\n"
  5350. "{\n"
  5351. " virtual int pure()=0;\n"
  5352. " A();\n"
  5353. " int m;\n"
  5354. "};\n"
  5355. "A::A():m(A::pure())\n"
  5356. "{}\n");
  5357. ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:3]: (warning) Call of pure virtual function 'pure' in constructor.\n", errout.str());
  5358. checkPureVirtualFunctionCall("class A\n"
  5359. " {\n"
  5360. " virtual void pure()=0; \n"
  5361. " virtual ~A(); \n"
  5362. " int m; \n"
  5363. "};\n"
  5364. "A::~A()\n"
  5365. "{pure();}\n");
  5366. ASSERT_EQUALS("[test.cpp:8] -> [test.cpp:3]: (warning) Call of pure virtual function 'pure' in destructor.\n", errout.str());
  5367. checkPureVirtualFunctionCall("class A\n"
  5368. " {\n"
  5369. " virtual void pure()=0;\n"
  5370. " void nonpure()\n"
  5371. " {pure();}\n"
  5372. " A(); \n"
  5373. "};\n"
  5374. "A::A()\n"
  5375. "{nonpure();}\n");
  5376. ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:5] -> [test.cpp:3]: (warning) Call of pure virtual function 'pure' in constructor.\n", errout.str());
  5377. checkPureVirtualFunctionCall("class A\n"
  5378. " {\n"
  5379. " virtual int pure()=0;\n"
  5380. " int nonpure()\n"
  5381. " {return pure();}\n"
  5382. " A(); \n"
  5383. " int m;\n"
  5384. "};\n"
  5385. "A::A():m(nonpure())\n"
  5386. "{}\n");
  5387. TODO_ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:5] -> [test.cpp:3]: (warning) Call of pure virtual function 'pure' in constructor.\n", "", errout.str());
  5388. checkPureVirtualFunctionCall("class A\n"
  5389. " {\n"
  5390. " virtual void pure()=0; \n"
  5391. " void nonpure()\n"
  5392. " {pure();}\n"
  5393. " virtual ~A();\n"
  5394. " int m;\n"
  5395. "};\n"
  5396. "A::~A()\n"
  5397. "{nonpure();}\n");
  5398. ASSERT_EQUALS("[test.cpp:10] -> [test.cpp:5] -> [test.cpp:3]: (warning) Call of pure virtual function 'pure' in destructor.\n", errout.str());
  5399. checkPureVirtualFunctionCall("class A\n"
  5400. "{\n"
  5401. " virtual void pure()=0;\n"
  5402. " A(bool b);\n"
  5403. "};\n"
  5404. "A::A(bool b)\n"
  5405. "{if (b) pure();}\n");
  5406. ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:3]: (warning) Call of pure virtual function 'pure' in constructor.\n", errout.str());
  5407. checkPureVirtualFunctionCall("class A\n"
  5408. " {\n"
  5409. " virtual void pure()=0; \n"
  5410. " virtual ~A(); \n"
  5411. " int m; \n"
  5412. "};\n"
  5413. "A::~A()\n"
  5414. "{if (b) pure();}\n");
  5415. ASSERT_EQUALS("[test.cpp:8] -> [test.cpp:3]: (warning) Call of pure virtual function 'pure' in destructor.\n", errout.str());
  5416. // ticket # 5831
  5417. checkPureVirtualFunctionCall("class abc {\n"
  5418. "public:\n"
  5419. " virtual ~abc() throw() {}\n"
  5420. " virtual void def(void* g) throw () = 0;\n"
  5421. "};\n");
  5422. ASSERT_EQUALS("", errout.str());
  5423. }
  5424. void pureVirtualFunctionCallOtherClass() {
  5425. checkPureVirtualFunctionCall("class A\n"
  5426. "{\n"
  5427. " virtual void pure()=0;\n"
  5428. " A(const A & a);\n"
  5429. "};\n"
  5430. "A::A(const A & a)\n"
  5431. "{a.pure();}\n");
  5432. ASSERT_EQUALS("", errout.str());
  5433. checkPureVirtualFunctionCall("class A\n"
  5434. "{\n"
  5435. " virtual void pure()=0;\n"
  5436. " A();\n"
  5437. "};\n"
  5438. "class B\n"
  5439. "{\n"
  5440. " virtual void pure()=0;\n"
  5441. "};\n"
  5442. "A::A()\n"
  5443. "{B b; b.pure();}\n");
  5444. ASSERT_EQUALS("", errout.str());
  5445. }
  5446. void pureVirtualFunctionCallWithBody() {
  5447. checkPureVirtualFunctionCall("class A\n"
  5448. "{\n"
  5449. " virtual void pureWithBody()=0;\n"
  5450. " A();\n"
  5451. "};\n"
  5452. "A::A()\n"
  5453. "{pureWithBody();}\n"
  5454. "void A::pureWithBody()\n"
  5455. "{}\n");
  5456. ASSERT_EQUALS("", errout.str());
  5457. checkPureVirtualFunctionCall("class A\n"
  5458. " {\n"
  5459. " virtual void pureWithBody()=0;\n"
  5460. " void nonpure()\n"
  5461. " {pureWithBody();}\n"
  5462. " A(); \n"
  5463. "};\n"
  5464. "A::A()\n"
  5465. "{nonpure();}\n"
  5466. "void A::pureWithBody()\n"
  5467. "{}\n");
  5468. ASSERT_EQUALS("", errout.str());
  5469. }
  5470. void pureVirtualFunctionCallPrevented() {
  5471. checkPureVirtualFunctionCall("class A\n"
  5472. " {\n"
  5473. " virtual void pure()=0;\n"
  5474. " void nonpure(bool bCallPure)\n"
  5475. " { if (bCallPure) pure();}\n"
  5476. " A(); \n"
  5477. "};\n"
  5478. "A::A()\n"
  5479. "{nonpure(false);}\n");
  5480. ASSERT_EQUALS("", errout.str());
  5481. checkPureVirtualFunctionCall("class A\n"
  5482. " {\n"
  5483. " virtual void pure()=0;\n"
  5484. " void nonpure(bool bCallPure)\n"
  5485. " { if (!bCallPure) ; else pure();}\n"
  5486. " A(); \n"
  5487. "};\n"
  5488. "A::A()\n"
  5489. "{nonpure(false);}\n");
  5490. ASSERT_EQUALS("", errout.str());
  5491. checkPureVirtualFunctionCall("class A\n"
  5492. " {\n"
  5493. " virtual void pure()=0;\n"
  5494. " void nonpure(bool bCallPure)\n"
  5495. " {\n"
  5496. " switch (bCallPure) {\n"
  5497. " case true: pure(); break;\n"
  5498. " }\n"
  5499. " }\n"
  5500. " A(); \n"
  5501. "};\n"
  5502. "A::A()\n"
  5503. "{nonpure(false);}\n");
  5504. ASSERT_EQUALS("", errout.str());
  5505. }
  5506. };
  5507. REGISTER_TEST(TestClass)