brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.7 KiB · 8dcb321 Raw
399 lines · cpp
1// RUN: %clang_analyze_cc1 -analyzer-checker=webkit.RefCntblBaseVirtualDtor -verify %s2 3struct RefCntblBase {4  void ref() {}5  void deref() {}6};7 8template<class T>9struct DerivedClassTmpl1 : T { };10// expected-warning@-1{{Struct 'RefCntblBase' is used as a base of struct 'DerivedClassTmpl1<RefCntblBase>' but doesn't have virtual destructor}}11 12DerivedClassTmpl1<RefCntblBase> a;13void foo(DerivedClassTmpl1<RefCntblBase>& obj) { obj.deref(); }14 15template<class T>16struct DerivedClassTmpl2 : T { };17// expected-warning@-1{{Struct 'RefCntblBase' is used as a base of struct 'DerivedClassTmpl2<RefCntblBase>' but doesn't have virtual destructor}}18 19template<class T> int foo(T) { DerivedClassTmpl2<T> f; return 42; }20int b = foo(RefCntblBase{});21 22 23template<class T>24struct DerivedClassTmpl3 : T { };25// expected-warning@-1{{Struct 'RefCntblBase' is used as a base of struct 'DerivedClassTmpl3<RefCntblBase>' but doesn't have virtual destructor}}26 27typedef DerivedClassTmpl3<RefCntblBase> Foo;28Foo c;29 30namespace WTF {31 32class RefCountedBase {33public:34  void ref() const { ++count; }35 36protected:37  bool derefBase() const38  {39    return !--count;40  }41 42private:43  mutable unsigned count;44};45 46template <typename T>47class RefCounted : public RefCountedBase {48public:49  void deref() const {50    if (derefBase())51      delete const_cast<T*>(static_cast<const T*>(this));52  }53 54protected:55  RefCounted() { }56};57 58template <typename X, typename T>59class ExoticRefCounted : public RefCountedBase {60public:61  void deref() const {62    if (derefBase())63      delete (const_cast<T*>(static_cast<const T*>(this)));64  }65};66 67template <typename X, typename T>68class BadBase : RefCountedBase {69public:70  void deref() const {71    if (derefBase())72      delete (const_cast<X*>(static_cast<const X*>(this)));73  }74};75 76template <typename T>77class FancyDeref {78public:79  void ref() const80  {81    ++refCount;82  }83 84  void deref() const85  {86    --refCount;87    if (refCount)88      return;89    auto deleteThis = [this] {90      delete static_cast<const T*>(this);91    };92    deleteThis();93  }94private:95  mutable unsigned refCount { 0 };96};97 98namespace Detail {99 100  template<typename Out, typename... In>101  class CallableWrapperBase {102  public:103    virtual ~CallableWrapperBase() { }104    virtual Out call(In...) = 0;105  };106 107  template<typename, typename, typename...> class CallableWrapper;108 109  template<typename CallableType, typename Out, typename... In>110  class CallableWrapper : public CallableWrapperBase<Out, In...> {111  public:112    explicit CallableWrapper(CallableType&& callable)113        : m_callable(WTFMove(callable)) { }114    CallableWrapper(const CallableWrapper&) = delete;115    CallableWrapper& operator=(const CallableWrapper&) = delete;116    Out call(In... in) final { return m_callable(in...); }117  private:118    CallableType m_callable;119  };120 121} // namespace Detail122 123template<typename> class Function;124 125template <typename Out, typename... In>126class Function<Out(In...)> {127public:128  using Impl = Detail::CallableWrapperBase<Out, In...>;129 130  Function() = default;131 132  template<typename CallableType>133  Function(CallableType&& callable)134      : m_callableWrapper(new Detail::CallableWrapper<CallableType, Out, In...>>(callable)) { }135 136  template<typename FunctionType>137  Function(FunctionType f)138      : m_callableWrapper(new Detail::CallableWrapper<FunctionType, Out, In...>>(f)) { }139 140  ~Function() {141  }142 143  Out operator()(In... in) const {144      ASSERT(m_callableWrapper);145      return m_callableWrapper->call(in...);146  }147 148  explicit operator bool() const { return !!m_callableWrapper; }149 150private:151  Impl* m_callableWrapper;152};153 154void ensureOnMainThread(const Function<void()>&& function);155 156enum class DestructionThread { Any, MainThread };157 158template <typename T, DestructionThread destructionThread = DestructionThread::Any>159class FancyDeref2 {160public:161  void ref() const162  {163    ++refCount;164  }165 166  void deref() const167  {168    --refCount;169    if (refCount)170      return;171    const_cast<FancyDeref2<T, destructionThread>*>(this)->destroy();172  }173 174private:175  void destroy() {176    delete static_cast<T*>(this);177  }178  mutable unsigned refCount { 0 };179};180 181template <typename S>182class DerivedFancyDeref2 : public FancyDeref2<S> {183};184 185template <typename T>186class BadFancyDeref {187public:188  void ref() const189  {190    ++refCount;191  }192 193  void deref() const194  {195    --refCount;196    if (refCount)197      return;198    auto deleteThis = [this] {199      delete static_cast<const T*>(this);200    };201    delete this;202  }203private:204  mutable unsigned refCount { 0 };205};206 207template <typename T>208class ThreadSafeRefCounted {209public:210  void ref() const { ++refCount; }211  void deref() const {212    if (!--refCount)213      delete const_cast<T*>(static_cast<const T*>(this));214  }215private:216  mutable unsigned refCount { 0 };217};218 219template <typename T>220class ThreadSafeRefCountedAndCanMakeThreadSafeWeakPtr {221public:222  void ref() const { ++refCount; }223  void deref() const {224    if (!--refCount)225      delete const_cast<T*>(static_cast<const T*>(this));226  }227private:228  mutable unsigned refCount { 0 };229};230 231} // namespace WTF232 233class DerivedClass4 : public WTF::RefCounted<DerivedClass4> { };234 235class DerivedClass4b : public WTF::ExoticRefCounted<int, DerivedClass4b> { };236 237class DerivedClass4cSub;238class DerivedClass4c : public WTF::BadBase<DerivedClass4cSub, DerivedClass4c> { };239// expected-warning@-1{{Class 'WTF::BadBase<DerivedClass4cSub, DerivedClass4c>' is used as a base of class 'DerivedClass4c' but doesn't have virtual destructor}}240class DerivedClass4cSub : public DerivedClass4c { };241void UseDerivedClass4c(DerivedClass4c &obj) { obj.deref(); }242 243class DerivedClass4d : public WTF::RefCounted<DerivedClass4d> {244public:245  virtual ~DerivedClass4d() { }246};247class DerivedClass4dSub : public DerivedClass4d { };248 249class DerivedClass5 : public DerivedClass4 { };250// expected-warning@-1{{Class 'DerivedClass4' is used as a base of class 'DerivedClass5' but doesn't have virtual destructor}}251void UseDerivedClass5(DerivedClass5 &obj) { obj.deref(); }252 253class DerivedClass6 : public WTF::ThreadSafeRefCounted<DerivedClass6> { };254void UseDerivedClass6(DerivedClass6 &obj) { obj.deref(); }255 256class DerivedClass7 : public DerivedClass6 { };257// expected-warning@-1{{Class 'DerivedClass6' is used as a base of class 'DerivedClass7' but doesn't have virtual destructor}}258void UseDerivedClass7(DerivedClass7 &obj) { obj.deref(); }259 260class DerivedClass8 : public WTF::ThreadSafeRefCountedAndCanMakeThreadSafeWeakPtr<DerivedClass8> { };261void UseDerivedClass8(DerivedClass8 &obj) { obj.deref(); }262 263class DerivedClass9 : public DerivedClass8 { };264// expected-warning@-1{{Class 'DerivedClass8' is used as a base of class 'DerivedClass9' but doesn't have virtual destructor}}265void UseDerivedClass9(DerivedClass9 &obj) { obj.deref(); }266 267class DerivedClass10 : public WTF::FancyDeref<DerivedClass10> { };268void UseDerivedClass10(DerivedClass10 &obj) { obj.deref(); }269 270class DerivedClass10b : public WTF::DerivedFancyDeref2<DerivedClass10b> { };271void UseDerivedClass10b(DerivedClass10b &obj) { obj.deref(); }272 273class DerivedClass10c : public WTF::BadFancyDeref<DerivedClass10c> { };274// expected-warning@-1{{Class 'WTF::BadFancyDeref<DerivedClass10c>' is used as a base of class 'DerivedClass10c' but doesn't have virtual destructor}}275void UseDerivedClass10c(DerivedClass10c &obj) { obj.deref(); }276 277class BaseClass1 {278public:279  void ref() const { ++refCount; }280  void deref() const;281private:282  enum class Type { Base, Derived } type { Type::Base };283  mutable unsigned refCount { 0 };284};285 286class DerivedClass11 : public BaseClass1 { };287 288void BaseClass1::deref() const289{290  --refCount;291  if (refCount)292    return;293  switch (type) {294  case Type::Base:295    delete const_cast<BaseClass1*>(this);296    break;297  case Type::Derived:298    delete const_cast<DerivedClass11*>(static_cast<const DerivedClass11*>(this));299    break;300  }301}302 303void UseDerivedClass11(DerivedClass11& obj) { obj.deref(); }304 305class BaseClass2;306static void deleteBase2(BaseClass2*);307 308class BaseClass2 {309public:310  void ref() const { ++refCount; }311  void deref() const312  {313    if (!--refCount)314      deleteBase2(const_cast<BaseClass2*>(this));315  }316  virtual bool isDerived() { return false; }317private:318  mutable unsigned refCount { 0 };319};320 321class DerivedClass12 : public BaseClass2 {322  bool isDerived() final { return true; }323};324 325void UseDerivedClass11(DerivedClass12& obj) { obj.deref(); }326 327void deleteBase2(BaseClass2* obj) {328  if (obj->isDerived())329    delete static_cast<DerivedClass12*>(obj);330  else331    delete obj;332}333 334class BaseClass3 {335public:336  void ref() const { ++refCount; }337  void deref() const338  {339    if (!--refCount)340      const_cast<BaseClass3*>(this)->destroy();341  }342  virtual bool isDerived() { return false; }343 344private:345  void destroy();346 347  mutable unsigned refCount { 0 };348};349 350class DerivedClass13 : public BaseClass3 {351  bool isDerived() final { return true; }352};353 354void UseDerivedClass11(DerivedClass13& obj) { obj.deref(); }355 356void BaseClass3::destroy() {357  if (isDerived())358    delete static_cast<DerivedClass13*>(this);359  else360    delete this;361}362 363class RecursiveBaseClass {364public:365  void ref() const {366    if (otherObject)367      otherObject->ref();368    else369      ++refCount;370  }371  void deref() const {372    if (otherObject)373      otherObject->deref();374    else {375      --refCount;376      if (refCount)377        return;378      delete this;379    }380  }381private:382  RecursiveBaseClass* otherObject { nullptr };383  mutable unsigned refCount { 0 };384};385 386class RecursiveDerivedClass : public RecursiveBaseClass { };387// expected-warning@-1{{Class 'RecursiveBaseClass' is used as a base of class 'RecursiveDerivedClass' but doesn't have virtual destructor}}388 389class DerivedClass14 : public WTF::RefCounted<DerivedClass14> {390public:391  virtual ~DerivedClass14() { }392};393 394void UseDerivedClass14(DerivedClass14& obj) { obj.deref(); }395 396class DerivedClass15 : public DerivedClass14 { };397 398void UseDerivedClass15(DerivedClass15& obj) { obj.deref(); }399