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 20 #include "checkautovariables.h" 21 #include "settings.h" 22 #include "testsuite.h" 23 #include "tokenize.h" 24 25 26 class TestAutoVariables : public TestFixture { 27 public: TestAutoVariables()28 TestAutoVariables() : TestFixture("TestAutoVariables") {} 29 30 private: 31 Settings settings; 32 check(const char code[],bool inconclusive=false,const char * filename="test.cpp")33 void check(const char code[], bool inconclusive = false, const char* filename = "test.cpp") { 34 // Clear the error buffer.. 35 errout.str(""); 36 37 settings.certainty.setEnabled(Certainty::inconclusive, inconclusive); 38 39 // Tokenize.. 40 Tokenizer tokenizer(&settings, this); 41 std::istringstream istr(code); 42 tokenizer.tokenize(istr, filename); 43 44 CheckAutoVariables checkAutoVariables; 45 checkAutoVariables.runChecks(&tokenizer, &settings, this); 46 } 47 run()48 void run() OVERRIDE { 49 settings.severity.enable(Severity::warning); 50 settings.severity.enable(Severity::style); 51 LOAD_LIB_2(settings.library, "std.cfg"); 52 LOAD_LIB_2(settings.library, "qt.cfg"); 53 54 TEST_CASE(testautovar1); 55 TEST_CASE(testautovar2); 56 TEST_CASE(testautovar3); // ticket #2925 57 TEST_CASE(testautovar4); // ticket #2928 58 TEST_CASE(testautovar5); // ticket #2926 59 TEST_CASE(testautovar6); // ticket #2931 60 TEST_CASE(testautovar7); // ticket #3066 61 TEST_CASE(testautovar8); 62 TEST_CASE(testautovar9); 63 TEST_CASE(testautovar10); // ticket #2930 - void f(char *p) { p = '\0'; } 64 TEST_CASE(testautovar11); // ticket #4641 - fp, assign local struct member address to function parameter 65 TEST_CASE(testautovar12); // ticket #5024 - crash 66 TEST_CASE(testautovar13); // ticket #5537 - crash 67 TEST_CASE(testautovar14); // ticket #4776 - assignment of function parameter, goto 68 TEST_CASE(testautovar15); // ticket #6538 69 TEST_CASE(testautovar16); // ticket #8114 70 TEST_CASE(testautovar_array1); 71 TEST_CASE(testautovar_array2); 72 TEST_CASE(testautovar_normal); // "normal" token list that does not remove casts etc 73 TEST_CASE(testautovar_ptrptr); // ticket #6956 74 TEST_CASE(testautovar_return1); 75 TEST_CASE(testautovar_return2); 76 TEST_CASE(testautovar_return3); 77 TEST_CASE(testautovar_return4); 78 TEST_CASE(testautovar_extern); 79 TEST_CASE(testautovar_reassigned); 80 TEST_CASE(testinvaliddealloc); 81 TEST_CASE(testinvaliddealloc_C); 82 TEST_CASE(testassign1); // Ticket #1819 83 TEST_CASE(testassign2); // Ticket #2765 84 85 TEST_CASE(assignAddressOfLocalArrayToGlobalPointer); 86 TEST_CASE(assignAddressOfLocalVariableToGlobalPointer); 87 TEST_CASE(assignAddressOfLocalVariableToMemberVariable); 88 89 TEST_CASE(returnLocalVariable1); 90 TEST_CASE(returnLocalVariable2); 91 TEST_CASE(returnLocalVariable3); // &x[0] 92 TEST_CASE(returnLocalVariable4); // x+y 93 TEST_CASE(returnLocalVariable5); // cast 94 TEST_CASE(returnLocalVariable6); // valueflow 95 96 // return reference.. 97 TEST_CASE(returnReference1); 98 TEST_CASE(returnReference2); 99 TEST_CASE(returnReference3); 100 TEST_CASE(returnReference4); 101 TEST_CASE(returnReference5); 102 TEST_CASE(returnReference6); 103 TEST_CASE(returnReference7); 104 TEST_CASE(returnReference8); 105 TEST_CASE(returnReference9); 106 TEST_CASE(returnReference10); 107 TEST_CASE(returnReference11); 108 TEST_CASE(returnReference12); 109 TEST_CASE(returnReference13); 110 TEST_CASE(returnReference14); 111 TEST_CASE(returnReference15); // #9432 112 TEST_CASE(returnReference16); // #9433 113 TEST_CASE(returnReference16); // #9433 114 TEST_CASE(returnReference17); // #9461 115 TEST_CASE(returnReference18); // #9482 116 TEST_CASE(returnReference19); // #9597 117 TEST_CASE(returnReference20); // #9536 118 TEST_CASE(returnReference21); // #9530 119 TEST_CASE(returnReference22); 120 TEST_CASE(returnReference23); 121 TEST_CASE(returnReferenceFunction); 122 TEST_CASE(returnReferenceContainer); 123 TEST_CASE(returnReferenceLiteral); 124 TEST_CASE(returnReferenceCalculation); 125 TEST_CASE(returnReferenceLambda); 126 TEST_CASE(returnReferenceInnerScope); 127 TEST_CASE(returnReferenceRecursive); 128 TEST_CASE(extendedLifetime); 129 130 TEST_CASE(danglingReference); 131 TEST_CASE(danglingTempReference); 132 133 // global namespace 134 TEST_CASE(testglobalnamespace); 135 136 TEST_CASE(returnParameterAddress); 137 138 TEST_CASE(testconstructor); // ticket #5478 - crash 139 140 TEST_CASE(variableIsUsedInScope); // ticket #5599 crash in variableIsUsedInScope() 141 142 TEST_CASE(danglingLifetimeLambda); 143 TEST_CASE(danglingLifetimeContainer); 144 TEST_CASE(danglingLifetime); 145 TEST_CASE(danglingLifetimeFunction); 146 TEST_CASE(danglingLifetimeAggegrateConstructor); 147 TEST_CASE(danglingLifetimeInitList); 148 TEST_CASE(danglingLifetimeImplicitConversion); 149 TEST_CASE(danglingTemporaryLifetime); 150 TEST_CASE(invalidLifetime); 151 TEST_CASE(deadPointer); 152 TEST_CASE(splitNamespaceAuto); // crash #10473 153 } 154 155 156 testautovar1()157 void testautovar1() { 158 check("void func1(int **res)\n" 159 "{\n" 160 " int num = 2;\n" 161 " *res = #\n" 162 "}"); 163 ASSERT_EQUALS("[test.cpp:4]: (error) Address of local auto-variable assigned to a function parameter.\n", errout.str()); 164 165 check("void func1(int **res)\n" 166 "{\n" 167 " int num = 2;\n" 168 " res = #\n" 169 "}"); 170 ASSERT_EQUALS("[test.cpp:4]: (warning) Assignment of function parameter has no effect outside the function. Did you forget dereferencing it?\n", errout.str()); 171 172 check("void func1(int **res)\n" 173 "{\n" 174 " int num = 2;\n" 175 " foo.res = #\n" 176 "}"); 177 ASSERT_EQUALS("", errout.str()); 178 } 179 testautovar2()180 void testautovar2() { 181 check("class Fred {\n" 182 " void func1(int **res);\n" 183 "}\n" 184 "void Fred::func1(int **res)\n" 185 "{\n" 186 " int num = 2;\n" 187 " *res = #\n" 188 "}"); 189 ASSERT_EQUALS("[test.cpp:7]: (error) Address of local auto-variable assigned to a function parameter.\n", errout.str()); 190 191 check("class Fred {\n" 192 " void func1(int **res);\n" 193 "}\n" 194 "void Fred::func1(int **res)\n" 195 "{\n" 196 " int num = 2;\n" 197 " res = #\n" 198 "}"); 199 ASSERT_EQUALS("[test.cpp:7]: (warning) Assignment of function parameter has no effect outside the function. Did you forget dereferencing it?\n", errout.str()); 200 201 check("class Fred {\n" 202 " void func1(int **res);\n" 203 "}\n" 204 "void Fred::func1(int **res)\n" 205 "{\n" 206 " int num = 2;\n" 207 " foo.res = #\n" 208 "}"); 209 ASSERT_EQUALS("", errout.str()); 210 } 211 testautovar3()212 void testautovar3() { // ticket #2925 213 check("void foo(int **p)\n" 214 "{\n" 215 " int x[100];\n" 216 " *p = x;\n" 217 "}"); 218 ASSERT_EQUALS("[test.cpp:4]: (error) Address of local auto-variable assigned to a function parameter.\n", errout.str()); 219 } 220 testautovar4()221 void testautovar4() { // ticket #2928 222 check("void foo(int **p)\n" 223 "{\n" 224 " static int x[100];\n" 225 " *p = x;\n" 226 "}"); 227 ASSERT_EQUALS("", errout.str()); 228 } 229 testautovar5()230 void testautovar5() { // ticket #2926 231 check("void foo(struct AB *ab)\n" 232 "{\n" 233 " char a;\n" 234 " ab->a = &a;\n" 235 "}"); 236 ASSERT_EQUALS("[test.cpp:4]: (error) Address of local auto-variable assigned to a function parameter.\n", errout.str()); 237 } 238 testautovar6()239 void testautovar6() { // ticket #2931 240 check("void foo(struct X *x)\n" 241 "{\n" 242 " char a[10];\n" 243 " x->str = a;\n" 244 "}", false); 245 ASSERT_EQUALS("", errout.str()); 246 247 check("void foo(struct X *x)\n" 248 "{\n" 249 " char a[10];\n" 250 " x->str = a;\n" 251 "}", true); 252 ASSERT_EQUALS("[test.cpp:4]: (error, inconclusive) Address of local auto-variable assigned to a function parameter.\n", errout.str()); 253 } 254 testautovar7()255 void testautovar7() { // ticket #3066 256 check("struct txt_scrollpane_s * TXT_NewScrollPane(struct txt_widget_s * target)\n" 257 "{\n" 258 " struct txt_scrollpane_s * scrollpane;\n" 259 " target->parent = &scrollpane->widget;\n" 260 " return scrollpane;\n" 261 "}", false); 262 ASSERT_EQUALS("", errout.str()); 263 } 264 testautovar8()265 void testautovar8() { 266 check("void foo(int*& p) {\n" 267 " int i = 0;\n" 268 " p = &i;\n" 269 "}", false); 270 ASSERT_EQUALS("[test.cpp:3]: (error) Address of local auto-variable assigned to a function parameter.\n", errout.str()); 271 272 check("void foo(std::string& s) {\n" 273 " s = foo;\n" 274 "}", false); 275 ASSERT_EQUALS("", errout.str()); 276 } 277 testautovar9()278 void testautovar9() { 279 check("struct FN {int i;};\n" 280 "struct FP {FN* f};\n" 281 "void foo(int*& p, FN* p_fp) {\n" 282 " FN fn;\n" 283 " FP fp;\n" 284 " p = &fn.i;\n" 285 "}", false); 286 ASSERT_EQUALS("[test.cpp:6]: (error) Address of local auto-variable assigned to a function parameter.\n", errout.str()); 287 288 check("struct FN {int i;};\n" 289 "struct FP {FN* f};\n" 290 "void foo(int*& p, FN* p_fp) {\n" 291 " FN fn;\n" 292 " FP fp;\n" 293 " p = &p_fp->i;\n" 294 "}", false); 295 ASSERT_EQUALS("", errout.str()); 296 297 check("struct FN {int i;};\n" 298 "struct FP {FN* f};\n" 299 "void foo(int*& p, FN* p_fp) {\n" 300 " FN fn;\n" 301 " FP fp;\n" 302 " p = &fp.f->i;\n" 303 "}", false); 304 ASSERT_EQUALS("", errout.str()); 305 } 306 testautovar10()307 void testautovar10() { // #2930 - assignment of function parameter 308 check("void foo(char* p) {\n" 309 " p = 0;\n" 310 "}"); 311 ASSERT_EQUALS("[test.cpp:2]: (warning) Assignment of function parameter has no effect outside the function. Did you forget dereferencing it?\n", errout.str()); 312 313 check("void foo(int b) {\n" 314 " b = foo(b);\n" 315 "}"); 316 ASSERT_EQUALS("[test.cpp:2]: (style) Assignment of function parameter has no effect outside the function.\n", errout.str()); 317 318 check("void foo(int b) {\n" 319 " b += 1;\n" 320 "}"); 321 ASSERT_EQUALS("[test.cpp:2]: (style) Assignment of function parameter has no effect outside the function.\n", errout.str()); 322 323 check("void foo(std::string s) {\n" 324 " s = foo(b);\n" 325 "}"); 326 ASSERT_EQUALS("[test.cpp:2]: (style) Assignment of function parameter has no effect outside the function.\n", errout.str()); 327 328 check("void foo(char* p) {\n" // don't warn for self assignment, there is another warning for this 329 " p = p;\n" 330 "}"); 331 ASSERT_EQUALS("", errout.str()); 332 333 check("void foo(char* p) {\n" 334 " if (!p) p = buf;\n" 335 " *p = 0;\n" 336 "}"); 337 ASSERT_EQUALS("", errout.str()); 338 339 check("void foo(char* p) {\n" 340 " if (!p) p = buf;\n" 341 " do_something(p);\n" 342 "}"); 343 ASSERT_EQUALS("", errout.str()); 344 345 check("void foo(char* p) {\n" 346 " while (!p) p = buf;\n" 347 "}"); 348 ASSERT_EQUALS("", errout.str()); 349 350 check("void foo(char* p) {\n" 351 " p = 0;\n" 352 " asm(\"somecmd\");\n" 353 "}"); 354 ASSERT_EQUALS("", errout.str()); 355 356 check("void foo(Foo* p) {\n" 357 " p = 0;\n" 358 "}"); 359 ASSERT_EQUALS("[test.cpp:2]: (warning) Assignment of function parameter has no effect outside the function. Did you forget dereferencing it?\n", errout.str()); 360 361 check("class Foo {};\n" 362 "void foo(Foo p) {\n" 363 " p = 0;\n" 364 "}"); 365 ASSERT_EQUALS("[test.cpp:3]: (style) Assignment of function parameter has no effect outside the function.\n", errout.str()); 366 367 check("void foo(Foo p) {\n" 368 " p = 0;\n" 369 "}"); 370 ASSERT_EQUALS("", errout.str()); 371 372 check("void foo(int& p) {\n" 373 " p = 0;\n" 374 "}"); 375 ASSERT_EQUALS("", errout.str()); 376 377 check("double foo(double d) {\n" // #5005 378 " int i = d;\n" 379 " d = i;\n" 380 " return d;" 381 "}",false); 382 ASSERT_EQUALS("", errout.str()); 383 384 check("void foo(int* ptr) {\n" // #4793 385 " ptr++;\n" 386 "}"); 387 ASSERT_EQUALS("[test.cpp:2]: (warning) Assignment of function parameter has no effect outside the function. Did you forget dereferencing it?\n", errout.str()); 388 389 check("void foo(int* ptr) {\n" // #3177 390 " --ptr;\n" 391 "}"); 392 ASSERT_EQUALS("[test.cpp:2]: (warning) Assignment of function parameter has no effect outside the function. Did you forget dereferencing it?\n", errout.str()); 393 394 check("void foo(struct S* const x) {\n" // #7839 395 " ++x->n;\n" 396 "}"); 397 ASSERT_EQUALS("", errout.str()); 398 } 399 testautovar11()400 void testautovar11() { // #4641 - fp, assign local struct member address to function parameter 401 check("struct A {\n" 402 " char (*data)[10];\n" 403 "};\n" 404 "void foo(char** p) {\n" 405 " struct A a = bar();\n" 406 " *p = &(*a.data)[0];\n" 407 "}"); 408 ASSERT_EQUALS("", errout.str()); 409 410 check("struct A {\n" 411 " char data[10];\n" 412 "};\n" 413 "void foo(char** p) {\n" 414 " struct A a = bar();\n" 415 " *p = &a.data[0];\n" 416 "}"); 417 ASSERT_EQUALS("[test.cpp:6]: (error) Address of local auto-variable assigned to a function parameter.\n", errout.str()); 418 419 check("void f(char **out) {\n" 420 " struct S *p = glob;\n" 421 " *out = &p->data;\n" 422 "}"); 423 ASSERT_EQUALS("", errout.str()); 424 425 // #4998 426 check("void f(s8**out) {\n" 427 " s8 *p;\n" // <- p is pointer => no error 428 " *out = &p[1];\n" 429 "}"); 430 ASSERT_EQUALS("", errout.str()); 431 432 check("void f(s8**out) {\n" 433 " s8 p[10];\n" // <- p is array => error 434 " *out = &p[1];\n" 435 "}"); 436 ASSERT_EQUALS("[test.cpp:3]: (error) Address of local auto-variable assigned to a function parameter.\n", errout.str()); 437 } 438 testautovar12()439 void testautovar12() { // Ticket #5024, #5050 - Crash on invalid input 440 ASSERT_THROW(check("void f(int* a) { a = }"), InternalError); 441 check("struct custom_type { custom_type(int) {} };\n" 442 "void func(int) {}\n" 443 "int var;\n" 444 "void init() { func(var); }\n" 445 "UNKNOWN_MACRO_EXPANDING_TO_SIGNATURE { custom_type a(var); }"); 446 } 447 testautovar13()448 void testautovar13() { // Ticket #5537 449 check("class FileManager {\n" 450 " FileManager() : UniqueRealDirs(*new UniqueDirContainer())\n" 451 " {}\n" 452 " ~FileManager() {\n" 453 " delete &UniqueRealDirs;\n" 454 " }\n" 455 "};"); 456 } 457 testautovar14()458 void testautovar14() { // Ticket #4776 459 check("void f(int x) {\n" 460 "label:" 461 " if (x>0) {\n" 462 " x = x >> 1;\n" 463 " goto label;\n" 464 " }\n" 465 "}"); 466 ASSERT_EQUALS("", errout.str()); 467 } 468 testautovar15()469 void testautovar15() { // Ticket #6538 470 check("static const float4 darkOutline(0.05f, 0.05f, 0.05f, 0.95f);\n" 471 "static const float darkLuminosity = 0.05 +\n" 472 " 0.0722f * math::powf(darkOutline[2], 2.2);\n" 473 "const float4* ChooseOutlineColor(const float4& textColor) {\n" 474 " const float lumdiff = something;\n" 475 " if (lumdiff > 5.0f)\n" 476 " return &darkOutline;\n" 477 " return 0;\n" 478 "}", false); 479 ASSERT_EQUALS("", errout.str()); 480 } 481 testautovar16()482 void testautovar16() { // Ticket #8114 483 check("void f(const void* ptr, bool* result) {\n" 484 " int dummy;\n" 485 " *result = (&dummy < ptr);\n" 486 "}"); 487 ASSERT_EQUALS("", errout.str()); 488 } 489 testautovar_array1()490 void testautovar_array1() { 491 check("void func1(int* arr[2])\n" 492 "{\n" 493 " int num=2;" 494 " arr[0]=#\n" 495 "}"); 496 ASSERT_EQUALS("[test.cpp:3]: (error) Address of local auto-variable assigned to a function parameter.\n", errout.str()); 497 } 498 testautovar_array2()499 void testautovar_array2() { 500 check("class Fred {\n" 501 " void func1(int* arr[2]);\n" 502 "}\n" 503 "void Fred::func1(int* arr[2])\n" 504 "{\n" 505 " int num=2;" 506 " arr[0]=#\n" 507 "}"); 508 ASSERT_EQUALS("[test.cpp:6]: (error) Address of local auto-variable assigned to a function parameter.\n", errout.str()); 509 } 510 testautovar_normal()511 void testautovar_normal() { 512 check("void f(XmDestinationCallbackStruct *ds)\n" 513 "{\n" 514 " XPoint DropPoint;\n" 515 " ds->location_data = (XtPointer *)&DropPoint;\n" 516 "}"); 517 ASSERT_EQUALS("[test.cpp:4]: (error) Address of local auto-variable assigned to a function parameter.\n", errout.str()); 518 } 519 testautovar_ptrptr()520 void testautovar_ptrptr() { // #6596 521 check("void remove_duplicate_matches (char **matches) {\n" 522 " char dead_slot;\n" 523 " matches[0] = (char *)&dead_slot;\n" 524 "}"); 525 ASSERT_EQUALS("[test.cpp:3]: (error) Address of local auto-variable assigned to a function parameter.\n", errout.str()); 526 } 527 testautovar_return1()528 void testautovar_return1() { 529 check("int* func1()\n" 530 "{\n" 531 " int num=2;" 532 " return #" 533 "}"); 534 ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:3] -> [test.cpp:3]: (error) Returning pointer to local variable 'num' that will be invalid when returning.\n", errout.str()); 535 } 536 testautovar_return2()537 void testautovar_return2() { 538 check("class Fred {\n" 539 " int* func1();\n" 540 "}\n" 541 "int* Fred::func1()\n" 542 "{\n" 543 " int num=2;" 544 " return #" 545 "}"); 546 ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:6] -> [test.cpp:6]: (error) Returning pointer to local variable 'num' that will be invalid when returning.\n", errout.str()); 547 } 548 testautovar_return3()549 void testautovar_return3() { 550 // #2975 - FP 551 check("void** f()\n" 552 "{\n" 553 " void *&value = tls[id];" 554 " return &value;" 555 "}"); 556 ASSERT_EQUALS("", errout.str()); 557 } 558 testautovar_return4()559 void testautovar_return4() { 560 // #8058 - FP ignore return in lambda 561 check("void foo() {\n" 562 " int cond2;\n" 563 " dostuff([&cond2]() { return &cond2; });\n" 564 "}"); 565 ASSERT_EQUALS("", errout.str()); 566 } 567 testautovar_extern()568 void testautovar_extern() { 569 check("struct foo *f()\n" 570 "{\n" 571 " extern struct foo f;\n" 572 " return &f;\n" 573 "}"); 574 ASSERT_EQUALS("", errout.str()); 575 } 576 testautovar_reassigned()577 void testautovar_reassigned() { 578 check("void foo(cb* pcb) {\n" 579 " int root0;\n" 580 " pcb->root0 = &root0;\n" 581 " dostuff(pcb);\n" 582 " pcb->root0 = 0;\n" 583 "}"); 584 ASSERT_EQUALS("", errout.str()); 585 586 check("void foo(cb* pcb) {\n" 587 " int root0;\n" 588 " pcb->root0 = &root0;\n" 589 " dostuff(pcb);\n" 590 " if (condition) return;\n" // <- not reassigned => error 591 " pcb->root0 = 0;\n" 592 "}"); 593 ASSERT_EQUALS("[test.cpp:3]: (error) Address of local auto-variable assigned to a function parameter.\n", errout.str()); 594 595 check("void foo(cb* pcb) {\n" 596 " int root0;\n" 597 " pcb->root0 = &root0;\n" 598 " dostuff(pcb);\n" 599 " if (condition)\n" 600 " pcb->root0 = 0;\n" // <- conditional reassign => error 601 "}"); 602 ASSERT_EQUALS("[test.cpp:3]: (error) Address of local auto-variable assigned to a function parameter.\n", errout.str()); 603 } 604 testinvaliddealloc()605 void testinvaliddealloc() { 606 check("void func1() {\n" 607 " char tmp1[256];\n" 608 " free(tmp1);\n" 609 " char tmp2[256];\n" 610 " delete tmp2;\n" 611 " char tmp3[256];\n" 612 " delete tmp3;\n" 613 " char tmp4[256];\n" 614 " delete[] (tmp4);\n" 615 " char tmp5[256];\n" 616 " delete[] tmp5;\n" 617 "}"); 618 ASSERT_EQUALS("[test.cpp:3]: (error) Deallocation of an auto-variable results in undefined behaviour.\n" 619 "[test.cpp:5]: (error) Deallocation of an auto-variable results in undefined behaviour.\n" 620 "[test.cpp:7]: (error) Deallocation of an auto-variable results in undefined behaviour.\n" 621 "[test.cpp:9]: (error) Deallocation of an auto-variable results in undefined behaviour.\n" 622 "[test.cpp:11]: (error) Deallocation of an auto-variable results in undefined behaviour.\n", errout.str()); 623 624 check("void func1() {\n" 625 " char* tmp1[256];\n" 626 " init(tmp1);\n" 627 " delete tmp1[34];\n" 628 "}"); 629 ASSERT_EQUALS("", errout.str()); 630 631 check("void func1() {\n" 632 " static char tmp1[256];\n" 633 " char *p = tmp1;\n" 634 " free(p);\n" 635 "}"); 636 ASSERT_EQUALS("[test.cpp:4]: (error) Deallocation of an static variable (tmp1) results in undefined behaviour.\n", errout.str()); 637 638 check("char tmp1[256];\n" 639 "void func1() {\n" 640 " char *p; if (x) p = tmp1;\n" 641 " free(p);\n" 642 "}"); 643 ASSERT_EQUALS("[test.cpp:4]: (error) Deallocation of an global variable (tmp1) results in undefined behaviour.\n", errout.str()); 644 645 check("void f()\n" 646 "{\n" 647 " char psz_title[10];\n" 648 " {\n" 649 " char *psz_title = 0;\n" 650 " abc(0, psz_title);\n" 651 " free(psz_title);\n" 652 " }\n" 653 "}"); 654 ASSERT_EQUALS("", errout.str()); 655 656 // #2298 new check: passing stack-address to free() 657 check("int main() {\n" 658 " int *p = malloc(4);\n" 659 " free(&p);\n" 660 " return 0;\n" 661 "}"); 662 ASSERT_EQUALS("[test.cpp:3]: (error) Deallocation of an auto-variable results in undefined behaviour.\n", errout.str()); 663 check("int main() {\n" 664 " int i;\n" 665 " free(&i);\n" 666 " return 0;\n" 667 "}"); 668 ASSERT_EQUALS("[test.cpp:3]: (error) Deallocation of an auto-variable results in undefined behaviour.\n", errout.str()); 669 670 // #5732 671 check("int main() {\n" 672 " long (*pKoeff)[256] = new long[9][256];\n" 673 " delete[] pKoeff;\n" 674 "}"); 675 ASSERT_EQUALS("", errout.str()); 676 677 check("int main() {\n" 678 " long *pKoeff[256];\n" 679 " delete[] pKoeff;\n" 680 "}"); 681 ASSERT_EQUALS("[test.cpp:3]: (error) Deallocation of an auto-variable results in undefined behaviour.\n", errout.str()); 682 683 check("int main() {\n" 684 " long *pKoeff[256];\n" 685 " free (pKoeff);\n" 686 "}"); 687 ASSERT_EQUALS("[test.cpp:3]: (error) Deallocation of an auto-variable results in undefined behaviour.\n", errout.str()); 688 689 check("void foo() {\n" 690 " const intPtr& intref = Getter();\n" 691 " delete intref;\n" 692 "}"); 693 ASSERT_EQUALS("", errout.str()); 694 695 check("void test() {\n" 696 " MyObj& obj = *new MyObj;\n" 697 " delete &obj;\n" 698 "}"); 699 ASSERT_EQUALS("", errout.str()); 700 701 // #6506 702 check("struct F {\n" 703 " void free(void*) {}\n" 704 "};\n" 705 "void foo() {\n" 706 " char c1[1];\n" 707 " F().free(c1);\n" 708 " char *c2 = 0;\n" 709 " F().free(&c2);\n" 710 "}"); 711 ASSERT_EQUALS("", errout.str()); 712 713 check("class foo {\n" 714 " void free(void* );\n" 715 " void someMethod() {\n" 716 " char **dst_copy = NULL;\n" 717 " free(&dst_copy);\n" 718 " }\n" 719 "};"); 720 ASSERT_EQUALS("", errout.str()); 721 722 // #6551 723 check("bool foo( ) {\n" 724 " SwTxtFld * pTxtFld = GetFldTxtAttrAt();\n" 725 " delete static_cast<SwFmtFld*>(&pTxtFld->GetAttr());\n" 726 "}"); 727 ASSERT_EQUALS("", errout.str()); 728 729 // #8910 730 check("void f() {\n" 731 " char stack[512];\n" 732 " RGNDATA *data;\n" 733 " if (data_size > sizeof (stack)) data = malloc (data_size);\n" 734 " else data = (RGNDATA *)stack;\n" 735 " if ((char *)data != stack) free (data);\n" 736 "}"); 737 ASSERT_EQUALS("", errout.str()); 738 739 // #8923 740 check("void f(char **args1, char *args2[]) {\n" 741 " free((char **)args1);\n" 742 " free((char **)args2);\n" 743 "}"); 744 ASSERT_EQUALS("", errout.str()); 745 } 746 testinvaliddealloc_C()747 void testinvaliddealloc_C() { 748 // #5691 749 check("void svn_repos_dir_delta2() {\n" 750 " struct context c;\n" 751 " SVN_ERR(delete(&c, root_baton, src_entry, pool));\n" 752 "}\n", false, "test.c"); 753 ASSERT_EQUALS("", errout.str()); 754 } 755 testassign1()756 void testassign1() { // Ticket #1819 757 check("void f(EventPtr *eventP, ActionPtr **actionsP) {\n" 758 " EventPtr event = *eventP;\n" 759 " *actionsP = &event->actions;\n" 760 "}"); 761 ASSERT_EQUALS("", errout.str()); 762 } 763 testassign2()764 void testassign2() { // Ticket #2765 765 check("static void function(unsigned long **datap) {\n" 766 " struct my_s *mr = global_structure_pointer;\n" 767 " *datap = &mr->value;\n" 768 "}"); 769 ASSERT_EQUALS("", errout.str()); 770 } 771 assignAddressOfLocalArrayToGlobalPointer()772 void assignAddressOfLocalArrayToGlobalPointer() { 773 check("int *p;\n" 774 "void f() {\n" 775 " int x[10];\n" 776 " p = x;\n" 777 "}"); 778 ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3] -> [test.cpp:4]: (error) Non-local variable 'p' will use pointer to local variable 'x'.\n", errout.str()); 779 780 check("int *p;\n" 781 "void f() {\n" 782 " int x[10];\n" 783 " p = x;\n" 784 " p = 0;\n" 785 "}"); 786 ASSERT_EQUALS("", errout.str()); 787 } 788 assignAddressOfLocalVariableToGlobalPointer()789 void assignAddressOfLocalVariableToGlobalPointer() { 790 check("int *p;\n" 791 "void f() {\n" 792 " int x;\n" 793 " p = &x;\n" 794 "}"); 795 ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3] -> [test.cpp:4]: (error) Non-local variable 'p' will use pointer to local variable 'x'.\n", errout.str()); 796 797 check("int *p;\n" 798 "void f() {\n" 799 " int x;\n" 800 " p = &x;\n" 801 " p = 0;\n" 802 "}"); 803 ASSERT_EQUALS("", errout.str()); 804 } 805 assignAddressOfLocalVariableToMemberVariable()806 void assignAddressOfLocalVariableToMemberVariable() { 807 check("struct A {\n" 808 " void f() {\n" 809 " int x;\n" 810 " ptr = &x;\n" 811 " }\n" 812 " int *ptr;\n" 813 "};"); 814 ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3] -> [test.cpp:4]: (error) Non-local variable 'ptr' will use pointer to local variable 'x'.\n", errout.str()); 815 816 check("struct A {\n" 817 " void f() {\n" 818 " int x;\n" 819 " ptr = &x;\n" 820 " ptr = 0;\n" 821 " }\n" 822 " int *ptr;\n" 823 "};"); 824 ASSERT_EQUALS("", errout.str()); 825 } 826 returnLocalVariable1()827 void returnLocalVariable1() { 828 check("char *foo()\n" 829 "{\n" 830 " char str[100] = {0};\n" 831 " return str;\n" 832 "}"); 833 ASSERT_EQUALS( 834 "[test.cpp:4] -> [test.cpp:3] -> [test.cpp:4]: (error) Returning pointer to local variable 'str' that will be invalid when returning.\n", 835 errout.str()); 836 837 check("char *foo()\n" // use ValueFlow 838 "{\n" 839 " char str[100] = {0};\n" 840 " char *p = str;\n" 841 " return p;\n" 842 "}"); 843 ASSERT_EQUALS( 844 "[test.cpp:4] -> [test.cpp:3] -> [test.cpp:5]: (error) Returning pointer to local variable 'str' that will be invalid when returning.\n", 845 errout.str()); 846 847 check("class Fred {\n" 848 " char *foo();\n" 849 "};\n" 850 "char *Fred::foo()\n" 851 "{\n" 852 " char str[100] = {0};\n" 853 " return str;\n" 854 "}"); 855 ASSERT_EQUALS( 856 "[test.cpp:7] -> [test.cpp:6] -> [test.cpp:7]: (error) Returning pointer to local variable 'str' that will be invalid when returning.\n", 857 errout.str()); 858 859 check("char * format_reg(char *outbuffer_start) {\n" 860 " return outbuffer_start;\n" 861 "}\n" 862 "void print_with_operands() {\n" 863 " char temp[42];\n" 864 " char *tp = temp;\n" 865 " tp = format_reg(tp);\n" 866 "}"); 867 ASSERT_EQUALS("", errout.str()); 868 } 869 returnLocalVariable2()870 void returnLocalVariable2() { 871 check("std::string foo()\n" 872 "{\n" 873 " char str[100] = {0};\n" 874 " return str;\n" 875 "}"); 876 ASSERT_EQUALS("", errout.str()); 877 878 check("class Fred {\n" 879 " std::string foo();\n" 880 "};\n" 881 "std::string Fred::foo()\n" 882 "{\n" 883 " char str[100] = {0};\n" 884 " return str;\n" 885 "}"); 886 ASSERT_EQUALS("", errout.str()); 887 } 888 889 returnLocalVariable3()890 void returnLocalVariable3() { // &x[..] 891 // #3030 892 check("char *foo() {\n" 893 " char q[] = \"AAAAAAAAAAAA\";\n" 894 " return &q[1];\n" 895 "}"); 896 ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2] -> [test.cpp:3]: (error) Returning pointer to local variable 'q' that will be invalid when returning.\n", errout.str()); 897 898 check("char *foo()\n" 899 "{\n" 900 " static char q[] = \"AAAAAAAAAAAA\";\n" 901 " return &q[1];\n" 902 "}"); 903 ASSERT_EQUALS("", errout.str()); 904 905 check("char *foo()\n" 906 "{\n" 907 "char q[] = \"AAAAAAAAAAAA\";\n" 908 "char *p;\n" 909 "p = &q[1];\n" 910 "return p;\n" 911 "}"); 912 ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:3] -> [test.cpp:6]: (error) Returning pointer to local variable 'q' that will be invalid when returning.\n", errout.str()); 913 } 914 returnLocalVariable4()915 void returnLocalVariable4() { // x+y 916 check("char *foo() {\n" 917 " char x[10] = {0};\n" 918 " return x+5;\n" 919 "}"); 920 ASSERT_EQUALS( 921 "[test.cpp:3] -> [test.cpp:2] -> [test.cpp:3]: (error) Returning pointer to local variable 'x' that will be invalid when returning.\n", 922 errout.str()); 923 924 check("char *foo(int y) {\n" 925 " char x[10] = {0};\n" 926 " return (x+8)-y;\n" 927 "}"); 928 ASSERT_EQUALS( 929 "[test.cpp:3] -> [test.cpp:2] -> [test.cpp:3]: (error) Returning pointer to local variable 'x' that will be invalid when returning.\n", 930 errout.str()); 931 } 932 returnLocalVariable5()933 void returnLocalVariable5() { // cast 934 check("char *foo() {\n" 935 " int x[10] = {0};\n" 936 " return (char *)x;\n" 937 "}"); 938 ASSERT_EQUALS( 939 "[test.cpp:3] -> [test.cpp:2] -> [test.cpp:3]: (error) Returning pointer to local variable 'x' that will be invalid when returning.\n", 940 errout.str()); 941 } 942 returnLocalVariable6()943 void returnLocalVariable6() { // valueflow 944 check("int *foo() {\n" 945 " int x = 123;\n" 946 " int p = &x;\n" 947 " return p;\n" 948 "}"); 949 ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning object that points to local variable 'x' that will be invalid when returning.\n", errout.str()); 950 } 951 returnReference1()952 void returnReference1() { 953 check("int &foo()\n" 954 "{\n" 955 " int s = 0;\n" 956 " int& x = s;\n" 957 " return x;\n" 958 "}"); 959 ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:5]: (error) Reference to local variable returned.\n", errout.str()); 960 961 check("std::string &foo()\n" 962 "{\n" 963 " std::string s;\n" 964 " return s;\n" 965 "}"); 966 ASSERT_EQUALS("[test.cpp:4]: (error) Reference to local variable returned.\n", errout.str()); 967 968 check("std::vector<int> &foo()\n" 969 "{\n" 970 " std::vector<int> v;\n" 971 " return v;\n" 972 "}"); 973 ASSERT_EQUALS("[test.cpp:4]: (error) Reference to local variable returned.\n", errout.str()); 974 975 check("std::vector<int> &foo()\n" 976 "{\n" 977 " static std::vector<int> v;\n" 978 " return v;\n" 979 "}"); 980 ASSERT_EQUALS("", errout.str()); 981 982 check("std::vector<int> &foo()\n" 983 "{\n" 984 " thread_local std::vector<int> v;\n" 985 " return v;\n" 986 "}"); 987 ASSERT_EQUALS("", errout.str()); 988 989 check("std::string hello()\n" 990 "{\n" 991 " return \"hello\";\n" 992 "}\n" 993 "\n" 994 "std::string &f()\n" 995 "{\n" 996 " return hello();\n" 997 "}"); 998 ASSERT_EQUALS("[test.cpp:8]: (error) Reference to temporary returned.\n", errout.str()); 999 1000 // make sure scope is used in function lookup 1001 check("class Fred {\n" 1002 " std::string hello() {\n" 1003 " return std::string();\n" 1004 " }\n" 1005 "};\n" 1006 "std::string &f() {\n" 1007 " return hello();\n" 1008 "}"); 1009 ASSERT_EQUALS("", errout.str()); 1010 1011 check("std::string hello() {\n" 1012 " return std::string();\n" 1013 "}\n" 1014 "\n" 1015 "std::string &f() {\n" 1016 " return hello();\n" 1017 "}"); 1018 ASSERT_EQUALS("[test.cpp:6]: (error) Reference to temporary returned.\n", errout.str()); 1019 1020 check("std::string hello() {\n" 1021 " return \"foo\";\n" 1022 "}\n" 1023 "\n" 1024 "std::string &f() {\n" 1025 " return hello().substr(1);\n" 1026 "}"); 1027 ASSERT_EQUALS("[test.cpp:6]: (error) Reference to temporary returned.\n", errout.str()); 1028 1029 check("class Foo;\n" 1030 "Foo hello() {\n" 1031 " return Foo();\n" 1032 "}\n" 1033 "\n" 1034 "Foo& f() {\n" 1035 " return hello();\n" 1036 "}"); 1037 ASSERT_EQUALS("[test.cpp:7]: (error) Reference to temporary returned.\n", errout.str()); 1038 1039 // make sure function overloads are handled properly 1040 check("class Foo;\n" 1041 "Foo & hello(bool) {\n" 1042 " static Foo foo;\n" 1043 " return foo;\n" 1044 "}\n" 1045 "Foo hello() {\n" 1046 " return Foo();\n" 1047 "}\n" 1048 "\n" 1049 "Foo& f() {\n" 1050 " return hello(true);\n" 1051 "}"); 1052 ASSERT_EQUALS("", errout.str()); 1053 1054 check("Foo hello() {\n" 1055 " return Foo();\n" 1056 "}\n" 1057 "\n" 1058 "Foo& f() {\n" // Unknown type - might be a reference 1059 " return hello();\n" 1060 "}"); 1061 ASSERT_EQUALS("", errout.str()); 1062 } 1063 returnReference2()1064 void returnReference2() { 1065 check("class Fred {\n" 1066 " std::string &foo();\n" 1067 "}\n" 1068 "std::string &Fred::foo()\n" 1069 "{\n" 1070 " std::string s;\n" 1071 " return s;\n" 1072 "}"); 1073 ASSERT_EQUALS("[test.cpp:7]: (error) Reference to local variable returned.\n", errout.str()); 1074 1075 check("class Fred {\n" 1076 " std::vector<int> &foo();\n" 1077 "};\n" 1078 "std::vector<int> &Fred::foo()\n" 1079 "{\n" 1080 " std::vector<int> v;\n" 1081 " return v;\n" 1082 "}"); 1083 ASSERT_EQUALS("[test.cpp:7]: (error) Reference to local variable returned.\n", errout.str()); 1084 1085 check("class Fred {\n" 1086 " std::vector<int> &foo();\n" 1087 "};\n" 1088 "std::vector<int> &Fred::foo()\n" 1089 "{\n" 1090 " static std::vector<int> v;\n" 1091 " return v;\n" 1092 "}"); 1093 ASSERT_EQUALS("", errout.str()); 1094 1095 check("class Fred {\n" 1096 " std::string &f();\n" 1097 "};\n" 1098 "std::string hello()\n" 1099 "{\n" 1100 " return \"hello\";\n" 1101 "}\n" 1102 "std::string &Fred::f()\n" 1103 "{\n" 1104 " return hello();\n" 1105 "}"); 1106 ASSERT_EQUALS("[test.cpp:10]: (error) Reference to temporary returned.\n", errout.str()); 1107 1108 check("class Fred {\n" 1109 " std::string hello();\n" 1110 " std::string &f();\n" 1111 "};\n" 1112 "std::string Fred::hello()\n" 1113 "{\n" 1114 " return \"hello\";\n" 1115 "}\n" 1116 "std::string &Fred::f()\n" 1117 "{\n" 1118 " return hello();\n" 1119 "}"); 1120 ASSERT_EQUALS("[test.cpp:11]: (error) Reference to temporary returned.\n", errout.str()); 1121 1122 check("class Bar;\n" 1123 "Bar foo() {\n" 1124 " return something;\n" 1125 "}\n" 1126 "Bar& bar() {\n" 1127 " return foo();\n" 1128 "}"); 1129 ASSERT_EQUALS("[test.cpp:6]: (error) Reference to temporary returned.\n", errout.str()); 1130 1131 check("std::map<int, string> foo() {\n" 1132 " return something;\n" 1133 "}\n" 1134 "std::map<int, string>& bar() {\n" 1135 " return foo();\n" 1136 "}"); 1137 ASSERT_EQUALS("[test.cpp:5]: (error) Reference to temporary returned.\n", errout.str()); 1138 1139 check("Bar foo() {\n" 1140 " return something;\n" 1141 "}\n" 1142 "Bar& bar() {\n" // Unknown type - might be a typedef to a reference type 1143 " return foo();\n" 1144 "}"); 1145 ASSERT_EQUALS("", errout.str()); 1146 // Don't crash with function in unknown scope (#4076) 1147 check("X& a::Bar() {}" 1148 "X& foo() {" 1149 " return Bar();" 1150 "}"); 1151 } 1152 returnReference3()1153 void returnReference3() { 1154 check("double & f(double & rd) {\n" 1155 " double ret = getValue();\n" 1156 " rd = ret;\n" 1157 " return rd;\n" 1158 "}", false); 1159 ASSERT_EQUALS("", errout.str()); 1160 } 1161 1162 // Returning reference to global variable returnReference4()1163 void returnReference4() { 1164 check("double a;\n" 1165 "double & f() {\n" 1166 " return a;\n" 1167 "}"); 1168 ASSERT_EQUALS("", errout.str()); 1169 } 1170 returnReference5()1171 void returnReference5() { 1172 check("struct A {\n" 1173 " int i;\n" 1174 "};\n" 1175 1176 "struct B {\n" 1177 " A a;\n" 1178 "};\n" 1179 1180 "struct C {\n" 1181 " B *b;\n" 1182 " const A& a() const {\n" 1183 " const B *pb = b;\n" 1184 " const A &ra = pb->a;\n" 1185 " return ra;\n" 1186 " }\n" 1187 "};"); 1188 ASSERT_EQUALS("", errout.str()); 1189 } 1190 returnReference6()1191 void returnReference6() { 1192 check("Fred & create() {\n" 1193 " Fred &fred(*new Fred);\n" 1194 " return fred;\n" 1195 "}"); 1196 ASSERT_EQUALS("", errout.str()); 1197 } 1198 returnReference7()1199 void returnReference7() { // 3791 - false positive for overloaded function 1200 check("std::string a();\n" 1201 "std::string &a(int);\n" 1202 "std::string &b() {\n" 1203 " return a(12);\n" 1204 "}"); 1205 ASSERT_EQUALS("", errout.str()); 1206 1207 check("std::string &a(int);\n" 1208 "std::string a();\n" 1209 "std::string &b() {\n" 1210 " return a(12);\n" 1211 "}"); 1212 ASSERT_EQUALS("", errout.str()); 1213 } 1214 returnReference8()1215 void returnReference8() { 1216 check("int& f(std::vector<int> &v) {\n" 1217 " std::vector<int>::iterator it = v.begin();\n" 1218 " int& value = *it;\n" 1219 " return value;\n" 1220 "}"); 1221 ASSERT_EQUALS("", errout.str()); 1222 } 1223 returnReference9()1224 void returnReference9() { 1225 check("int& f(bool b, int& x, int& y) {\n" 1226 " return b ? x : y;\n" 1227 "}"); 1228 ASSERT_EQUALS("", errout.str()); 1229 } 1230 returnReference10()1231 void returnReference10() { 1232 check("class A { int f() const; };\n" 1233 "int& g() {\n" 1234 " A a;\n" 1235 " return a.f();\n" 1236 "}"); 1237 ASSERT_EQUALS("[test.cpp:4]: (error) Reference to temporary returned.\n", errout.str()); 1238 1239 check("class A { int& f() const; };\n" 1240 "int& g() {\n" 1241 " A a;\n" 1242 " return a.f();\n" 1243 "}"); 1244 ASSERT_EQUALS("", errout.str()); 1245 } 1246 returnReference11()1247 void returnReference11() { 1248 check("class A { static int f(); };\n" 1249 "int& g() {\n" 1250 " return A::f();\n" 1251 "}"); 1252 ASSERT_EQUALS("[test.cpp:3]: (error) Reference to temporary returned.\n", errout.str()); 1253 1254 check("class A { static int& f(); };\n" 1255 "int& g() {\n" 1256 " return A::f();\n" 1257 "}"); 1258 ASSERT_EQUALS("", errout.str()); 1259 1260 check("namespace A { int& f(); }\n" 1261 "int& g() {\n" 1262 " return A::f();\n" 1263 "}"); 1264 ASSERT_EQUALS("", errout.str()); 1265 } 1266 returnReference12()1267 void returnReference12() { 1268 check("class A { static int& f(); };\n" 1269 "auto g() {\n" 1270 " return &A::f;\n" 1271 "}"); 1272 ASSERT_EQUALS("", errout.str()); 1273 1274 check("class A { static int& f(); };\n" 1275 "auto g() {\n" 1276 " auto x = &A::f;\n" 1277 " return x;\n" 1278 "}"); 1279 ASSERT_EQUALS("", errout.str()); 1280 } 1281 returnReference13()1282 void returnReference13() { 1283 check("std::vector<int> v;\n" 1284 "void* vp = &v;\n" 1285 "int& foo(size_t i) {\n" 1286 " return ((std::vector<int>*)vp)->at(i);\n" 1287 "}"); 1288 ASSERT_EQUALS("", errout.str()); 1289 1290 check("std::vector<int> v;\n" 1291 "void* vp = &v;\n" 1292 "int& foo(size_t i) {\n" 1293 " return static_cast<std::vector<int>*>(vp)->at(i);\n" 1294 "}"); 1295 ASSERT_EQUALS("", errout.str()); 1296 } 1297 returnReference14()1298 void returnReference14() { 1299 check("struct C { void* m; };\n" 1300 "struct A { void* &f(); };\n" 1301 "C* g() {\n" 1302 " static C c;\n" 1303 " return &c;\n" 1304 "}\n" 1305 "void* &A::f() {\n" 1306 " return g()->m;\n" 1307 "}"); 1308 ASSERT_EQUALS("", errout.str()); 1309 } 1310 returnReference15()1311 void returnReference15() { 1312 check("template <class T>\n" 1313 "const int& f() {\n" 1314 " static int s;\n" 1315 " return s;\n" 1316 "}\n" 1317 "template <class T>\n" 1318 "const int& f(const T&) {\n" 1319 " return f<T>();\n" 1320 "}"); 1321 ASSERT_EQUALS("", errout.str()); 1322 1323 check("template <class T>\n" 1324 "int g();\n" 1325 "template <class T>\n" 1326 "const int& f(const T&) {\n" 1327 " return g<T>();\n" 1328 "}"); 1329 TODO_ASSERT_EQUALS("error", "", errout.str()); 1330 } 1331 returnReference16()1332 void returnReference16() { 1333 check("int& f(std::tuple<int>& x) {\n" 1334 " return std::get<0>(x);\n" 1335 "}"); 1336 ASSERT_EQUALS("", errout.str()); 1337 1338 check("int& f(int x) {\n" 1339 " return std::get<0>(std::make_tuple(x));\n" 1340 "}"); 1341 TODO_ASSERT_EQUALS("error", "", errout.str()); 1342 } 1343 returnReference17()1344 void returnReference17() { 1345 check("auto g() -> int&;\n" 1346 "int& f() {\n" 1347 " return g();\n" 1348 "}"); 1349 ASSERT_EQUALS("", errout.str()); 1350 } 1351 returnReference18()1352 void returnReference18() { 1353 check("template<class T>\n" 1354 "auto f(T& x) -> decltype(x);\n" 1355 "int& g(int* x) {\n" 1356 " return f(*x);\n" 1357 "}"); 1358 ASSERT_EQUALS("", errout.str()); 1359 } 1360 1361 // #9597 returnReference19()1362 void returnReference19() { 1363 check("struct C : B {\n" 1364 " const B &f() const { return (const B &)*this; }\n" 1365 "}"); 1366 ASSERT_EQUALS("", errout.str()); 1367 } 1368 1369 // #9536 returnReference20()1370 void returnReference20() { 1371 check("struct a {\n" 1372 " int& operator()() const;\n" 1373 "};\n" 1374 "int& b() {\n" 1375 " return a()();\n" 1376 "}"); 1377 ASSERT_EQUALS("", errout.str()); 1378 1379 check("auto a() {\n" 1380 " return []() -> int& {\n" 1381 " static int b;\n" 1382 " return b;\n" 1383 " };\n" 1384 "}\n" 1385 "const int& c() {\n" 1386 " return a()();\n" 1387 "}"); 1388 ASSERT_EQUALS("", errout.str()); 1389 1390 check("std::function<int&()> a();\n" 1391 "int& b() {\n" 1392 " return a()();\n" 1393 "}"); 1394 ASSERT_EQUALS("", errout.str()); 1395 1396 // #9889 1397 check("int f(std::vector<std::function<int&()>>& v, int i) {\n" 1398 " auto& j = v[i]();\n" 1399 " return j;\n" 1400 "}\n"); 1401 ASSERT_EQUALS("", errout.str()); 1402 } 1403 1404 // #9530 returnReference21()1405 void returnReference21() { 1406 check("int& f(int& x) {\n" 1407 " return {x};\n" 1408 "}\n"); 1409 ASSERT_EQUALS("", errout.str()); 1410 } 1411 returnReference22()1412 void returnReference22() { 1413 check("int& f() {\n" 1414 " std::unique_ptr<int> p = std::make_unique<int>(1);\n" 1415 " return *p;\n" 1416 "}\n"); 1417 ASSERT_EQUALS("[test.cpp:3]: (error) Reference to local variable returned.\n", errout.str()); 1418 1419 check("void g(const std::unique_ptr<int>&);\n" 1420 "int& f() {\n" 1421 " std::unique_ptr<int> p = std::make_unique<int>(1);\n" 1422 " g(p);\n" 1423 " return *p;\n" 1424 "}\n"); 1425 ASSERT_EQUALS("[test.cpp:5]: (error) Reference to local variable returned.\n", errout.str()); 1426 1427 check("void g(std::shared_ptr<int>);\n" 1428 "int& f() {\n" 1429 " std::shared_ptr<int> p = std::make_shared<int>(1);\n" 1430 " g(p);\n" 1431 " return *p;\n" 1432 "}\n"); 1433 ASSERT_EQUALS("", errout.str()); 1434 1435 check("std::shared_ptr<int> g();\n" 1436 "int& f() {\n" 1437 " return *g();\n" 1438 "}\n"); 1439 ASSERT_EQUALS("", errout.str()); 1440 1441 check("std::unique_ptr<int> g();\n" 1442 "int& f() {\n" 1443 " return *g();\n" 1444 "}\n"); 1445 ASSERT_EQUALS("[test.cpp:3]: (error) Reference to temporary returned.\n", errout.str()); 1446 1447 check("struct A { int x; };\n" 1448 "int& f() {\n" 1449 " std::unique_ptr<A> p = std::make_unique<A>();\n" 1450 " return p->x;\n" 1451 "}\n"); 1452 ASSERT_EQUALS("[test.cpp:4]: (error) Reference to local variable returned.\n", errout.str()); 1453 } 1454 returnReference23()1455 void returnReference23() { 1456 check("const std::vector<int> * g();\n" 1457 "const std::vector<int>& f() {\n" 1458 " return *g();\n" 1459 "}\n"); 1460 ASSERT_EQUALS("", errout.str()); 1461 } 1462 returnReferenceFunction()1463 void returnReferenceFunction() { 1464 check("int& f(int& a) {\n" 1465 " return a;\n" 1466 "}\n" 1467 "int& hello() {\n" 1468 " int x = 0;\n" 1469 " return f(x);\n" 1470 "}"); 1471 ASSERT_EQUALS( 1472 "[test.cpp:1] -> [test.cpp:2] -> [test.cpp:6] -> [test.cpp:6]: (error) Reference to local variable returned.\n", 1473 errout.str()); 1474 1475 check("int& f(int& a) {\n" 1476 " return a;\n" 1477 "}\n" 1478 "int* hello() {\n" 1479 " int x = 0;\n" 1480 " return &f(x);\n" 1481 "}"); 1482 ASSERT_EQUALS( 1483 "[test.cpp:1] -> [test.cpp:2] -> [test.cpp:6] -> [test.cpp:6] -> [test.cpp:5] -> [test.cpp:6]: (error) Returning pointer to local variable 'x' that will be invalid when returning.\n", 1484 errout.str()); 1485 1486 check("int* f(int * x) {\n" 1487 " return x;\n" 1488 "}\n" 1489 "int * g(int x) {\n" 1490 " return f(&x);\n" 1491 "}"); 1492 ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:5] -> [test.cpp:4] -> [test.cpp:5]: (error) Returning pointer to local variable 'x' that will be invalid when returning.\n", errout.str()); 1493 1494 check("int* f(int * x) {\n" 1495 " x = nullptr;\n" 1496 " return x;\n" 1497 "}\n" 1498 "int * g(int x) {\n" 1499 " return f(&x);\n" 1500 "}"); 1501 ASSERT_EQUALS("", errout.str()); 1502 1503 check("int f(int& a) {\n" 1504 " return a;\n" 1505 "}\n" 1506 "int& hello() {\n" 1507 " int x = 0;\n" 1508 " return f(x);\n" 1509 "}"); 1510 ASSERT_EQUALS("[test.cpp:6]: (error) Reference to temporary returned.\n", errout.str()); 1511 1512 check("int& f(int a) {\n" 1513 " return a;\n" 1514 "}\n" 1515 "int& hello() {\n" 1516 " int x = 0;\n" 1517 " return f(x);\n" 1518 "}"); 1519 ASSERT_EQUALS("[test.cpp:2]: (error) Reference to local variable returned.\n", errout.str()); 1520 1521 check("int f(int a) {\n" 1522 " return a;\n" 1523 "}\n" 1524 "int& hello() {\n" 1525 " int x = 0;\n" 1526 " return f(x);\n" 1527 "}"); 1528 ASSERT_EQUALS("[test.cpp:6]: (error) Reference to temporary returned.\n", errout.str()); 1529 1530 check("template<class T>\n" 1531 "int& f(int& x, T y) {\n" 1532 " x += y;\n" 1533 " return x;\n" 1534 "}"); 1535 ASSERT_EQUALS("", errout.str()); 1536 } 1537 returnReferenceContainer()1538 void returnReferenceContainer() { 1539 check("auto& f() {\n" 1540 " std::vector<int> x;\n" 1541 " return x[0];\n" 1542 "}"); 1543 ASSERT_EQUALS("[test.cpp:3]: (error) Reference to local variable returned.\n", errout.str()); 1544 1545 check("auto& f() {\n" 1546 " std::vector<int> x;\n" 1547 " return x.front();\n" 1548 "}"); 1549 ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:3]: (error) Reference to local variable returned.\n", errout.str()); 1550 1551 check("std::vector<int> g();\n" 1552 "auto& f() {\n" 1553 " return g().front();\n" 1554 "}"); 1555 ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:3]: (error) Reference to temporary returned.\n", errout.str()); 1556 1557 check("auto& f() {\n" 1558 " return std::vector<int>{1}.front();\n" 1559 "}"); 1560 ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:2]: (error) Reference to temporary returned.\n", errout.str()); 1561 1562 check("struct A { int foo; };\n" 1563 "int& f(std::vector<A> v) {\n" 1564 " auto it = v.begin();\n" 1565 " return it->foo;\n" 1566 "}"); 1567 ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (error) Reference to local variable returned.\n", errout.str()); 1568 1569 check("template <class T, class K, class V>\n" 1570 "const V& get_default(const T& t, const K& k, const V& v) {\n" 1571 " auto it = t.find(k);\n" 1572 " if (it == t.end()) return v;\n" 1573 " return it->second;\n" 1574 "}\n" 1575 "const int& bar(const std::unordered_map<int, int>& m, int k) {\n" 1576 " auto x = 0;\n" 1577 " return get_default(m, k, x);\n" 1578 "}\n", 1579 true); 1580 ASSERT_EQUALS( 1581 "[test.cpp:2] -> [test.cpp:4] -> [test.cpp:9] -> [test.cpp:9]: (error, inconclusive) Reference to local variable returned.\n", 1582 errout.str()); 1583 1584 check("template <class T, class K, class V>\n" 1585 "const V& get_default(const T& t, const K& k, const V& v) {\n" 1586 " auto it = t.find(k);\n" 1587 " if (it == t.end()) return v;\n" 1588 " return it->second;\n" 1589 "}\n" 1590 "const int& bar(const std::unordered_map<int, int>& m, int k) {\n" 1591 " return get_default(m, k, 0);\n" 1592 "}\n", 1593 true); 1594 ASSERT_EQUALS( 1595 "[test.cpp:2] -> [test.cpp:4] -> [test.cpp:8] -> [test.cpp:8]: (error, inconclusive) Reference to temporary returned.\n", 1596 errout.str()); 1597 1598 check("struct A { int foo; };\n" 1599 "int& f(std::vector<A>& v) {\n" 1600 " auto it = v.begin();\n" 1601 " return it->foo;\n" 1602 "}"); 1603 ASSERT_EQUALS("", errout.str()); 1604 } 1605 returnReferenceLiteral()1606 void returnReferenceLiteral() { 1607 check("const std::string &a() {\n" 1608 " return \"foo\";\n" 1609 "}"); 1610 ASSERT_EQUALS("[test.cpp:2]: (error) Reference to temporary returned.\n", errout.str()); 1611 1612 check("const std::string a() {\n" 1613 " return \"foo\";\n" 1614 "}"); 1615 ASSERT_EQUALS("", errout.str()); 1616 1617 check("const std::string& f(const std::string& x) { return x; }\n" 1618 "const std::string &a() {\n" 1619 " return f(\"foo\");\n" 1620 "}"); 1621 ASSERT_EQUALS( 1622 "[test.cpp:1] -> [test.cpp:1] -> [test.cpp:3] -> [test.cpp:3]: (error) Reference to temporary returned.\n", 1623 errout.str()); 1624 1625 check("const char * f(const char * x) { return x; }\n" 1626 "const std::string &a() {\n" 1627 " return f(\"foo\");\n" 1628 "}"); 1629 ASSERT_EQUALS("[test.cpp:3]: (error) Reference to temporary returned.\n", errout.str()); 1630 } 1631 returnReferenceCalculation()1632 void returnReferenceCalculation() { 1633 check("const std::string &a(const std::string& str) {\n" 1634 " return \"foo\" + str;\n" 1635 "}"); 1636 ASSERT_EQUALS("[test.cpp:2]: (error) Reference to temporary returned.\n", errout.str()); 1637 1638 check("int& operator<<(int out, int path) {\n" 1639 " return out << path;\n" 1640 "}"); 1641 ASSERT_EQUALS("[test.cpp:2]: (error) Reference to temporary returned.\n", errout.str()); 1642 1643 check("std::ostream& operator<<(std::ostream& out, const std::string& path) {\n" 1644 " return out << path;\n" 1645 "}"); 1646 ASSERT_EQUALS("", errout.str()); 1647 1648 check("std::ostream& operator<<(std::ostream* out, const std::string& path) {\n" 1649 " return *out << path;\n" 1650 "}"); 1651 ASSERT_EQUALS("", errout.str()); 1652 1653 check("Unknown1& operator<<(Unknown1 out, Unknown2 path) {\n" 1654 " return out << path;\n" 1655 "}"); 1656 ASSERT_EQUALS("", errout.str()); 1657 1658 check("int& a(int b) {\n" 1659 " return 2*(b+1);\n" 1660 "}"); 1661 ASSERT_EQUALS("[test.cpp:2]: (error) Reference to temporary returned.\n", errout.str()); 1662 1663 check("const std::string &a(const std::string& str) {\n" 1664 " return str;\n" 1665 "}"); 1666 ASSERT_EQUALS("", errout.str()); 1667 1668 check("const std::string &a(int bar) {\n" 1669 " return foo(bar + 1);\n" 1670 "}"); 1671 ASSERT_EQUALS("", errout.str()); 1672 1673 check("const std::string a(const std::string& str) {\n" 1674 " return \"foo\" + str;\n" 1675 "}"); 1676 ASSERT_EQUALS("", errout.str()); 1677 1678 check("int& incValue(int& value) {\n" 1679 " return ++value;\n" 1680 "}"); 1681 ASSERT_EQUALS("", errout.str()); 1682 } 1683 returnReferenceLambda()1684 void returnReferenceLambda() { 1685 // #6787 1686 check("const Item& foo(const Container& items) const {\n" 1687 " return bar(items.begin(), items.end(),\n" 1688 " [](const Item& lhs, const Item& rhs) {\n" 1689 " return false;\n" 1690 " });\n" 1691 "}"); 1692 ASSERT_EQUALS("", errout.str()); 1693 1694 // #5844 1695 check("map<string,string> const &getVariableTable() {\n" 1696 "static map<string,string> const s_var = []{\n" 1697 " map<string,string> var;\n" 1698 " return var;\n" 1699 " }();\n" 1700 "return s_var;\n" 1701 "}"); 1702 ASSERT_EQUALS("", errout.str()); 1703 1704 // #7583 1705 check("Command& foo() {\n" 1706 " return f([]() -> int { return 1; });\n" 1707 "}"); 1708 ASSERT_EQUALS("", errout.str()); 1709 } 1710 returnReferenceInnerScope()1711 void returnReferenceInnerScope() { 1712 // #6951 1713 check("const Callback& make() {\n" 1714 " struct _Wrapper {\n" 1715 " static ulong call(void* o, const void* f, const void*[]) {\n" 1716 " return 1;\n" 1717 " }\n" 1718 " };\n" 1719 " return _make(_Wrapper::call, pmf);\n" 1720 "}"); 1721 ASSERT_EQUALS("", errout.str()); 1722 } 1723 returnReferenceRecursive()1724 void returnReferenceRecursive() { 1725 check("int& f() { return f(); }"); 1726 ASSERT_EQUALS("", errout.str()); 1727 1728 check("int& g(int& i) { return i; }\n" 1729 "int& f() { return g(f()); }"); 1730 ASSERT_EQUALS("", errout.str()); 1731 } 1732 extendedLifetime()1733 void extendedLifetime() { 1734 check("void g(int*);\n" 1735 "int h();\n" 1736 "auto f() {\n" 1737 " const int& x = h();\n" 1738 " return [&] { return x; };\n" 1739 "}"); 1740 ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:5] -> [test.cpp:4] -> [test.cpp:5]: (error) Returning lambda that captures local variable 'x' that will be invalid when returning.\n", errout.str()); 1741 1742 check("void g(int*);\n" 1743 "int h();\n" 1744 "int* f() {\n" 1745 " const int& x = h();\n" 1746 " return &x;\n" 1747 "}"); 1748 ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:5] -> [test.cpp:4] -> [test.cpp:5]: (error) Returning pointer to local variable 'x' that will be invalid when returning.\n", errout.str()); 1749 1750 check("void g(int*);\n" 1751 "int h();\n" 1752 "void f() {\n" 1753 " int& x = h();\n" 1754 " g(&x);\n" 1755 "}"); 1756 ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:5] -> [test.cpp:5]: (error) Using pointer to temporary.\n" 1757 "[test.cpp:4] -> [test.cpp:5]: (error) Using reference to dangling temporary.\n", errout.str()); 1758 1759 check("void g(int*);\n" 1760 "int h();\n" 1761 "void f() {\n" 1762 " const int& x = h();\n" 1763 " g(&x);\n" 1764 "}"); 1765 ASSERT_EQUALS("", errout.str()); 1766 1767 check("struct Data {\n" 1768 " std::string path;\n" 1769 "};\n" 1770 "const char* foo() {\n" 1771 " const Data& data = getData();\n" 1772 " return data.path.c_str();\n" 1773 "}"); 1774 ASSERT_EQUALS("", errout.str()); 1775 } 1776 danglingReference()1777 void danglingReference() { 1778 check("int f( int k )\n" 1779 "{\n" 1780 " static int &r = k;\n" 1781 " return r;\n" 1782 "}"); 1783 ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:3]: (error) Non-local reference variable 'r' to local variable 'k'\n", 1784 errout.str()); 1785 1786 check("int &f( int & k )\n" 1787 "{\n" 1788 " static int &r = k;\n" 1789 " return r;\n" 1790 "}"); 1791 ASSERT_EQUALS("", errout.str()); 1792 } 1793 danglingTempReference()1794 void danglingTempReference() { 1795 check("const std::string& g(const std::string& str_cref) {\n" 1796 " return str_cref;\n" 1797 "}\n" 1798 "void f() {\n" 1799 " const auto& str_cref2 = g(std::string(\"hello\"));\n" 1800 " std::cout << str_cref2 << std::endl;\n" 1801 "}\n"); 1802 ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:1] -> [test.cpp:2] -> [test.cpp:5] -> [test.cpp:6]: (error) Using reference to dangling temporary.\n", errout.str()); 1803 1804 // Lifetime extended 1805 check("std::string g(const std::string& str_cref) {\n" 1806 " return str_cref;\n" 1807 "}\n" 1808 "void f() {\n" 1809 " const auto& str_cref2 = g(std::string(\"hello\"));\n" 1810 " std::cout << str_cref2 << std::endl;\n" 1811 "}\n"); 1812 ASSERT_EQUALS("", errout.str()); 1813 1814 check("char f() {\n" 1815 " char c = 0;\n" 1816 " char&& cr = std::move(c);\n" 1817 " return cr;\n" 1818 "}\n"); 1819 ASSERT_EQUALS("", errout.str()); 1820 1821 // #9987 1822 check("void g(std::vector<int>);\n" 1823 "void f() {\n" 1824 " std::vector<int>&& v = {};\n" 1825 " g(std::move(v));\n" 1826 "}\n"); 1827 ASSERT_EQUALS("", errout.str()); 1828 1829 check("void g(std::vector<int>);\n" 1830 "std::vector<int> h();\n" 1831 "void f() {\n" 1832 " std::vector<int>&& v = h();\n" 1833 " g(std::move(v));\n" 1834 "}\n"); 1835 ASSERT_EQUALS("", errout.str()); 1836 } 1837 testglobalnamespace()1838 void testglobalnamespace() { 1839 check("class SharedPtrHolder\n" 1840 "{\n" 1841 " ::std::tr1::shared_ptr<int> pNum;\n" 1842 "public:\n" 1843 " void SetNum(const ::std::tr1::shared_ptr<int> & apNum)\n" 1844 " {\n" 1845 " pNum = apNum;\n" 1846 " }\n" 1847 "}"); 1848 1849 ASSERT_EQUALS("", errout.str()); 1850 } 1851 returnParameterAddress()1852 void returnParameterAddress() { 1853 check("int* foo(int y)\n" 1854 "{\n" 1855 " return &y;\n" 1856 "}"); 1857 1858 ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:1] -> [test.cpp:3]: (error) Returning pointer to local variable 'y' that will be invalid when returning.\n", errout.str()); 1859 1860 check("int ** foo(int * y)\n" 1861 "{\n" 1862 " return &y;\n" 1863 "}"); 1864 1865 ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:1] -> [test.cpp:3]: (error) Returning pointer to local variable 'y' that will be invalid when returning.\n", errout.str()); 1866 1867 check("const int * foo(const int & y)\n" 1868 "{\n" 1869 " return &y;\n" 1870 "}"); 1871 1872 ASSERT_EQUALS("", errout.str()); 1873 1874 check("int * foo(int * y)\n" 1875 "{\n" 1876 " return y;\n" 1877 "}"); 1878 1879 ASSERT_EQUALS("", errout.str()); 1880 1881 check("struct s { void *p; };\n" 1882 "extern struct s* f(void);\n" 1883 "void g(void **q)\n" 1884 "{\n" 1885 " struct s *r = f();\n" 1886 " *q = &r->p;\n" 1887 "}"); 1888 1889 ASSERT_EQUALS("", errout.str()); 1890 } 1891 testconstructor()1892 void testconstructor() { // Ticket #5478 - crash while checking a constructor 1893 check("class const_tree_iterator {\n" 1894 " const_tree_iterator(bool (*_incream)(node_type*&)) {}\n" 1895 " const_tree_iterator& parent() {\n" 1896 " return const_tree_iterator(foo);\n" 1897 " }\n" 1898 "};"); 1899 } 1900 variableIsUsedInScope()1901 void variableIsUsedInScope() { 1902 check("void removed_cb (GList *uids) {\n" 1903 "for (; uids; uids = uids->next) {\n" 1904 "}\n" 1905 "}\n" 1906 "void opened_cb () {\n" 1907 " g_signal_connect (G_CALLBACK (removed_cb));\n" 1908 "}"); 1909 } 1910 danglingLifetimeLambda()1911 void danglingLifetimeLambda() { 1912 check("auto f() {\n" 1913 " int a = 1;\n" 1914 " auto l = [&](){ return a; };\n" 1915 " return l;\n" 1916 "}"); 1917 ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning lambda that captures local variable 'a' that will be invalid when returning.\n", errout.str()); 1918 1919 check("auto f() {\n" 1920 " int a = 1;\n" 1921 " return [&](){ return a; };\n" 1922 "}"); 1923 ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2] -> [test.cpp:3]: (error) Returning lambda that captures local variable 'a' that will be invalid when returning.\n", errout.str()); 1924 1925 check("auto f(int a) {\n" 1926 " return [&](){ return a; };\n" 1927 "}"); 1928 ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:1] -> [test.cpp:2]: (error) Returning lambda that captures local variable 'a' that will be invalid when returning.\n", errout.str()); 1929 1930 check("auto f(int a) {\n" 1931 " auto p = &a;\n" 1932 " return [=](){ return p; };\n" 1933 "}"); 1934 ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3] -> [test.cpp:1] -> [test.cpp:3]: (error) Returning lambda that captures local variable 'a' that will be invalid when returning.\n", errout.str()); 1935 1936 check("auto g(int& a) {\n" 1937 " int p = a;\n" 1938 " return [&](){ return p; };\n" 1939 "}"); 1940 ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2] -> [test.cpp:3]: (error) Returning lambda that captures local variable 'p' that will be invalid when returning.\n", errout.str()); 1941 1942 check("auto f() {\n" 1943 " return [=](){\n" 1944 " int a = 1;\n" 1945 " return [&](){ return a; };\n" 1946 " };\n" 1947 "}"); 1948 ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3] -> [test.cpp:4]: (error) Returning lambda that captures local variable 'a' that will be invalid when returning.\n", errout.str()); 1949 1950 check("auto f(int b) {\n" 1951 " return [=](int a){\n" 1952 " a += b;\n" 1953 " return [&](){ return a; };\n" 1954 " };\n" 1955 "}"); 1956 ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning lambda that captures local variable 'a' that will be invalid when returning.\n", errout.str()); 1957 1958 check("auto g(int& a) {\n" 1959 " return [&](){ return a; };\n" 1960 "}"); 1961 ASSERT_EQUALS("", errout.str()); 1962 1963 check("auto g(int a) {\n" 1964 " auto p = a;\n" 1965 " return [=](){ return p; };\n" 1966 "}"); 1967 ASSERT_EQUALS("", errout.str()); 1968 1969 check("auto g(int& a) {\n" 1970 " auto p = a;\n" 1971 " return [=](){ return p; };\n" 1972 "}"); 1973 ASSERT_EQUALS("", errout.str()); 1974 1975 check("auto g(int& a) {\n" 1976 " int& p = a;\n" 1977 " return [&](){ return p; };\n" 1978 "}"); 1979 ASSERT_EQUALS("", errout.str()); 1980 1981 check("template<class F>\n" 1982 "void g(F);\n" 1983 "auto f() {\n" 1984 " int x;\n" 1985 " return g([&]() { return x; });\n" 1986 "}"); 1987 ASSERT_EQUALS("", errout.str()); 1988 1989 check("auto f() {\n" 1990 " int i = 0;\n" 1991 " return [&i] {};\n" 1992 "}\n"); 1993 ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2] -> [test.cpp:3]: (error) Returning lambda that captures local variable 'i' that will be invalid when returning.\n", errout.str()); 1994 1995 check("auto f() {\n" 1996 " int i = 0;\n" 1997 " return [i] {};\n" 1998 "}\n"); 1999 ASSERT_EQUALS("", errout.str()); 2000 2001 check("auto f() {\n" 2002 " int i = 0;\n" 2003 " return [=, &i] {};\n" 2004 "}\n"); 2005 ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2] -> [test.cpp:3]: (error) Returning lambda that captures local variable 'i' that will be invalid when returning.\n", errout.str()); 2006 2007 check("auto f() {\n" 2008 " int i = 0;\n" 2009 " int j = 0;\n" 2010 " return [=, &i] { return j; };\n" 2011 "}\n"); 2012 ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning lambda that captures local variable 'i' that will be invalid when returning.\n", errout.str()); 2013 2014 check("auto f() {\n" 2015 " int i = 0;\n" 2016 " return [&, i] {};\n" 2017 "}\n"); 2018 ASSERT_EQUALS("", errout.str()); 2019 2020 check("auto f() {\n" 2021 " int i = 0;\n" 2022 " int j = 0;\n" 2023 " return [&, i] { return j; };\n" 2024 "}\n"); 2025 ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3] -> [test.cpp:4]: (error) Returning lambda that captures local variable 'j' that will be invalid when returning.\n", errout.str()); 2026 2027 check("auto f(int& i) {\n" 2028 " int j = 0;\n" 2029 " return [=, &i] { return j; };\n" 2030 "}\n"); 2031 ASSERT_EQUALS("", errout.str()); 2032 2033 check("void f(int*);\n" 2034 "auto g(int y) {\n" 2035 " int x = y;\n" 2036 " return [=] {\n" 2037 " g(&x);\n" 2038 " };\n" 2039 "}\n"); 2040 ASSERT_EQUALS("", errout.str()); 2041 2042 check("struct A {\n" 2043 " int x;\n" 2044 "};\n" 2045 "auto f() {\n" 2046 " A a;\n" 2047 " return [=] {\n" 2048 " const A* ap = &a;\n" 2049 " ap->x;\n" 2050 " };\n" 2051 "}\n"); 2052 ASSERT_EQUALS("", errout.str()); 2053 } 2054 danglingLifetimeContainer()2055 void danglingLifetimeContainer() { 2056 check("auto f(const std::vector<int>& x) {\n" 2057 " auto it = x.begin();\n" 2058 " return it;\n" 2059 "}"); 2060 ASSERT_EQUALS("", errout.str()); 2061 2062 check("auto f() {\n" 2063 " std::vector<int> x;\n" 2064 " auto it = x.begin();\n" 2065 " return it;\n" 2066 "}"); 2067 ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning iterator to local container 'x' that will be invalid when returning.\n", errout.str()); 2068 2069 check("auto f() {\n" 2070 " std::vector<int> x;\n" 2071 " auto p = x.data();\n" 2072 " return p;\n" 2073 "}"); 2074 ASSERT_EQUALS( 2075 "[test.cpp:3] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning pointer to local variable 'x' that will be invalid when returning.\n", 2076 errout.str()); 2077 2078 check("auto f() {\n" 2079 " std::vector<int> x;\n" 2080 " auto p = &x[0];\n" 2081 " return p;\n" 2082 "}"); 2083 ASSERT_EQUALS( 2084 "[test.cpp:3] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning pointer to local variable 'x' that will be invalid when returning.\n", 2085 errout.str()); 2086 2087 check("struct A { int foo; };\n" 2088 "int* f(std::vector<A> v) {\n" 2089 " auto it = v.begin();\n" 2090 " return &it->foo;\n" 2091 "}"); 2092 ASSERT_EQUALS( 2093 "[test.cpp:3] -> [test.cpp:4] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning object that points to local variable 'v' that will be invalid when returning.\n", 2094 errout.str()); 2095 2096 check("auto f(std::vector<int> x) {\n" 2097 " auto it = x.begin();\n" 2098 " return it;\n" 2099 "}"); 2100 ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:1] -> [test.cpp:3]: (error) Returning iterator to local container 'x' that will be invalid when returning.\n", errout.str()); 2101 2102 check("auto f() {\n" 2103 " std::vector<int> x;\n" 2104 " auto it = x.begin();\n" 2105 " return std::next(it);\n" 2106 "}"); 2107 ASSERT_EQUALS( 2108 "[test.cpp:3] -> [test.cpp:4] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning object that points to local variable 'x' that will be invalid when returning.\n", 2109 errout.str()); 2110 2111 check("auto f() {\n" 2112 " std::vector<int> x;\n" 2113 " auto it = x.begin();\n" 2114 " return it + 1;\n" 2115 "}"); 2116 ASSERT_EQUALS( 2117 "[test.cpp:3] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning iterator to local container 'x' that will be invalid when returning.\n", 2118 errout.str()); 2119 2120 check("auto f() {\n" 2121 " std::vector<int> x;\n" 2122 " auto it = x.begin();\n" 2123 " return std::next(it + 1);\n" 2124 "}"); 2125 ASSERT_EQUALS( 2126 "[test.cpp:3] -> [test.cpp:4] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning object that points to local variable 'x' that will be invalid when returning.\n", 2127 errout.str()); 2128 2129 check("std::vector<int*> f() {\n" 2130 " int i = 0;\n" 2131 " std::vector<int*> v;\n" 2132 " v.push_back(&i);\n" 2133 " return v;\n" 2134 "}"); 2135 ASSERT_EQUALS( 2136 "[test.cpp:4] -> [test.cpp:4] -> [test.cpp:2] -> [test.cpp:5]: (error) Returning object that points to local variable 'i' that will be invalid when returning.\n", 2137 errout.str()); 2138 2139 check("std::vector<int*> f() {\n" 2140 " std::vector<int*> r;\n" 2141 " int i = 0;\n" 2142 " std::vector<int*> v;\n" 2143 " v.push_back(&i);\n" 2144 " r.assign(v.begin(), v.end());\n" 2145 " return r;\n" 2146 "}"); 2147 ASSERT_EQUALS( 2148 "[test.cpp:5] -> [test.cpp:5] -> [test.cpp:5] -> [test.cpp:3] -> [test.cpp:7]: (error) Returning object that points to local variable 'i' that will be invalid when returning.\n", 2149 errout.str()); 2150 2151 check("struct A {\n" 2152 " std::vector<int*> v;\n" 2153 " void f() {\n" 2154 " int i;\n" 2155 " v.push_back(&i);\n" 2156 " }\n" 2157 "};"); 2158 ASSERT_EQUALS( 2159 "[test.cpp:5] -> [test.cpp:5] -> [test.cpp:4] -> [test.cpp:5]: (error) Non-local variable 'v' will use object that points to local variable 'i'.\n", 2160 errout.str()); 2161 2162 check("struct A {\n" 2163 " std::vector<int*> v;\n" 2164 " void f() {\n" 2165 " int i;\n" 2166 " int * p = &i;\n" 2167 " v.push_back(p);\n" 2168 " }\n" 2169 "};"); 2170 ASSERT_EQUALS( 2171 "[test.cpp:5] -> [test.cpp:6] -> [test.cpp:4] -> [test.cpp:6]: (error) Non-local variable 'v' will use object that points to local variable 'i'.\n", 2172 errout.str()); 2173 2174 check("struct A {\n" 2175 " std::vector<int*> m;\n" 2176 " void f() {\n" 2177 " int x;\n" 2178 " std::vector<int*> v;\n" 2179 " v.push_back(&x);\n" 2180 " m.insert(m.end(), v.begin(), v.end());\n" 2181 " }\n" 2182 "};"); 2183 ASSERT_EQUALS( 2184 "[test.cpp:6] -> [test.cpp:6] -> [test.cpp:6] -> [test.cpp:4] -> [test.cpp:7]: (error) Non-local variable 'm' will use object that points to local variable 'x'.\n", 2185 errout.str()); 2186 2187 check("std::vector<int>::iterator f(std::vector<int> v) {\n" 2188 " for(auto it = v.begin();it != v.end();it++) {\n" 2189 " return it;\n" 2190 " }\n" 2191 " return {};\n" 2192 "}"); 2193 ASSERT_EQUALS( 2194 "[test.cpp:2] -> [test.cpp:1] -> [test.cpp:3]: (error) Returning iterator to local container 'v' that will be invalid when returning.\n", 2195 errout.str()); 2196 2197 check("const char * f() {\n" 2198 " std::string ba(\"hello\");\n" 2199 " return ba.c_str();\n" 2200 "}"); 2201 ASSERT_EQUALS( 2202 "[test.cpp:3] -> [test.cpp:2] -> [test.cpp:3]: (error) Returning pointer to local variable 'ba' that will be invalid when returning.\n", 2203 errout.str()); 2204 2205 check("template <class T, class K, class V>\n" 2206 "const V* get_default(const T& t, const K& k, const V* v) {\n" 2207 " auto it = t.find(k);\n" 2208 " if (it == t.end()) return v;\n" 2209 " return &it->second;\n" 2210 "}\n" 2211 "const int* bar(const std::unordered_map<int, int>& m, int k) {\n" 2212 " auto x = 0;\n" 2213 " return get_default(m, k, &x);\n" 2214 "}\n", 2215 true); 2216 ASSERT_EQUALS( 2217 "[test.cpp:9] -> [test.cpp:9] -> [test.cpp:8] -> [test.cpp:9]: (error, inconclusive) Returning pointer to local variable 'x' that will be invalid when returning.\n", 2218 errout.str()); 2219 2220 check("std::vector<int> g();\n" 2221 "auto f() {\n" 2222 " return g().begin();\n" 2223 "}"); 2224 TODO_ASSERT_EQUALS( 2225 "[test.cpp:3] -> [test.cpp:3]: (error) Returning iterator that will be invalid when returning.\n", 2226 "", 2227 errout.str()); 2228 2229 check("std::vector<int> f();\n" 2230 "auto f() {\n" 2231 " auto it = g().begin();\n" 2232 " return it;\n" 2233 "}"); 2234 TODO_ASSERT_EQUALS("error", "", errout.str()); 2235 2236 check("std::vector<int> f();\n" 2237 "int& f() {\n" 2238 " return *g().begin();\n" 2239 "}"); 2240 TODO_ASSERT_EQUALS("error", "", errout.str()); 2241 2242 check("struct A {\n" 2243 " std::vector<std::string> v;\n" 2244 " void f() {\n" 2245 " char s[3];\n" 2246 " v.push_back(s);\n" 2247 " }\n" 2248 "};"); 2249 ASSERT_EQUALS("", errout.str()); 2250 2251 check("std::vector<std::string> f() {\n" 2252 " const char * s = \"hello\";\n" 2253 " std::vector<std::string> v;\n" 2254 " v.push_back(s);\n" 2255 " return v;\n" 2256 "}"); 2257 ASSERT_EQUALS("", errout.str()); 2258 2259 check("auto f() {\n" 2260 " static std::vector<int> x;\n" 2261 " return x.begin();\n" 2262 "}"); 2263 ASSERT_EQUALS("", errout.str()); 2264 2265 check("std::string g() {\n" 2266 " std::vector<char> v;\n" 2267 " return v.data();\n" 2268 "}"); 2269 ASSERT_EQUALS("", errout.str()); 2270 2271 check("std::vector<int>::iterator f(std::vector<int>* v) {\n" 2272 " return v->begin();\n" 2273 "}"); 2274 ASSERT_EQUALS("", errout.str()); 2275 2276 check("std::vector<int>::iterator f(std::vector<int>* v) {\n" 2277 " std::vector<int>* v = new std::vector<int>();\n" 2278 " return v->begin();\n" 2279 "}"); 2280 ASSERT_EQUALS("", errout.str()); 2281 2282 check("int f(std::vector<int> v) {\n" 2283 " return *v.begin();\n" 2284 "}"); 2285 ASSERT_EQUALS("", errout.str()); 2286 2287 check("int f(std::vector<int> v) {\n" 2288 " return v.end() - v.begin();\n" 2289 "}"); 2290 ASSERT_EQUALS("", errout.str()); 2291 2292 check("auto g() {\n" 2293 " std::vector<char> v;\n" 2294 " return {v, [v]() { return v.data(); }};\n" 2295 "}"); 2296 ASSERT_EQUALS("", errout.str()); 2297 2298 check("template<class F>\n" 2299 "void g(F);\n" 2300 "auto f() {\n" 2301 " std::vector<char> v;\n" 2302 " return g([&]() { return v.data(); });\n" 2303 "}"); 2304 ASSERT_EQUALS("", errout.str()); 2305 2306 check("std::vector<int> g();\n" 2307 "struct A {\n" 2308 " std::vector<int> m;\n" 2309 " void f() {\n" 2310 " std::vector<int> v = g();\n" 2311 " m.insert(m.end(), v.begin(), v.end());\n" 2312 " }\n" 2313 "};"); 2314 ASSERT_EQUALS("", errout.str()); 2315 2316 check("void f(bool b) {\n" 2317 " std::vector<int> v = {1};\n" 2318 " if (b) {\n" 2319 " int a[] = {0};\n" 2320 " v.insert(a, a+1);\n" 2321 " }\n" 2322 " return v.back() == 0;\n" 2323 "}"); 2324 ASSERT_EQUALS("", errout.str()); 2325 2326 check("class A {\n" 2327 " int f( P p ) {\n" 2328 " std::vector< S > maps;\n" 2329 " m2.insert( m1.begin(), m1.end() );\n" 2330 " }\n" 2331 " struct B {};\n" 2332 " std::map< S, B > m1;\n" 2333 " std::map< S, B > m2;\n" 2334 "};"); 2335 ASSERT_EQUALS("", errout.str()); 2336 2337 check("struct A {\n" 2338 " std::vector<int*> v;\n" 2339 " int x;\n" 2340 " void f() {\n" 2341 " v.push_back(&x);\n" 2342 " }\n" 2343 "};"); 2344 ASSERT_EQUALS("", errout.str()); 2345 2346 check("size_t f(const std::string& x) {\n" 2347 " std::string y = \"x\";\n" 2348 " return y.find(x);\n" 2349 "}"); 2350 ASSERT_EQUALS("", errout.str()); 2351 2352 check("std::string* f();\n" 2353 "const char* g() {\n" 2354 " std::string* var = f();\n" 2355 " return var->c_str();\n" 2356 "}"); 2357 ASSERT_EQUALS("", errout.str()); 2358 2359 check("std::string f() {\n" 2360 " std::vector<char> data{};\n" 2361 " data.push_back('a');\n" 2362 " return std::string{ data.data(), data.size() };\n" 2363 "}"); 2364 ASSERT_EQUALS("", errout.str()); 2365 2366 check("std::vector<char*> f() {\n" 2367 " char a = 0;\n" 2368 " return std::vector<char*>{&a};\n" 2369 "}"); 2370 ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:3] -> [test.cpp:2] -> [test.cpp:3]: (error) Returning object that points to local variable 'a' that will be invalid when returning.\n", errout.str()); 2371 2372 check("std::vector<int>* g();\n" 2373 "int& f() {\n" 2374 " auto* p = g();\n" 2375 " return p->front();\n" 2376 "}\n"); 2377 ASSERT_EQUALS("", errout.str()); 2378 2379 check("std::vector<std::vector<int>> g();\n" 2380 "void f() {\n" 2381 " for(auto& x:g())\n" 2382 " std::sort(x.begin(), x.end());\n" 2383 "}\n"); 2384 ASSERT_EQUALS("", errout.str()); 2385 2386 check("struct A {\n" 2387 " std::vector<int*> v;\n" 2388 " void add(int* i) {\n" 2389 " v.push_back(i);\n" 2390 " }\n" 2391 " void f() {\n" 2392 " int i = 0;\n" 2393 " add(&i);\n" 2394 " }\n" 2395 "};\n"); 2396 ASSERT_EQUALS( 2397 "[test.cpp:8] -> [test.cpp:8] -> [test.cpp:4] -> [test.cpp:7] -> [test.cpp:4]: (error) Non-local variable 'v' will use object that points to local variable 'i'.\n", 2398 errout.str()); 2399 2400 check("struct A {\n" 2401 " std::vector<int*> v;\n" 2402 " void add(int* i) {\n" 2403 " v.push_back(i);\n" 2404 " }\n" 2405 "};\n" 2406 "void f() {\n" 2407 " A a;\n" 2408 " int i = 0;\n" 2409 " a.add(&i);\n" 2410 "}\n"); 2411 ASSERT_EQUALS("", errout.str()); 2412 2413 check("struct A {\n" 2414 " std::vector<int*> v;\n" 2415 " void add(int* i) {\n" 2416 " v.push_back(i);\n" 2417 " }\n" 2418 " void f() {\n" 2419 " A a;\n" 2420 " int i = 0;\n" 2421 " a.add(&i);\n" 2422 " }\n" 2423 "};\n"); 2424 ASSERT_EQUALS("", errout.str()); 2425 2426 check("int f() {\n" 2427 " int i;\n" 2428 " {\n" 2429 " std::vector<int> vec;\n" 2430 " const auto iter = vec.begin();\n" 2431 " i = (int)(iter - vec.begin());\n" 2432 " }\n" 2433 " return i;\n" 2434 "}\n"); 2435 ASSERT_EQUALS("", errout.str()); 2436 2437 check("int* get(std::vector<int>& container) {\n" 2438 " Sequence seq(container);\n" 2439 " for (auto& r : seq) {\n" 2440 " return &r;\n" 2441 " }\n" 2442 " return &*seq.begin();\n" 2443 "}\n"); 2444 ASSERT_EQUALS("", errout.str()); 2445 } 2446 danglingLifetime()2447 void danglingLifetime() { 2448 check("auto f() {\n" 2449 " std::vector<int> a;\n" 2450 " auto it = a.begin();\n" 2451 " return [=](){ return it; };\n" 2452 "}"); 2453 ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning lambda that captures local variable 'a' that will be invalid when returning.\n", errout.str()); 2454 2455 check("auto f(std::vector<int> a) {\n" 2456 " auto it = a.begin();\n" 2457 " return [=](){ return it; };\n" 2458 "}"); 2459 ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3] -> [test.cpp:1] -> [test.cpp:3]: (error) Returning lambda that captures local variable 'a' that will be invalid when returning.\n", errout.str()); 2460 2461 check("struct e {};\n" 2462 "e * j() {\n" 2463 " e c[20];\n" 2464 " return c;\n" 2465 "}"); 2466 ASSERT_EQUALS( 2467 "[test.cpp:4] -> [test.cpp:3] -> [test.cpp:4]: (error) Returning pointer to local variable 'c' that will be invalid when returning.\n", 2468 errout.str()); 2469 2470 check("auto f(std::vector<int>& a) {\n" 2471 " auto it = a.begin();\n" 2472 " return [=](){ return it; };\n" 2473 "}"); 2474 ASSERT_EQUALS("", errout.str()); 2475 2476 check("int * f(int a[]) {\n" 2477 " return a;\n" 2478 "}"); 2479 ASSERT_EQUALS("", errout.str()); 2480 2481 check("void f() {\n" 2482 " struct b {\n" 2483 " uint32_t f[6];\n" 2484 " } d;\n" 2485 " uint32_t *a = d.f;\n" 2486 "}"); 2487 ASSERT_EQUALS("", errout.str()); 2488 2489 // Don't decay std::array 2490 check("std::array<char, 1> f() {\n" 2491 " std::array<char, 1> x;\n" 2492 " return x;\n" 2493 "}"); 2494 ASSERT_EQUALS("", errout.str()); 2495 2496 // Make sure we don't hang 2497 check("struct A;\n" 2498 "void f() {\n" 2499 " using T = A[3];\n" 2500 " A &&a = T{1, 2, 3}[1];\n" 2501 "}"); 2502 ASSERT_EQUALS("", errout.str()); 2503 2504 // Make sure we don't hang 2505 check("struct A;\n" 2506 "void f() {\n" 2507 " using T = A[3];\n" 2508 " A &&a = T{1, 2, 3}[1]();\n" 2509 "}"); 2510 ASSERT_EQUALS("", errout.str()); 2511 2512 // Make sure we don't hang 2513 check("struct A;\n" 2514 "void f() {\n" 2515 " using T = A[3];\n" 2516 " A &&a = T{1, 2, 3}[1];\n" 2517 "}"); 2518 ASSERT_EQUALS("", errout.str()); 2519 2520 // Make sure we don't hang 2521 check("struct A;\n" 2522 "void f() {\n" 2523 " using T = A[3];\n" 2524 " A &&a = T{1, 2, 3}[1]();\n" 2525 "}"); 2526 ASSERT_EQUALS("", errout.str()); 2527 2528 // Crash #8872 2529 check("struct a {\n" 2530 " void operator()(b c) override {\n" 2531 " d(c, [&] { c->e });\n" 2532 " }\n" 2533 "};"); 2534 ASSERT_EQUALS("", errout.str()); 2535 2536 check("struct a {\n" 2537 " void operator()(b c) override {\n" 2538 " d(c, [=] { c->e });\n" 2539 " }\n" 2540 "};"); 2541 ASSERT_EQUALS("", errout.str()); 2542 2543 check("struct a {\n" 2544 " a(char* b) {}\n" 2545 "};\n" 2546 "a f() {\n" 2547 " char c[20];\n" 2548 " return c;\n" 2549 "}"); 2550 ASSERT_EQUALS("", errout.str()); 2551 2552 check("struct a {\n" 2553 " a(char* b) {}\n" 2554 "};\n" 2555 "a g() {\n" 2556 " char c[20];\n" 2557 " a d = c;\n" 2558 " return d;\n" 2559 "}"); 2560 ASSERT_EQUALS("", errout.str()); 2561 2562 check("void f() {\n" 2563 " struct a {\n" 2564 " std::vector<int> v;\n" 2565 " auto g() { return v.end(); }\n" 2566 " };\n" 2567 "}"); 2568 ASSERT_EQUALS("", errout.str()); 2569 2570 check("int * f(std::vector<int>& v) {\n" 2571 " for(int & x : v)\n" 2572 " return &x;\n" 2573 " return nullptr;\n" 2574 "}"); 2575 ASSERT_EQUALS("", errout.str()); 2576 2577 // #9275 2578 check("struct S {\n" 2579 " void f();\n" 2580 " std::string m;\n" 2581 "}\n" 2582 "void S::f() {\n" 2583 " char buf[1024];\n" 2584 " const char* msg = buf;\n" 2585 " m = msg;\n" 2586 "}"); 2587 ASSERT_EQUALS("", errout.str()); 2588 2589 // #9201 2590 check("int* f() {\n" 2591 " struct a { int m; };\n" 2592 " static a b{0};\n" 2593 " return &b.m;\n" 2594 "}"); 2595 ASSERT_EQUALS("", errout.str()); 2596 2597 // #9453 2598 check("int *ptr;\n" 2599 "void foo(int arr[]) {\n" 2600 " ptr = &arr[2];\n" 2601 "}"); 2602 ASSERT_EQUALS("", errout.str()); 2603 2604 // #9639 2605 check("struct Fred {\n" 2606 " std::string s;\n" 2607 "};\n" 2608 "const Fred &getFred();\n" 2609 "const char * f() {\n" 2610 " const Fred &fred = getFred();\n" 2611 " return fred.s.c_str();\n" 2612 "}"); 2613 ASSERT_EQUALS("", errout.str()); 2614 2615 // #9534 2616 check("struct A {\n" 2617 " int* x;\n" 2618 "};\n" 2619 "int* f(int i, std::vector<A>& v) {\n" 2620 " A& y = v[i];\n" 2621 " return &y.x[i];\n" 2622 "}"); 2623 ASSERT_EQUALS("", errout.str()); 2624 2625 // #9712 2626 check("std::string f(const char *str) {\n" 2627 " char value[256];\n" 2628 " return value;\n" 2629 "}"); 2630 ASSERT_EQUALS("", errout.str()); 2631 2632 // #9770 2633 check("class C {\n" 2634 " std::string f(const char*);\n" 2635 "};\n" 2636 "std::string C::f(const char*) {\n" 2637 " const char data[] = \"x\";\n" 2638 " return data;\n" 2639 "}\n"); 2640 ASSERT_EQUALS("", errout.str()); 2641 2642 // #9899 2643 check("struct A {\n" 2644 " std::vector<int> v;\n" 2645 " void f(std::vector<int> w) {\n" 2646 " v = std::move(w);\n" 2647 " }\n" 2648 " void g(std::vector<int> w) {\n" 2649 " f(std::move(w));\n" 2650 " }\n" 2651 "};\n"); 2652 ASSERT_EQUALS("", errout.str()); 2653 2654 //Make sure we can still take the address of a reference without warning 2655 check("int* foo() {\n" 2656 " int& x = getX();\n" 2657 " return &x;\n" 2658 "}\n"); 2659 ASSERT_EQUALS("", errout.str()); 2660 check("struct C {\n" 2661 " int* m_x;\n" 2662 " void foo() {\n" 2663 " const int& x = getX();\n" 2664 " m_x = &x;\n" 2665 " }\n" 2666 "}\n"); 2667 ASSERT_EQUALS("", errout.str()); 2668 2669 // #10090 2670 check("struct a {\n" 2671 " int b{};\n" 2672 "};\n" 2673 "struct c {\n" 2674 " int* c{};\n" 2675 " a* d{};\n" 2676 "};\n" 2677 "a* f();\n" 2678 "c g() {\n" 2679 " c e;\n" 2680 " e.d = f();\n" 2681 " if (e.d)\n" 2682 " e.c = &e.d->b;\n" 2683 " return e;\n" 2684 "}\n"); 2685 ASSERT_EQUALS("", errout.str()); 2686 2687 // #10214 2688 check("struct A {\n" 2689 " std::string key;\n" 2690 " const char *value;\n" 2691 "};\n" 2692 "const char *f(const std::string &key, const std::vector<A> &lookup) {\n" 2693 " const auto &entry =\n" 2694 " std::find_if(lookup.begin(), lookup.end(),\n" 2695 " [key](const auto &v) { return v.key == key; });\n" 2696 " return (entry == lookup.end()) ? \"\" : entry->value;\n" 2697 "}\n"); 2698 ASSERT_EQUALS("", errout.str()); 2699 2700 // #9811 2701 check("struct Base {\n" 2702 " virtual auto get() -> int & = 0;\n" 2703 "};\n" 2704 "struct A : public Base {\n" 2705 " int z = 42;\n" 2706 " auto get() -> int & override { return z; }\n" 2707 " auto getMore() -> int & { return get(); }\n" 2708 "};\n"); 2709 ASSERT_EQUALS("", errout.str()); 2710 } 2711 danglingLifetimeFunction()2712 void danglingLifetimeFunction() { 2713 check("auto f() {\n" 2714 " int a;\n" 2715 " return std::ref(a);\n" 2716 "}"); 2717 ASSERT_EQUALS( 2718 "[test.cpp:3] -> [test.cpp:2] -> [test.cpp:3]: (error) Returning object that points to local variable 'a' that will be invalid when returning.\n", 2719 errout.str()); 2720 2721 check("auto f() {\n" 2722 " int a;\n" 2723 " return std::make_tuple(std::ref(a));\n" 2724 "}"); 2725 ASSERT_EQUALS( 2726 "[test.cpp:3] -> [test.cpp:3] -> [test.cpp:2] -> [test.cpp:3]: (error) Returning object that points to local variable 'a' that will be invalid when returning.\n", 2727 errout.str()); 2728 2729 check("template<class T>\n" 2730 "auto by_value(T x) {\n" 2731 " return [=] { return x; };\n" 2732 "}\n" 2733 "auto g() {\n" 2734 " std::vector<int> v;\n" 2735 " return by_value(v.begin());\n" 2736 "}"); 2737 ASSERT_EQUALS( 2738 "[test.cpp:7] -> [test.cpp:7] -> [test.cpp:3] -> [test.cpp:3] -> [test.cpp:6] -> [test.cpp:7]: (error) Returning object that points to local variable 'v' that will be invalid when returning.\n", 2739 errout.str()); 2740 2741 check("template<class T>\n" 2742 "auto by_value(const T& x) {\n" 2743 " return [=] { return x; };\n" 2744 "}\n" 2745 "auto g() {\n" 2746 " std::vector<int> v;\n" 2747 " return by_value(v.begin());\n" 2748 "}\n"); 2749 ASSERT_EQUALS( 2750 "[test.cpp:7] -> [test.cpp:7] -> [test.cpp:3] -> [test.cpp:3] -> [test.cpp:2] -> [test.cpp:6] -> [test.cpp:7]: (error) Returning object that points to local variable 'v' that will be invalid when returning.\n", 2751 errout.str()); 2752 2753 check("auto by_ref(int& x) {\n" 2754 " return [&] { return x; };\n" 2755 "}\n" 2756 "auto f() {\n" 2757 " int i = 0;\n" 2758 " return by_ref(i);\n" 2759 "}"); 2760 ASSERT_EQUALS( 2761 "[test.cpp:2] -> [test.cpp:1] -> [test.cpp:2] -> [test.cpp:6] -> [test.cpp:5] -> [test.cpp:6]: (error) Returning object that points to local variable 'i' that will be invalid when returning.\n", 2762 errout.str()); 2763 2764 check("auto by_ref(const int& x) {\n" 2765 " return [=] { return x; };\n" 2766 "}\n" 2767 "auto f() {\n" 2768 " int i = 0;\n" 2769 " return by_ref(i);\n" 2770 "}\n"); 2771 ASSERT_EQUALS("", errout.str()); 2772 2773 check("auto f(int x) {\n" 2774 " int a;\n" 2775 " std::tie(a) = x;\n" 2776 " return a;\n" 2777 "}"); 2778 ASSERT_EQUALS("", errout.str()); 2779 2780 check("std::pair<std::string, std::string>\n" 2781 "str_pair(std::string const & a, std::string const & b) {\n" 2782 " return std::make_pair(a, b);\n" 2783 "}\n" 2784 "std::vector<std::pair<std::string, std::string> > create_parameters() {\n" 2785 " std::vector<std::pair<std::string, std::string> > par;\n" 2786 " par.push_back(str_pair(\"param1\", \"prop_a\"));\n" 2787 " par.push_back(str_pair(\"param2\", \"prop_b\"));\n" 2788 " par.push_back(str_pair(\"param3\", \"prop_c\"));\n" 2789 " return par;\n" 2790 "}\n"); 2791 ASSERT_EQUALS("", errout.str()); 2792 } 2793 danglingLifetimeAggegrateConstructor()2794 void danglingLifetimeAggegrateConstructor() { 2795 check("struct A {\n" 2796 " const int& x;\n" 2797 " int y;\n" 2798 "};\n" 2799 "A f() {\n" 2800 " int i = 0;\n" 2801 " return A{i, i};\n" 2802 "}"); 2803 ASSERT_EQUALS( 2804 "[test.cpp:7] -> [test.cpp:6] -> [test.cpp:7]: (error) Returning object that points to local variable 'i' that will be invalid when returning.\n", 2805 errout.str()); 2806 2807 check("struct A {\n" 2808 " const int& x;\n" 2809 " int y;\n" 2810 "};\n" 2811 "A f() {\n" 2812 " int i = 0;\n" 2813 " return {i, i};\n" 2814 "}"); 2815 ASSERT_EQUALS( 2816 "[test.cpp:7] -> [test.cpp:6] -> [test.cpp:7]: (error) Returning object that points to local variable 'i' that will be invalid when returning.\n", 2817 errout.str()); 2818 2819 check("struct A {\n" 2820 " const int& x;\n" 2821 " int y;\n" 2822 "};\n" 2823 "A f() {\n" 2824 " int i = 0;\n" 2825 " A r{i, i};\n" 2826 " return r;\n" 2827 "}"); 2828 ASSERT_EQUALS( 2829 "[test.cpp:7] -> [test.cpp:6] -> [test.cpp:8]: (error) Returning object that points to local variable 'i' that will be invalid when returning.\n", 2830 errout.str()); 2831 2832 check("struct A {\n" 2833 " const int& x;\n" 2834 " int y;\n" 2835 "};\n" 2836 "A f() {\n" 2837 " int i = 0;\n" 2838 " A r = {i, i};\n" 2839 " return r;\n" 2840 "}"); 2841 ASSERT_EQUALS( 2842 "[test.cpp:7] -> [test.cpp:6] -> [test.cpp:8]: (error) Returning object that points to local variable 'i' that will be invalid when returning.\n", 2843 errout.str()); 2844 2845 check("struct A {\n" 2846 " const int& x;\n" 2847 " int y;\n" 2848 "};\n" 2849 "A f(int& x) {\n" 2850 " int i = 0;\n" 2851 " return A{i, x};\n" 2852 "}"); 2853 ASSERT_EQUALS( 2854 "[test.cpp:7] -> [test.cpp:6] -> [test.cpp:7]: (error) Returning object that points to local variable 'i' that will be invalid when returning.\n", 2855 errout.str()); 2856 2857 check("struct A {\n" 2858 " const int& x;\n" 2859 " int y;\n" 2860 "};\n" 2861 "A f(int& x) {\n" 2862 " int i = 0;\n" 2863 " return A{x, i};\n" 2864 "}"); 2865 ASSERT_EQUALS("", errout.str()); 2866 2867 check("struct A {\n" 2868 " const int& x;\n" 2869 " int y;\n" 2870 "};\n" 2871 "A f(int& x) {\n" 2872 " return A{x, x};\n" 2873 "}"); 2874 ASSERT_EQUALS("", errout.str()); 2875 2876 check("struct A { int i; const int& j; };\n" 2877 "A f(int& x) {\n" 2878 " int y = 0;\n" 2879 " return A{y, x};\n" 2880 "}"); 2881 ASSERT_EQUALS("", errout.str()); 2882 } 2883 danglingLifetimeInitList()2884 void danglingLifetimeInitList() { 2885 check("std::vector<int*> f() {\n" 2886 " int i = 0;\n" 2887 " std::vector<int*> v = {&i, &i};\n" 2888 " return v;\n" 2889 "}"); 2890 ASSERT_EQUALS( 2891 "[test.cpp:3] -> [test.cpp:3] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning object that points to local variable 'i' that will be invalid when returning.\n", 2892 errout.str()); 2893 2894 // TODO: Ast is missing for this case 2895 check("std::vector<int*> f() {\n" 2896 " int i = 0;\n" 2897 " std::vector<int*> v{&i, &i};\n" 2898 " return v;\n" 2899 "}"); 2900 TODO_ASSERT_EQUALS( 2901 "[test.cpp:3] -> [test.cpp:3] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning object that points to local variable 'i' that will be invalid when returning.\n", 2902 "", 2903 errout.str()); 2904 2905 check("std::vector<int*> f() {\n" 2906 " int i = 0;\n" 2907 " return {&i, &i};\n" 2908 "}"); 2909 ASSERT_EQUALS( 2910 "[test.cpp:3] -> [test.cpp:3] -> [test.cpp:2] -> [test.cpp:3]: (error) Returning object that points to local variable 'i' that will be invalid when returning.\n", 2911 errout.str()); 2912 2913 check("std::vector<int*> f(int& x) {\n" 2914 " return {&x, &x};\n" 2915 "}"); 2916 ASSERT_EQUALS("", errout.str()); 2917 2918 check("std::vector<std::string> f() {\n" 2919 " std::set<std::string> x;\n" 2920 " x.insert(\"1\");\n" 2921 " x.insert(\"2\");\n" 2922 " return { x.begin(), x.end() };\n" 2923 "}"); 2924 ASSERT_EQUALS("", errout.str()); 2925 } 2926 danglingLifetimeImplicitConversion()2927 void danglingLifetimeImplicitConversion() { 2928 check("struct A { A(const char *a); };\n" 2929 "A f() {\n" 2930 " std::string ba(\"hello\");\n" 2931 " return ba.c_str();\n" 2932 "}"); 2933 ASSERT_EQUALS("", errout.str()); 2934 2935 check("struct A { A(const char *a); };\n" 2936 "A f() {\n" 2937 " std::string ba(\"hello\");\n" 2938 " A bp = ba.c_str();\n" 2939 " return bp;\n" 2940 "}"); 2941 ASSERT_EQUALS("", errout.str()); 2942 2943 check("struct A { A(const char *a); };\n" 2944 "std::vector<A> f() {\n" 2945 " std::string ba(\"hello\");\n" 2946 " std::vector<A> v;\n" 2947 " v.push_back(ba.c_str());\n" 2948 " return v;\n" 2949 "}"); 2950 ASSERT_EQUALS("", errout.str()); 2951 2952 check("std::string f(const std::string& x) {\n" 2953 " const char c[] = \"\";\n" 2954 " if (!x.empty())\n" 2955 " return x + c;\n" 2956 " return \"\";\n" 2957 "}"); 2958 ASSERT_EQUALS("", errout.str()); 2959 2960 check("std::string f(const std::string& x) {\n" 2961 " const char c[] = \"123\";\n" 2962 " if (!x.empty())\n" 2963 " return c + 1;\n" 2964 " return \"\";\n" 2965 "}"); 2966 ASSERT_EQUALS("", errout.str()); 2967 } 2968 danglingTemporaryLifetime()2969 void danglingTemporaryLifetime() { 2970 check("const int& g(const int& x) {\n" 2971 " return x;\n" 2972 "}\n" 2973 "void f(int& i) {\n" 2974 " int* x = &g(0);\n" 2975 " i += *x;\n" 2976 "}"); 2977 ASSERT_EQUALS( 2978 "[test.cpp:1] -> [test.cpp:2] -> [test.cpp:5] -> [test.cpp:5] -> [test.cpp:6]: (error) Using pointer to temporary.\n", 2979 errout.str()); 2980 2981 check("QString f() {\n" 2982 " QString a(\"dummyValue\");\n" 2983 " const char* b = a.toStdString().c_str();\n" 2984 " QString c = b;\n" 2985 " return c;\n" 2986 "}"); 2987 ASSERT_EQUALS( 2988 "[test.cpp:3] -> [test.cpp:4]: (error) Using pointer to temporary.\n", 2989 errout.str()); 2990 2991 check("auto f(std::string s) {\n" 2992 " const char *x = s.substr(1,2).c_str();\n" 2993 " auto i = s.substr(4,5).begin();\n" 2994 " return *i;\n" 2995 "}"); 2996 ASSERT_EQUALS( 2997 "[test.cpp:3] -> [test.cpp:4]: (error) Using iterator to temporary.\n", 2998 errout.str()); 2999 3000 check("std::string f() {\n" 3001 " std::stringstream tmp;\n" 3002 " const std::string &str = tmp.str();\n" 3003 " return std::string(str.c_str(), 1);\n" 3004 "}"); 3005 ASSERT_EQUALS("", errout.str()); 3006 3007 check("int get_value();\n" 3008 "const int &get_reference1() {\n" 3009 " const int &x = get_value();\n" 3010 " return x;\n" 3011 "}\n"); 3012 ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (error) Reference to temporary returned.\n", errout.str()); 3013 3014 check("int get_value();\n" 3015 "const int &get_reference2() {\n" 3016 " const int &x1 = get_value();\n" 3017 " const int &x2 = x1;\n" 3018 " return x2;\n" 3019 "}\n"); 3020 ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3] -> [test.cpp:5]: (error) Reference to temporary returned.\n", 3021 errout.str()); 3022 3023 check("const std::string& getState() {\n" 3024 " static const std::string& state = \"\";\n" 3025 " return state;\n" 3026 "}\n"); 3027 ASSERT_EQUALS("", errout.str()); 3028 3029 check("struct var {\n" 3030 " void fun();\n" 3031 "}x;\n" 3032 "var* T(const char*) {\n" 3033 " return &x;\n" 3034 "}\n" 3035 "std::string GetTemp();\n" 3036 "void f() {\n" 3037 " auto a = T(GetTemp().c_str());\n" 3038 " a->fun();\n" 3039 "}\n"); 3040 ASSERT_EQUALS("", errout.str()); 3041 } 3042 invalidLifetime()3043 void invalidLifetime() { 3044 check("void foo(int a) {\n" 3045 " std::function<void()> f;\n" 3046 " if (a > 0) {\n" 3047 " int b = a + 1;\n" 3048 " f = [&]{ return b; };\n" 3049 " }\n" 3050 " f();\n" 3051 "}"); 3052 ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:4] -> [test.cpp:7]: (error) Using lambda that captures local variable 'b' that is out of scope.\n", errout.str()); 3053 3054 check("void f(bool b) {\n" 3055 " int* x;\n" 3056 " if(b) {\n" 3057 " int y[6] = {0,1,2,3,4,5};\n" 3058 " x = y;\n" 3059 " }\n" 3060 " x[3];\n" 3061 "}"); 3062 ASSERT_EQUALS( 3063 "[test.cpp:5] -> [test.cpp:4] -> [test.cpp:7]: (error) Using pointer to local variable 'y' that is out of scope.\n", 3064 errout.str()); 3065 3066 check("void foo(int a) {\n" 3067 " std::function<void()> f;\n" 3068 " if (a > 0) {\n" 3069 " int b = a + 1;\n" 3070 " f = [&]{ return b; };\n" 3071 " f();\n" 3072 " }\n" 3073 "}"); 3074 ASSERT_EQUALS("", errout.str()); 3075 3076 check("struct a {\n" 3077 " b();\n" 3078 " std::list<int> c;\n" 3079 "};\n" 3080 "void a::b() {\n" 3081 " c.end()\n" 3082 "}"); 3083 ASSERT_EQUALS("", errout.str()); 3084 3085 check("void b(char f[], char c[]) {\n" 3086 " std::string d(c); {\n" 3087 " std::string e;\n" 3088 " b(f, e.c_str())\n" 3089 " }\n" 3090 "}"); 3091 ASSERT_EQUALS("", errout.str()); 3092 3093 check("void f(bool b) {\n" 3094 " std::string s;\n" 3095 " if(b) {\n" 3096 " char buf[3];\n" 3097 " s = buf;\n" 3098 " }\n" 3099 " std::cout << s;\n" 3100 "}"); 3101 ASSERT_EQUALS("", errout.str()); 3102 3103 check("int &a[];\n" 3104 "void b(){int *c = a};"); 3105 ASSERT_EQUALS("", errout.str()); 3106 3107 check("struct A {\n" 3108 " int x;\n" 3109 "};\n" 3110 "struct B {\n" 3111 " std::function<void()> x;\n" 3112 " void f() {\n" 3113 " this->x = [&] {\n" 3114 " B y;\n" 3115 " return y.x;\n" 3116 " };\n" 3117 " }\n" 3118 "};"); 3119 ASSERT_EQUALS("", errout.str()); 3120 } 3121 deadPointer()3122 void deadPointer() { 3123 check("void f() {\n" 3124 " int *p = p1;\n" 3125 " if (cond) {\n" 3126 " int x;\n" 3127 " p = &x;\n" 3128 " }\n" 3129 " *p = 0;\n" 3130 "}"); 3131 ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:4] -> [test.cpp:7]: (error) Using pointer to local variable 'x' that is out of scope.\n", errout.str()); 3132 3133 // FP: don't warn in subfunction 3134 check("void f(struct KEY *key) {\n" 3135 " key->x = 0;\n" 3136 "}\n" 3137 "\n" 3138 "int main() {\n" 3139 " struct KEY *tmp = 0;\n" 3140 " struct KEY k;\n" 3141 "\n" 3142 " if (condition) {\n" 3143 " tmp = &k;\n" 3144 " } else {\n" 3145 " }\n" 3146 " f(tmp);\n" 3147 "}"); 3148 ASSERT_EQUALS("", errout.str()); 3149 3150 // Don't warn about references (#6399) 3151 check("void f() {\n" 3152 " wxAuiToolBarItem* former_hover = NULL;\n" 3153 " for (i = 0, count = m_items.GetCount(); i < count; ++i) {\n" 3154 " wxAuiToolBarItem& item = m_items.Item(i);\n" 3155 " former_hover = &item;\n" 3156 " }\n" 3157 " if (former_hover != pitem)\n" 3158 " dosth();\n" 3159 "}"); 3160 ASSERT_EQUALS("", errout.str()); 3161 3162 check("void f() {\n" 3163 " wxAuiToolBarItem* former_hover = NULL;\n" 3164 " for (i = 0, count = m_items.GetCount(); i < count; ++i) {\n" 3165 " wxAuiToolBarItem item = m_items.Item(i);\n" 3166 " former_hover = &item;\n" 3167 " }\n" 3168 " if (former_hover != pitem)\n" 3169 " dosth();\n" 3170 "}"); 3171 ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:4] -> [test.cpp:7]: (error) Using pointer to local variable 'item' that is out of scope.\n", errout.str()); 3172 3173 // #6575 3174 check("void trp_deliver_signal() {\n" 3175 " union {\n" 3176 " Uint32 theData[25];\n" 3177 " EventReport repData;\n" 3178 " };\n" 3179 " EventReport * rep = &repData;\n" 3180 " rep->setEventType(NDB_LE_Connected);\n" 3181 "}"); 3182 ASSERT_EQUALS("", errout.str()); 3183 3184 // #8785 3185 check("int f(bool a, bool b) {\n" 3186 " int *iPtr = 0;\n" 3187 " if(b) {\n" 3188 " int x = 42;\n" 3189 " iPtr = &x;\n" 3190 " }\n" 3191 " if(b && a)\n" 3192 " return *iPtr;\n" 3193 " return 0;\n" 3194 "}"); 3195 ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:4] -> [test.cpp:8]: (error) Using pointer to local variable 'x' that is out of scope.\n", errout.str()); 3196 } 3197 splitNamespaceAuto()3198 void splitNamespaceAuto() { // #10473 3199 check("namespace ns\n" 3200 "{\n" 3201 " auto var{ 0 };\n" 3202 "}\n" 3203 "namespace ns\n" 3204 "{\n" 3205 " int i;\n" 3206 "}\n"); 3207 ASSERT_EQUALS("", errout.str()); 3208 } 3209 3210 }; 3211 3212 REGISTER_TEST(TestAutoVariables) 3213