TestRefCountedThisInsideConstructor.cpp (4872B)
1 #include <functional> 2 3 #include <mozilla/RefPtr.h> 4 5 struct RefCountedBase { 6 void AddRef(); 7 void Release(); 8 }; 9 10 struct Bar; 11 12 struct Foo : RefCountedBase { 13 void foo(); 14 }; 15 16 struct Bar : RefCountedBase { 17 Bar() { 18 RefPtr<Bar> self = this; // expected-error {{Refcounting `this` inside the constructor is a footgun, `this` may be destructed at the end of the constructor unless there's another strong reference. Consider adding a separate Create function and do the work there.}} 19 auto self2 = RefPtr(this); // expected-error {{Refcounting `this` inside the constructor is a footgun, `this` may be destructed at the end of the constructor unless there's another strong reference. Consider adding a separate Create function and do the work there.}} 20 auto self3 = RefPtr{this}; // expected-error {{Refcounting `this` inside the constructor is a footgun, `this` may be destructed at the end of the constructor unless there's another strong reference. Consider adding a separate Create function and do the work there.}} 21 RefPtr<Bar> self4(this); // expected-error {{Refcounting `this` inside the constructor is a footgun, `this` may be destructed at the end of the constructor unless there's another strong reference. Consider adding a separate Create function and do the work there.}} 22 RefPtr<Bar> self5{this}; // expected-error {{Refcounting `this` inside the constructor is a footgun, `this` may be destructed at the end of the constructor unless there's another strong reference. Consider adding a separate Create function and do the work there.}} 23 [self=RefPtr{this}]{}(); // expected-error {{Refcounting `this` inside the constructor is a footgun, `this` may be destructed at the end of the constructor unless there's another strong reference. Consider adding a separate Create function and do the work there.}} 24 refptr(RefPtr{this}); // expected-error {{Refcounting `this` inside the constructor is a footgun, `this` may be destructed at the end of the constructor unless there's another strong reference. Consider adding a separate Create function and do the work there.}} 25 refptr(this); // expected-error {{Refcounting `this` inside the constructor is a footgun, `this` may be destructed at the end of the constructor unless there's another strong reference. Consider adding a separate Create function and do the work there.}} 26 } 27 28 explicit Bar(float f) { 29 // Does not match member expressions with `this` 30 RefPtr<Foo> foo = this->mFoo; 31 foo->foo(); 32 auto foo2 = RefPtr(this->mFoo); 33 foo2->foo(); 34 auto foo3 = RefPtr{this->mFoo}; 35 foo3->foo(); 36 } 37 38 explicit Bar(short i); 39 40 explicit Bar(int i): mBar(this) {} // expected-error {{Refcounting `this` inside the constructor is a footgun, `this` may be destructed at the end of the constructor unless there's another strong reference. Consider adding a separate Create function and do the work there.}} 41 explicit Bar(int i, int i2): mBar(RefPtr(this)) {} // expected-error {{Refcounting `this` inside the constructor is a footgun, `this` may be destructed at the end of the constructor unless there's another strong reference. Consider adding a separate Create function and do the work there.}} 42 43 void Init() { 44 // Does not match outside the constructor 45 RefPtr<Bar> self = this; 46 auto self2 = RefPtr(this); 47 auto self3 = RefPtr{this}; 48 } 49 50 void refptr(const RefPtr<Bar>& aBar) {} 51 52 RefPtr<Foo> mFoo; 53 RefPtr<Bar> mBar; 54 }; 55 56 // Test case for non-inline constructor 57 Bar::Bar(short i) { 58 RefPtr<Bar> self = this; // expected-error {{Refcounting `this` inside the constructor is a footgun, `this` may be destructed at the end of the constructor unless there's another strong reference. Consider adding a separate Create function and do the work there.}} 59 auto self2 = RefPtr(this); // expected-error {{Refcounting `this` inside the constructor is a footgun, `this` may be destructed at the end of the constructor unless there's another strong reference. Consider adding a separate Create function and do the work there.}} 60 auto self3 = RefPtr{this}; // expected-error {{Refcounting `this` inside the constructor is a footgun, `this` may be destructed at the end of the constructor unless there's another strong reference. Consider adding a separate Create function and do the work there.}} 61 } 62 63 // Same goes for any class with MOZ_IS_REFPTR (not including nsCOMPtr because SM 64 // doesn't have it) 65 template <typename T> class MOZ_IS_REFPTR MyRefPtr { 66 public: 67 MOZ_IMPLICIT MyRefPtr(T *aPtr) : mPtr(aPtr) {} 68 T *mPtr; 69 }; 70 71 class Baz : RefCountedBase { 72 Baz() { 73 MyRefPtr<Baz> self = this; // expected-error {{Refcounting `this` inside the constructor is a footgun, `this` may be destructed at the end of the constructor unless there's another strong reference. Consider adding a separate Create function and do the work there.}} 74 (void)self; 75 } 76 };