1 /* 2 * Cppcheck - A tool for static C/C++ code analysis 3 * Copyright (C) 2007-2021 Cppcheck team. 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #include <tinyxml2.h> 20 21 #include "checkfunctions.h" 22 #include "library.h" 23 #include "settings.h" 24 #include "standards.h" 25 #include "testsuite.h" 26 #include "tokenize.h" 27 28 29 class TestFunctions : public TestFixture { 30 public: TestFunctions()31 TestFunctions() : TestFixture("TestFunctions") {} 32 33 private: 34 Settings settings; 35 run()36 void run() OVERRIDE { 37 settings.severity.enable(Severity::style); 38 settings.severity.enable(Severity::warning); 39 settings.severity.enable(Severity::performance); 40 settings.severity.enable(Severity::portability); 41 settings.certainty.enable(Certainty::inconclusive); 42 settings.libraries.emplace_back("posix"); 43 settings.standards.c = Standards::C11; 44 settings.standards.cpp = Standards::CPP11; 45 LOAD_LIB_2(settings.library, "std.cfg"); 46 LOAD_LIB_2(settings.library, "posix.cfg"); 47 48 // Prohibited functions 49 TEST_CASE(prohibitedFunctions_posix); 50 TEST_CASE(prohibitedFunctions_index); 51 TEST_CASE(prohibitedFunctions_qt_index); // FP when using the Qt function 'index'? 52 TEST_CASE(prohibitedFunctions_rindex); 53 TEST_CASE(prohibitedFunctions_var); // no false positives for variables 54 TEST_CASE(prohibitedFunctions_gets); // dangerous function 55 TEST_CASE(prohibitedFunctions_alloca); 56 TEST_CASE(prohibitedFunctions_declaredFunction); // declared function ticket #3121 57 TEST_CASE(prohibitedFunctions_std_gets); // test std::gets 58 TEST_CASE(prohibitedFunctions_multiple); // multiple use of obsolete functions 59 TEST_CASE(prohibitedFunctions_c_declaration); // c declared function 60 TEST_CASE(prohibitedFunctions_functionWithBody); // function with body 61 TEST_CASE(prohibitedFunctions_crypt); // Non-reentrant function 62 TEST_CASE(prohibitedFunctions_namespaceHandling); 63 64 // Invalid function usage 65 TEST_CASE(invalidFunctionUsage1); 66 TEST_CASE(invalidFunctionUsageStrings); 67 68 // Math function usage 69 TEST_CASE(mathfunctionCall_fmod); 70 TEST_CASE(mathfunctionCall_sqrt); 71 TEST_CASE(mathfunctionCall_log); 72 TEST_CASE(mathfunctionCall_acos); 73 TEST_CASE(mathfunctionCall_asin); 74 TEST_CASE(mathfunctionCall_pow); 75 TEST_CASE(mathfunctionCall_atan2); 76 TEST_CASE(mathfunctionCall_precision); 77 78 // Ignored return value 79 TEST_CASE(checkIgnoredReturnValue); 80 TEST_CASE(checkIgnoredErrorCode); 81 82 // memset.. 83 TEST_CASE(memsetZeroBytes); 84 TEST_CASE(memsetInvalid2ndParam); 85 86 // missing "return" 87 TEST_CASE(checkMissingReturn); 88 89 // std::move for locar variable 90 TEST_CASE(returnLocalStdMove1); 91 TEST_CASE(returnLocalStdMove2); 92 TEST_CASE(returnLocalStdMove3); 93 TEST_CASE(returnLocalStdMove4); 94 95 TEST_CASE(returnLocalStdMove5); 96 } 97 check(const char code[],const char filename[]="test.cpp",const Settings * settings_=nullptr)98 void check(const char code[], const char filename[]="test.cpp", const Settings* settings_=nullptr) { 99 // Clear the error buffer.. 100 errout.str(""); 101 102 if (!settings_) 103 settings_ = &settings; 104 105 // Tokenize.. 106 Tokenizer tokenizer(settings_, this); 107 std::istringstream istr(code); 108 tokenizer.tokenize(istr, filename); 109 110 CheckFunctions checkFunctions(&tokenizer, settings_, this); 111 checkFunctions.runChecks(&tokenizer, settings_, this); 112 } 113 prohibitedFunctions_posix()114 void prohibitedFunctions_posix() { 115 check("void f()\n" 116 "{\n" 117 " bsd_signal(SIGABRT, SIG_IGN);\n" 118 "}"); 119 ASSERT_EQUALS("[test.cpp:3]: (style) Obsolescent function 'bsd_signal' called. It is recommended to use 'sigaction' instead.\n", errout.str()); 120 121 check("int f()\n" 122 "{\n" 123 " int bsd_signal(0);\n" 124 " return bsd_signal;\n" 125 "}"); 126 ASSERT_EQUALS("", errout.str()); 127 128 check("void f()\n" 129 "{\n" 130 " struct hostent *hp;\n" 131 " if(!hp = gethostbyname(\"127.0.0.1\")) {\n" 132 " exit(1);\n" 133 " }\n" 134 "}"); 135 ASSERT_EQUALS("[test.cpp:4]: (style) Obsolescent function 'gethostbyname' called. It is recommended to use 'getaddrinfo' instead.\n", errout.str()); 136 137 check("void f()\n" 138 "{\n" 139 " long addr;\n" 140 " addr = inet_addr(\"127.0.0.1\");\n" 141 " if(!hp = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET)) {\n" 142 " exit(1);\n" 143 " }\n" 144 "}"); 145 ASSERT_EQUALS("[test.cpp:5]: (style) Obsolescent function 'gethostbyaddr' called. It is recommended to use 'getnameinfo' instead.\n", errout.str()); 146 147 check("void f()\n" 148 "{\n" 149 " usleep( 1000 );\n" 150 "}"); 151 ASSERT_EQUALS("[test.cpp:3]: (style) Obsolescent function 'usleep' called. It is recommended to use 'nanosleep' or 'setitimer' instead.\n", errout.str()); 152 } 153 prohibitedFunctions_index()154 void prohibitedFunctions_index() { 155 check("namespace n1 {\n" 156 " int index(){ return 1; };\n" 157 "}\n" 158 "int main()\n" 159 "{\n" 160 " n1::index();\n" 161 " return 0;\n" 162 "}"); 163 ASSERT_EQUALS("", errout.str()); 164 165 check("std::size_t f()\n" 166 "{\n" 167 " std::size_t index(0);\n" 168 " index++;\n" 169 " return index;\n" 170 "}"); 171 ASSERT_EQUALS("", errout.str()); 172 173 check("int f()\n" 174 "{\n" 175 " return this->index();\n" 176 "}"); 177 ASSERT_EQUALS("", errout.str()); 178 179 check("void f()\n" 180 "{\n" 181 " int index( 0 );\n" 182 "}"); 183 ASSERT_EQUALS("", errout.str()); 184 185 check("const char f()\n" 186 "{\n" 187 " const char var[6] = \"index\";\n" 188 " const char i = index(var, 0);\n" 189 " return i;\n" 190 "}"); 191 ASSERT_EQUALS("[test.cpp:4]: (style) Obsolescent function 'index' called. It is recommended to use 'strchr' instead.\n", 192 errout.str()); 193 } 194 prohibitedFunctions_qt_index()195 void prohibitedFunctions_qt_index() { 196 check("void TDataModel::forceRowRefresh(int row) {\n" 197 " emit dataChanged(index(row, 0), index(row, columnCount() - 1));\n" 198 "}"); 199 ASSERT_EQUALS("[test.cpp:2]: (style) Obsolescent function 'index' called. It is recommended to use 'strchr' instead.\n", errout.str()); 200 } 201 prohibitedFunctions_rindex()202 void prohibitedFunctions_rindex() { 203 check("void f()\n" 204 "{\n" 205 " int rindex( 0 );\n" 206 "}"); 207 ASSERT_EQUALS("", errout.str()); 208 209 check("void f()\n" 210 "{\n" 211 " const char var[7] = \"rindex\";\n" 212 " print(rindex(var, 0));\n" 213 "}"); 214 ASSERT_EQUALS("[test.cpp:4]: (style) Obsolescent function 'rindex' called. It is recommended to use 'strrchr' instead.\n", errout.str()); 215 } 216 217 prohibitedFunctions_var()218 void prohibitedFunctions_var() { 219 check("class Fred {\n" 220 "public:\n" 221 " Fred() : index(0) { }\n" 222 " int index;\n" 223 "};"); 224 ASSERT_EQUALS("", errout.str()); 225 } 226 prohibitedFunctions_gets()227 void prohibitedFunctions_gets() { 228 check("void f()\n" 229 "{\n" 230 " char *x = gets(a);\n" 231 "}"); 232 ASSERT_EQUALS("[test.cpp:3]: (warning) Obsolete function 'gets' called. It is recommended to use 'fgets' or 'gets_s' instead.\n", errout.str()); 233 234 check("void f()\n" 235 "{\n" 236 " foo(x, gets(a));\n" 237 "}"); 238 ASSERT_EQUALS("[test.cpp:3]: (warning) Obsolete function 'gets' called. It is recommended to use 'fgets' or 'gets_s' instead.\n", errout.str()); 239 } 240 prohibitedFunctions_alloca()241 void prohibitedFunctions_alloca() { 242 check("void f()\n" 243 "{\n" 244 " char *x = alloca(10);\n" 245 "}", "test.cpp"); // #4382 - there are no VLAs in C++ 246 ASSERT_EQUALS("[test.cpp:3]: (warning) Obsolete function 'alloca' called.\n", errout.str()); 247 248 check("void f()\n" 249 "{\n" 250 " char *x = alloca(10);\n" 251 "}", "test.c"); 252 ASSERT_EQUALS("[test.c:3]: (warning) Obsolete function 'alloca' called. In C99 and later it is recommended to use a variable length array instead.\n", errout.str()); 253 254 settings.standards.c = Standards::C89; 255 settings.standards.cpp = Standards::CPP03; 256 check("void f()\n" 257 "{\n" 258 " char *x = alloca(10);\n" 259 "}", "test.cpp"); // #4382 - there are no VLAs in C++ 260 ASSERT_EQUALS("", errout.str()); 261 262 check("void f()\n" 263 "{\n" 264 " char *x = alloca(10);\n" 265 "}", "test.c"); // #7558 - no alternative to alloca in C89 266 ASSERT_EQUALS("", errout.str()); 267 268 check("void f()\n" 269 "{\n" 270 " char *x = alloca(10);\n" 271 "}", "test.c"); 272 ASSERT_EQUALS("", errout.str()); 273 settings.standards.c = Standards::C11; 274 settings.standards.cpp = Standards::CPP11; 275 } 276 277 // ticket #3121 prohibitedFunctions_declaredFunction()278 void prohibitedFunctions_declaredFunction() { 279 check("int ftime ( int a )\n" 280 "{\n" 281 " return a;\n" 282 "}\n" 283 "int main ()\n" 284 "{\n" 285 " int b ; b = ftime ( 1 ) ;\n" 286 " return 0 ;\n" 287 "}"); 288 ASSERT_EQUALS("", errout.str()); 289 } 290 291 // test std::gets prohibitedFunctions_std_gets()292 void prohibitedFunctions_std_gets() { 293 check("void f(char * str)\n" 294 "{\n" 295 " char *x = std::gets(str);\n" 296 " char *y = gets(str);\n" 297 "}"); 298 ASSERT_EQUALS("[test.cpp:3]: (warning) Obsolete function 'gets' called. It is recommended to use 'fgets' or 'gets_s' instead.\n" 299 "[test.cpp:4]: (warning) Obsolete function 'gets' called. It is recommended to use 'fgets' or 'gets_s' instead.\n", errout.str()); 300 } 301 302 // multiple use prohibitedFunctions_multiple()303 void prohibitedFunctions_multiple() { 304 check("void f(char * str)\n" 305 "{\n" 306 " char *x = std::gets(str);\n" 307 " usleep( 1000 );\n" 308 "}"); 309 ASSERT_EQUALS("[test.cpp:3]: (warning) Obsolete function 'gets' called. It is recommended to use 'fgets' or 'gets_s' instead.\n" 310 "[test.cpp:4]: (style) Obsolescent function 'usleep' called. It is recommended to use 'nanosleep' or 'setitimer' instead.\n", errout.str()); 311 } 312 prohibitedFunctions_c_declaration()313 void prohibitedFunctions_c_declaration() { 314 check("char * gets ( char * c ) ;\n" 315 "int main ()\n" 316 "{\n" 317 " char s [ 10 ] ;\n" 318 " gets ( s ) ;\n" 319 " return 0;\n" 320 "}"); 321 ASSERT_EQUALS("[test.cpp:5]: (warning) Obsolete function 'gets' called. It is recommended to use 'fgets' or 'gets_s' instead.\n", errout.str()); 322 323 check("int getcontext(ucontext_t *ucp);\n" 324 "void f (ucontext_t *ucp)\n" 325 "{\n" 326 " getcontext ( ucp ) ;\n" 327 "}"); 328 ASSERT_EQUALS("[test.cpp:4]: (portability) Obsolescent function 'getcontext' called. Applications are recommended to be rewritten to use POSIX threads.\n", errout.str()); 329 } 330 prohibitedFunctions_functionWithBody()331 void prohibitedFunctions_functionWithBody() { 332 check("char * gets ( char * c ) { return c; }\n" 333 "int main ()\n" 334 "{\n" 335 " char s [ 10 ] ;\n" 336 " gets ( s ) ;\n" 337 " return 0;\n" 338 "}"); 339 ASSERT_EQUALS("", errout.str()); 340 } 341 prohibitedFunctions_crypt()342 void prohibitedFunctions_crypt() { 343 check("void f(char *pwd)\n" 344 "{\n" 345 " char *cpwd;" 346 " crypt(pwd, cpwd);\n" 347 "}"); 348 ASSERT_EQUALS("[test.cpp:3]: (warning) Return value of function crypt() is not used.\n" 349 "[test.cpp:3]: (portability) Non reentrant function 'crypt' called. For threadsafe applications it is recommended to use the reentrant replacement function 'crypt_r'.\n", errout.str()); 350 351 check("void f()\n" 352 "{\n" 353 " char *pwd = getpass(\"Password:\");" 354 " char *cpwd;" 355 " crypt(pwd, cpwd);\n" 356 "}"); 357 ASSERT_EQUALS("[test.cpp:3]: (warning) Return value of function crypt() is not used.\n" 358 "[test.cpp:3]: (portability) Non reentrant function 'crypt' called. For threadsafe applications it is recommended to use the reentrant replacement function 'crypt_r'.\n", errout.str()); 359 360 check("int f()\n" 361 "{\n" 362 " int crypt = 0;" 363 " return crypt;\n" 364 "}"); 365 ASSERT_EQUALS("", errout.str()); 366 } 367 prohibitedFunctions_namespaceHandling()368 void prohibitedFunctions_namespaceHandling() { 369 check("void f()\n" 370 "{\n" 371 " time_t t = 0;" 372 " std::localtime(&t);\n" 373 "}"); 374 ASSERT_EQUALS("[test.cpp:3]: (portability) Non reentrant function 'localtime' called. For threadsafe applications it is recommended to use the reentrant replacement function 'localtime_r'.\n", errout.str()); 375 376 // Passed as function argument 377 check("void f()\n" 378 "{\n" 379 " printf(\"Magic guess: %d\", getpwent());\n" 380 "}"); 381 ASSERT_EQUALS("[test.cpp:3]: (portability) Non reentrant function 'getpwent' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getpwent_r'.\n", errout.str()); 382 383 // Pass return value 384 check("void f()\n" 385 "{\n" 386 " time_t t = 0;" 387 " struct tm *foo = localtime(&t);\n" 388 "}"); 389 ASSERT_EQUALS("[test.cpp:3]: (portability) Non reentrant function 'localtime' called. For threadsafe applications it is recommended to use the reentrant replacement function 'localtime_r'.\n", errout.str()); 390 391 // Access via global namespace 392 check("void f()\n" 393 "{\n" 394 " ::getpwent();\n" 395 "}"); 396 ASSERT_EQUALS("[test.cpp:3]: (warning) Return value of function getpwent() is not used.\n" 397 "[test.cpp:3]: (portability) Non reentrant function 'getpwent' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getpwent_r'.\n", errout.str()); 398 399 // Be quiet on function definitions 400 check("int getpwent()\n" 401 "{\n" 402 " return 123;\n" 403 "}"); 404 ASSERT_EQUALS("", errout.str()); 405 406 // Be quiet on other namespaces 407 check("void f()\n" 408 "{\n" 409 " foobar::getpwent();\n" 410 "}"); 411 ASSERT_EQUALS("", errout.str()); 412 413 // Be quiet on class member functions 414 check("void f()\n" 415 "{\n" 416 " foobar.getpwent();\n" 417 "}"); 418 ASSERT_EQUALS("", errout.str()); 419 } 420 invalidFunctionUsage1()421 void invalidFunctionUsage1() { 422 check("void f() { memset(a,b,sizeof(a)!=12); }"); 423 ASSERT_EQUALS("[test.cpp:1]: (error) Invalid memset() argument nr 3. A non-boolean value is required.\n", errout.str()); 424 425 check("void f() { memset(a,b,sizeof(a)!=0); }"); 426 ASSERT_EQUALS("[test.cpp:1]: (error) Invalid memset() argument nr 3. A non-boolean value is required.\n", errout.str()); 427 428 check("void f() { memset(a,b,!c); }"); 429 ASSERT_EQUALS("[test.cpp:1]: (error) Invalid memset() argument nr 3. A non-boolean value is required.\n", errout.str()); 430 431 // Ticket #6990 432 check("void f(bool c) { memset(a,b,c); }"); 433 ASSERT_EQUALS("[test.cpp:1]: (error) Invalid memset() argument nr 3. A non-boolean value is required.\n", errout.str()); 434 check("void f() { memset(a,b,true); }"); 435 ASSERT_EQUALS("[test.cpp:1]: (error) Invalid memset() argument nr 3. A non-boolean value is required.\n", errout.str()); 436 437 // Ticket #6588 (c mode) 438 check("void record(char* buf, int n) {\n" 439 " memset(buf, 0, n < 255);\n" /* KO */ 440 " memset(buf, 0, n < 255 ? n : 255);\n" /* OK */ 441 "}", "test.c"); 442 ASSERT_EQUALS("[test.c:2]: (error) Invalid memset() argument nr 3. A non-boolean value is required.\n", errout.str()); 443 444 // Ticket #6588 (c++ mode) 445 check("void record(char* buf, int n) {\n" 446 " memset(buf, 0, n < 255);\n" /* KO */ 447 " memset(buf, 0, n < 255 ? n : 255);\n" /* OK */ 448 "}"); 449 ASSERT_EQUALS("[test.cpp:2]: (error) Invalid memset() argument nr 3. A non-boolean value is required.\n", errout.str()); 450 451 check("int boolArgZeroIsInvalidButOneIsValid(int a, int param) {\n" 452 " return div(a, param > 0);\n" 453 "}"); 454 ASSERT_EQUALS("[test.cpp:2]: (error) Invalid div() argument nr 2. The value is 0 or 1 (boolean) but the valid values are ':-1,1:'.\n", errout.str()); 455 456 check("void boolArgZeroIsValidButOneIsInvalid(int param) {\n" 457 " strtol(a, b, param > 0);\n" 458 "}"); 459 ASSERT_EQUALS("[test.cpp:2]: (error) Invalid strtol() argument nr 3. The value is 0 or 1 (boolean) but the valid values are '0,2:36'.\n", errout.str()); 460 461 check("void f() { strtol(a,b,1); }"); 462 ASSERT_EQUALS("[test.cpp:1]: (error) Invalid strtol() argument nr 3. The value is 1 but the valid values are '0,2:36'.\n", errout.str()); 463 464 check("void f() { strtol(a,b,10); }"); 465 ASSERT_EQUALS("", errout.str()); 466 } 467 invalidFunctionUsageStrings()468 void invalidFunctionUsageStrings() { 469 check("size_t f() { char x = 'x'; return strlen(&x); }"); 470 ASSERT_EQUALS("[test.cpp:1]: (error) Invalid strlen() argument nr 1. A nul-terminated string is required.\n", errout.str()); 471 472 check("size_t f() { return strlen(&x); }"); 473 ASSERT_EQUALS("", errout.str()); 474 475 check("size_t f(char x) { return strlen(&x); }"); 476 ASSERT_EQUALS("[test.cpp:1]: (error) Invalid strlen() argument nr 1. A nul-terminated string is required.\n", errout.str()); 477 478 check("size_t f() { char x = '\\0'; return strlen(&x); }"); 479 ASSERT_EQUALS("", errout.str()); 480 481 check("size_t f() {\n" 482 " char x;\n" 483 " if (y)\n" 484 " x = '\\0';\n" 485 " else\n" 486 " x = 'a';\n" 487 " return strlen(&x);\n" 488 "}"); 489 ASSERT_EQUALS("[test.cpp:7]: (error) Invalid strlen() argument nr 1. A nul-terminated string is required.\n", errout.str()); 490 491 check("int f() { char x = '\\0'; return strcmp(\"Hello world\", &x); }"); 492 ASSERT_EQUALS("", errout.str()); 493 494 check("int f() { char x = 'x'; return strcmp(\"Hello world\", &x); }"); 495 ASSERT_EQUALS("[test.cpp:1]: (error) Invalid strcmp() argument nr 2. A nul-terminated string is required.\n", errout.str()); 496 497 check("size_t f(char x) { char * y = &x; return strlen(y); }"); 498 TODO_ASSERT_EQUALS("[test.cpp:1]: (error) Invalid strlen() argument nr 1. A nul-terminated string is required.\n", "", errout.str()); 499 500 check("size_t f(char x) { char * y = &x; char *z = y; return strlen(z); }"); 501 TODO_ASSERT_EQUALS("[test.cpp:1]: (error) Invalid strlen() argument nr 1. A nul-terminated string is required.\n", "", errout.str()); 502 503 check("size_t f() { char x = 'x'; char * y = &x; char *z = y; return strlen(z); }"); 504 TODO_ASSERT_EQUALS("[test.cpp:1]: (error) Invalid strlen() argument nr 1. A nul-terminated string is required.\n", "", errout.str()); 505 506 check("size_t f() { char x = '\\0'; char * y = &x; char *z = y; return strlen(z); }"); 507 ASSERT_EQUALS("", errout.str()); 508 509 check("size_t f() { char x[] = \"Hello world\"; return strlen(x); }"); 510 ASSERT_EQUALS("", errout.str()); 511 512 check("size_t f(char x[]) { return strlen(x); }"); 513 ASSERT_EQUALS("", errout.str()); 514 515 check("int f(char x, char y) { return strcmp(&x, &y); }"); 516 ASSERT_EQUALS("[test.cpp:1]: (error) Invalid strcmp() argument nr 1. A nul-terminated string is required.\n" 517 "[test.cpp:1]: (error) Invalid strcmp() argument nr 2. A nul-terminated string is required.\n", errout.str()); 518 519 check("size_t f() { char x[] = \"Hello world\"; return strlen(&x[0]); }"); 520 ASSERT_EQUALS("", errout.str()); 521 522 check("size_t f() { char* x = \"Hello world\"; return strlen(&x[0]); }"); 523 ASSERT_EQUALS("", errout.str()); 524 525 check("struct S {\n" 526 " char x;\n" 527 "};\n" 528 "size_t f() {\n" 529 " S s1 = {0};\n" 530 " S s2;\n;" 531 " s2.x = 'x';\n" 532 " size_t l1 = strlen(&s1.x);\n" 533 " size_t l2 = strlen(&s2.x);\n" 534 " return l1 + l2;\n" 535 "}"); 536 TODO_ASSERT_EQUALS("[test.cpp:9]: (error) Invalid strlen() argument nr 1. A nul-terminated string is required.\n", "", errout.str()); 537 538 check("const char x = 'x'; size_t f() { return strlen(&x); }"); 539 TODO_ASSERT_EQUALS("[test.cpp:1]: (error) Invalid strlen() argument nr 1. A nul-terminated string is required.\n", "", errout.str()); 540 541 check("const char x = 'x'; size_t f() { char y = x; return strlen(&y); }"); 542 ASSERT_EQUALS("[test.cpp:1]: (error) Invalid strlen() argument nr 1. A nul-terminated string is required.\n", errout.str()); 543 544 check("const char x = '\\0'; size_t f() { return strlen(&x); }"); 545 ASSERT_EQUALS("", errout.str()); 546 547 check("const char x = '\\0'; size_t f() { char y = x; return strlen(&y); }"); 548 ASSERT_EQUALS("", errout.str()); 549 550 check("size_t f() {\n" 551 " char * a = \"Hello world\";\n" 552 " char ** b = &a;\n" 553 " return strlen(&b[0][0]);\n" 554 "}"); 555 ASSERT_EQUALS("", errout.str()); 556 557 check("size_t f() {\n" 558 " char ca[] = \"asdf\";\n" 559 " return strlen((char*) &ca);\n" 560 "}"); 561 ASSERT_EQUALS("", errout.str()); 562 563 // #5225 564 check("int main(void)\n" 565 "{\n" 566 " char str[80] = \"hello worl\";\n" 567 " char d = 'd';\n" 568 " strcat(str, &d);\n" 569 " puts(str);\n" 570 " return 0;\n" 571 "}"); 572 ASSERT_EQUALS("[test.cpp:5]: (error) Invalid strcat() argument nr 2. A nul-terminated string is required.\n", errout.str()); 573 } 574 mathfunctionCall_sqrt()575 void mathfunctionCall_sqrt() { 576 // sqrt, sqrtf, sqrtl 577 check("void foo()\n" 578 "{\n" 579 " std::cout << sqrt(-1) << std::endl;\n" 580 " std::cout << sqrtf(-1) << std::endl;\n" 581 " std::cout << sqrtl(-1) << std::endl;\n" 582 "}"); 583 ASSERT_EQUALS("[test.cpp:3]: (error) Invalid sqrt() argument nr 1. The value is -1 but the valid values are '0.0:'.\n" 584 "[test.cpp:4]: (error) Invalid sqrtf() argument nr 1. The value is -1 but the valid values are '0.0:'.\n" 585 "[test.cpp:5]: (error) Invalid sqrtl() argument nr 1. The value is -1 but the valid values are '0.0:'.\n", errout.str()); 586 587 // implementation-defined behaviour for "finite values of x<0" only: 588 check("void foo()\n" 589 "{\n" 590 " std::cout << sqrt(-0.) << std::endl;\n" 591 " std::cout << sqrtf(-0.) << std::endl;\n" 592 " std::cout << sqrtl(-0.) << std::endl;\n" 593 "}"); 594 ASSERT_EQUALS("", errout.str()); 595 596 check("void foo()\n" 597 "{\n" 598 " std::cout << sqrt(1) << std::endl;\n" 599 " std::cout << sqrtf(1) << std::endl;\n" 600 " std::cout << sqrtl(1) << std::endl;\n" 601 "}"); 602 ASSERT_EQUALS("", errout.str()); 603 } 604 mathfunctionCall_log()605 void mathfunctionCall_log() { 606 // log,log10,logf,logl,log10f,log10l,log2,log2f,log2l,log1p,log1pf,log1pl 607 check("void foo()\n" 608 "{\n" 609 " std::cout << log(-2) << std::endl;\n" 610 " std::cout << logf(-2) << std::endl;\n" 611 " std::cout << logl(-2) << std::endl;\n" 612 " std::cout << log10(-2) << std::endl;\n" 613 " std::cout << log10f(-2) << std::endl;\n" 614 " std::cout << log10l(-2) << std::endl;\n" 615 " std::cout << log2(-2) << std::endl;\n" 616 " std::cout << log2f(-2) << std::endl;\n" 617 " std::cout << log2l(-2) << std::endl;\n" 618 " std::cout << log1p(-3) << std::endl;\n" 619 " std::cout << log1pf(-3) << std::endl;\n" 620 " std::cout << log1pl(-3) << std::endl;\n" 621 "}"); 622 ASSERT_EQUALS("[test.cpp:3]: (error) Invalid log() argument nr 1. The value is -2 but the valid values are '4.94066e-324:'.\n" 623 "[test.cpp:4]: (error) Invalid logf() argument nr 1. The value is -2 but the valid values are '1.4013e-45:'.\n" 624 "[test.cpp:5]: (error) Invalid logl() argument nr 1. The value is -2 but the valid values are '4.94066e-324:'.\n" 625 "[test.cpp:6]: (error) Invalid log10() argument nr 1. The value is -2 but the valid values are '4.94066e-324:'.\n" 626 "[test.cpp:7]: (error) Invalid log10f() argument nr 1. The value is -2 but the valid values are '1.4013e-45:'.\n" 627 "[test.cpp:8]: (error) Invalid log10l() argument nr 1. The value is -2 but the valid values are '4.94066e-324:'.\n" 628 "[test.cpp:9]: (error) Invalid log2() argument nr 1. The value is -2 but the valid values are '4.94066e-324:'.\n" 629 "[test.cpp:10]: (error) Invalid log2f() argument nr 1. The value is -2 but the valid values are '1.4013e-45:'.\n" 630 "[test.cpp:11]: (error) Invalid log2l() argument nr 1. The value is -2 but the valid values are '4.94066e-324:'.\n" 631 "[test.cpp:3]: (warning) Passing value -2 to log() leads to implementation-defined result.\n" 632 "[test.cpp:4]: (warning) Passing value -2 to logf() leads to implementation-defined result.\n" 633 "[test.cpp:5]: (warning) Passing value -2 to logl() leads to implementation-defined result.\n" 634 "[test.cpp:6]: (warning) Passing value -2 to log10() leads to implementation-defined result.\n" 635 "[test.cpp:7]: (warning) Passing value -2 to log10f() leads to implementation-defined result.\n" 636 "[test.cpp:8]: (warning) Passing value -2 to log10l() leads to implementation-defined result.\n" 637 "[test.cpp:9]: (warning) Passing value -2 to log2() leads to implementation-defined result.\n" 638 "[test.cpp:10]: (warning) Passing value -2 to log2f() leads to implementation-defined result.\n" 639 "[test.cpp:11]: (warning) Passing value -2 to log2l() leads to implementation-defined result.\n" 640 "[test.cpp:12]: (warning) Passing value -3 to log1p() leads to implementation-defined result.\n" 641 "[test.cpp:13]: (warning) Passing value -3 to log1pf() leads to implementation-defined result.\n" 642 "[test.cpp:14]: (warning) Passing value -3 to log1pl() leads to implementation-defined result.\n", errout.str()); 643 644 check("void foo()\n" 645 "{\n" 646 " std::cout << log(-1) << std::endl;\n" 647 " std::cout << logf(-1) << std::endl;\n" 648 " std::cout << logl(-1) << std::endl;\n" 649 " std::cout << log10(-1) << std::endl;\n" 650 " std::cout << log10f(-1) << std::endl;\n" 651 " std::cout << log10l(-1) << std::endl;\n" 652 " std::cout << log2(-1) << std::endl;\n" 653 " std::cout << log2f(-1) << std::endl;\n" 654 " std::cout << log2l(-1) << std::endl;\n" 655 " std::cout << log1p(-2) << std::endl;\n" 656 " std::cout << log1pf(-2) << std::endl;\n" 657 " std::cout << log1pl(-2) << std::endl;\n" 658 "}"); 659 ASSERT_EQUALS("[test.cpp:3]: (error) Invalid log() argument nr 1. The value is -1 but the valid values are '4.94066e-324:'.\n" 660 "[test.cpp:4]: (error) Invalid logf() argument nr 1. The value is -1 but the valid values are '1.4013e-45:'.\n" 661 "[test.cpp:5]: (error) Invalid logl() argument nr 1. The value is -1 but the valid values are '4.94066e-324:'.\n" 662 "[test.cpp:6]: (error) Invalid log10() argument nr 1. The value is -1 but the valid values are '4.94066e-324:'.\n" 663 "[test.cpp:7]: (error) Invalid log10f() argument nr 1. The value is -1 but the valid values are '1.4013e-45:'.\n" 664 "[test.cpp:8]: (error) Invalid log10l() argument nr 1. The value is -1 but the valid values are '4.94066e-324:'.\n" 665 "[test.cpp:9]: (error) Invalid log2() argument nr 1. The value is -1 but the valid values are '4.94066e-324:'.\n" 666 "[test.cpp:10]: (error) Invalid log2f() argument nr 1. The value is -1 but the valid values are '1.4013e-45:'.\n" 667 "[test.cpp:11]: (error) Invalid log2l() argument nr 1. The value is -1 but the valid values are '4.94066e-324:'.\n" 668 "[test.cpp:3]: (warning) Passing value -1 to log() leads to implementation-defined result.\n" 669 "[test.cpp:4]: (warning) Passing value -1 to logf() leads to implementation-defined result.\n" 670 "[test.cpp:5]: (warning) Passing value -1 to logl() leads to implementation-defined result.\n" 671 "[test.cpp:6]: (warning) Passing value -1 to log10() leads to implementation-defined result.\n" 672 "[test.cpp:7]: (warning) Passing value -1 to log10f() leads to implementation-defined result.\n" 673 "[test.cpp:8]: (warning) Passing value -1 to log10l() leads to implementation-defined result.\n" 674 "[test.cpp:9]: (warning) Passing value -1 to log2() leads to implementation-defined result.\n" 675 "[test.cpp:10]: (warning) Passing value -1 to log2f() leads to implementation-defined result.\n" 676 "[test.cpp:11]: (warning) Passing value -1 to log2l() leads to implementation-defined result.\n" 677 "[test.cpp:12]: (warning) Passing value -2 to log1p() leads to implementation-defined result.\n" 678 "[test.cpp:13]: (warning) Passing value -2 to log1pf() leads to implementation-defined result.\n" 679 "[test.cpp:14]: (warning) Passing value -2 to log1pl() leads to implementation-defined result.\n", errout.str()); 680 681 check("void foo()\n" 682 "{\n" 683 " std::cout << log(-1.0) << std::endl;\n" 684 " std::cout << logf(-1.0) << std::endl;\n" 685 " std::cout << logl(-1.0) << std::endl;\n" 686 " std::cout << log10(-1.0) << std::endl;\n" 687 " std::cout << log10f(-1.0) << std::endl;\n" 688 " std::cout << log10l(-1.0) << std::endl;\n" 689 " std::cout << log2(-1.0) << std::endl;\n" 690 " std::cout << log2f(-1.0) << std::endl;\n" 691 " std::cout << log2l(-1.0) << std::endl;\n" 692 " std::cout << log1p(-2.0) << std::endl;\n" 693 " std::cout << log1pf(-2.0) << std::endl;\n" 694 " std::cout << log1pl(-2.0) << std::endl;\n" 695 "}"); 696 ASSERT_EQUALS("[test.cpp:3]: (error) Invalid log() argument nr 1. The value is -1 but the valid values are '4.94066e-324:'.\n" 697 "[test.cpp:4]: (error) Invalid logf() argument nr 1. The value is -1 but the valid values are '1.4013e-45:'.\n" 698 "[test.cpp:5]: (error) Invalid logl() argument nr 1. The value is -1 but the valid values are '4.94066e-324:'.\n" 699 "[test.cpp:6]: (error) Invalid log10() argument nr 1. The value is -1 but the valid values are '4.94066e-324:'.\n" 700 "[test.cpp:7]: (error) Invalid log10f() argument nr 1. The value is -1 but the valid values are '1.4013e-45:'.\n" 701 "[test.cpp:8]: (error) Invalid log10l() argument nr 1. The value is -1 but the valid values are '4.94066e-324:'.\n" 702 "[test.cpp:9]: (error) Invalid log2() argument nr 1. The value is -1 but the valid values are '4.94066e-324:'.\n" 703 "[test.cpp:10]: (error) Invalid log2f() argument nr 1. The value is -1 but the valid values are '1.4013e-45:'.\n" 704 "[test.cpp:11]: (error) Invalid log2l() argument nr 1. The value is -1 but the valid values are '4.94066e-324:'.\n" 705 "[test.cpp:3]: (warning) Passing value -1.0 to log() leads to implementation-defined result.\n" 706 "[test.cpp:4]: (warning) Passing value -1.0 to logf() leads to implementation-defined result.\n" 707 "[test.cpp:5]: (warning) Passing value -1.0 to logl() leads to implementation-defined result.\n" 708 "[test.cpp:6]: (warning) Passing value -1.0 to log10() leads to implementation-defined result.\n" 709 "[test.cpp:7]: (warning) Passing value -1.0 to log10f() leads to implementation-defined result.\n" 710 "[test.cpp:8]: (warning) Passing value -1.0 to log10l() leads to implementation-defined result.\n" 711 "[test.cpp:9]: (warning) Passing value -1.0 to log2() leads to implementation-defined result.\n" 712 "[test.cpp:10]: (warning) Passing value -1.0 to log2f() leads to implementation-defined result.\n" 713 "[test.cpp:11]: (warning) Passing value -1.0 to log2l() leads to implementation-defined result.\n" 714 "[test.cpp:12]: (warning) Passing value -2.0 to log1p() leads to implementation-defined result.\n" 715 "[test.cpp:13]: (warning) Passing value -2.0 to log1pf() leads to implementation-defined result.\n" 716 "[test.cpp:14]: (warning) Passing value -2.0 to log1pl() leads to implementation-defined result.\n", errout.str()); 717 718 check("void foo()\n" 719 "{\n" 720 " std::cout << log(-0.1) << std::endl;\n" 721 " std::cout << logf(-0.1) << std::endl;\n" 722 " std::cout << logl(-0.1) << std::endl;\n" 723 " std::cout << log10(-0.1) << std::endl;\n" 724 " std::cout << log10f(-0.1) << std::endl;\n" 725 " std::cout << log10l(-0.1) << std::endl;\n" 726 " std::cout << log2(-0.1) << std::endl;\n" 727 " std::cout << log2f(-0.1) << std::endl;\n" 728 " std::cout << log2l(-0.1) << std::endl;\n" 729 " std::cout << log1p(-1.1) << std::endl;\n" 730 " std::cout << log1pf(-1.1) << std::endl;\n" 731 " std::cout << log1pl(-1.1) << std::endl;\n" 732 "}"); 733 ASSERT_EQUALS("[test.cpp:3]: (error) Invalid log() argument nr 1. The value is -0.1 but the valid values are '4.94066e-324:'.\n" 734 "[test.cpp:4]: (error) Invalid logf() argument nr 1. The value is -0.1 but the valid values are '1.4013e-45:'.\n" 735 "[test.cpp:5]: (error) Invalid logl() argument nr 1. The value is -0.1 but the valid values are '4.94066e-324:'.\n" 736 "[test.cpp:6]: (error) Invalid log10() argument nr 1. The value is -0.1 but the valid values are '4.94066e-324:'.\n" 737 "[test.cpp:7]: (error) Invalid log10f() argument nr 1. The value is -0.1 but the valid values are '1.4013e-45:'.\n" 738 "[test.cpp:8]: (error) Invalid log10l() argument nr 1. The value is -0.1 but the valid values are '4.94066e-324:'.\n" 739 "[test.cpp:9]: (error) Invalid log2() argument nr 1. The value is -0.1 but the valid values are '4.94066e-324:'.\n" 740 "[test.cpp:10]: (error) Invalid log2f() argument nr 1. The value is -0.1 but the valid values are '1.4013e-45:'.\n" 741 "[test.cpp:11]: (error) Invalid log2l() argument nr 1. The value is -0.1 but the valid values are '4.94066e-324:'.\n" 742 "[test.cpp:3]: (warning) Passing value -0.1 to log() leads to implementation-defined result.\n" 743 "[test.cpp:4]: (warning) Passing value -0.1 to logf() leads to implementation-defined result.\n" 744 "[test.cpp:5]: (warning) Passing value -0.1 to logl() leads to implementation-defined result.\n" 745 "[test.cpp:6]: (warning) Passing value -0.1 to log10() leads to implementation-defined result.\n" 746 "[test.cpp:7]: (warning) Passing value -0.1 to log10f() leads to implementation-defined result.\n" 747 "[test.cpp:8]: (warning) Passing value -0.1 to log10l() leads to implementation-defined result.\n" 748 "[test.cpp:9]: (warning) Passing value -0.1 to log2() leads to implementation-defined result.\n" 749 "[test.cpp:10]: (warning) Passing value -0.1 to log2f() leads to implementation-defined result.\n" 750 "[test.cpp:11]: (warning) Passing value -0.1 to log2l() leads to implementation-defined result.\n" 751 "[test.cpp:12]: (warning) Passing value -1.1 to log1p() leads to implementation-defined result.\n" 752 "[test.cpp:13]: (warning) Passing value -1.1 to log1pf() leads to implementation-defined result.\n" 753 "[test.cpp:14]: (warning) Passing value -1.1 to log1pl() leads to implementation-defined result.\n", errout.str()); 754 755 check("void foo()\n" 756 "{\n" 757 " std::cout << log(0) << std::endl;\n" 758 " std::cout << logf(0.) << std::endl;\n" 759 " std::cout << logl(0.0) << std::endl;\n" 760 " std::cout << log10(0.0) << std::endl;\n" 761 " std::cout << log10f(0) << std::endl;\n" 762 " std::cout << log10l(0.) << std::endl;\n" 763 " std::cout << log2(0.) << std::endl;\n" 764 " std::cout << log2f(0.0) << std::endl;\n" 765 " std::cout << log2l(0) << std::endl;\n" 766 " std::cout << log1p(-1.) << std::endl;\n" 767 " std::cout << log1pf(-1.0) << std::endl;\n" 768 " std::cout << log1pl(-1) << std::endl;\n" 769 "}"); 770 ASSERT_EQUALS("[test.cpp:3]: (error) Invalid log() argument nr 1. The value is 0 but the valid values are '4.94066e-324:'.\n" 771 "[test.cpp:4]: (error) Invalid logf() argument nr 1. The value is 0 but the valid values are '1.4013e-45:'.\n" 772 "[test.cpp:5]: (error) Invalid logl() argument nr 1. The value is 0 but the valid values are '4.94066e-324:'.\n" 773 "[test.cpp:6]: (error) Invalid log10() argument nr 1. The value is 0 but the valid values are '4.94066e-324:'.\n" 774 "[test.cpp:7]: (error) Invalid log10f() argument nr 1. The value is 0 but the valid values are '1.4013e-45:'.\n" 775 "[test.cpp:8]: (error) Invalid log10l() argument nr 1. The value is 0 but the valid values are '4.94066e-324:'.\n" 776 "[test.cpp:9]: (error) Invalid log2() argument nr 1. The value is 0 but the valid values are '4.94066e-324:'.\n" 777 "[test.cpp:10]: (error) Invalid log2f() argument nr 1. The value is 0 but the valid values are '1.4013e-45:'.\n" 778 "[test.cpp:11]: (error) Invalid log2l() argument nr 1. The value is 0 but the valid values are '4.94066e-324:'.\n" 779 "[test.cpp:3]: (warning) Passing value 0 to log() leads to implementation-defined result.\n" 780 "[test.cpp:4]: (warning) Passing value 0. to logf() leads to implementation-defined result.\n" 781 "[test.cpp:5]: (warning) Passing value 0.0 to logl() leads to implementation-defined result.\n" 782 "[test.cpp:6]: (warning) Passing value 0.0 to log10() leads to implementation-defined result.\n" 783 "[test.cpp:7]: (warning) Passing value 0 to log10f() leads to implementation-defined result.\n" 784 "[test.cpp:8]: (warning) Passing value 0. to log10l() leads to implementation-defined result.\n" 785 "[test.cpp:9]: (warning) Passing value 0. to log2() leads to implementation-defined result.\n" 786 "[test.cpp:10]: (warning) Passing value 0.0 to log2f() leads to implementation-defined result.\n" 787 "[test.cpp:11]: (warning) Passing value 0 to log2l() leads to implementation-defined result.\n" 788 "[test.cpp:12]: (warning) Passing value -1. to log1p() leads to implementation-defined result.\n" 789 "[test.cpp:13]: (warning) Passing value -1.0 to log1pf() leads to implementation-defined result.\n" 790 "[test.cpp:14]: (warning) Passing value -1 to log1pl() leads to implementation-defined result.\n", errout.str()); 791 792 check("void foo()\n" 793 "{\n" 794 " std::cout << log(1E-3) << std::endl;\n" 795 " std::cout << logf(1E-3) << std::endl;\n" 796 " std::cout << logl(1E-3) << std::endl;\n" 797 " std::cout << log10(1E-3) << std::endl;\n" 798 " std::cout << log10f(1E-3) << std::endl;\n" 799 " std::cout << log10l(1E-3) << std::endl;\n" 800 " std::cout << log2(1E-3) << std::endl;\n" 801 " std::cout << log2f(1E-3) << std::endl;\n" 802 " std::cout << log2l(1E-3) << std::endl;\n" 803 " std::cout << log1p(-1+1E-3) << std::endl;\n" 804 " std::cout << log1pf(-1+1E-3) << std::endl;\n" 805 " std::cout << log1pl(-1+1E-3) << std::endl;\n" 806 " std::cout << log(1.0E-3) << std::endl;\n" 807 " std::cout << logf(1.0E-3) << std::endl;\n" 808 " std::cout << logl(1.0E-3) << std::endl;\n" 809 " std::cout << log10(1.0E-3) << std::endl;\n" 810 " std::cout << log10f(1.0E-3) << std::endl;\n" 811 " std::cout << log10l(1.0E-3) << std::endl;\n" 812 " std::cout << log2(1.0E-3) << std::endl;\n" 813 " std::cout << log2f(1.0E-3) << std::endl;\n" 814 " std::cout << log2l(1.0E-3) << std::endl;\n" 815 " std::cout << log1p(-1+1.0E-3) << std::endl;\n" 816 " std::cout << log1pf(-1+1.0E-3) << std::endl;\n" 817 " std::cout << log1pl(-1+1.0E-3) << std::endl;\n" 818 " std::cout << log(1.0E+3) << std::endl;\n" 819 " std::cout << logf(1.0E+3) << std::endl;\n" 820 " std::cout << logl(1.0E+3) << std::endl;\n" 821 " std::cout << log10(1.0E+3) << std::endl;\n" 822 " std::cout << log10f(1.0E+3) << std::endl;\n" 823 " std::cout << log10l(1.0E+3) << std::endl;\n" 824 " std::cout << log2(1.0E+3) << std::endl;\n" 825 " std::cout << log2f(1.0E+3) << std::endl;\n" 826 " std::cout << log2l(1.0E+3) << std::endl;\n" 827 " std::cout << log1p(1.0E+3) << std::endl;\n" 828 " std::cout << log1pf(1.0E+3) << std::endl;\n" 829 " std::cout << log1pl(1.0E+3) << std::endl;\n" 830 " std::cout << log(2.0) << std::endl;\n" 831 " std::cout << logf(2.0) << std::endl;\n" 832 " std::cout << logf(2.0f) << std::endl;\n" 833 " std::cout << log10(2.0) << std::endl;\n" 834 " std::cout << log10f(2.0) << std::endl;\n" 835 " std::cout << log10f(2.0f) << std::endl;\n" 836 " std::cout << log2(2.0) << std::endl;\n" 837 " std::cout << log2f(2.0) << std::endl;\n" 838 " std::cout << log2f(2.0f) << std::endl;\n" 839 " std::cout << log1p(2.0) << std::endl;\n" 840 " std::cout << log1pf(2.0) << std::endl;\n" 841 " std::cout << log1pf(2.0f) << std::endl;\n" 842 "}"); 843 ASSERT_EQUALS("", errout.str()); 844 845 check("void foo()\n" 846 "{\n" 847 " std::string *log(0);\n" 848 "}"); 849 ASSERT_EQUALS("", errout.str()); 850 851 // #3473 - no warning if "log" is a variable 852 check("Fred::Fred() : log(0) { }"); 853 ASSERT_EQUALS("", errout.str()); 854 855 // #5748 856 check("void f() { foo.log(0); }"); 857 ASSERT_EQUALS("", errout.str()); 858 } 859 mathfunctionCall_acos()860 void mathfunctionCall_acos() { 861 // acos, acosf, acosl 862 check("void foo()\n" 863 "{\n" 864 " return acos(-1) \n" 865 " + acos(0.1) \n" 866 " + acos(0.0001) \n" 867 " + acos(0.01) \n" 868 " + acos(1.0E-1) \n" 869 " + acos(-1.0E-1) \n" 870 " + acos(+1.0E-1) \n" 871 " + acos(0.1E-1) \n" 872 " + acos(+0.1E-1) \n" 873 " + acos(-0.1E-1) \n" 874 " + acosf(-1) \n" 875 " + acosf(0.1) \n" 876 " + acosf(0.0001) \n" 877 " + acosf(0.01) \n" 878 " + acosf(1.0E-1) \n" 879 " + acosf(-1.0E-1) \n" 880 " + acosf(+1.0E-1) \n" 881 " + acosf(0.1E-1) \n" 882 " + acosf(+0.1E-1) \n" 883 " + acosf(-0.1E-1) \n" 884 " + acosl(-1) \n" 885 " + acosl(0.1) \n" 886 " + acosl(0.0001) \n" 887 " + acosl(0.01) \n" 888 " + acosl(1.0E-1) \n" 889 " + acosl(-1.0E-1) \n" 890 " + acosl(+1.0E-1) \n" 891 " + acosl(0.1E-1) \n" 892 " + acosl(+0.1E-1) \n" 893 " + acosl(-0.1E-1);\n" 894 "}"); 895 ASSERT_EQUALS("", errout.str()); 896 897 check("void foo()\n" 898 "{\n" 899 " std::cout << acos(1.1) << std::endl;\n" 900 " std::cout << acosf(1.1) << std::endl;\n" 901 " std::cout << acosl(1.1) << std::endl;\n" 902 "}"); 903 ASSERT_EQUALS("[test.cpp:3]: (error) Invalid acos() argument nr 1. The value is 1.1 but the valid values are '-1.0:1.0'.\n" 904 "[test.cpp:4]: (error) Invalid acosf() argument nr 1. The value is 1.1 but the valid values are '-1.0:1.0'.\n" 905 "[test.cpp:5]: (error) Invalid acosl() argument nr 1. The value is 1.1 but the valid values are '-1.0:1.0'.\n", errout.str()); 906 907 check("void foo()\n" 908 "{\n" 909 " std::cout << acos(-1.1) << std::endl;\n" 910 " std::cout << acosf(-1.1) << std::endl;\n" 911 " std::cout << acosl(-1.1) << std::endl;\n" 912 "}"); 913 ASSERT_EQUALS("[test.cpp:3]: (error) Invalid acos() argument nr 1. The value is -1.1 but the valid values are '-1.0:1.0'.\n" 914 "[test.cpp:4]: (error) Invalid acosf() argument nr 1. The value is -1.1 but the valid values are '-1.0:1.0'.\n" 915 "[test.cpp:5]: (error) Invalid acosl() argument nr 1. The value is -1.1 but the valid values are '-1.0:1.0'.\n", errout.str()); 916 } 917 mathfunctionCall_asin()918 void mathfunctionCall_asin() { 919 // asin, asinf, asinl 920 check("void foo()\n" 921 "{\n" 922 " return asin(1) \n" 923 " + asin(-1) \n" 924 " + asin(0.1) \n" 925 " + asin(0.0001) \n" 926 " + asin(0.01) \n" 927 " + asin(1.0E-1) \n" 928 " + asin(-1.0E-1) \n" 929 " + asin(+1.0E-1) \n" 930 " + asin(0.1E-1) \n" 931 " + asin(+0.1E-1) \n" 932 " + asin(-0.1E-1) \n" 933 " + asinf(1) \n" 934 " + asinf(-1) \n" 935 " + asinf(0.1) \n" 936 " + asinf(0.0001) \n" 937 " + asinf(0.01) \n" 938 " + asinf(1.0E-1) \n" 939 " + asinf(-1.0E-1) \n" 940 " + asinf(+1.0E-1) \n" 941 " + asinf(0.1E-1) \n" 942 " + asinf(+0.1E-1) \n" 943 " + asinf(-0.1E-1) \n" 944 " + asinl(1) \n" 945 " + asinl(-1) \n" 946 " + asinl(0.1) \n" 947 " + asinl(0.0001) \n" 948 " + asinl(0.01) \n" 949 " + asinl(1.0E-1) \n" 950 " + asinl(-1.0E-1) \n" 951 " + asinl(+1.0E-1) \n" 952 " + asinl(0.1E-1) \n" 953 " + asinl(+0.1E-1) \n" 954 " + asinl(-0.1E-1);\n" 955 "}"); 956 ASSERT_EQUALS("", errout.str()); 957 958 check("void foo()\n" 959 "{\n" 960 " std::cout << asin(1.1) << std::endl;\n" 961 " std::cout << asinf(1.1) << std::endl;\n" 962 " std::cout << asinl(1.1) << std::endl;\n" 963 "}"); 964 ASSERT_EQUALS("[test.cpp:3]: (error) Invalid asin() argument nr 1. The value is 1.1 but the valid values are '-1.0:1.0'.\n" 965 "[test.cpp:4]: (error) Invalid asinf() argument nr 1. The value is 1.1 but the valid values are '-1.0:1.0'.\n" 966 "[test.cpp:5]: (error) Invalid asinl() argument nr 1. The value is 1.1 but the valid values are '-1.0:1.0'.\n", errout.str()); 967 968 check("void foo()\n" 969 "{\n" 970 " std::cout << asin(-1.1) << std::endl;\n" 971 " std::cout << asinf(-1.1) << std::endl;\n" 972 " std::cout << asinl(-1.1) << std::endl;\n" 973 "}"); 974 ASSERT_EQUALS("[test.cpp:3]: (error) Invalid asin() argument nr 1. The value is -1.1 but the valid values are '-1.0:1.0'.\n" 975 "[test.cpp:4]: (error) Invalid asinf() argument nr 1. The value is -1.1 but the valid values are '-1.0:1.0'.\n" 976 "[test.cpp:5]: (error) Invalid asinl() argument nr 1. The value is -1.1 but the valid values are '-1.0:1.0'.\n", errout.str()); 977 } 978 mathfunctionCall_pow()979 void mathfunctionCall_pow() { 980 // pow, powf, powl 981 check("void foo()\n" 982 "{\n" 983 " std::cout << pow(0,-10) << std::endl;\n" 984 " std::cout << powf(0,-10) << std::endl;\n" 985 " std::cout << powl(0,-10) << std::endl;\n" 986 "}"); 987 ASSERT_EQUALS("[test.cpp:3]: (warning) Passing values 0 and -10 to pow() leads to implementation-defined result.\n" 988 "[test.cpp:4]: (warning) Passing values 0 and -10 to powf() leads to implementation-defined result.\n" 989 "[test.cpp:5]: (warning) Passing values 0 and -10 to powl() leads to implementation-defined result.\n", errout.str()); 990 991 check("void foo()\n" 992 "{\n" 993 " std::cout << pow(0,10) << std::endl;\n" 994 " std::cout << powf(0,10) << std::endl;\n" 995 " std::cout << powl(0,10) << std::endl;\n" 996 "}"); 997 ASSERT_EQUALS("", errout.str()); 998 } 999 mathfunctionCall_atan2()1000 void mathfunctionCall_atan2() { 1001 // atan2 1002 check("void foo()\n" 1003 "{\n" 1004 " std::cout << atan2(1,1) ;\n" 1005 " std::cout << atan2(-1,-1) ;\n" 1006 " std::cout << atan2(0.1,1) ;\n" 1007 " std::cout << atan2(0.0001,100) ;\n" 1008 " std::cout << atan2(0.0,1e-1) ;\n" 1009 " std::cout << atan2(1.0E-1,-3) ;\n" 1010 " std::cout << atan2(-1.0E-1,+2) ;\n" 1011 " std::cout << atan2(+1.0E-1,0) ;\n" 1012 " std::cout << atan2(0.1E-1,3) ;\n" 1013 " std::cout << atan2(+0.1E-1,1) ;\n" 1014 " std::cout << atan2(-0.1E-1,8) ;\n" 1015 " std::cout << atan2f(1,1) ;\n" 1016 " std::cout << atan2f(-1,-1) ;\n" 1017 " std::cout << atan2f(0.1,1) ;\n" 1018 " std::cout << atan2f(0.0001,100) ;\n" 1019 " std::cout << atan2f(0.0,1e-1) ;\n" 1020 " std::cout << atan2f(1.0E-1,-3) ;\n" 1021 " std::cout << atan2f(-1.0E-1,+2) ;\n" 1022 " std::cout << atan2f(+1.0E-1,0) ;\n" 1023 " std::cout << atan2f(0.1E-1,3) ;\n" 1024 " std::cout << atan2f(+0.1E-1,1) ;\n" 1025 " std::cout << atan2f(-0.1E-1,8) ;\n" 1026 " std::cout << atan2l(1,1) ;\n" 1027 " std::cout << atan2l(-1,-1) ;\n" 1028 " std::cout << atan2l(0.1,1) ;\n" 1029 " std::cout << atan2l(0.0001,100) ;\n" 1030 " std::cout << atan2l(0.0,1e-1) ;\n" 1031 " std::cout << atan2l(1.0E-1,-3) ;\n" 1032 " std::cout << atan2l(-1.0E-1,+2) ;\n" 1033 " std::cout << atan2l(+1.0E-1,0) ;\n" 1034 " std::cout << atan2l(0.1E-1,3) ;\n" 1035 " std::cout << atan2l(+0.1E-1,1) ;\n" 1036 " std::cout << atan2l(-0.1E-1,8) ;\n" 1037 "}"); 1038 ASSERT_EQUALS("", errout.str()); 1039 1040 check("void foo()\n" 1041 "{\n" 1042 " std::cout << atan2(0,0) << std::endl;\n" 1043 " std::cout << atan2f(0,0) << std::endl;\n" 1044 " std::cout << atan2l(0,0) << std::endl;\n" 1045 "}"); 1046 ASSERT_EQUALS("[test.cpp:3]: (warning) Passing values 0 and 0 to atan2() leads to implementation-defined result.\n" 1047 "[test.cpp:4]: (warning) Passing values 0 and 0 to atan2f() leads to implementation-defined result.\n" 1048 "[test.cpp:5]: (warning) Passing values 0 and 0 to atan2l() leads to implementation-defined result.\n", errout.str()); 1049 } 1050 mathfunctionCall_fmod()1051 void mathfunctionCall_fmod() { 1052 // fmod, fmodl, fmodf 1053 check("void foo()\n" 1054 "{\n" 1055 " std::cout << fmod(1.0,0) << std::endl;\n" 1056 " std::cout << fmodf(1.0,0) << std::endl;\n" 1057 " std::cout << fmodl(1.0,0) << std::endl;\n" 1058 "}"); 1059 ASSERT_EQUALS("[test.cpp:3]: (warning) Passing values 1.0 and 0 to fmod() leads to implementation-defined result.\n" 1060 "[test.cpp:4]: (warning) Passing values 1.0 and 0 to fmodf() leads to implementation-defined result.\n" 1061 "[test.cpp:5]: (warning) Passing values 1.0 and 0 to fmodl() leads to implementation-defined result.\n", errout.str()); 1062 1063 check("void foo()\n" 1064 "{\n" 1065 " std::cout << fmod(1.0,1) << std::endl;\n" 1066 " std::cout << fmodf(1.0,1) << std::endl;\n" 1067 " std::cout << fmodl(1.0,1) << std::endl;\n" 1068 "}"); 1069 ASSERT_EQUALS("", errout.str()); 1070 } 1071 mathfunctionCall_precision()1072 void mathfunctionCall_precision() { 1073 check("void foo() {\n" 1074 " print(exp(x) - 1);\n" 1075 " print(log(1 + x));\n" 1076 " print(1 - erf(x));\n" 1077 "}"); 1078 ASSERT_EQUALS("[test.cpp:2]: (style) Expression 'exp(x) - 1' can be replaced by 'expm1(x)' to avoid loss of precision.\n" 1079 "[test.cpp:3]: (style) Expression 'log(1 + x)' can be replaced by 'log1p(x)' to avoid loss of precision.\n" 1080 "[test.cpp:4]: (style) Expression '1 - erf(x)' can be replaced by 'erfc(x)' to avoid loss of precision.\n", errout.str()); 1081 1082 check("void foo() {\n" 1083 " print(exp(x) - 1.0);\n" 1084 " print(log(1.0 + x));\n" 1085 " print(1.0 - erf(x));\n" 1086 "}"); 1087 ASSERT_EQUALS("[test.cpp:2]: (style) Expression 'exp(x) - 1' can be replaced by 'expm1(x)' to avoid loss of precision.\n" 1088 "[test.cpp:3]: (style) Expression 'log(1 + x)' can be replaced by 'log1p(x)' to avoid loss of precision.\n" 1089 "[test.cpp:4]: (style) Expression '1 - erf(x)' can be replaced by 'erfc(x)' to avoid loss of precision.\n", errout.str()); 1090 1091 check("void foo() {\n" 1092 " print(exp(3 + x*f(a)) - 1);\n" 1093 " print(log(x*4 + 1));\n" 1094 " print(1 - erf(34*x + f(x) - c));\n" 1095 "}"); 1096 ASSERT_EQUALS("[test.cpp:2]: (style) Expression 'exp(x) - 1' can be replaced by 'expm1(x)' to avoid loss of precision.\n" 1097 "[test.cpp:3]: (style) Expression 'log(1 + x)' can be replaced by 'log1p(x)' to avoid loss of precision.\n" 1098 "[test.cpp:4]: (style) Expression '1 - erf(x)' can be replaced by 'erfc(x)' to avoid loss of precision.\n", errout.str()); 1099 1100 check("void foo() {\n" 1101 " print(2*exp(x) - 1);\n" 1102 " print(1 - erf(x)/2.0);\n" 1103 "}"); 1104 ASSERT_EQUALS("", errout.str()); 1105 } 1106 checkIgnoredReturnValue()1107 void checkIgnoredReturnValue() { 1108 Settings settings2; 1109 settings2.severity.enable(Severity::warning); 1110 const char xmldata[] = "<?xml version=\"1.0\"?>\n" 1111 "<def version=\"2\">\n" 1112 " <function name=\"mystrcmp,foo::mystrcmp\">\n" 1113 " <use-retval/>\n" 1114 " <arg nr=\"1\"/>\n" 1115 " <arg nr=\"2\"/>\n" 1116 " </function>\n" 1117 "</def>"; 1118 tinyxml2::XMLDocument doc; 1119 doc.Parse(xmldata, sizeof(xmldata)); 1120 settings2.library.load(doc); 1121 1122 check("void foo() {\n" 1123 " mystrcmp(a, b);\n" 1124 "}", "test.cpp", &settings2); 1125 ASSERT_EQUALS("[test.cpp:2]: (warning) Return value of function mystrcmp() is not used.\n", errout.str()); 1126 1127 check("void foo() {\n" 1128 " foo::mystrcmp(a, b);\n" 1129 "}", "test.cpp", &settings2); 1130 ASSERT_EQUALS("[test.cpp:2]: (warning) Return value of function foo::mystrcmp() is not used.\n", errout.str()); 1131 1132 check("void f() {\n" 1133 " foo x;\n" 1134 " x.mystrcmp(a, b);\n" 1135 "}", "test.cpp", &settings2); 1136 ASSERT_EQUALS("[test.cpp:3]: (warning) Return value of function x.mystrcmp() is not used.\n", errout.str()); 1137 1138 check("bool mystrcmp(char* a, char* b);\n" // cppcheck sees a custom strcmp definition, but it returns a value. Assume it is the one specified in the library. 1139 "void foo() {\n" 1140 " mystrcmp(a, b);\n" 1141 "}", "test.cpp", &settings2); 1142 ASSERT_EQUALS("[test.cpp:3]: (warning) Return value of function mystrcmp() is not used.\n", errout.str()); 1143 1144 check("void mystrcmp(char* a, char* b);\n" // cppcheck sees a custom strcmp definition which returns void! 1145 "void foo() {\n" 1146 " mystrcmp(a, b);\n" 1147 "}", "test.cpp", &settings2); 1148 ASSERT_EQUALS("", errout.str()); 1149 1150 check("void foo() {\n" 1151 " class mystrcmp { mystrcmp() {} };\n" // strcmp is a constructor definition here 1152 "}", "test.cpp", &settings2); 1153 ASSERT_EQUALS("", errout.str()); 1154 1155 check("void foo() {\n" 1156 " return mystrcmp(a, b);\n" 1157 "}", "test.cpp", &settings2); 1158 ASSERT_EQUALS("", errout.str()); 1159 1160 check("void foo() {\n" 1161 " return foo::mystrcmp(a, b);\n" 1162 "}", "test.cpp", &settings2); 1163 ASSERT_EQUALS("", errout.str()); 1164 1165 check("void foo() {\n" 1166 " if(mystrcmp(a, b));\n" 1167 "}", "test.cpp", &settings2); 1168 ASSERT_EQUALS("", errout.str()); 1169 1170 check("void foo() {\n" 1171 " bool b = mystrcmp(a, b);\n" 1172 "}", "test.cpp", &settings2); 1173 ASSERT_EQUALS("", errout.str()); 1174 1175 // #6194 1176 check("void foo() {\n" 1177 " MyStrCmp mystrcmp(x, y);\n" 1178 "}", "test.cpp", &settings2); 1179 ASSERT_EQUALS("", errout.str()); 1180 1181 // #6197 1182 check("void foo() {\n" 1183 " abc::def.mystrcmp(a,b);\n" 1184 "}", "test.cpp", &settings2); 1185 ASSERT_EQUALS("", errout.str()); 1186 1187 // #6233 1188 check("int main() {\n" 1189 " auto lambda = [](double value) {\n" 1190 " double rounded = floor(value + 0.5);\n" 1191 " printf(\"Rounded value = %f\\n\", rounded);\n" 1192 " };\n" 1193 " lambda(13.3);\n" 1194 " return 0;\n" 1195 "}"); 1196 ASSERT_EQUALS("", errout.str()); 1197 1198 // #6669 1199 check("void foo(size_t size) {\n" 1200 " void * res{malloc(size)};\n" 1201 "}"); 1202 ASSERT_EQUALS("", errout.str()); 1203 1204 // #7447 1205 check("void foo() {\n" 1206 " int x{mystrcmp(a,b)};\n" 1207 "}", "test.cpp", &settings2); 1208 ASSERT_EQUALS("", errout.str()); 1209 1210 // #7905 1211 check("void foo() {\n" 1212 " int x({mystrcmp(a,b)});\n" 1213 "}", "test.cpp", &settings2); 1214 ASSERT_EQUALS("", errout.str()); 1215 1216 check("void foo() {\n" // don't crash 1217 " DEBUG(123)(mystrcmp(a,b))(fd);\n" 1218 "}", "test.c", &settings2); 1219 check("struct teststruct {\n" 1220 " int testfunc1() __attribute__ ((warn_unused_result)) { return 1; }\n" 1221 " [[nodiscard]] int testfunc2() { return 1; }\n" 1222 " void foo() { testfunc1(); testfunc2(); }\n" 1223 "};\n" 1224 "int main() {\n" 1225 " teststruct TestStruct1;\n" 1226 " TestStruct1.testfunc1();\n" 1227 " TestStruct1.testfunc2();\n" 1228 " return 0;\n" 1229 "}", "test.cpp", &settings2); 1230 ASSERT_EQUALS("[test.cpp:4]: (warning) Return value of function testfunc1() is not used.\n" 1231 "[test.cpp:4]: (warning) Return value of function testfunc2() is not used.\n" 1232 "[test.cpp:8]: (warning) Return value of function TestStruct1.testfunc1() is not used.\n" 1233 "[test.cpp:9]: (warning) Return value of function TestStruct1.testfunc2() is not used.\n", errout.str()); 1234 1235 // #9006 1236 check("template <typename... a> uint8_t b(std::tuple<uint8_t> d) {\n" 1237 " std::tuple<a...> c{std::move(d)};\n" 1238 " return std::get<0>(c);\n" 1239 "}"); 1240 ASSERT_EQUALS("", errout.str()); 1241 1242 check("struct A { int x; };\n" 1243 "template <class... Ts>\n" 1244 "A f(int x, Ts... xs) {\n" 1245 " return {std::move(x), static_cast<int>(xs)...};\n" 1246 "}\n" 1247 "A g() { return f(1); }"); 1248 ASSERT_EQUALS("", errout.str()); 1249 1250 // #8412 - unused operator result 1251 check("void foo() {\n" 1252 " !mystrcmp(a, b);\n" 1253 "}", "test.cpp", &settings2); 1254 ASSERT_EQUALS("[test.cpp:2]: (warning) Return value of function mystrcmp() is not used.\n", errout.str()); 1255 1256 } 1257 checkIgnoredErrorCode()1258 void checkIgnoredErrorCode() { 1259 Settings settings2; 1260 settings2.addEnabled("style"); 1261 const char xmldata[] = "<?xml version=\"1.0\"?>\n" 1262 "<def version=\"2\">\n" 1263 " <function name=\"mystrcmp\">\n" 1264 " <use-retval type=\"error-code\"/>\n" 1265 " <arg nr=\"1\"/>\n" 1266 " <arg nr=\"2\"/>\n" 1267 " </function>\n" 1268 "</def>"; 1269 tinyxml2::XMLDocument doc; 1270 doc.Parse(xmldata, sizeof(xmldata)); 1271 settings2.library.load(doc); 1272 1273 check("void foo() {\n" 1274 " mystrcmp(a, b);\n" 1275 "}", "test.cpp", &settings2); 1276 ASSERT_EQUALS("[test.cpp:2]: (style) Error code from the return value of function mystrcmp() is not used.\n", errout.str()); 1277 } 1278 memsetZeroBytes()1279 void memsetZeroBytes() { 1280 check("void f() {\n" 1281 " memset(p, 10, 0x0);\n" 1282 "}"); 1283 ASSERT_EQUALS("[test.cpp:2]: (warning) memset() called to fill 0 bytes.\n", errout.str()); 1284 1285 check("void f() {\n" 1286 " memset(p, sizeof(p), 0);\n" 1287 "}"); 1288 ASSERT_EQUALS("[test.cpp:2]: (warning) memset() called to fill 0 bytes.\n", errout.str()); 1289 1290 check("void f() {\n" 1291 " memset(p, sizeof(p), i);\n" 1292 "}"); 1293 ASSERT_EQUALS("", errout.str()); 1294 1295 // #6269 false positives in case of overloaded standard library functions 1296 check("class c {\n" 1297 " void memset( int i );\n" 1298 " void f( void ) {\n" 1299 " memset( 0 );\n" 1300 " }\n" 1301 "};"); 1302 ASSERT_EQUALS("", errout.str()); 1303 1304 // #7285 1305 check("void f() {\n" 1306 " memset(&tm, sizeof(tm), 0);\n" 1307 "}"); 1308 ASSERT_EQUALS("[test.cpp:2]: (warning) memset() called to fill 0 bytes.\n", errout.str()); 1309 1310 } 1311 memsetInvalid2ndParam()1312 void memsetInvalid2ndParam() { 1313 check("void f() {\n" 1314 " int* is = new int[10];\n" 1315 " memset(is, 1.0f, 40);\n" 1316 " int* is2 = new int[10];\n" 1317 " memset(is2, 0.1f, 40);\n" 1318 "}"); 1319 ASSERT_EQUALS("[test.cpp:3]: (portability) The 2nd memset() argument '1.0f' is a float, its representation is implementation defined.\n" 1320 "[test.cpp:5]: (portability) The 2nd memset() argument '0.1f' is a float, its representation is implementation defined.\n", errout.str()); 1321 1322 check("void f() {\n" 1323 " int* is = new int[10];\n" 1324 " float g = computeG();\n" 1325 " memset(is, g, 40);\n" 1326 "}"); 1327 ASSERT_EQUALS("[test.cpp:4]: (portability) The 2nd memset() argument 'g' is a float, its representation is implementation defined.\n", errout.str()); 1328 1329 check("void f() {\n" 1330 " int* is = new int[10];\n" 1331 " memset(is, 0.0f, 40);\n" 1332 "}"); 1333 ASSERT_EQUALS("", errout.str()); 1334 1335 check("void f() {\n" // FP 1336 " float x = 2.3f;\n" 1337 " memset(a, (x?64:0), 40);\n" 1338 "}"); 1339 ASSERT_EQUALS("", errout.str()); 1340 1341 check("void f() {\n" 1342 " short ss[] = {1, 2};\n" 1343 " memset(ss, 256, 4);\n" 1344 " short ss2[2];\n" 1345 " memset(ss2, -129, 4);\n" 1346 "}"); 1347 ASSERT_EQUALS("[test.cpp:3]: (warning) The 2nd memset() argument '256' doesn't fit into an 'unsigned char'.\n" 1348 "[test.cpp:5]: (warning) The 2nd memset() argument '-129' doesn't fit into an 'unsigned char'.\n", errout.str()); 1349 1350 check("void f() {\n" 1351 " int is[10];\n" 1352 " memset(is, 0xEE, 40);\n" 1353 " unsigned char* cs = malloc(256);\n" 1354 " memset(cs, -1, 256);\n" 1355 " short* ss[30];\n" 1356 " memset(ss, -128, 60);\n" 1357 " char cs2[30];\n" 1358 " memset(cs2, 255, 30);\n" 1359 " char cs3[30];\n" 1360 " memset(cs3, 0, 30);\n" 1361 "}"); 1362 ASSERT_EQUALS("", errout.str()); 1363 1364 check("void f() {\n" 1365 " int is[10];\n" 1366 " const int i = g();\n" 1367 " memset(is, 1.0f + i, 40);\n" 1368 "}"); 1369 ASSERT_EQUALS("[test.cpp:4]: (portability) The 2nd memset() argument '1.0f+i' is a float, its representation is implementation defined.\n", errout.str()); 1370 } 1371 checkMissingReturn()1372 void checkMissingReturn() { 1373 check("int f() {}"); 1374 ASSERT_EQUALS("[test.cpp:1]: (error) Found a exit path from function with non-void return type that has missing return statement\n", errout.str()); 1375 1376 { 1377 const char code[] = "int main(void) {}"; 1378 Settings s; 1379 1380 s.standards.c = Standards::C89; 1381 check(code, "test.c", &s); // c code (c89) 1382 ASSERT_EQUALS("[test.c:1]: (error) Found a exit path from function with non-void return type that has missing return statement\n", errout.str()); 1383 1384 s.standards.c = Standards::C99; 1385 check(code, "test.c", &s); // c code (c99) 1386 ASSERT_EQUALS("", errout.str()); 1387 1388 check(code, "test.cpp", &s); // c++ code 1389 ASSERT_EQUALS("", errout.str()); 1390 } 1391 1392 check("F(A,B) { x=1; }"); 1393 ASSERT_EQUALS("", errout.str()); 1394 1395 check("auto foo4() -> void {}"); 1396 ASSERT_EQUALS("", errout.str()); 1397 1398 check("void STDCALL foo() {}"); 1399 ASSERT_EQUALS("", errout.str()); 1400 1401 check("void operator=(int y) { x=y; }"); 1402 ASSERT_EQUALS("", errout.str()); 1403 1404 check("int f() {\n" 1405 "back:\n" 1406 " return 0;\n" 1407 "ng:\n" 1408 " x=y;\n" 1409 " goto back;\n" 1410 "}\n"); 1411 ASSERT_EQUALS("", errout.str()); 1412 1413 // unreachable code.. 1414 check("int foo(int x) {\n" 1415 " return 1;\n" 1416 " (void)x;\n" 1417 "}"); 1418 ASSERT_EQUALS("", errout.str()); 1419 1420 check("int foo(int x) {\n" 1421 " if (x) goto out;\n" 1422 " return 1;\n" 1423 "out:\n" 1424 "}"); 1425 ASSERT_EQUALS("[test.cpp:3]: (error) Found a exit path from function with non-void return type that has missing return statement\n", errout.str()); 1426 1427 // switch 1428 check("int f() {\n" 1429 " switch (x) {\n" 1430 " case 1: break;\n" // <- error 1431 " case 2: return 1;\n" 1432 " }\n" 1433 "}"); 1434 ASSERT_EQUALS("[test.cpp:3]: (error) Found a exit path from function with non-void return type that has missing return statement\n", errout.str()); 1435 1436 check("int f() {\n" 1437 " switch (x) {\n" 1438 " case 1: return 2; break;\n" 1439 " default: return 1;\n" 1440 " }\n" 1441 "}"); 1442 ASSERT_EQUALS("", errout.str()); 1443 1444 // if/else 1445 check("int f(int x) {\n" 1446 " if (x) {\n" 1447 " return 1;\n" 1448 " }\n" // <- error (missing else) 1449 "}"); 1450 ASSERT_EQUALS("[test.cpp:4]: (error) Found a exit path from function with non-void return type that has missing return statement\n", errout.str()); 1451 1452 check("int f(int x) {\n" 1453 " if (x) {\n" 1454 " ;\n" // <- error 1455 " } else {\n" 1456 " return 1;\n" 1457 " }\n" 1458 "}"); 1459 ASSERT_EQUALS("[test.cpp:3]: (error) Found a exit path from function with non-void return type that has missing return statement\n", errout.str()); 1460 1461 check("int f() {\n" 1462 " if (!0) {\n" 1463 " return 1;\n" 1464 " }\n" 1465 "}"); 1466 ASSERT_EQUALS("", errout.str()); 1467 1468 check("int f() {\n" 1469 " if (!0) {}\n" 1470 "}"); 1471 ASSERT_EQUALS("[test.cpp:2]: (error) Found a exit path from function with non-void return type that has missing return statement\n", errout.str()); 1472 1473 // loop 1474 check("int f(int x) {\n" 1475 " while (1) {\n" 1476 " dostuff();\n" 1477 " }\n" 1478 "}"); 1479 ASSERT_EQUALS("", errout.str()); 1480 1481 // return {..} 1482 check("std::pair<int, int> typeDecl(int tok) {\n" 1483 " if (!tok)\n" 1484 " return {};\n" 1485 " else\n" 1486 " return {1, 2};\n" 1487 "}"); 1488 ASSERT_EQUALS("", errout.str()); 1489 1490 // noreturn function 1491 check("int f(int x) { exit(0); }"); 1492 ASSERT_EQUALS("", errout.str()); 1493 1494 check("int f(int x) { assert(0); }"); 1495 ASSERT_EQUALS("", errout.str()); 1496 1497 check("int f(int x) { if (x) return 1; else return bar({1}, {}); }"); 1498 ASSERT_EQUALS("", errout.str()); 1499 } 1500 1501 // NRVO check returnLocalStdMove1()1502 void returnLocalStdMove1() { 1503 check("struct A{}; A f() { A var; return std::move(var); }"); 1504 ASSERT_EQUALS("[test.cpp:1]: (performance) Using std::move for returning object by-value from function will affect copy elision optimization." 1505 " More: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-return-move-local\n", errout.str()); 1506 } 1507 1508 // RVO, C++03 ctor style returnLocalStdMove2()1509 void returnLocalStdMove2() { 1510 check("struct A{}; A f() { return std::move( A() ); }"); 1511 ASSERT_EQUALS("[test.cpp:1]: (performance) Using std::move for returning object by-value from function will affect copy elision optimization." 1512 " More: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-return-move-local\n", errout.str()); 1513 } 1514 1515 // RVO, new ctor style returnLocalStdMove3()1516 void returnLocalStdMove3() { 1517 check("struct A{}; A f() { return std::move(A{}); }"); 1518 ASSERT_EQUALS("[test.cpp:1]: (performance) Using std::move for returning object by-value from function will affect copy elision optimization." 1519 " More: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-return-move-local\n", errout.str()); 1520 } 1521 1522 // Function argument returnLocalStdMove4()1523 void returnLocalStdMove4() { 1524 check("struct A{}; A f(A a) { return std::move(A{}); }"); 1525 ASSERT_EQUALS("[test.cpp:1]: (performance) Using std::move for returning object by-value from function will affect copy elision optimization." 1526 " More: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-return-move-local\n", errout.str()); 1527 } 1528 returnLocalStdMove5()1529 void returnLocalStdMove5() { 1530 check("struct A{} a; A f1() { return std::move(a); }\n" 1531 "A f2() { volatile A var; return std::move(var); }"); 1532 ASSERT_EQUALS("", errout.str()); 1533 } 1534 }; 1535 1536 REGISTER_TEST(TestFunctions) 1537