#include #define MOZ_IMPLICIT __attribute__((annotate("moz_implicit"))) template class already_AddRefed { public: already_AddRefed(); T* mPtr; }; template class RefPtr { public: RefPtr(); MOZ_IMPLICIT RefPtr(T* aIn); MOZ_IMPLICIT RefPtr(already_AddRefed aIn); RefPtr(const RefPtr& aOther) = default; RefPtr& operator=(const RefPtr&) = default; // We must define non-defaulted move operations as in the real RefPtr to make // the type non-trivially-copyable. RefPtr(RefPtr&&); RefPtr& operator=(RefPtr&&); void swap(RefPtr& aOther); ~RefPtr(); T* mPtr; }; template class nsCOMPtr { public: nsCOMPtr(); MOZ_IMPLICIT nsCOMPtr(T* aIn); MOZ_IMPLICIT nsCOMPtr(already_AddRefed aIn); ~nsCOMPtr(); T* mPtr; }; class Type { public: static nsCOMPtr someStaticCOMPtr; void f(nsCOMPtr ignoredArgument, Type *param) { nsCOMPtr never_referenced; nsCOMPtr kfdg_t1(this); nsCOMPtr kfdg_t2 = this; nsCOMPtr kfdg_t3 = (this); nsCOMPtr kfdg_m1(p); // expected-error {{Unused "kungFuDeathGrip" 'nsCOMPtr' objects constructed from members are prohibited}} expected-note {{Please switch all accesses to this member to go through 'kfdg_m1', or explicitly pass 'kfdg_m1' to `mozilla::Unused`}} nsCOMPtr kfdg_m2 = p; // expected-error {{Unused "kungFuDeathGrip" 'nsCOMPtr' objects constructed from members are prohibited}} expected-note {{Please switch all accesses to this member to go through 'kfdg_m2', or explicitly pass 'kfdg_m2' to `mozilla::Unused`}} nsCOMPtr kfdg_m3(p); kfdg_m3.mPtr->f(nullptr, nullptr); nsCOMPtr kfdg_m4 = p; kfdg_m4.mPtr->f(nullptr, nullptr); nsCOMPtr kfdg_a1((already_AddRefed())); nsCOMPtr kfdg_a2 = already_AddRefed(); nsCOMPtr kfdg_p1(param); nsCOMPtr kfdg_p2 = param; RefPtr never_referenced2; RefPtr kfdg_t4(this); RefPtr kfdg_t5 = this; RefPtr kfdg_t6 = (this); RefPtr kfdg_m5(p); // expected-error {{Unused "kungFuDeathGrip" 'RefPtr' objects constructed from members are prohibited}} expected-note {{Please switch all accesses to this member to go through 'kfdg_m5', or explicitly pass 'kfdg_m5' to `mozilla::Unused`}} RefPtr kfdg_m6 = p; // expected-error {{Unused "kungFuDeathGrip" 'RefPtr' objects constructed from members are prohibited}} expected-note {{Please switch all accesses to this member to go through 'kfdg_m6', or explicitly pass 'kfdg_m6' to `mozilla::Unused`}} RefPtr kfdg_m7(p); kfdg_m7.mPtr->f(nullptr, nullptr); RefPtr kfdg_m8 = p; kfdg_m8.mPtr->f(nullptr, nullptr); RefPtr kfdg_a3((already_AddRefed())); RefPtr kfdg_a4 = already_AddRefed(); RefPtr kfdg_p3(param); RefPtr kfdg_p4 = param; } Type *p; }; struct Type2 { void f() { mWeakRef->f(nullptr, nullptr); } void g() { RefPtr kfdg; kfdg.swap(mStrongRef); f(); } void h() { RefPtr kfdg = std::move(mStrongRef); f(); } RefPtr mStrongRef; Type* mWeakRef; }; void f(nsCOMPtr ignoredArgument, Type *param) { nsCOMPtr never_referenced; Type t; // Type *p = nullptr; nsCOMPtr kfdg_m1(t.p); // expected-error {{Unused "kungFuDeathGrip" 'nsCOMPtr' objects constructed from members are prohibited}} expected-note {{Please switch all accesses to this member to go through 'kfdg_m1', or explicitly pass 'kfdg_m1' to `mozilla::Unused`}} nsCOMPtr kfdg_m2 = t.p; // expected-error {{Unused "kungFuDeathGrip" 'nsCOMPtr' objects constructed from members are prohibited}} expected-note {{Please switch all accesses to this member to go through 'kfdg_m2', or explicitly pass 'kfdg_m2' to `mozilla::Unused`}} nsCOMPtr kfdg_m3(t.p); kfdg_m3.mPtr->f(nullptr, nullptr); nsCOMPtr kfdg_m4 = t.p; kfdg_m4.mPtr->f(nullptr, nullptr); nsCOMPtr kfdg_a1((already_AddRefed())); nsCOMPtr kfdg_a2 = already_AddRefed(); nsCOMPtr kfdg_p1(param); nsCOMPtr kfdg_p2 = param; RefPtr never_referenced2; RefPtr kfdg_m5(t.p); // expected-error {{Unused "kungFuDeathGrip" 'RefPtr' objects constructed from members are prohibited}} expected-note {{Please switch all accesses to this member to go through 'kfdg_m5', or explicitly pass 'kfdg_m5' to `mozilla::Unused`}} RefPtr kfdg_m6 = t.p; // expected-error {{Unused "kungFuDeathGrip" 'RefPtr' objects constructed from members are prohibited}} expected-note {{Please switch all accesses to this member to go through 'kfdg_m6', or explicitly pass 'kfdg_m6' to `mozilla::Unused`}} RefPtr kfdg_m7(t.p); kfdg_m7.mPtr->f(nullptr, nullptr); RefPtr kfdg_m8 = t.p; kfdg_m8.mPtr->f(nullptr, nullptr); RefPtr kfdg_a3((already_AddRefed())); RefPtr kfdg_a4 = already_AddRefed(); RefPtr kfdg_p3(param); RefPtr kfdg_p4 = param; } nsCOMPtr Type::someStaticCOMPtr(nullptr);