tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 };