/* * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #include namespace weak_ptr_constructors { struct Base { int* f1; Base(int* f1 = nullptr) : f1(f1) {} }; struct Derived : public Base { int* f2; Derived(int* f1 = nullptr) : Base(f1) {} }; std::weak_ptr empty() { return std::weak_ptr(); } std::weak_ptr fromWeakBaseConstr(std::weak_ptr b) { return std::weak_ptr(b); } std::weak_ptr fromWeakBaseAssign(std::weak_ptr b) { std::weak_ptr result; result = b; return result; } std::weak_ptr fromWeakDerivedConstr(std::weak_ptr d) { return std::weak_ptr(d); } std::weak_ptr fromWeakDerivedAssign(std::weak_ptr d) { std::weak_ptr result; result = d; return result; } std::weak_ptr fromSharedBaseConstr(std::shared_ptr b) { return std::weak_ptr(b); } std::weak_ptr fromSharedBaseAssign(std::shared_ptr b) { std::weak_ptr result; result = b; return result; } std::weak_ptr fromSharedDerivedConstr(std::shared_ptr d) { return std::weak_ptr(d); } std::weak_ptr fromSharedDerivedConstr2(std::shared_ptr d) { std::weak_ptr sd(d); return std::weak_ptr(sd); } std::weak_ptr fromSharedDerivedAssign(std::shared_ptr d) { std::weak_ptr sd(d); std::weak_ptr result; result = sd; return result; } } // namespace weak_ptr_constructors namespace weak_ptr_derefs { using namespace weak_ptr_constructors; int safeGetFromEmpty_good() { auto w = empty(); auto s = w.lock(); while (!s) ; return *s->f1; // never reached } std::shared_ptr safeGet(std::weak_ptr p) { auto s = p.lock(); while (!s) ; return s; } int FN_safeGetFromWeakBaseConstr_bad(int v) { auto b = std::make_shared(&v); auto s = safeGet(fromWeakBaseConstr(std::weak_ptr(b))); b->f1 = nullptr; return *s->f1; } int FN_safeGetFromWeakBaseAssign_bad(int v) { auto b = std::make_shared(&v); auto s = safeGet(fromWeakBaseAssign(std::weak_ptr(b))); b->f1 = nullptr; return *s->f1; } int FN_safeGetFromWeakDerivedConstr_bad(int v) { auto d = std::make_shared(&v); auto s = safeGet(fromWeakDerivedConstr(std::weak_ptr(d))); d->f1 = nullptr; return *s->f1; } int FN_safeGetFromWeakDerivedAssign_bad(int v) { auto d = std::make_shared(&v); auto s = safeGet(fromWeakDerivedAssign(std::weak_ptr(d))); d->f1 = nullptr; return *s->f1; } int FN_safeGetFromSharedBaseConstr_bad(int v) { auto b = std::make_shared(&v); auto s = safeGet(fromSharedBaseConstr(b)); b->f1 = nullptr; return *s->f1; } int FN_safeGetFromSharedBaseAssign_bad(int v) { auto b = std::make_shared(&v); auto s = safeGet(fromSharedBaseAssign(b)); b->f1 = nullptr; return *s->f1; } int FN_safeGetFromSharedDerivedConstr_bad(int v) { auto b = std::make_shared(&v); auto s = safeGet(fromSharedDerivedConstr(b)); b->f1 = nullptr; return *s->f1; } int FN_safeGetFromSharedDerivedConstr2_bad(int v) { auto b = std::make_shared(&v); auto s = safeGet(fromSharedDerivedConstr2(b)); b->f1 = nullptr; return *s->f1; } int FN_safeGetFromSharedDerivedAssign_bad(int v) { auto b = std::make_shared(&v); auto s = safeGet(fromSharedDerivedAssign(b)); b->f1 = nullptr; return *s->f1; } } // namespace weak_ptr_derefs namespace weak_ptr_modifiers { void reset(std::weak_ptr& p) { p.reset(); } void swap(std::weak_ptr& p) { std::weak_ptr q; q.swap(p); } } // namespace weak_ptr_modifiers namespace weak_ptr_observers { using namespace weak_ptr_constructors; long use_count(std::weak_ptr& p) { return p.use_count(); } void use_count_empty_bad() { std::weak_ptr p; if (p.use_count() == 0) { int* x = nullptr; *x = 42; } } void use_count_after_reset_bad(std::weak_ptr& p) { p.reset(); if (p.use_count() == 0) { int* x = nullptr; *x = 42; } } bool expired(std::weak_ptr& p) { return p.expired(); } void expired_empty_bad() { std::weak_ptr p; if (p.expired()) { int* x = nullptr; *x = 42; } } void expired_after_reset_bad(std::weak_ptr& p) { p.reset(); if (p.expired()) { int* x = nullptr; *x = 42; } } void expired_after_swap_bad(std::weak_ptr& p) { std::weak_ptr q; q.swap(p); if (p.expired()) { int* x = nullptr; *x = 42; } } std::shared_ptr lock(std::weak_ptr& p) { return p.lock(); } void FN_empty_weak_lock_returns_null_bad() { std::weak_ptr p; auto s = p.lock(); int _ = *s.get(); } void FN_expired_means_null_bad(std::weak_ptr& p) { if (p.expired()) { auto s = p.lock(); int _ = *s.get(); } } void FN_lock_can_be_null_bad(std::weak_ptr& p) { auto s = p.lock(); int _ = *s.get(); } int safe_deref_ok(std::weak_ptr& p) { if (auto s = p.lock()) { return *s.get(); } return 0; } std::shared_ptr shared_still_in_scope_good_FP() { /* It's not a big issue to FP in this case. Code should not be written like that anyway. */ auto s = std::make_shared(); auto p = std::weak_ptr(s); auto s2 = p.lock(); auto _ = *s2.get(); return s; } bool owner_before(std::weak_ptr& p, std::weak_ptr& q) { return p.owner_before(q); } bool owner_before(std::weak_ptr& p, std::shared_ptr& q) { return p.owner_before(q); } } // namespace weak_ptr_observers