You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

256 lines
5.6 KiB

/*
* 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 <memory>
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<Base> empty() { return std::weak_ptr<Base>(); }
std::weak_ptr<Base> fromWeakBaseConstr(std::weak_ptr<Base> b) {
return std::weak_ptr<Base>(b);
}
std::weak_ptr<Base> fromWeakBaseAssign(std::weak_ptr<Base> b) {
std::weak_ptr<Base> result;
result = b;
return result;
}
std::weak_ptr<Base> fromWeakDerivedConstr(std::weak_ptr<Derived> d) {
return std::weak_ptr<Base>(d);
}
std::weak_ptr<Base> fromWeakDerivedAssign(std::weak_ptr<Derived> d) {
std::weak_ptr<Base> result;
result = d;
return result;
}
std::weak_ptr<Base> fromSharedBaseConstr(std::shared_ptr<Base> b) {
return std::weak_ptr<Base>(b);
}
std::weak_ptr<Base> fromSharedBaseAssign(std::shared_ptr<Base> b) {
std::weak_ptr<Base> result;
result = b;
return result;
}
std::weak_ptr<Base> fromSharedDerivedConstr(std::shared_ptr<Derived> d) {
return std::weak_ptr<Base>(d);
}
std::weak_ptr<Base> fromSharedDerivedConstr2(std::shared_ptr<Derived> d) {
std::weak_ptr<Derived> sd(d);
return std::weak_ptr<Base>(sd);
}
std::weak_ptr<Base> fromSharedDerivedAssign(std::shared_ptr<Derived> d) {
std::weak_ptr<Derived> sd(d);
std::weak_ptr<Base> 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<Base> safeGet(std::weak_ptr<Base> p) {
auto s = p.lock();
while (!s)
;
return s;
}
int FN_safeGetFromWeakBaseConstr_bad(int v) {
auto b = std::make_shared<Base>(&v);
auto s = safeGet(fromWeakBaseConstr(std::weak_ptr<Base>(b)));
b->f1 = nullptr;
return *s->f1;
}
int FN_safeGetFromWeakBaseAssign_bad(int v) {
auto b = std::make_shared<Base>(&v);
auto s = safeGet(fromWeakBaseAssign(std::weak_ptr<Base>(b)));
b->f1 = nullptr;
return *s->f1;
}
int FN_safeGetFromWeakDerivedConstr_bad(int v) {
auto d = std::make_shared<Derived>(&v);
auto s = safeGet(fromWeakDerivedConstr(std::weak_ptr<Derived>(d)));
d->f1 = nullptr;
return *s->f1;
}
int FN_safeGetFromWeakDerivedAssign_bad(int v) {
auto d = std::make_shared<Derived>(&v);
auto s = safeGet(fromWeakDerivedAssign(std::weak_ptr<Derived>(d)));
d->f1 = nullptr;
return *s->f1;
}
int FN_safeGetFromSharedBaseConstr_bad(int v) {
auto b = std::make_shared<Base>(&v);
auto s = safeGet(fromSharedBaseConstr(b));
b->f1 = nullptr;
return *s->f1;
}
int FN_safeGetFromSharedBaseAssign_bad(int v) {
auto b = std::make_shared<Base>(&v);
auto s = safeGet(fromSharedBaseAssign(b));
b->f1 = nullptr;
return *s->f1;
}
int FN_safeGetFromSharedDerivedConstr_bad(int v) {
auto b = std::make_shared<Derived>(&v);
auto s = safeGet(fromSharedDerivedConstr(b));
b->f1 = nullptr;
return *s->f1;
}
int FN_safeGetFromSharedDerivedConstr2_bad(int v) {
auto b = std::make_shared<Derived>(&v);
auto s = safeGet(fromSharedDerivedConstr2(b));
b->f1 = nullptr;
return *s->f1;
}
int FN_safeGetFromSharedDerivedAssign_bad(int v) {
auto b = std::make_shared<Derived>(&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<int>& p) { p.reset(); }
void swap(std::weak_ptr<int>& p) {
std::weak_ptr<int> q;
q.swap(p);
}
} // namespace weak_ptr_modifiers
namespace weak_ptr_observers {
using namespace weak_ptr_constructors;
long use_count(std::weak_ptr<int>& p) { return p.use_count(); }
void use_count_empty_bad() {
std::weak_ptr<int> p;
if (p.use_count() == 0) {
int* x = nullptr;
*x = 42;
}
}
void use_count_after_reset_bad(std::weak_ptr<int>& p) {
p.reset();
if (p.use_count() == 0) {
int* x = nullptr;
*x = 42;
}
}
bool expired(std::weak_ptr<int>& p) { return p.expired(); }
void expired_empty_bad() {
std::weak_ptr<int> p;
if (p.expired()) {
int* x = nullptr;
*x = 42;
}
}
void expired_after_reset_bad(std::weak_ptr<int>& p) {
p.reset();
if (p.expired()) {
int* x = nullptr;
*x = 42;
}
}
void expired_after_swap_bad(std::weak_ptr<int>& p) {
std::weak_ptr<int> q;
q.swap(p);
if (p.expired()) {
int* x = nullptr;
*x = 42;
}
}
std::shared_ptr<int> lock(std::weak_ptr<int>& p) { return p.lock(); }
void FN_empty_weak_lock_returns_null_bad() {
std::weak_ptr<int> p;
auto s = p.lock();
int _ = *s.get();
}
void FN_expired_means_null_bad(std::weak_ptr<int>& p) {
if (p.expired()) {
auto s = p.lock();
int _ = *s.get();
}
}
void FN_lock_can_be_null_bad(std::weak_ptr<int>& p) {
auto s = p.lock();
int _ = *s.get();
}
int safe_deref_ok(std::weak_ptr<int>& p) {
if (auto s = p.lock()) {
return *s.get();
}
return 0;
}
std::shared_ptr<int> 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<int>();
auto p = std::weak_ptr<int>(s);
auto s2 = p.lock();
auto _ = *s2.get();
return s;
}
bool owner_before(std::weak_ptr<Base>& p, std::weak_ptr<Base>& q) {
return p.owner_before(q);
}
bool owner_before(std::weak_ptr<Base>& p, std::shared_ptr<Derived>& q) {
return p.owner_before(q);
}
} // namespace weak_ptr_observers