1 // RUN: %clang_cc1 -fsyntax-only -Wdangling -Wdangling-field -Wreturn-stack-address -verify %s 2 #include "Inputs/lifetime-analysis.h" 3 struct [[gsl::Owner(int)]] MyIntOwner { 4 MyIntOwner(); 5 int &operator*(); 6 }; 7 8 struct [[gsl::Pointer(int)]] MyIntPointer { 9 MyIntPointer(int *p = nullptr); 10 // Conversion operator and constructor conversion will result in two 11 // different ASTs. The former is tested with another owner and 12 // pointer type. 13 MyIntPointer(const MyIntOwner &); 14 int &operator*(); 15 MyIntOwner toOwner(); 16 }; 17 18 struct MySpecialIntPointer : MyIntPointer { 19 }; 20 21 // We did see examples in the wild when a derived class changes 22 // the ownership model. So we have a test for it. 23 struct [[gsl::Owner(int)]] MyOwnerIntPointer : MyIntPointer { 24 }; 25 26 struct [[gsl::Pointer(long)]] MyLongPointerFromConversion { 27 MyLongPointerFromConversion(long *p = nullptr); 28 long &operator*(); 29 }; 30 31 struct [[gsl::Owner(long)]] MyLongOwnerWithConversion { 32 MyLongOwnerWithConversion(); 33 operator MyLongPointerFromConversion(); 34 long &operator*(); 35 MyIntPointer releaseAsMyPointer(); 36 long *releaseAsRawPointer(); 37 }; 38 39 void danglingHeapObject() { 40 new MyLongPointerFromConversion(MyLongOwnerWithConversion{}); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} 41 new MyIntPointer(MyIntOwner{}); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} 42 } 43 44 void intentionalFalseNegative() { 45 int i; 46 MyIntPointer p{&i}; 47 // In this case we do not have enough information in a statement local 48 // analysis to detect the problem. 49 new MyIntPointer(p); 50 new MyIntPointer(MyIntPointer{p}); 51 } 52 53 MyIntPointer ownershipTransferToMyPointer() { 54 MyLongOwnerWithConversion t; 55 return t.releaseAsMyPointer(); // ok 56 } 57 58 long *ownershipTransferToRawPointer() { 59 MyLongOwnerWithConversion t; 60 return t.releaseAsRawPointer(); // ok 61 } 62 63 struct Y { 64 int a[4]; 65 }; 66 67 void dangligGslPtrFromTemporary() { 68 MyIntPointer p = Y{}.a; // TODO 69 (void)p; 70 } 71 72 struct DanglingGslPtrField { 73 MyIntPointer p; // expected-note {{pointer member declared here}} 74 MyLongPointerFromConversion p2; // expected-note {{pointer member declared here}} 75 DanglingGslPtrField(int i) : p(&i) {} // TODO 76 DanglingGslPtrField() : p2(MyLongOwnerWithConversion{}) {} // expected-warning {{initializing pointer member 'p2' to point to a temporary object whose lifetime is shorter than the lifetime of the constructed object}} 77 DanglingGslPtrField(double) : p(MyIntOwner{}) {} // expected-warning {{initializing pointer member 'p' to point to a temporary object whose lifetime is shorter than the lifetime of the constructed object}} 78 }; 79 80 MyIntPointer danglingGslPtrFromLocal() { 81 int j; 82 return &j; // TODO 83 } 84 85 MyIntPointer returningLocalPointer() { 86 MyIntPointer localPointer; 87 return localPointer; // ok 88 } 89 90 MyIntPointer daglingGslPtrFromLocalOwner() { 91 MyIntOwner localOwner; 92 return localOwner; // expected-warning {{address of stack memory associated with local variable 'localOwner' returned}} 93 } 94 95 MyLongPointerFromConversion daglingGslPtrFromLocalOwnerConv() { 96 MyLongOwnerWithConversion localOwner; 97 return localOwner; // expected-warning {{address of stack memory associated with local variable 'localOwner' returned}} 98 } 99 100 MyIntPointer danglingGslPtrFromTemporary() { 101 return MyIntOwner{}; // expected-warning {{returning address of local temporary object}} 102 } 103 104 MyIntOwner makeTempOwner(); 105 106 MyIntPointer danglingGslPtrFromTemporary2() { 107 return makeTempOwner(); // expected-warning {{returning address of local temporary object}} 108 } 109 110 MyLongPointerFromConversion danglingGslPtrFromTemporaryConv() { 111 return MyLongOwnerWithConversion{}; // expected-warning {{returning address of local temporary object}} 112 } 113 114 int *noFalsePositive(MyIntOwner &o) { 115 MyIntPointer p = o; 116 return &*p; // ok 117 } 118 119 MyIntPointer global; 120 MyLongPointerFromConversion global2; 121 122 void initLocalGslPtrWithTempOwner() { 123 MyIntPointer p = MyIntOwner{}; // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} 124 MyIntPointer pp = p = MyIntOwner{}; // expected-warning {{object backing the pointer p will be}} 125 p = MyIntOwner{}; // expected-warning {{object backing the pointer p }} 126 pp = p; // no warning 127 global = MyIntOwner{}; // expected-warning {{object backing the pointer global }} 128 MyLongPointerFromConversion p2 = MyLongOwnerWithConversion{}; // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} 129 p2 = MyLongOwnerWithConversion{}; // expected-warning {{object backing the pointer p2 }} 130 global2 = MyLongOwnerWithConversion{}; // expected-warning {{object backing the pointer global2 }} 131 } 132 133 134 struct Unannotated { 135 typedef std::vector<int>::iterator iterator; 136 iterator begin(); 137 operator iterator() const; 138 }; 139 140 void modelIterators() { 141 std::vector<int>::iterator it = std::vector<int>().begin(); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} 142 (void)it; 143 } 144 145 std::vector<int>::iterator modelIteratorReturn() { 146 return std::vector<int>().begin(); // expected-warning {{returning address of local temporary object}} 147 } 148 149 const int *modelFreeFunctions() { 150 return std::data(std::vector<int>()); // expected-warning {{returning address of local temporary object}} 151 } 152 153 int &modelAnyCast() { 154 return std::any_cast<int&>(std::any{}); // expected-warning {{returning reference to local temporary object}} 155 } 156 157 int modelAnyCast2() { 158 return std::any_cast<int>(std::any{}); // ok 159 } 160 161 int modelAnyCast3() { 162 return std::any_cast<int&>(std::any{}); // ok 163 } 164 165 const char *danglingRawPtrFromLocal() { 166 std::basic_string<char> s; 167 return s.c_str(); // expected-warning {{address of stack memory associated with local variable 's' returned}} 168 } 169 170 int &danglingRawPtrFromLocal2() { 171 std::optional<int> o; 172 return o.value(); // expected-warning {{reference to stack memory associated with local variable 'o' returned}} 173 } 174 175 int &danglingRawPtrFromLocal3() { 176 std::optional<int> o; 177 return *o; // expected-warning {{reference to stack memory associated with local variable 'o' returned}} 178 } 179 180 // GH100384 181 std::string_view containerWithAnnotatedElements() { 182 std::string_view c1 = std::vector<std::string>().at(0); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} 183 c1 = std::vector<std::string>().at(0); // expected-warning {{object backing the pointer}} 184 185 // no warning on constructing from gsl-pointer 186 std::string_view c2 = std::vector<std::string_view>().at(0); 187 188 std::vector<std::string> local; 189 return local.at(0); // expected-warning {{address of stack memory associated with local variable}} 190 } 191 192 std::string_view localUniquePtr(int i) { 193 std::unique_ptr<std::string> c1; 194 if (i) 195 return *c1; // expected-warning {{address of stack memory associated with local variable}} 196 std::unique_ptr<std::string_view> c2; 197 return *c2; // expect no-warning. 198 } 199 200 std::string_view localOptional(int i) { 201 std::optional<std::string> o; 202 if (i) 203 return o.value(); // expected-warning {{address of stack memory associated with local variable}} 204 std::optional<std::string_view> abc; 205 return abc.value(); // expect no warning 206 } 207 208 const char *danglingRawPtrFromTemp() { 209 return std::basic_string<char>().c_str(); // expected-warning {{returning address of local temporary object}} 210 } 211 212 std::unique_ptr<int> getUniquePtr(); 213 214 int *danglingUniquePtrFromTemp() { 215 return getUniquePtr().get(); // expected-warning {{returning address of local temporary object}} 216 } 217 218 int *danglingUniquePtrFromTemp2() { 219 return std::unique_ptr<int>().get(); // expected-warning {{returning address of local temporary object}} 220 } 221 222 void danglingReferenceFromTempOwner() { 223 int &&r = *std::optional<int>(); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} 224 int &&r2 = *std::optional<int>(5); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} 225 int &&r3 = std::optional<int>(5).value(); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} 226 int &r4 = std::vector<int>().at(3); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} 227 } 228 229 std::vector<int> getTempVec(); 230 std::optional<std::vector<int>> getTempOptVec(); 231 232 void testLoops() { 233 for (auto i : getTempVec()) // ok 234 ; 235 for (auto i : *getTempOptVec()) // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} 236 ; 237 } 238 239 int &usedToBeFalsePositive(std::vector<int> &v) { 240 std::vector<int>::iterator it = v.begin(); 241 int& value = *it; 242 return value; // ok 243 } 244 245 int &doNotFollowReferencesForLocalOwner() { 246 std::unique_ptr<int> localOwner; 247 int &p = *localOwner.get(); 248 // In real world code localOwner is usually moved here. 249 return p; // ok 250 } 251 252 const char *trackThroughMultiplePointer() { 253 return std::basic_string_view<char>(std::basic_string<char>()).begin(); // expected-warning {{returning address of local temporary object}} 254 } 255 256 struct X { 257 X(std::unique_ptr<int> up) : 258 pointee(*up), pointee2(up.get()), pointer(std::move(up)) {} 259 int &pointee; 260 int *pointee2; 261 std::unique_ptr<int> pointer; 262 }; 263 264 struct [[gsl::Owner]] XOwner { 265 int* get() const [[clang::lifetimebound]]; 266 }; 267 struct X2 { 268 // A common usage that moves the passing owner to the class. 269 // verify no warning on this case. 270 X2(XOwner owner) : 271 pointee(owner.get()), 272 owner(std::move(owner)) {} 273 int* pointee; 274 XOwner owner; 275 }; 276 277 std::vector<int>::iterator getIt(); 278 std::vector<int> getVec(); 279 280 const int &handleGslPtrInitsThroughReference() { 281 const auto &it = getIt(); // Ok, it is lifetime extended. 282 return *it; 283 } 284 285 void handleGslPtrInitsThroughReference2() { 286 const std::vector<int> &v = getVec(); 287 const int *val = v.data(); // Ok, it is lifetime extended. 288 } 289 290 void handleTernaryOperator(bool cond) { 291 std::basic_string<char> def; 292 std::basic_string_view<char> v = cond ? def : ""; // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} 293 } 294 295 std::string operator+(std::string_view s1, std::string_view s2); 296 void danglingStringviewAssignment(std::string_view a1, std::string_view a2) { 297 a1 = std::string(); // expected-warning {{object backing}} 298 a2 = a1 + a1; // expected-warning {{object backing}} 299 } 300 301 std::reference_wrapper<int> danglingPtrFromNonOwnerLocal() { 302 int i = 5; 303 return i; // TODO 304 } 305 306 std::reference_wrapper<int> danglingPtrFromNonOwnerLocal2() { 307 int i = 5; 308 return std::ref(i); // TODO 309 } 310 311 std::reference_wrapper<int> danglingPtrFromNonOwnerLocal3() { 312 int i = 5; 313 return std::reference_wrapper<int>(i); // TODO 314 } 315 316 std::reference_wrapper<Unannotated> danglingPtrFromNonOwnerLocal4() { 317 Unannotated i; 318 return std::reference_wrapper<Unannotated>(i); // TODO 319 } 320 321 std::reference_wrapper<Unannotated> danglingPtrFromNonOwnerLocal5() { 322 Unannotated i; 323 return std::ref(i); // TODO 324 } 325 326 int *returnPtrToLocalArray() { 327 int a[5]; 328 return std::begin(a); // TODO 329 } 330 331 struct ptr_wrapper { 332 std::vector<int>::iterator member; 333 }; 334 335 ptr_wrapper getPtrWrapper(); 336 337 std::vector<int>::iterator returnPtrFromWrapper() { 338 ptr_wrapper local = getPtrWrapper(); 339 return local.member; 340 } 341 342 std::vector<int>::iterator returnPtrFromWrapperThroughRef() { 343 ptr_wrapper local = getPtrWrapper(); 344 ptr_wrapper &local2 = local; 345 return local2.member; 346 } 347 348 std::vector<int>::iterator returnPtrFromWrapperThroughRef2() { 349 ptr_wrapper local = getPtrWrapper(); 350 std::vector<int>::iterator &local2 = local.member; 351 return local2; 352 } 353 354 void checkPtrMemberFromAggregate() { 355 std::vector<int>::iterator local = getPtrWrapper().member; // OK. 356 } 357 358 std::vector<int>::iterator doNotInterferWithUnannotated() { 359 Unannotated value; 360 // Conservative choice for now. Probably not ok, but we do not warn. 361 return std::begin(value); 362 } 363 364 std::vector<int>::iterator doNotInterferWithUnannotated2() { 365 Unannotated value; 366 return value; 367 } 368 369 std::vector<int>::iterator supportDerefAddrofChain(int a, std::vector<int>::iterator value) { 370 switch (a) { 371 default: 372 return value; 373 case 1: 374 return *&value; 375 case 2: 376 return *&*&value; 377 case 3: 378 return *&*&*&value; 379 } 380 } 381 382 int &supportDerefAddrofChain2(int a, std::vector<int>::iterator value) { 383 switch (a) { 384 default: 385 return *value; 386 case 1: 387 return **&value; 388 case 2: 389 return **&*&value; 390 case 3: 391 return **&*&*&value; 392 } 393 } 394 395 int *supportDerefAddrofChain3(int a, std::vector<int>::iterator value) { 396 switch (a) { 397 default: 398 return &*value; 399 case 1: 400 return &*&*value; 401 case 2: 402 return &*&**&value; 403 case 3: 404 return &*&**&*&value; 405 } 406 } 407 408 MyIntPointer handleDerivedToBaseCast1(MySpecialIntPointer ptr) { 409 return ptr; 410 } 411 412 MyIntPointer handleDerivedToBaseCast2(MyOwnerIntPointer ptr) { 413 return ptr; // expected-warning {{address of stack memory associated with parameter 'ptr' returned}} 414 } 415 416 std::vector<int>::iterator noFalsePositiveWithVectorOfPointers() { 417 std::vector<std::vector<int>::iterator> iters; 418 return iters.at(0); 419 } 420 421 void testForBug49342() 422 { 423 auto it = std::iter<char>{} - 2; // Used to be false positive. 424 } 425 426 namespace GH93386 { 427 // verify no duplicated diagnostics are emitted. 428 struct [[gsl::Pointer]] S { 429 S(const std::vector<int>& abc [[clang::lifetimebound]]); 430 }; 431 432 S test(std::vector<int> a) { 433 return S(a); // expected-warning {{address of stack memory associated with}} 434 } 435 436 auto s = S(std::vector<int>()); // expected-warning {{temporary whose address is used as value of local variable}} 437 438 // Verify no regression on the follow case. 439 std::string_view test2(int i, std::optional<std::string_view> a) { 440 if (i) 441 return std::move(*a); 442 return std::move(a.value()); 443 } 444 445 struct Foo; 446 struct FooView { 447 FooView(const Foo& foo [[clang::lifetimebound]]); 448 }; 449 FooView test3(int i, std::optional<Foo> a) { 450 if (i) 451 return *a; // expected-warning {{address of stack memory}} 452 return a.value(); // expected-warning {{address of stack memory}} 453 } 454 } // namespace GH93386 455 456 namespace GH100549 { 457 struct UrlAnalyzed { 458 UrlAnalyzed(std::string_view url [[clang::lifetimebound]]); 459 }; 460 std::string StrCat(std::string_view, std::string_view); 461 void test1() { 462 UrlAnalyzed url(StrCat("abc", "bcd")); // expected-warning {{object backing the pointer will be destroyed}} 463 } 464 465 std::string_view ReturnStringView(std::string_view abc [[clang::lifetimebound]]); 466 467 void test() { 468 std::string_view svjkk1 = ReturnStringView(StrCat("bar", "x")); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} 469 } 470 } // namespace GH100549 471 472 namespace GH108272 { 473 template <typename T> 474 struct [[gsl::Owner]] StatusOr { 475 const T &value() [[clang::lifetimebound]]; 476 }; 477 478 template <typename V> 479 class Wrapper1 { 480 public: 481 operator V() const; 482 V value; 483 }; 484 std::string_view test1() { 485 StatusOr<Wrapper1<std::string_view>> k; 486 // Be conservative in this case, as there is not enough information available 487 // to infer the lifetime relationship for the Wrapper1 type. 488 std::string_view good = StatusOr<Wrapper1<std::string_view>>().value(); 489 return k.value(); 490 } 491 492 template <typename V> 493 class Wrapper2 { 494 public: 495 operator V() const [[clang::lifetimebound]]; 496 V value; 497 }; 498 std::string_view test2() { 499 StatusOr<Wrapper2<std::string_view>> k; 500 // We expect dangling issues as the conversion operator is lifetimebound。 501 std::string_view bad = StatusOr<Wrapper2<std::string_view>>().value(); // expected-warning {{temporary whose address is used as value of}} 502 return k.value(); // expected-warning {{address of stack memory associated}} 503 } 504 } // namespace GH108272 505 506 namespace GH100526 { 507 void test() { 508 std::vector<std::string_view> v1({std::string()}); // expected-warning {{object backing the pointer will be destroyed at the end}} 509 std::vector<std::string_view> v2({ 510 std::string(), // expected-warning {{object backing the pointer will be destroyed at the end}} 511 std::string_view() 512 }); 513 std::vector<std::string_view> v3({ 514 std::string_view(), 515 std::string() // expected-warning {{object backing the pointer will be destroyed at the end}} 516 }); 517 518 std::optional<std::string_view> o1 = std::string(); // expected-warning {{object backing the pointer}} 519 520 std::string s; 521 // This is a tricky use-after-free case, what it does: 522 // 1. make_optional creates a temporary "optional<string>"" object 523 // 2. the temporary object owns the underlying string which is copied from s. 524 // 3. the t3 object holds the view to the underlying string of the temporary object. 525 std::optional<std::string_view> o2 = std::make_optional(s); // expected-warning {{object backing the pointer}} 526 std::optional<std::string_view> o3 = std::optional<std::string>(s); // expected-warning {{object backing the pointer}} 527 std::optional<std::string_view> o4 = std::optional<std::string_view>(s); 528 529 // FIXME: should work for assignment cases 530 v1 = {std::string()}; 531 o1 = std::string(); 532 533 // no warning on copying pointers. 534 std::vector<std::string_view> n1 = {std::string_view()}; 535 std::optional<std::string_view> n2 = {std::string_view()}; 536 std::optional<std::string_view> n3 = std::string_view(); 537 std::optional<std::string_view> n4 = std::make_optional(std::string_view()); 538 const char* b = ""; 539 std::optional<std::string_view> n5 = std::make_optional(b); 540 std::optional<std::string_view> n6 = std::make_optional("test"); 541 } 542 543 std::vector<std::string_view> test2(int i) { 544 std::vector<std::string_view> t; 545 if (i) 546 return t; // this is fine, no dangling 547 return std::vector<std::string_view>(t.begin(), t.end()); 548 } 549 550 class Foo { 551 public: 552 operator std::string_view() const { return ""; } 553 }; 554 class [[gsl::Owner]] FooOwner { 555 public: 556 operator std::string_view() const { return ""; } 557 }; 558 std::optional<Foo> GetFoo(); 559 std::optional<FooOwner> GetFooOwner(); 560 561 template <typename T> 562 struct [[gsl::Owner]] Container1 { 563 Container1(); 564 }; 565 template <typename T> 566 struct [[gsl::Owner]] Container2 { 567 template<typename U> 568 Container2(const Container1<U>& C2); 569 }; 570 571 std::optional<std::string_view> test3(int i) { 572 std::string s; 573 std::string_view sv; 574 if (i) 575 return s; // expected-warning {{address of stack memory associated}} 576 return sv; // fine 577 Container2<std::string_view> c1 = Container1<Foo>(); // no diagnostic as Foo is not an Owner. 578 Container2<std::string_view> c2 = Container1<FooOwner>(); // expected-warning {{object backing the pointer will be destroyed}} 579 return GetFoo(); // fine, we don't know Foo is owner or not, be conservative. 580 return GetFooOwner(); // expected-warning {{returning address of local temporary object}} 581 } 582 583 std::optional<int*> test4(int a) { 584 return std::make_optional(nullptr); // fine 585 } 586 587 588 template <typename T> 589 struct [[gsl::Owner]] StatusOr { 590 const T &valueLB() const [[clang::lifetimebound]]; 591 const T &valueNoLB() const; 592 }; 593 594 template<typename T> 595 struct [[gsl::Pointer]] Span { 596 Span(const std::vector<T> &V); 597 598 const int& getFieldLB() const [[clang::lifetimebound]]; 599 const int& getFieldNoLB() const; 600 }; 601 602 603 /////// From Owner<Pointer> /////// 604 605 // Pointer from Owner<Pointer> 606 std::string_view test5() { 607 // The Owner<Pointer> doesn't own the object which its inner pointer points to. 608 std::string_view a = StatusOr<std::string_view>().valueLB(); // OK 609 return StatusOr<std::string_view>().valueLB(); // OK 610 611 // No dangling diagnostics on non-lifetimebound methods. 612 std::string_view b = StatusOr<std::string_view>().valueNoLB(); 613 return StatusOr<std::string_view>().valueNoLB(); 614 } 615 616 // Pointer<Pointer> from Owner<Pointer> 617 // Prevent regression GH108463 618 Span<int*> test6(std::vector<int*> v) { 619 Span<int *> dangling = std::vector<int*>(); // expected-warning {{object backing the pointer}} 620 dangling = std::vector<int*>(); // expected-warning {{object backing the pointer}} 621 return v; // expected-warning {{address of stack memory}} 622 } 623 624 /////// From Owner<Owner<Pointer>> /////// 625 626 // Pointer from Owner<Owner<Pointer>> 627 int* test7(StatusOr<StatusOr<int*>> aa) { 628 // No dangling diagnostic on pointer. 629 return aa.valueLB().valueLB(); // OK. 630 } 631 632 // Owner<Pointer> from Owner<Owner<Pointer>> 633 std::vector<int*> test8(StatusOr<std::vector<int*>> aa) { 634 return aa.valueLB(); // OK, no pointer being construct on this case. 635 return aa.valueNoLB(); 636 } 637 638 // Pointer<Pointer> from Owner<Owner<Pointer>> 639 Span<int*> test9(StatusOr<std::vector<int*>> aa) { 640 return aa.valueLB(); // expected-warning {{address of stack memory associated}} 641 return aa.valueNoLB(); // OK. 642 } 643 644 /////// From Owner<Owner> /////// 645 646 // Pointer<Owner>> from Owner<Owner> 647 Span<std::string> test10(StatusOr<std::vector<std::string>> aa) { 648 return aa.valueLB(); // expected-warning {{address of stack memory}} 649 return aa.valueNoLB(); // OK. 650 } 651 652 /////// From Owner<Pointer<Owner>> /////// 653 654 // Pointer<Owner>> from Owner<Pointer<Owner>> 655 Span<std::string> test11(StatusOr<Span<std::string>> aa) { 656 return aa.valueLB(); // OK 657 return aa.valueNoLB(); // OK. 658 } 659 660 // Lifetimebound and gsl::Pointer. 661 const int& test12(Span<int> a) { 662 return a.getFieldLB(); // expected-warning {{reference to stack memory associated}} 663 return a.getFieldNoLB(); // OK. 664 } 665 666 void test13() { 667 // FIXME: RHS is Owner<Pointer>, we skip this case to avoid false positives. 668 std::optional<Span<int*>> abc = std::vector<int*>{}; 669 670 std::optional<Span<int>> t = std::vector<int> {}; // expected-warning {{object backing the pointer will be destroyed}} 671 } 672 673 } // namespace GH100526 674 675 namespace std { 676 template <typename T> 677 class __set_iterator {}; 678 679 template<typename T> 680 struct BB { 681 typedef __set_iterator<T> iterator; 682 }; 683 684 template <typename T> 685 class set { 686 public: 687 typedef typename BB<T>::iterator iterator; 688 iterator begin() const; 689 }; 690 } // namespace std 691 namespace GH118064{ 692 693 void test() { 694 auto y = std::set<int>{}.begin(); // expected-warning {{object backing the pointer}} 695 } 696 } // namespace GH118064 697 698 namespace LifetimeboundInterleave { 699 700 const std::string& Ref(const std::string& abc [[clang::lifetimebound]]); 701 702 std::string_view TakeSv(std::string_view abc [[clang::lifetimebound]]); 703 std::string_view TakeStrRef(const std::string& abc [[clang::lifetimebound]]); 704 std::string_view TakeStr(std::string abc [[clang::lifetimebound]]); 705 706 std::string_view test1() { 707 std::string_view t1 = Ref(std::string()); // expected-warning {{object backing}} 708 t1 = Ref(std::string()); // expected-warning {{object backing}} 709 return Ref(std::string()); // expected-warning {{returning address}} 710 711 std::string_view t2 = TakeSv(std::string()); // expected-warning {{object backing}} 712 t2 = TakeSv(std::string()); // expected-warning {{object backing}} 713 return TakeSv(std::string()); // expected-warning {{returning address}} 714 715 std::string_view t3 = TakeStrRef(std::string()); // expected-warning {{temporary}} 716 t3 = TakeStrRef(std::string()); // expected-warning {{object backing}} 717 return TakeStrRef(std::string()); // expected-warning {{returning address}} 718 719 720 std::string_view t4 = TakeStr(std::string()); 721 t4 = TakeStr(std::string()); 722 return TakeStr(std::string()); 723 } 724 725 template <typename T> 726 struct Foo { 727 const T& get() const [[clang::lifetimebound]]; 728 const T& getNoLB() const; 729 }; 730 std::string_view test2(Foo<std::string> r1, Foo<std::string_view> r2) { 731 std::string_view t1 = Foo<std::string>().get(); // expected-warning {{object backing}} 732 t1 = Foo<std::string>().get(); // expected-warning {{object backing}} 733 return r1.get(); // expected-warning {{address of stack}} 734 735 std::string_view t2 = Foo<std::string_view>().get(); 736 t2 = Foo<std::string_view>().get(); 737 return r2.get(); 738 739 // no warning on no-LB-annotated method. 740 std::string_view t3 = Foo<std::string>().getNoLB(); 741 t3 = Foo<std::string>().getNoLB(); 742 return r1.getNoLB(); 743 } 744 745 struct Bar {}; 746 struct [[gsl::Pointer]] Pointer { 747 Pointer(const Bar & bar [[clang::lifetimebound]]); 748 }; 749 Pointer test3(Bar bar) { 750 Pointer p = Pointer(Bar()); // expected-warning {{temporary}} 751 p = Pointer(Bar()); // expected-warning {{object backing}} 752 return bar; // expected-warning {{address of stack}} 753 } 754 755 template<typename T> 756 struct MySpan { 757 MySpan(const std::vector<T>& v); 758 using iterator = std::iterator<T>; 759 iterator begin() const [[clang::lifetimebound]]; 760 }; 761 template <typename T> 762 typename MySpan<T>::iterator ReturnFirstIt(const MySpan<T>& v [[clang::lifetimebound]]); 763 764 void test4() { 765 std::vector<int> v{1}; 766 // MySpan<T> doesn't own any underlying T objects, the pointee object of 767 // the MySpan iterator is still alive when the whole span is destroyed, thus 768 // no diagnostic. 769 const int& t1 = *MySpan<int>(v).begin(); 770 const int& t2 = *ReturnFirstIt(MySpan<int>(v)); 771 // Ideally, we would diagnose the following case, but due to implementation 772 // constraints, we do not. 773 const int& t4 = *MySpan<int>(std::vector<int>{}).begin(); 774 775 auto it1 = MySpan<int>(v).begin(); // expected-warning {{temporary whose address is use}} 776 auto it2 = ReturnFirstIt(MySpan<int>(v)); // expected-warning {{temporary whose address is used}} 777 } 778 779 } // namespace LifetimeboundInterleave 780 781 namespace GH120206 { 782 struct S { 783 std::string_view s; 784 }; 785 786 struct [[gsl::Owner]] Q1 { 787 const S* get() const [[clang::lifetimebound]]; 788 }; 789 std::string_view test1(int c, std::string_view sv) { 790 std::string_view k = c > 1 ? Q1().get()->s : sv; 791 if (c == 1) 792 return c > 1 ? Q1().get()->s : sv; 793 Q1 q; 794 return c > 1 ? q.get()->s : sv; 795 } 796 797 struct Q2 { 798 const S* get() const [[clang::lifetimebound]]; 799 }; 800 std::string_view test2(int c, std::string_view sv) { 801 std::string_view k = c > 1 ? Q2().get()->s : sv; 802 if (c == 1) 803 return c > 1 ? Q2().get()->s : sv; 804 Q2 q; 805 return c > 1 ? q.get()->s : sv; 806 } 807 808 } // namespace GH120206 809 810 namespace GH120543 { 811 struct S { 812 std::string_view sv; 813 std::string s; 814 }; 815 struct Q { 816 const S* get() const [[clang::lifetimebound]]; 817 }; 818 819 std::string_view foo(std::string_view sv [[clang::lifetimebound]]); 820 821 void test1() { 822 std::string_view k1 = S().sv; // OK 823 std::string_view k2 = S().s; // expected-warning {{object backing the pointer will}} 824 825 std::string_view k3 = Q().get()->sv; // OK 826 std::string_view k4 = Q().get()->s; // expected-warning {{object backing the pointer will}} 827 828 std::string_view lb1 = foo(S().s); // expected-warning {{object backing the pointer will}} 829 std::string_view lb2 = foo(Q().get()->s); // expected-warning {{object backing the pointer will}} 830 } 831 832 struct Bar {}; 833 struct Foo { 834 std::vector<Bar> v; 835 }; 836 Foo getFoo(); 837 void test2() { 838 const Foo& foo = getFoo(); 839 const Bar& bar = foo.v.back(); // OK 840 } 841 842 struct Foo2 { 843 std::unique_ptr<Bar> bar; 844 }; 845 846 struct Test { 847 Test(Foo2 foo) : bar(foo.bar.get()), // OK 848 storage(std::move(foo.bar)) {}; 849 850 Bar* bar; 851 std::unique_ptr<Bar> storage; 852 }; 853 854 } // namespace GH120543 855