Summary: These have proved to be too fragile to maintain as they would often break compilation of user code. They have been off by default for more than a year now (D7350715). Removing the include models shows a more accurate picture of what infer results look like in production. As such, lots of tests have changed, mostly biabduction but also in inferbo. SIOF was using include-based models too but now libc++ is better and iostreams are implemented in a way that SIOF understands (instead of being magical creatures) so nothing changed there. Reviewed By: skcho Differential Revision: D16602171 fbshipit-source-id: ce38f045bmaster
parent
675c79480d
commit
13d54990bd
@ -1,9 +0,0 @@
|
||||
#include <infer_model/portability.h>
|
||||
|
||||
#ifdef INFER_CPP11_ON
|
||||
|
||||
#include<infer_model/atomic.h>
|
||||
|
||||
#else
|
||||
// atomic headers don't exist for pre-C++11 code
|
||||
#endif
|
@ -1,11 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// this file exists in gcc headers and we need to capture those includes
|
||||
#include <infer_model/begin_name_override.inc>
|
||||
#include_next <backward/auto_ptr.h>
|
||||
#include <infer_model/end_name_override.inc>
|
@ -1,12 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// <atomic> in libstdc++ is including 'bits/atomic_base.h', which gets included
|
||||
// by other library files as well. Override this header with <atmoic> to avoid
|
||||
// the problem
|
||||
#include <atomic>
|
@ -1,15 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// locale_conv in libstdc++ is including 'bits/unique_ptr.h' via
|
||||
// #include "unique_ptr.h". Infer can't redirect those includes
|
||||
// so instead include unique_ptr via our header first. Then, it
|
||||
// won't be included again in 'bits/locale_conv.h'
|
||||
#include <bits/unique_ptr.h>
|
||||
|
||||
#include_next <bits/locale_conv.h>
|
@ -1,13 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// this file exists in gcc headers and we need to capture those includes
|
||||
#include <infer_model/begin_name_override.inc>
|
||||
#include_next <bits/shared_ptr.h>
|
||||
#include <infer_model/end_name_override.inc>
|
||||
|
||||
#include <infer_model/shared_ptr.h>
|
@ -1,13 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// this file exists in gcc headers and we need to capture those includes
|
||||
#include <infer_model/begin_name_override.inc>
|
||||
#include_next <bits/unique_ptr.h>
|
||||
#include <infer_model/end_name_override.inc>
|
||||
|
||||
#include <infer_model/unique_ptr.h>
|
@ -1,18 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// glog/logging library has functionally equivalent but simpler
|
||||
// definitions of some CHECK_* macros when STATIC_ANALYSIS is defined.
|
||||
// Since infer wants those definitions, define the macro before including
|
||||
// glog/logging.h
|
||||
#ifndef STATIC_ANALYSIS
|
||||
#define STATIC_ANALYSIS
|
||||
#include_next <glog/logging.h>
|
||||
#undef STATIC_ANALYSIS
|
||||
#else
|
||||
#include_next <glog/logging.h>
|
||||
#endif
|
@ -1,982 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <infer_model/common.h>
|
||||
#include <infer_model/infer_traits.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
|
||||
INFER_NAMESPACE_STD_BEGIN
|
||||
|
||||
typedef enum memory_order {
|
||||
memory_order_relaxed,
|
||||
memory_order_consume,
|
||||
memory_order_acquire,
|
||||
memory_order_release,
|
||||
memory_order_acq_rel,
|
||||
memory_order_seq_cst
|
||||
} memory_order;
|
||||
|
||||
template <typename T>
|
||||
T kill_dependency(T y) noexcept {
|
||||
return y;
|
||||
}
|
||||
|
||||
// lock-free property
|
||||
#define ATOMIC_BOOL_LOCK_FREE 2
|
||||
#define ATOMIC_CHAR_LOCK_FREE 2
|
||||
#define ATOMIC_CHAR16_T_LOCK_FREE 2
|
||||
#define ATOMIC_CHAR32_T_LOCK_FREE 2
|
||||
#define ATOMIC_WCHAR_T_LOCK_FREE 2
|
||||
#define ATOMIC_SHORT_LOCK_FREE 2
|
||||
#define ATOMIC_INT_LOCK_FREE 2
|
||||
#define ATOMIC_LONG_LOCK_FREE 2
|
||||
#define ATOMIC_LLONG_LOCK_FREE 2
|
||||
#define ATOMIC_POINTER_LOCK_FREE 2
|
||||
|
||||
// NOTE1: We are missing the atomic<bool> specialization here. Will need to add
|
||||
// it when necessary
|
||||
// NOTE2: In reality, most of the atomic operations, including load, store,
|
||||
// exchange, etc. are implemented with compiler intrinsics. Some of them are
|
||||
// really hard to emulate with a source-level model due to various constraints
|
||||
// in the source language. We try our best here to violate as few constraints as
|
||||
// possible, but if it turns out to be a problem in practice, we may need to
|
||||
// consider moving some of the model implementation to BuiltinDefn.
|
||||
|
||||
template <typename T>
|
||||
struct __infer_atomic_base {
|
||||
bool is_lock_free() const volatile noexcept { return false; }
|
||||
bool is_lock_free() const noexcept { return false; }
|
||||
|
||||
// Note that the biabduction analysis has a hard time understanding memcpy
|
||||
// with non-array args. If this function turns out to be a blocker for the
|
||||
// backend, consider moving it to BuiltinDefn.
|
||||
void store(T t, memory_order mo = memory_order_seq_cst) volatile noexcept {
|
||||
memcpy(&_wrapped_value, &t, sizeof(T));
|
||||
}
|
||||
void store(T t, memory_order mo = memory_order_seq_cst) noexcept {
|
||||
memcpy(&_wrapped_value, &t, sizeof(T));
|
||||
}
|
||||
|
||||
T load(memory_order mo = memory_order_seq_cst) const volatile noexcept {
|
||||
return _wrapped_value;
|
||||
}
|
||||
T load(memory_order mo = memory_order_seq_cst) const noexcept {
|
||||
return _wrapped_value;
|
||||
}
|
||||
operator T() const volatile noexcept { return _wrapped_value; }
|
||||
operator T() const noexcept { return _wrapped_value; }
|
||||
|
||||
// Note that these two functions are not standard-compliant: if T is not
|
||||
// copy-constructible, then we are going to get a compilation failure.
|
||||
// The body of this function could be a candidate for BuiltinDefn, if
|
||||
// necessary.
|
||||
T exchange(T t, memory_order mo = memory_order_seq_cst) volatile noexcept {
|
||||
T tmp = _wrapped_value;
|
||||
_wrapped_value = t;
|
||||
return tmp;
|
||||
}
|
||||
T exchange(T t, memory_order mo = memory_order_seq_cst) noexcept {
|
||||
T tmp = _wrapped_value;
|
||||
_wrapped_value = t;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// For arbitrary type T, we have to rely on memcmp/memcpy instead of
|
||||
// operator==/operator= for comparison/assignment
|
||||
// Note that the biabduction analysis has a hard time understanding memcpy
|
||||
// with non-array args. If this function turns out to be a blocker for the
|
||||
// backend, consider moving it to BuiltinDefn.
|
||||
bool __infer_compare_exchange_impl(T* expected,
|
||||
T* desired) volatile noexcept {
|
||||
if (memcmp(&_wrapped_value, expected, sizeof(T))) {
|
||||
memcpy(&_wrapped_value, desired, sizeof(T));
|
||||
return true;
|
||||
} else {
|
||||
memcpy(expected, &_wrapped_value, sizeof(T));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool __infer_compare_exchange_impl(T* expected, T* desired) noexcept {
|
||||
if (memcmp(&_wrapped_value, expected, sizeof(T))) {
|
||||
memcpy(&_wrapped_value, desired, sizeof(T));
|
||||
return true;
|
||||
} else {
|
||||
memcpy(expected, &_wrapped_value, sizeof(T));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool compare_exchange_weak(
|
||||
T& expected,
|
||||
T desired,
|
||||
memory_order mo = memory_order_seq_cst) volatile noexcept {
|
||||
return __infer_compare_exchange_impl(&expected, &desired);
|
||||
}
|
||||
bool compare_exchange_weak(T& expected,
|
||||
T desired,
|
||||
memory_order mo = memory_order_seq_cst) noexcept {
|
||||
return __infer_compare_exchange_impl(&expected, &desired);
|
||||
}
|
||||
bool compare_exchange_weak(T& expected,
|
||||
T desired,
|
||||
memory_order succ,
|
||||
memory_order fail) volatile noexcept {
|
||||
return __infer_compare_exchange_impl(&expected, &desired);
|
||||
}
|
||||
bool compare_exchange_weak(T& expected,
|
||||
T desired,
|
||||
memory_order succ,
|
||||
memory_order fail) noexcept {
|
||||
return __infer_compare_exchange_impl(&expected, &desired);
|
||||
}
|
||||
bool compare_exchange_strong(
|
||||
T& expected,
|
||||
T desired,
|
||||
memory_order mo = memory_order_seq_cst) volatile noexcept {
|
||||
return __infer_compare_exchange_impl(&expected, &desired);
|
||||
}
|
||||
bool compare_exchange_strong(
|
||||
T& expected, T desired, memory_order mo = memory_order_seq_cst) noexcept {
|
||||
return __infer_compare_exchange_impl(&expected, &desired);
|
||||
}
|
||||
bool compare_exchange_strong(T& expected,
|
||||
T desired,
|
||||
memory_order succ,
|
||||
memory_order fail) volatile noexcept {
|
||||
return __infer_compare_exchange_impl(&expected, &desired);
|
||||
}
|
||||
bool compare_exchange_strong(T& expected,
|
||||
T desired,
|
||||
memory_order succ,
|
||||
memory_order fail) noexcept {
|
||||
return __infer_compare_exchange_impl(&expected, &desired);
|
||||
}
|
||||
|
||||
__infer_atomic_base() noexcept = default;
|
||||
constexpr __infer_atomic_base(T desired) : _wrapped_value(desired) {}
|
||||
__infer_atomic_base(const __infer_atomic_base&) = delete;
|
||||
__infer_atomic_base& operator=(const __infer_atomic_base&) = delete;
|
||||
__infer_atomic_base& operator=(const __infer_atomic_base&) volatile = delete;
|
||||
T operator=(T other) volatile noexcept {
|
||||
store(other);
|
||||
return other;
|
||||
}
|
||||
T operator=(T other) noexcept {
|
||||
store(other);
|
||||
return other;
|
||||
}
|
||||
|
||||
T _wrapped_value;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct __infer_atomic_integral : public __infer_atomic_base<T> {
|
||||
typedef __infer_atomic_base<T> __base;
|
||||
__infer_atomic_integral() noexcept = default;
|
||||
constexpr __infer_atomic_integral(T d) noexcept : __base(d) {}
|
||||
|
||||
bool is_lock_free() const volatile noexcept { return true; }
|
||||
bool is_lock_free() const noexcept { return true; }
|
||||
void store(T t, memory_order mo = memory_order_seq_cst) volatile noexcept {
|
||||
this->_wrapped_value = t;
|
||||
}
|
||||
void store(T t, memory_order mo = memory_order_seq_cst) noexcept {
|
||||
this->_wrapped_value = t;
|
||||
}
|
||||
T load(memory_order mo = memory_order_seq_cst) const volatile noexcept {
|
||||
return this->_wrapped_value;
|
||||
}
|
||||
T load(memory_order mo = memory_order_seq_cst) const noexcept {
|
||||
return this->_wrapped_value;
|
||||
}
|
||||
operator T() const volatile noexcept { return this->_wrapped_value; }
|
||||
operator T() const noexcept { return this->_wrapped_value; }
|
||||
|
||||
bool __infer_compare_exchange_impl(T& expected, T desired) volatile noexcept {
|
||||
if (this->_wrapped_value == expected) {
|
||||
this->_wrapped_value = desired;
|
||||
return true;
|
||||
} else {
|
||||
expected = this->_wrapped_value;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool __infer_compare_exchange_impl(T& expected, T desired) noexcept {
|
||||
if (this->_wrapped_value == expected) {
|
||||
this->_wrapped_value = desired;
|
||||
return true;
|
||||
} else {
|
||||
expected = this->_wrapped_value;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool compare_exchange_weak(
|
||||
T& expected,
|
||||
T desired,
|
||||
memory_order mo = memory_order_seq_cst) volatile noexcept {
|
||||
return __infer_compare_exchange_impl(expected, desired);
|
||||
}
|
||||
bool compare_exchange_weak(T& expected,
|
||||
T desired,
|
||||
memory_order mo = memory_order_seq_cst) noexcept {
|
||||
return __infer_compare_exchange_impl(expected, desired);
|
||||
}
|
||||
bool compare_exchange_weak(T& expected,
|
||||
T desired,
|
||||
memory_order succ,
|
||||
memory_order fail) volatile noexcept {
|
||||
return __infer_compare_exchange_impl(expected, desired);
|
||||
}
|
||||
bool compare_exchange_weak(T& expected,
|
||||
T desired,
|
||||
memory_order succ,
|
||||
memory_order fail) noexcept {
|
||||
return __infer_compare_exchange_impl(expected, desired);
|
||||
}
|
||||
bool compare_exchange_strong(
|
||||
T& expected,
|
||||
T desired,
|
||||
memory_order mo = memory_order_seq_cst) volatile noexcept {
|
||||
return __infer_compare_exchange_impl(expected, desired);
|
||||
}
|
||||
bool compare_exchange_strong(
|
||||
T& expected, T desired, memory_order mo = memory_order_seq_cst) noexcept {
|
||||
return __infer_compare_exchange_impl(expected, desired);
|
||||
}
|
||||
bool compare_exchange_strong(T& expected,
|
||||
T desired,
|
||||
memory_order succ,
|
||||
memory_order fail) volatile noexcept {
|
||||
return __infer_compare_exchange_impl(expected, desired);
|
||||
}
|
||||
bool compare_exchange_strong(T& expected,
|
||||
T desired,
|
||||
memory_order succ,
|
||||
memory_order fail) noexcept {
|
||||
return __infer_compare_exchange_impl(expected, desired);
|
||||
}
|
||||
|
||||
T operator=(T other) volatile noexcept {
|
||||
this->_wrapped_value = other;
|
||||
return other;
|
||||
}
|
||||
T operator=(T other) noexcept {
|
||||
this->_wrapped_value = other;
|
||||
return other;
|
||||
}
|
||||
|
||||
T fetch_add(T op, memory_order mo = memory_order_seq_cst) volatile noexcept {
|
||||
T ret = this->_wrapped_value;
|
||||
this->_wrapped_value += op;
|
||||
return ret;
|
||||
}
|
||||
T fetch_add(T op, memory_order mo = memory_order_seq_cst) noexcept {
|
||||
T ret = this->_wrapped_value;
|
||||
this->_wrapped_value += op;
|
||||
return ret;
|
||||
}
|
||||
T fetch_sub(T op, memory_order mo = memory_order_seq_cst) volatile noexcept {
|
||||
T ret = this->_wrapped_value;
|
||||
this->_wrapped_value -= op;
|
||||
return ret;
|
||||
}
|
||||
T fetch_sub(T op, memory_order mo = memory_order_seq_cst) noexcept {
|
||||
T ret = this->_wrapped_value;
|
||||
this->_wrapped_value -= op;
|
||||
return ret;
|
||||
}
|
||||
T fetch_and(T op, memory_order mo = memory_order_seq_cst) volatile noexcept {
|
||||
T ret = this->_wrapped_value;
|
||||
this->_wrapped_value &= op;
|
||||
return ret;
|
||||
}
|
||||
T fetch_and(T op, memory_order mo = memory_order_seq_cst) noexcept {
|
||||
T ret = this->_wrapped_value;
|
||||
this->_wrapped_value &= op;
|
||||
return ret;
|
||||
}
|
||||
T fetch_or(T op, memory_order mo = memory_order_seq_cst) volatile noexcept {
|
||||
T ret = this->_wrapped_value;
|
||||
this->_wrapped_value |= op;
|
||||
return ret;
|
||||
}
|
||||
T fetch_or(T op, memory_order mo = memory_order_seq_cst) noexcept {
|
||||
T ret = this->_wrapped_value;
|
||||
this->_wrapped_value |= op;
|
||||
return ret;
|
||||
}
|
||||
T fetch_xor(T op, memory_order mo = memory_order_seq_cst) volatile noexcept {
|
||||
T ret = this->_wrapped_value;
|
||||
this->_wrapped_value ^= op;
|
||||
return ret;
|
||||
}
|
||||
T fetch_xor(T op, memory_order mo = memory_order_seq_cst) noexcept {
|
||||
T ret = this->_wrapped_value;
|
||||
this->_wrapped_value ^= op;
|
||||
return ret;
|
||||
}
|
||||
|
||||
T operator++(int) volatile noexcept { return fetch_add(T(1)); }
|
||||
T operator++(int) noexcept { return fetch_add(T(1)); }
|
||||
T operator--(int) volatile noexcept { return fetch_sub(T(1)); }
|
||||
T operator--(int) noexcept { return fetch_sub(T(1)); }
|
||||
T operator++() volatile noexcept { return fetch_add(T(1)) + T(1); }
|
||||
T operator++() noexcept { return fetch_add(T(1)) + T(1); }
|
||||
T operator--() volatile noexcept { return fetch_sub(T(1)) - T(1); }
|
||||
T operator--() noexcept { return fetch_sub(T(1)) - T(1); }
|
||||
T operator+=(T op) volatile noexcept { return fetch_add(op) + op; }
|
||||
T operator+=(T op) noexcept { return fetch_add(op) + op; }
|
||||
T operator-=(T op) volatile noexcept { return fetch_sub(op) - op; }
|
||||
T operator-=(T op) noexcept { return fetch_sub(op) - op; }
|
||||
T operator&=(T op) volatile noexcept { return fetch_and(op) & op; }
|
||||
T operator&=(T op) noexcept { return fetch_and(op) & op; }
|
||||
T operator|=(T op) volatile noexcept { return fetch_or(op) | op; }
|
||||
T operator|=(T op) noexcept { return fetch_or(op) | op; }
|
||||
T operator^=(T op) volatile noexcept { return fetch_xor(op) ^ op; }
|
||||
T operator^=(T op) noexcept { return fetch_xor(op) ^ op; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct atomic : public __infer_atomic_base<T> {
|
||||
typedef __infer_atomic_base<T> __base;
|
||||
atomic() noexcept = default;
|
||||
constexpr atomic(T d) noexcept : __base(d) {}
|
||||
|
||||
T operator=(T d) volatile noexcept {
|
||||
__base::store(d);
|
||||
return d;
|
||||
}
|
||||
T operator=(T d) noexcept {
|
||||
__base::store(d);
|
||||
return d;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct atomic<char> : public __infer_atomic_integral<char> {
|
||||
typedef __infer_atomic_integral<char> __base;
|
||||
typedef char __integral_type;
|
||||
atomic() noexcept = default;
|
||||
constexpr atomic(__integral_type d) noexcept : __base(d) {}
|
||||
|
||||
using __base::operator=;
|
||||
};
|
||||
template <>
|
||||
struct atomic<signed char> : public __infer_atomic_integral<signed char> {
|
||||
typedef __infer_atomic_integral<signed char> __base;
|
||||
typedef signed char __integral_type;
|
||||
atomic() noexcept = default;
|
||||
constexpr atomic(__integral_type d) noexcept : __base(d) {}
|
||||
|
||||
using __base::operator=;
|
||||
};
|
||||
template <>
|
||||
struct atomic<unsigned char> : public __infer_atomic_integral<unsigned char> {
|
||||
typedef __infer_atomic_integral<unsigned char> __base;
|
||||
typedef unsigned char __integral_type;
|
||||
atomic() noexcept = default;
|
||||
constexpr atomic(__integral_type d) noexcept : __base(d) {}
|
||||
|
||||
using __base::operator=;
|
||||
};
|
||||
template <>
|
||||
struct atomic<short> : public __infer_atomic_integral<short> {
|
||||
typedef __infer_atomic_integral<short> __base;
|
||||
typedef short __integral_type;
|
||||
atomic() noexcept = default;
|
||||
constexpr atomic(__integral_type d) noexcept : __base(d) {}
|
||||
|
||||
using __base::operator=;
|
||||
};
|
||||
template <>
|
||||
struct atomic<unsigned short> : public __infer_atomic_integral<unsigned short> {
|
||||
typedef __infer_atomic_integral<unsigned short> __base;
|
||||
typedef unsigned short __integral_type;
|
||||
atomic() noexcept = default;
|
||||
constexpr atomic(__integral_type d) noexcept : __base(d) {}
|
||||
|
||||
using __base::operator=;
|
||||
};
|
||||
template <>
|
||||
struct atomic<int> : public __infer_atomic_integral<int> {
|
||||
typedef __infer_atomic_integral<int> __base;
|
||||
typedef int __integral_type;
|
||||
atomic() noexcept = default;
|
||||
constexpr atomic(__integral_type d) noexcept : __base(d) {}
|
||||
|
||||
using __base::operator=;
|
||||
};
|
||||
template <>
|
||||
struct atomic<unsigned int> : public __infer_atomic_integral<unsigned int> {
|
||||
typedef __infer_atomic_integral<unsigned int> __base;
|
||||
typedef unsigned int __integral_type;
|
||||
atomic() noexcept = default;
|
||||
constexpr atomic(__integral_type d) noexcept : __base(d) {}
|
||||
|
||||
using __base::operator=;
|
||||
};
|
||||
template <>
|
||||
struct atomic<long> : public __infer_atomic_integral<long> {
|
||||
typedef __infer_atomic_integral<long> __base;
|
||||
typedef long __integral_type;
|
||||
atomic() noexcept = default;
|
||||
constexpr atomic(__integral_type d) noexcept : __base(d) {}
|
||||
|
||||
using __base::operator=;
|
||||
};
|
||||
template <>
|
||||
struct atomic<unsigned long> : public __infer_atomic_integral<unsigned long> {
|
||||
typedef __infer_atomic_integral<unsigned long> __base;
|
||||
typedef unsigned long __integral_type;
|
||||
atomic() noexcept = default;
|
||||
constexpr atomic(__integral_type d) noexcept : __base(d) {}
|
||||
|
||||
using __base::operator=;
|
||||
};
|
||||
template <>
|
||||
struct atomic<long long> : public __infer_atomic_integral<long long> {
|
||||
typedef __infer_atomic_integral<long long> __base;
|
||||
typedef long long __integral_type;
|
||||
atomic() noexcept = default;
|
||||
constexpr atomic(__integral_type d) noexcept : __base(d) {}
|
||||
|
||||
using __base::operator=;
|
||||
};
|
||||
template <>
|
||||
struct atomic<unsigned long long>
|
||||
: public __infer_atomic_integral<unsigned long long> {
|
||||
typedef __infer_atomic_integral<unsigned long long> __base;
|
||||
typedef unsigned long long __integral_type;
|
||||
atomic() noexcept = default;
|
||||
constexpr atomic(__integral_type d) noexcept : __base(d) {}
|
||||
|
||||
using __base::operator=;
|
||||
};
|
||||
template <>
|
||||
struct atomic<wchar_t> : public __infer_atomic_integral<wchar_t> {
|
||||
typedef __infer_atomic_integral<wchar_t> __base;
|
||||
typedef wchar_t __integral_type;
|
||||
atomic() noexcept = default;
|
||||
constexpr atomic(__integral_type d) noexcept : __base(d) {}
|
||||
|
||||
using __base::operator=;
|
||||
};
|
||||
template <>
|
||||
struct atomic<char16_t> : public __infer_atomic_integral<char16_t> {
|
||||
typedef __infer_atomic_integral<char16_t> __base;
|
||||
typedef char16_t __integral_type;
|
||||
atomic() noexcept = default;
|
||||
constexpr atomic(__integral_type d) noexcept : __base(d) {}
|
||||
|
||||
using __base::operator=;
|
||||
};
|
||||
template <>
|
||||
struct atomic<char32_t> : public __infer_atomic_integral<char32_t> {
|
||||
typedef __infer_atomic_integral<char32_t> __base;
|
||||
typedef char32_t __integral_type;
|
||||
atomic() noexcept = default;
|
||||
constexpr atomic(__integral_type d) noexcept : __base(d) {}
|
||||
|
||||
using __base::operator=;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct atomic<T*> : public __infer_atomic_base<T*> {
|
||||
typedef __infer_atomic_base<T*> __base;
|
||||
atomic() noexcept = default;
|
||||
constexpr atomic(T* d) noexcept : __base(d) {}
|
||||
|
||||
bool is_lock_free() const volatile noexcept { return true; }
|
||||
bool is_lock_free() const noexcept { return true; }
|
||||
void store(T* t, memory_order mo = memory_order_seq_cst) volatile noexcept {
|
||||
this->_wrapped_value = t;
|
||||
}
|
||||
void store(T* t, memory_order mo = memory_order_seq_cst) noexcept {
|
||||
this->_wrapped_value = t;
|
||||
}
|
||||
T* load(memory_order mo = memory_order_seq_cst) const volatile noexcept {
|
||||
return this->_wrapped_value;
|
||||
}
|
||||
T* load(memory_order mo = memory_order_seq_cst) const noexcept {
|
||||
return this->_wrapped_value;
|
||||
}
|
||||
operator T*() const volatile noexcept { return this->_wrapped_value; }
|
||||
operator T*() const noexcept { return this->_wrapped_value; }
|
||||
|
||||
bool __infer_compare_exchange_impl(T*& expected,
|
||||
T* desired) volatile noexcept {
|
||||
if (this->_wrapped_value == expected) {
|
||||
this->_wrapped_value = desired;
|
||||
return true;
|
||||
} else {
|
||||
expected = this->_wrapped_value;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool __infer_compare_exchange_impl(T*& expected, T* desired) noexcept {
|
||||
if (this->_wrapped_value == expected) {
|
||||
this->_wrapped_value = desired;
|
||||
return true;
|
||||
} else {
|
||||
expected = this->_wrapped_value;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool compare_exchange_weak(
|
||||
T*& expected,
|
||||
T* desired,
|
||||
memory_order mo = memory_order_seq_cst) volatile noexcept {
|
||||
return __infer_compare_exchange_impl(expected, desired);
|
||||
}
|
||||
bool compare_exchange_weak(T*& expected,
|
||||
T* desired,
|
||||
memory_order mo = memory_order_seq_cst) noexcept {
|
||||
return __infer_compare_exchange_impl(expected, desired);
|
||||
}
|
||||
bool compare_exchange_weak(T*& expected,
|
||||
T* desired,
|
||||
memory_order succ,
|
||||
memory_order fail) volatile noexcept {
|
||||
return __infer_compare_exchange_impl(expected, desired);
|
||||
}
|
||||
bool compare_exchange_weak(T*& expected,
|
||||
T* desired,
|
||||
memory_order succ,
|
||||
memory_order fail) noexcept {
|
||||
return __infer_compare_exchange_impl(expected, desired);
|
||||
}
|
||||
bool compare_exchange_strong(
|
||||
T*& expected,
|
||||
T* desired,
|
||||
memory_order mo = memory_order_seq_cst) volatile noexcept {
|
||||
return __infer_compare_exchange_impl(expected, desired);
|
||||
}
|
||||
bool compare_exchange_strong(
|
||||
T*& expected,
|
||||
T* desired,
|
||||
memory_order mo = memory_order_seq_cst) noexcept {
|
||||
return __infer_compare_exchange_impl(expected, desired);
|
||||
}
|
||||
bool compare_exchange_strong(T*& expected,
|
||||
T* desired,
|
||||
memory_order succ,
|
||||
memory_order fail) volatile noexcept {
|
||||
return __infer_compare_exchange_impl(expected, desired);
|
||||
}
|
||||
bool compare_exchange_strong(T*& expected,
|
||||
T* desired,
|
||||
memory_order succ,
|
||||
memory_order fail) noexcept {
|
||||
return __infer_compare_exchange_impl(expected, desired);
|
||||
}
|
||||
|
||||
T* operator=(T* d) volatile noexcept {
|
||||
this->_wrapped_value = d;
|
||||
return d;
|
||||
}
|
||||
T* operator=(T* d) noexcept {
|
||||
this->_wrapped_value = d;
|
||||
return d;
|
||||
}
|
||||
|
||||
T* fetch_add(ptrdiff_t op,
|
||||
memory_order mo = memory_order_seq_cst) volatile noexcept {
|
||||
T* ret = this->_wrapped_value;
|
||||
this->_wrapped_value += op;
|
||||
return ret;
|
||||
}
|
||||
T* fetch_add(ptrdiff_t op, memory_order mo = memory_order_seq_cst) noexcept {
|
||||
T* ret = this->_wrapped_value;
|
||||
this->_wrapped_value += op;
|
||||
return ret;
|
||||
}
|
||||
T* fetch_sub(ptrdiff_t op,
|
||||
memory_order mo = memory_order_seq_cst) volatile noexcept {
|
||||
T* ret = this->_wrapped_value;
|
||||
this->_wrapped_value -= op;
|
||||
return ret;
|
||||
}
|
||||
T* fetch_sub(ptrdiff_t op, memory_order mo = memory_order_seq_cst) noexcept {
|
||||
T* ret = this->_wrapped_value;
|
||||
this->_wrapped_value -= op;
|
||||
return ret;
|
||||
}
|
||||
|
||||
T* operator++(int) volatile noexcept { return fetch_add(1); }
|
||||
T* operator++(int) noexcept { return fetch_add(1); }
|
||||
T* operator--(int) volatile noexcept { return fetch_sub(1); }
|
||||
T* operator--(int) noexcept { return fetch_sub(1); }
|
||||
T* operator++() volatile noexcept { return fetch_add(1) + 1; }
|
||||
T* operator++() noexcept { return fetch_add(1) + T(1); }
|
||||
T* operator--() volatile noexcept { return fetch_sub(1) - 1; }
|
||||
T* operator--() noexcept { return fetch_sub(1) - 1; }
|
||||
T* operator+=(ptrdiff_t op) volatile noexcept { return fetch_add(op) + op; }
|
||||
T* operator+=(ptrdiff_t op) noexcept { return fetch_add(op) + op; }
|
||||
T* operator-=(ptrdiff_t op) volatile noexcept { return fetch_sub(op) - op; }
|
||||
T* operator-=(ptrdiff_t op) noexcept { return fetch_sub(op) - op; }
|
||||
};
|
||||
|
||||
// named typedefs
|
||||
typedef atomic<bool> atomic_bool;
|
||||
typedef atomic<char> atomic_char;
|
||||
typedef atomic<signed char> atomic_schar;
|
||||
typedef atomic<unsigned char> atomic_uchar;
|
||||
typedef atomic<short> atomic_short;
|
||||
typedef atomic<unsigned short> atomic_ushort;
|
||||
typedef atomic<int> atomic_int;
|
||||
typedef atomic<unsigned int> atomic_uint;
|
||||
typedef atomic<long> atomic_long;
|
||||
typedef atomic<unsigned long> atomic_ulong;
|
||||
typedef atomic<long long> atomic_llong;
|
||||
typedef atomic<unsigned long long> atomic_ullong;
|
||||
typedef atomic<char16_t> atomic_char16_t;
|
||||
typedef atomic<char32_t> atomic_char32_t;
|
||||
typedef atomic<wchar_t> atomic_wchar_t;
|
||||
typedef atomic<int_least8_t> atomic_int_least8_t;
|
||||
typedef atomic<uint_least8_t> atomic_uint_least8_t;
|
||||
typedef atomic<int_least16_t> atomic_int_least16_t;
|
||||
typedef atomic<uint_least16_t> atomic_uint_least16_t;
|
||||
typedef atomic<int_least32_t> atomic_int_least32_t;
|
||||
typedef atomic<uint_least32_t> atomic_uint_least32_t;
|
||||
typedef atomic<int_least64_t> atomic_int_least64_t;
|
||||
typedef atomic<uint_least64_t> atomic_uint_least64_t;
|
||||
typedef atomic<int_fast8_t> atomic_int_fast8_t;
|
||||
typedef atomic<uint_fast8_t> atomic_uint_fast8_t;
|
||||
typedef atomic<int_fast16_t> atomic_int_fast16_t;
|
||||
typedef atomic<uint_fast16_t> atomic_uint_fast16_t;
|
||||
typedef atomic<int_fast32_t> atomic_int_fast32_t;
|
||||
typedef atomic<uint_fast32_t> atomic_uint_fast32_t;
|
||||
typedef atomic<int_fast64_t> atomic_int_fast64_t;
|
||||
typedef atomic<uint_fast64_t> atomic_uint_fast64_t;
|
||||
typedef atomic<intptr_t> atomic_intptr_t;
|
||||
typedef atomic<uintptr_t> atomic_uintptr_t;
|
||||
typedef atomic<size_t> atomic_size_t;
|
||||
typedef atomic<ptrdiff_t> atomic_ptrdiff_t;
|
||||
typedef atomic<intmax_t> atomic_intmax_t;
|
||||
typedef atomic<uintmax_t> atomic_uintmax_t;
|
||||
|
||||
// general operations on atomic types
|
||||
template <typename T>
|
||||
bool atomic_is_lock_free(const volatile atomic<T>* a) noexcept {
|
||||
return a->is_lock_free();
|
||||
}
|
||||
template <typename T>
|
||||
void atomic_is_lock_free(const atomic<T>* a) noexcept {
|
||||
return a->is_lock_free();
|
||||
}
|
||||
template <typename T>
|
||||
void atomic_init(volatile atomic<T>* a, T d) noexcept {
|
||||
a->store(d);
|
||||
}
|
||||
template <typename T>
|
||||
bool atomic_init(atomic<T>* a, T d) noexcept {
|
||||
a->store(d);
|
||||
}
|
||||
template <typename T>
|
||||
void atomic_store(volatile atomic<T>* a, T d) noexcept {
|
||||
a->store(d);
|
||||
}
|
||||
template <typename T>
|
||||
void atomic_store(atomic<T>* a, T d) noexcept {
|
||||
a->store(d);
|
||||
}
|
||||
template <typename T>
|
||||
void atomic_store_explicit(volatile atomic<T>* a,
|
||||
T d,
|
||||
memory_order mo) noexcept {
|
||||
a->store(d, mo);
|
||||
}
|
||||
template <typename T>
|
||||
void atomic_store_explicit(atomic<T>* a, T d, memory_order mo) noexcept {
|
||||
a->store(d, mo);
|
||||
}
|
||||
template <typename T>
|
||||
T atomic_load(const volatile atomic<T>* a) noexcept {
|
||||
return a->load();
|
||||
}
|
||||
template <typename T>
|
||||
T atomic_load(const atomic<T>* a) noexcept {
|
||||
return a->load();
|
||||
}
|
||||
template <typename T>
|
||||
T atomic_load_explicit(const volatile atomic<T>* a, memory_order mo) noexcept {
|
||||
return a->load(mo);
|
||||
}
|
||||
template <typename T>
|
||||
T atomic_load_explicit(const atomic<T>* a, memory_order mo) noexcept {
|
||||
return a->load(mo);
|
||||
}
|
||||
template <typename T>
|
||||
T atomic_exchange(volatile atomic<T>* a, T d) noexcept {
|
||||
return a->exchange(d);
|
||||
}
|
||||
template <typename T>
|
||||
T atomic_exchange(atomic<T>* a, T d) noexcept {
|
||||
return a->exchange(d);
|
||||
}
|
||||
template <typename T>
|
||||
T atomic_echange_explicit(volatile atomic<T>* a,
|
||||
T d,
|
||||
memory_order mo) noexcept {
|
||||
return a->exchange(d, mo);
|
||||
}
|
||||
template <typename T>
|
||||
T atomic_exchange_explicit(atomic<T>* a, T d, memory_order mo) noexcept {
|
||||
return a->exchange(d, mo);
|
||||
}
|
||||
template <typename T>
|
||||
bool atomic_compare_exchange_weak(volatile atomic<T>* a, T* d, T e) noexcept {
|
||||
return a->compare_exchange_weak(*d, e);
|
||||
}
|
||||
template <typename T>
|
||||
bool atomic_compare_exchange_weak(atomic<T>* a, T* d, T e) noexcept {
|
||||
return a->compare_exchange_weak(*d, e);
|
||||
}
|
||||
template <typename T>
|
||||
bool atomic_compare_exchange_strong(volatile atomic<T>* a, T* d, T e) noexcept {
|
||||
return a->compare_exchange_strong(*d, e);
|
||||
}
|
||||
template <typename T>
|
||||
bool atomic_compare_exchange_strong(atomic<T>* a, T* d, T e) noexcept {
|
||||
return a->compare_exchange_strong(*d, e);
|
||||
}
|
||||
template <typename T>
|
||||
bool atomic_compare_exchange_weak_explicit(volatile atomic<T>* a,
|
||||
T* d,
|
||||
T e,
|
||||
memory_order so,
|
||||
memory_order fo) noexcept {
|
||||
return a->compare_exchange_weak(*d, e, so, fo);
|
||||
}
|
||||
template <typename T>
|
||||
bool atomic_compare_exchange_weak_explicit(
|
||||
atomic<T>* a, T* d, T e, memory_order so, memory_order fo) noexcept {
|
||||
return a->compare_exchange_weak(*d, e, so, fo);
|
||||
}
|
||||
template <typename T>
|
||||
bool atomic_compare_exchange_strong_explicit(volatile atomic<T>* a,
|
||||
T* d,
|
||||
T e,
|
||||
memory_order so,
|
||||
memory_order fo) noexcept {
|
||||
return a->compare_exchange_strong(*d, e, so, fo);
|
||||
}
|
||||
template <typename T>
|
||||
bool atomic_compare_exchange_strong_explicit(
|
||||
atomic<T>* a, T* d, T e, memory_order so, memory_order fo) noexcept {
|
||||
return a->compare_exchange_strong(*d, e, so, fo);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T atomic_fetch_add(volatile __infer_atomic_integral<T>* a, T i) noexcept {
|
||||
return a->fetch_add(i);
|
||||
}
|
||||
template <typename T>
|
||||
T atomic_fetch_add(__infer_atomic_integral<T>* a, T i) noexcept {
|
||||
return a->fetch_add(i);
|
||||
}
|
||||
template <typename T>
|
||||
T atomic_fetch_add_explicit(volatile __infer_atomic_integral<T>* a,
|
||||
T i,
|
||||
memory_order mo) noexcept {
|
||||
return a->fetch_add(i, mo);
|
||||
}
|
||||
template <typename T>
|
||||
T atomic_fetch_add_explicit(__infer_atomic_integral<T>* a,
|
||||
T i,
|
||||
memory_order mo) noexcept {
|
||||
return a->fetch_add(i, mo);
|
||||
}
|
||||
template <typename T>
|
||||
T atomic_fetch_sub(volatile __infer_atomic_integral<T>* a, T i) noexcept {
|
||||
return a->fetch_sub(i);
|
||||
}
|
||||
template <typename T>
|
||||
T atomic_fetch_sub(__infer_atomic_integral<T>* a, T i) noexcept {
|
||||
return a->fetch_sub(i);
|
||||
}
|
||||
template <typename T>
|
||||
T atomic_fetch_sub_explicit(volatile __infer_atomic_integral<T>* a,
|
||||
T i,
|
||||
memory_order mo) noexcept {
|
||||
return a->fetch_sub(i, mo);
|
||||
}
|
||||
template <typename T>
|
||||
T atomic_fetch_sub_explicit(__infer_atomic_integral<T>* a,
|
||||
T i,
|
||||
memory_order mo) noexcept {
|
||||
return a->fetch_sub(i, mo);
|
||||
}
|
||||
template <typename T>
|
||||
T atomic_fetch_and(volatile __infer_atomic_integral<T>* a, T i) noexcept {
|
||||
return a->fetch_and(i);
|
||||
}
|
||||
template <typename T>
|
||||
T atomic_fetch_and(__infer_atomic_integral<T>* a, T i) noexcept {
|
||||
return a->fetch_and(i);
|
||||
}
|
||||
template <typename T>
|
||||
T atomic_fetch_and_explicit(volatile __infer_atomic_integral<T>* a,
|
||||
T i,
|
||||
memory_order mo) noexcept {
|
||||
return a->fetch_and(i, mo);
|
||||
}
|
||||
template <typename T>
|
||||
T atomic_fetch_and_explicit(__infer_atomic_integral<T>* a,
|
||||
T i,
|
||||
memory_order mo) noexcept {
|
||||
return a->fetch_and(i, mo);
|
||||
}
|
||||
template <typename T>
|
||||
T atomic_fetch_or(volatile __infer_atomic_integral<T>* a, T i) noexcept {
|
||||
return a->fetch_or(i);
|
||||
}
|
||||
template <typename T>
|
||||
T atomic_fetch_or(__infer_atomic_integral<T>* a, T i) noexcept {
|
||||
return a->fetch_or(i);
|
||||
}
|
||||
template <typename T>
|
||||
T atomic_fetch_or_explicit(volatile __infer_atomic_integral<T>* a,
|
||||
T i,
|
||||
memory_order mo) noexcept {
|
||||
return a->fetch_or(i, mo);
|
||||
}
|
||||
template <typename T>
|
||||
T atomic_fetch_or_explicit(__infer_atomic_integral<T>* a,
|
||||
T i,
|
||||
memory_order mo) noexcept {
|
||||
return a->fetch_or(i, mo);
|
||||
}
|
||||
template <typename T>
|
||||
T atomic_fetch_xor(volatile __infer_atomic_integral<T>* a, T i) noexcept {
|
||||
return a->fetch_xor(i);
|
||||
}
|
||||
template <typename T>
|
||||
T atomic_fetch_xor(__infer_atomic_integral<T>* a, T i) noexcept {
|
||||
return a->fetch_xor(i);
|
||||
}
|
||||
template <typename T>
|
||||
T atomic_fetch_xor_explicit(volatile __infer_atomic_integral<T>* a,
|
||||
T i,
|
||||
memory_order mo) noexcept {
|
||||
return a->fetch_xor(i, mo);
|
||||
}
|
||||
template <typename T>
|
||||
T atomic_fetch_xor_explicit(__infer_atomic_integral<T>* a,
|
||||
T i,
|
||||
memory_order mo) noexcept {
|
||||
return a->fetch_xor(i, mo);
|
||||
}
|
||||
|
||||
// partial specialization for pointers
|
||||
template <typename T>
|
||||
T* atomic_fetch_add(volatile atomic<T*>* a, ptrdiff_t i) noexcept {
|
||||
return a->fetch_add(i);
|
||||
}
|
||||
template <typename T>
|
||||
T* atomic_fetch_add(atomic<T*>* a, ptrdiff_t i) noexcept {
|
||||
return a->fetch_add(i);
|
||||
}
|
||||
template <typename T>
|
||||
T* atomic_fetch_add_explicit(volatile atomic<T*>* a,
|
||||
ptrdiff_t i,
|
||||
memory_order mo) noexcept {
|
||||
return a->fetch_add(i, mo);
|
||||
}
|
||||
template <typename T>
|
||||
T* atomic_fetch_add_explicit(atomic<T*>* a,
|
||||
ptrdiff_t i,
|
||||
memory_order mo) noexcept {
|
||||
return a->fetch_add(i, mo);
|
||||
}
|
||||
template <typename T>
|
||||
T* atomic_fetch_sub(volatile atomic<T*>* a, ptrdiff_t i) noexcept {
|
||||
return a->fetch_sub(i);
|
||||
}
|
||||
template <typename T>
|
||||
T* atomic_fetch_sub(atomic<T*>* a, ptrdiff_t i) noexcept {
|
||||
return a->fetch_sub(i);
|
||||
}
|
||||
template <typename T>
|
||||
T* atomic_fetch_sub_explicit(volatile atomic<T*>* a,
|
||||
ptrdiff_t i,
|
||||
memory_order mo) noexcept {
|
||||
return a->fetch_sub(i, mo);
|
||||
}
|
||||
template <typename T>
|
||||
T* atomic_fetch_sub_explicit(atomic<T*>* a,
|
||||
ptrdiff_t i,
|
||||
memory_order mo) noexcept {
|
||||
return a->fetch_sub(i, mo);
|
||||
}
|
||||
|
||||
typedef struct atomic_flag {
|
||||
bool a;
|
||||
|
||||
atomic_flag() noexcept = default;
|
||||
constexpr atomic_flag(bool i) noexcept : a(i) {}
|
||||
atomic_flag(const atomic_flag&) = delete;
|
||||
atomic_flag& operator=(const atomic_flag&) = delete;
|
||||
atomic_flag& operator=(const atomic_flag&) volatile = delete;
|
||||
|
||||
bool test_and_set(memory_order mo = memory_order_seq_cst) volatile noexcept {
|
||||
bool ret = a;
|
||||
a = true;
|
||||
return ret;
|
||||
}
|
||||
bool test_and_set(memory_order mo = memory_order_seq_cst) noexcept {
|
||||
bool ret = a;
|
||||
a = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void clear(memory_order mo = memory_order_seq_cst) volatile noexcept {
|
||||
a = false;
|
||||
}
|
||||
void clear(memory_order mo = memory_order_seq_cst) noexcept { a = false; }
|
||||
|
||||
} atomic_flag;
|
||||
|
||||
bool atomic_flag_test_and_set(volatile atomic_flag* f) noexcept {
|
||||
return f->test_and_set();
|
||||
}
|
||||
bool atomic_flag_test_and_set(atomic_flag* f) noexcept {
|
||||
return f->test_and_set();
|
||||
}
|
||||
bool atomic_flag_test_and_set_explicit(volatile atomic_flag* f,
|
||||
memory_order m) noexcept {
|
||||
return f->test_and_set(m);
|
||||
}
|
||||
bool atomic_flag_test_and_set_explicit(atomic_flag* f,
|
||||
memory_order m) noexcept {
|
||||
return f->test_and_set(m);
|
||||
}
|
||||
void atomic_flag_clear(volatile atomic_flag* f) noexcept { f->clear(); }
|
||||
void atomic_flag_clear(atomic_flag* f) noexcept { f->clear(); }
|
||||
void atomic_flag_clear_explicit(volatile atomic_flag* f,
|
||||
memory_order mo) noexcept {
|
||||
f->clear(mo);
|
||||
}
|
||||
void atomic_flag_clear_explicit(atomic_flag* f, memory_order mo) noexcept {
|
||||
f->clear(mo);
|
||||
}
|
||||
|
||||
void atomic_thread_fence(memory_order mo) noexcept {}
|
||||
void atomic_signal_fence(memory_order mo) noexcept {}
|
||||
|
||||
#define ATOMIC_FLAG_INIT \
|
||||
{ false }
|
||||
#define ATOMIC_VAR_INIT(__v) \
|
||||
{ __v }
|
||||
|
||||
INFER_NAMESPACE_STD_END
|
@ -1,13 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define make_shared std__make_shared
|
||||
#define enable_shared_from_this std__enable_shared_from_this
|
||||
#define shared_ptr std__shared_ptr
|
||||
#define unique_ptr std__unique_ptr
|
||||
#define make_unique std__make_unique
|
||||
#define weak_ptr std__weak_ptr
|
@ -1,11 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <infer_model/portability.h>
|
||||
#include <infer_no_model/crash_on_exec.h>
|
@ -1,13 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#undef make_shared
|
||||
#undef enable_shared_from_this
|
||||
#undef shared_ptr
|
||||
#undef unique_ptr
|
||||
#undef make_unique
|
||||
#undef weak_ptr
|
@ -1,18 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace infer_traits {
|
||||
// all friends of this class and will be translated as type T by infer
|
||||
// frontend instead of their own type
|
||||
template <class T>
|
||||
class TranslateAsType {};
|
||||
} // namespace infer_traits
|
||||
|
||||
#define INFER_MODEL_AS_DEREF_FIRST_ARG \
|
||||
__attribute__((annotate("__infer_replace_with_deref_first_arg"))) {}
|
@ -1,13 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include_next <iostream>
|
||||
|
||||
// this is a marker so that infer can tell whether iostream has been included by
|
||||
// a give source file
|
||||
std::ios_base::Init __infer_translation_unit_init_streams;
|
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
// This is a hacky attempt to follow what folly does
|
||||
// https://github.com/facebook/folly/blob/b1eb6819f3ffe6b645f39d505ca8ace3116b7873/folly/configure.ac#L232
|
||||
// Depending whether the project is compiled with libc++ or stdlibc++, include
|
||||
// their internal config headers to get information about versions
|
||||
// clang-format off
|
||||
#if __has_include(<__config>) // defines _LIBCPP_VERSION
|
||||
#include <__config>
|
||||
#elif __has_include(<bits/c++config.h>) // defines __GLIBCXX__
|
||||
#include <bits/c++config.h>
|
||||
#endif
|
||||
// clang-format on
|
||||
|
||||
// Figure out whether the library really supports c++11 standard
|
||||
#if __cplusplus >= 201103L
|
||||
#if __GLIBCXX__ >= 20130531
|
||||
// C++11 is really supported from gcc 4.8.1 onward.
|
||||
#define INFER_CPP11_ON 1
|
||||
#elif defined _LIBCPP_VERSION // for now assume libc++ always supported c++11
|
||||
#define INFER_CPP11_ON 1
|
||||
#endif
|
||||
#endif // __cplusplus >= 201103L
|
||||
|
||||
#if !defined(INFER_USE_LIBCPP) && defined(_LIBCPP_VERSION)
|
||||
#define INFER_USE_LIBCPP 1
|
||||
#elif defined(FOLLY_USE_LIBCPP) // follow folly configuration if it's available
|
||||
#define INFER_USE_LIBCPP 1
|
||||
#endif
|
||||
|
||||
// Follow what folly does - gnu libstdc++ implementation is different from
|
||||
// llvm's libc++. This way folly can forward declare decls from std library
|
||||
// even when they are infer models
|
||||
// https://github.com/facebook/folly/blob/b1eb6819f3ffe6b645f39d505ca8ace3116b7873/folly/Portability.h#L253-L255
|
||||
// On top of that, define platform-dependent STL iterators.
|
||||
#if INFER_USE_LIBCPP
|
||||
#include <__config>
|
||||
#define INFER_NAMESPACE_STD_BEGIN _LIBCPP_BEGIN_NAMESPACE_STD
|
||||
#define INFER_NAMESPACE_STD_END _LIBCPP_END_NAMESPACE_STD
|
||||
#define STD_ITER(T, C) __wrap_iter<T>
|
||||
#else
|
||||
#define INFER_NAMESPACE_STD_BEGIN namespace std {
|
||||
#define INFER_NAMESPACE_STD_END }
|
||||
#define STD_ITER(T, C) __gnu_cxx::__normal_iterator<T, C>
|
||||
#endif
|
@ -1,431 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
// ASSERT that __cplusplus >= 201103L
|
||||
|
||||
#include <infer_model/common.h>
|
||||
#include <infer_model/infer_traits.h>
|
||||
#include <infer_model/weak_ptr.h>
|
||||
|
||||
INFER_NAMESPACE_STD_BEGIN
|
||||
|
||||
// use inheritance to avoid compilation errors when using
|
||||
// methods / non-member functions that are not modeled
|
||||
// WARNING: if sizeof(shared_ptr) becomes different than 16, it may
|
||||
// lead to compilation errors
|
||||
template <class T>
|
||||
class shared_ptr : public std__shared_ptr<T> {
|
||||
|
||||
// translate shared_ptr as type T*
|
||||
friend class infer_traits::TranslateAsType<T*>;
|
||||
|
||||
// shared_ptr<T> in infer is translated as T*.
|
||||
// Some facts:
|
||||
// 1. shared_ptr<T>* translated as T**
|
||||
// 2. typeof(this) translated as T**
|
||||
// 3. typeof(this) in clang's AST is shared_ptr<T>*
|
||||
// When writing models for shared_ptr, we need to use infer's representation
|
||||
// In order to achieve that and not break compilation, there is some ugly
|
||||
// casting going around. We are using void* and void** to make compilation
|
||||
// happy - infer doesn't care about those types that much since they are
|
||||
// pointers anyway.
|
||||
// Example of model_X function declaration:
|
||||
// static void model_X(infer_shared_ptr_t self, ... params)
|
||||
// model_X are really C functions, but to simplify linking process, they are
|
||||
// defined inside shared_ptr class as static methods.
|
||||
// When using model_X functions, call them like so:
|
||||
// model_X(__cast_to_infer_ptr(this), args)
|
||||
|
||||
/// type of 'this' in shared_ptr<T> as seen by infer
|
||||
typedef const void** infer_shared_ptr_t;
|
||||
// use it to avoid compilation errors and make infer analyzer happy
|
||||
#define __cast_to_infer_ptr(self) ((infer_shared_ptr_t)self)
|
||||
|
||||
// provide overload for volatile void* to accommodate for situation when
|
||||
// T is volatile ('volatile int' for example). 'void*' and 'nullptr_t'
|
||||
// overloads are to avoid 'call to model_set is ambiguous' compilation errors
|
||||
static void model_set(infer_shared_ptr_t self, nullptr_t value) {
|
||||
*self = value;
|
||||
}
|
||||
|
||||
static void model_set(infer_shared_ptr_t self, const void* value) {
|
||||
*self = value;
|
||||
}
|
||||
|
||||
static void model_set(infer_shared_ptr_t self, volatile void* value) {
|
||||
*self = const_cast<const void*>(value);
|
||||
}
|
||||
|
||||
static void model_set(infer_shared_ptr_t self, void* value) {
|
||||
*self = const_cast<const void*>(value);
|
||||
}
|
||||
|
||||
static void model_copy(infer_shared_ptr_t self, infer_shared_ptr_t other) {
|
||||
/* TODO - increase refcount*/
|
||||
*self = *other;
|
||||
}
|
||||
|
||||
static void model_move(infer_shared_ptr_t self, infer_shared_ptr_t other) {
|
||||
model_copy(self, other);
|
||||
model_set(other, nullptr);
|
||||
}
|
||||
|
||||
static void model_swap(infer_shared_ptr_t infer_self,
|
||||
infer_shared_ptr_t infer_other) {
|
||||
const void* t = *infer_self;
|
||||
*infer_self = *infer_other;
|
||||
*infer_other = t;
|
||||
}
|
||||
|
||||
public:
|
||||
// Conversion constructors to allow implicit conversions.
|
||||
// it's here purely to avoid compilation errors
|
||||
template <class Y,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
shared_ptr(const std__shared_ptr<Y>& r) {}
|
||||
|
||||
template <class Y>
|
||||
shared_ptr(const std__shared_ptr<Y>& r, T* p) noexcept {}
|
||||
|
||||
// constructors:
|
||||
constexpr shared_ptr() noexcept {
|
||||
model_set(__cast_to_infer_ptr(this), nullptr);
|
||||
}
|
||||
|
||||
shared_ptr(nullptr_t) : shared_ptr() {}
|
||||
|
||||
// Extra template argument is used to create constructors/assignment overloads
|
||||
// for Y types where it's possible to convert Y* to T*.
|
||||
// typename = typename enable_if<is_convertible<Y*, T*>::value>::type
|
||||
// thanks to that, clang will not create some functions that would cause
|
||||
// compilation errors. More info:
|
||||
// http://en.cppreference.com/w/cpp/language/sfinae
|
||||
template <class Y,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
explicit shared_ptr(Y* p) {
|
||||
model_set(__cast_to_infer_ptr(this), p);
|
||||
}
|
||||
|
||||
template <class Y,
|
||||
class D,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
shared_ptr(Y* p, D d) : shared_ptr<T>(p) {}
|
||||
|
||||
template <class Y,
|
||||
class D,
|
||||
class A,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
shared_ptr(Y* p, D d, A a) : shared_ptr<T>(p) {}
|
||||
|
||||
template <class D>
|
||||
shared_ptr(nullptr_t p, D d) : shared_ptr<T>(p) {}
|
||||
|
||||
template <class D, class A>
|
||||
shared_ptr(nullptr_t p, D d, A a) : shared_ptr<T>(p) {}
|
||||
|
||||
template <class Y>
|
||||
shared_ptr(const shared_ptr<Y>& r, T* p) noexcept {
|
||||
model_set(__cast_to_infer_ptr(this), p); /* TODO */
|
||||
}
|
||||
|
||||
shared_ptr(const shared_ptr& r) noexcept {
|
||||
model_copy(__cast_to_infer_ptr(this), __cast_to_infer_ptr(&r));
|
||||
}
|
||||
|
||||
template <class Y,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
shared_ptr(const shared_ptr<Y>& r) noexcept {
|
||||
model_copy(__cast_to_infer_ptr(this), __cast_to_infer_ptr(&r));
|
||||
}
|
||||
|
||||
shared_ptr(shared_ptr&& r) noexcept {
|
||||
model_move(__cast_to_infer_ptr(this), __cast_to_infer_ptr(&r));
|
||||
}
|
||||
|
||||
template <class Y,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
shared_ptr(shared_ptr<Y>&& r) noexcept {
|
||||
model_move(__cast_to_infer_ptr(this), __cast_to_infer_ptr(&r));
|
||||
}
|
||||
|
||||
template <class Y,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
explicit shared_ptr(const weak_ptr<Y>& r) : shared_ptr(std::move(r.lock())) {
|
||||
// TODO: throw if r is empty
|
||||
}
|
||||
|
||||
/* Because of implementation differences between libc++ and stdlibc++, don't
|
||||
* define this constructor (it will be defined elsewhere in case of
|
||||
* stdlibc++). Because it may be defined elsewhere, don't check whether Y*
|
||||
* converts to T* - otherwise there might be compilation error (out-of-line
|
||||
* definition).
|
||||
* No definition here might cause compilation problems if project is
|
||||
* using auto_ptrs with libc++ */
|
||||
template <class Y>
|
||||
shared_ptr(auto_ptr<Y>&& r); // {}
|
||||
|
||||
template <class Y,
|
||||
class D,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
shared_ptr(unique_ptr<Y, D>&& r) : shared_ptr<T>(r.release()) {}
|
||||
|
||||
// destructor:
|
||||
~shared_ptr() { reset((T*)nullptr); }
|
||||
|
||||
// assignment:
|
||||
shared_ptr& operator=(const shared_ptr& r) noexcept {
|
||||
// shared_ptr<T>(r).swap(*this);
|
||||
model_copy(__cast_to_infer_ptr(this), __cast_to_infer_ptr(&r));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Y,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
shared_ptr& operator=(const shared_ptr<Y>& r) noexcept {
|
||||
// shared_ptr<T>(r).swap(*this);
|
||||
model_copy(__cast_to_infer_ptr(this), __cast_to_infer_ptr(&r));
|
||||
return *this;
|
||||
}
|
||||
|
||||
shared_ptr& operator=(shared_ptr&& r) noexcept {
|
||||
// shared_ptr<T>(std::move(r)).swap(*this);
|
||||
model_move(__cast_to_infer_ptr(this), __cast_to_infer_ptr(&r));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Y,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
shared_ptr& operator=(shared_ptr<Y>&& r) {
|
||||
// shared_ptr<T>(std::move(r)).swap(*this);
|
||||
model_move(__cast_to_infer_ptr(this), __cast_to_infer_ptr(&r));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Y,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
shared_ptr& operator=(auto_ptr<Y>&& r) { /* ?? */
|
||||
}
|
||||
template <class Y,
|
||||
class D,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
shared_ptr& operator=(unique_ptr<Y, D>&& r) {
|
||||
// shared_ptr<T>(std::move(r)).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// modifiers:
|
||||
void swap(shared_ptr& r) noexcept {
|
||||
model_swap(__cast_to_infer_ptr(this), __cast_to_infer_ptr(&r));
|
||||
}
|
||||
|
||||
void reset() noexcept { reset((T*)nullptr); }
|
||||
|
||||
template <class Y,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
void reset(Y* p) {
|
||||
/*
|
||||
if (unique()) {
|
||||
delete __data;
|
||||
}
|
||||
*/
|
||||
model_set(__cast_to_infer_ptr(this), p);
|
||||
// TODO adjust refcounts
|
||||
}
|
||||
|
||||
template <class Y,
|
||||
class D,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
void reset(Y* p, D d) {
|
||||
reset(p);
|
||||
}
|
||||
|
||||
template <class Y,
|
||||
class D,
|
||||
class A,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
void reset(Y* p, D d, A a) {
|
||||
reset(p);
|
||||
}
|
||||
|
||||
// observers:
|
||||
T* get() const noexcept INFER_MODEL_AS_DEREF_FIRST_ARG;
|
||||
|
||||
typename std::add_lvalue_reference<T>::type operator*() const
|
||||
noexcept INFER_MODEL_AS_DEREF_FIRST_ARG;
|
||||
|
||||
T* operator->() const noexcept INFER_MODEL_AS_DEREF_FIRST_ARG;
|
||||
long use_count() const noexcept { return 2; /* FIXME */ }
|
||||
bool unique() const noexcept { return use_count() == 1; /* FIXME */ }
|
||||
explicit operator bool() const noexcept {
|
||||
// for some reason analyzer can't cast to bool correctly, trick with two
|
||||
// negations creates right specs for this function
|
||||
return !!(bool)(*__cast_to_infer_ptr(this));
|
||||
}
|
||||
template <class U>
|
||||
bool owner_before(shared_ptr<U> const& b) const {
|
||||
return true; /* FIXME - use non-det*/
|
||||
}
|
||||
template <class U>
|
||||
bool owner_before(weak_ptr<U> const& b) const {
|
||||
return true; /* FIXME - use non-det */
|
||||
}
|
||||
};
|
||||
template <class _Tp, class _Up>
|
||||
inline bool operator==(const shared_ptr<_Tp>& __x,
|
||||
const shared_ptr<_Up>& __y) noexcept {
|
||||
return __x.get() == __y.get();
|
||||
}
|
||||
|
||||
template <class _Tp, class _Up>
|
||||
inline bool operator!=(const shared_ptr<_Tp>& __x,
|
||||
const shared_ptr<_Up>& __y) noexcept {
|
||||
return !(__x == __y);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Up>
|
||||
inline bool operator<(const shared_ptr<_Tp>& __x,
|
||||
const shared_ptr<_Up>& __y) noexcept {
|
||||
typedef typename common_type<_Tp*, _Up*>::type _Vp;
|
||||
return less<_Vp>()(__x.get(), __y.get());
|
||||
}
|
||||
|
||||
template <class _Tp, class _Up>
|
||||
inline bool operator>(const shared_ptr<_Tp>& __x,
|
||||
const shared_ptr<_Up>& __y) noexcept {
|
||||
return __y < __x;
|
||||
}
|
||||
|
||||
template <class _Tp, class _Up>
|
||||
inline bool operator<=(const shared_ptr<_Tp>& __x,
|
||||
const shared_ptr<_Up>& __y) noexcept {
|
||||
return !(__y < __x);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Up>
|
||||
inline bool operator>=(const shared_ptr<_Tp>& __x,
|
||||
const shared_ptr<_Up>& __y) noexcept {
|
||||
return !(__x < __y);
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
inline bool operator==(const shared_ptr<_Tp>& __x, nullptr_t) noexcept {
|
||||
return !__x;
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
inline bool operator==(nullptr_t, const shared_ptr<_Tp>& __x) noexcept {
|
||||
return !__x;
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
inline bool operator!=(const shared_ptr<_Tp>& __x, nullptr_t) noexcept {
|
||||
return static_cast<bool>(__x);
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
inline bool operator!=(nullptr_t, const shared_ptr<_Tp>& __x) noexcept {
|
||||
return static_cast<bool>(__x);
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
inline bool operator<(const shared_ptr<_Tp>& __x, nullptr_t) noexcept {
|
||||
return less<_Tp*>()(__x.get(), nullptr);
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
inline bool operator<(nullptr_t, const shared_ptr<_Tp>& __x) noexcept {
|
||||
return less<_Tp*>()(nullptr, __x.get());
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
inline bool operator>(const shared_ptr<_Tp>& __x, nullptr_t) noexcept {
|
||||
return nullptr < __x;
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
inline bool operator>(nullptr_t, const shared_ptr<_Tp>& __x) noexcept {
|
||||
return __x < nullptr;
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
inline bool operator<=(const shared_ptr<_Tp>& __x, nullptr_t) noexcept {
|
||||
return !(nullptr < __x);
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
inline bool operator<=(nullptr_t, const shared_ptr<_Tp>& __x) noexcept {
|
||||
return !(__x < nullptr);
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
inline bool operator>=(const shared_ptr<_Tp>& __x, nullptr_t) noexcept {
|
||||
return !(__x < nullptr);
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
inline bool operator>=(nullptr_t, const shared_ptr<_Tp>& __x) noexcept {
|
||||
return !(nullptr < __x);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct hash<shared_ptr<T>> : public hash<std__shared_ptr<T>> {};
|
||||
|
||||
// shared_ptr casts - call original functions but change return type to
|
||||
// std::shared_ptr
|
||||
template <class T, class U>
|
||||
shared_ptr<T> static_pointer_cast(shared_ptr<U> const& r) noexcept {
|
||||
return static_pointer_cast<T, U>((const std__shared_ptr<U>&)r);
|
||||
}
|
||||
template <class T, class U>
|
||||
shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const& r) noexcept {
|
||||
return dynamic_pointer_cast<T, U>((const std__shared_ptr<U>&)r);
|
||||
}
|
||||
template <class T, class U>
|
||||
shared_ptr<T> const_pointer_cast(shared_ptr<U> const& r) noexcept {
|
||||
return const_pointer_cast<T, U>((const std__shared_ptr<U>&)r);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
class enable_shared_from_this : public std__enable_shared_from_this<T> {
|
||||
public:
|
||||
shared_ptr<T> shared_from_this() {
|
||||
return std__enable_shared_from_this<T>::shared_from_this();
|
||||
}
|
||||
shared_ptr<T const> shared_from_this() const {
|
||||
return std__enable_shared_from_this<T>::shared_from_this();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class... Args>
|
||||
shared_ptr<T> make_shared(Args&&... args) {
|
||||
return shared_ptr<T>(::new T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct owner_less;
|
||||
|
||||
template <class T>
|
||||
struct owner_less<shared_ptr<T>>
|
||||
: binary_function<shared_ptr<T>, shared_ptr<T>, bool> {
|
||||
typedef bool result_type;
|
||||
|
||||
bool operator()(shared_ptr<T> const& x, shared_ptr<T> const& y) const {
|
||||
return x.owner_before(y);
|
||||
}
|
||||
|
||||
bool operator()(shared_ptr<T> const& x, weak_ptr<T> const& y) const {
|
||||
return x.owner_before(y);
|
||||
}
|
||||
|
||||
bool operator()(weak_ptr<T> const& x, shared_ptr<T> const& y) const {
|
||||
return x.owner_before(y);
|
||||
}
|
||||
};
|
||||
|
||||
#undef __cast_to_infer_ptr
|
||||
INFER_NAMESPACE_STD_END
|
@ -1,473 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <infer_model/common.h>
|
||||
#include <infer_model/infer_traits.h>
|
||||
|
||||
INFER_NAMESPACE_STD_BEGIN
|
||||
|
||||
// IMPORTANT
|
||||
// There is specialization of unique_ptr below and it's mosly copy paste.
|
||||
// When changing model, remember to change it for specialization as well!
|
||||
template <class _Tp, class _Dp = default_delete<_Tp>>
|
||||
struct unique_ptr {
|
||||
|
||||
// use SFINAE to determine whether _Del::pointer exists
|
||||
class _Pointer {
|
||||
template <typename _Up>
|
||||
static typename _Up::pointer __test(typename _Up::pointer*);
|
||||
|
||||
template <typename _Up>
|
||||
static _Tp* __test(...);
|
||||
|
||||
typedef typename remove_reference<_Dp>::type _Del;
|
||||
|
||||
public:
|
||||
typedef decltype(__test<_Del>(0)) type;
|
||||
};
|
||||
|
||||
public:
|
||||
typedef typename _Pointer::type pointer;
|
||||
typedef _Tp element_type;
|
||||
typedef _Dp deleter_type;
|
||||
|
||||
private:
|
||||
/* std::unique_ptr<T> in infer is translated as T*
|
||||
Look at model of std::shared_ptr for more details */
|
||||
|
||||
// translate shared_ptr as type 'pointer'
|
||||
friend class infer_traits::TranslateAsType<pointer>;
|
||||
|
||||
/// type of 'this' in unique_ptr<T> as seen by infer
|
||||
typedef const void** infer_unique_ptr_t;
|
||||
// use it to avoid compilation errors and make infer analyzer happy
|
||||
#define __cast_to_infer_ptr(self) ((infer_unique_ptr_t)self)
|
||||
|
||||
// provide overload for volatile void* to accommodate for situation when
|
||||
// T is volatile ('volatile int' for example). 'void*' and 'nullptr_t'
|
||||
// overloads are to avoid 'call to model_set is ambiguous' compilation errors
|
||||
static void model_set(infer_unique_ptr_t self, nullptr_t value) noexcept {
|
||||
*self = value;
|
||||
}
|
||||
|
||||
static void model_set(infer_unique_ptr_t self, const void* value) noexcept {
|
||||
*self = value;
|
||||
}
|
||||
|
||||
static void model_set(infer_unique_ptr_t self,
|
||||
volatile void* value) noexcept {
|
||||
*self = const_cast<const void*>(value);
|
||||
}
|
||||
|
||||
static void model_set(infer_unique_ptr_t self, void* value) noexcept {
|
||||
*self = const_cast<const void*>(value);
|
||||
}
|
||||
|
||||
// in case 'pointer' type is not type pointer, enable catch all overload of
|
||||
// `model_set` to prevent compliation issues
|
||||
static void model_set(...) noexcept { /* no model for this overload */
|
||||
}
|
||||
|
||||
static void model_move(infer_unique_ptr_t self,
|
||||
infer_unique_ptr_t other) noexcept {
|
||||
*self = *other;
|
||||
model_set(other, nullptr);
|
||||
}
|
||||
|
||||
static void model_swap(infer_unique_ptr_t infer_self,
|
||||
infer_unique_ptr_t infer_other) noexcept {
|
||||
const void* t = *infer_self;
|
||||
*infer_self = *infer_other;
|
||||
*infer_other = t;
|
||||
}
|
||||
|
||||
pointer __ignore__; // used to keep sizeof(unique_ptr) same as in standard
|
||||
|
||||
public:
|
||||
template <class Y>
|
||||
unique_ptr(const std__unique_ptr<Y>& u) {}
|
||||
|
||||
constexpr unique_ptr() noexcept {
|
||||
model_set(__cast_to_infer_ptr(this), nullptr);
|
||||
}
|
||||
|
||||
constexpr unique_ptr(nullptr_t) noexcept : unique_ptr<_Tp, _Dp>() {}
|
||||
|
||||
explicit unique_ptr(pointer ptr) noexcept {
|
||||
model_set(__cast_to_infer_ptr(this), ptr);
|
||||
}
|
||||
|
||||
unique_ptr(pointer ptr,
|
||||
typename conditional<
|
||||
is_reference<deleter_type>::value,
|
||||
deleter_type,
|
||||
typename add_lvalue_reference<const deleter_type>::type>::type
|
||||
__d) noexcept
|
||||
: unique_ptr<_Tp, _Dp>(ptr) {}
|
||||
|
||||
unique_ptr(pointer ptr,
|
||||
typename remove_reference<deleter_type>::type&& __d) noexcept
|
||||
: unique_ptr<_Tp, _Dp>(ptr) {}
|
||||
|
||||
unique_ptr(unique_ptr&& u) noexcept {
|
||||
model_move(__cast_to_infer_ptr(this), __cast_to_infer_ptr(&u));
|
||||
}
|
||||
|
||||
template <class _Up,
|
||||
class _Ep,
|
||||
typename = typename enable_if<
|
||||
!is_array<_Up>::value &&
|
||||
is_convertible<typename unique_ptr<_Up, _Ep>::pointer,
|
||||
pointer>::value &&
|
||||
is_convertible<_Ep, deleter_type>::value &&
|
||||
(!is_reference<deleter_type>::value ||
|
||||
is_same<deleter_type, _Ep>::value)>::type>
|
||||
unique_ptr(unique_ptr<_Up, _Ep>&& u) noexcept {
|
||||
model_move(__cast_to_infer_ptr(this), __cast_to_infer_ptr(&u));
|
||||
}
|
||||
|
||||
template <
|
||||
class _Up,
|
||||
typename = typename enable_if<is_convertible<_Up*, _Tp*>::value>::type>
|
||||
unique_ptr(auto_ptr<_Up>&& __p) noexcept;
|
||||
|
||||
~unique_ptr() { reset(); }
|
||||
|
||||
unique_ptr& operator=(unique_ptr&& __u) noexcept {
|
||||
model_move(__cast_to_infer_ptr(this), __cast_to_infer_ptr(&__u));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class _Up,
|
||||
class _Ep,
|
||||
typename = typename enable_if<
|
||||
!is_array<_Up>::value &&
|
||||
is_convertible<typename unique_ptr<_Up, _Ep>::pointer,
|
||||
pointer>::value &&
|
||||
is_assignable<deleter_type&, _Ep&&>::value>::type>
|
||||
unique_ptr& operator=(unique_ptr<_Up, _Ep>&& __u) noexcept {
|
||||
model_move(__cast_to_infer_ptr(this), __cast_to_infer_ptr(&__u));
|
||||
return *this;
|
||||
}
|
||||
|
||||
unique_ptr& operator=(nullptr_t) noexcept {
|
||||
reset();
|
||||
return *this;
|
||||
}
|
||||
typename add_lvalue_reference<_Tp>::type operator*() const
|
||||
INFER_MODEL_AS_DEREF_FIRST_ARG;
|
||||
|
||||
pointer operator->() const INFER_MODEL_AS_DEREF_FIRST_ARG;
|
||||
|
||||
pointer get() const INFER_MODEL_AS_DEREF_FIRST_ARG;
|
||||
|
||||
typedef typename remove_reference<deleter_type>::type& _Dp_reference;
|
||||
typedef const typename remove_reference<deleter_type>::type&
|
||||
_Dp_const_reference;
|
||||
_Dp_const_reference get_deleter() const {}
|
||||
_Dp_reference get_deleter() {}
|
||||
|
||||
explicit operator bool() const {
|
||||
return !!(bool)(*__cast_to_infer_ptr(this));
|
||||
}
|
||||
pointer release() INFER_MODEL_AS_DEREF_FIRST_ARG;
|
||||
|
||||
void reset(pointer p = nullptr) { model_set(__cast_to_infer_ptr(this), p); }
|
||||
|
||||
void swap(unique_ptr& u) {
|
||||
model_swap(__cast_to_infer_ptr(this), __cast_to_infer_ptr(&u));
|
||||
}
|
||||
};
|
||||
|
||||
template <class _Tp, class _Dp>
|
||||
struct unique_ptr<_Tp[], _Dp> {
|
||||
// use SFINAE to determine whether _Del::pointer exists
|
||||
class _Pointer {
|
||||
template <typename _Up>
|
||||
static typename _Up::pointer __test(typename _Up::pointer*);
|
||||
|
||||
template <typename _Up>
|
||||
static _Tp* __test(...);
|
||||
|
||||
typedef typename remove_reference<_Dp>::type _Del;
|
||||
|
||||
public:
|
||||
typedef decltype(__test<_Del>(0)) type;
|
||||
};
|
||||
|
||||
public:
|
||||
typedef typename _Pointer::type pointer;
|
||||
typedef _Tp element_type;
|
||||
typedef _Dp deleter_type;
|
||||
|
||||
private:
|
||||
// translate shared_ptr as type pointer
|
||||
friend class infer_traits::TranslateAsType<pointer>;
|
||||
|
||||
/// type of 'this' in unique_ptr<T> as seen by infer
|
||||
typedef const void** infer_unique_ptr_t;
|
||||
// use it to avoid compilation errors and make infer analyzer happy
|
||||
#define __cast_to_infer_ptr(self) ((infer_unique_ptr_t)self)
|
||||
|
||||
static void model_set(infer_unique_ptr_t self, const void* value) noexcept {
|
||||
*self = value;
|
||||
}
|
||||
|
||||
// in case 'pointer' type is not type pointer, enable catch all overload of
|
||||
// `model_set` to prevent compliation issues
|
||||
static void model_set(...) noexcept { /* no model for this overload */
|
||||
}
|
||||
|
||||
static void model_move(infer_unique_ptr_t self,
|
||||
infer_unique_ptr_t other) noexcept {
|
||||
*self = *other;
|
||||
model_set(other, nullptr);
|
||||
}
|
||||
|
||||
static void model_swap(infer_unique_ptr_t infer_self,
|
||||
infer_unique_ptr_t infer_other) noexcept {
|
||||
const void* t = *infer_self;
|
||||
*infer_self = *infer_other;
|
||||
*infer_other = t;
|
||||
}
|
||||
|
||||
pointer __ignore__; // used to keep sizeof(unique_ptr) same as in standard
|
||||
|
||||
public:
|
||||
constexpr unique_ptr() noexcept {
|
||||
model_set(__cast_to_infer_ptr(this), nullptr);
|
||||
}
|
||||
|
||||
constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() {}
|
||||
|
||||
explicit unique_ptr(pointer ptr) noexcept {
|
||||
model_set(__cast_to_infer_ptr(this), ptr);
|
||||
}
|
||||
|
||||
unique_ptr(pointer ptr,
|
||||
typename conditional<
|
||||
is_reference<deleter_type>::value,
|
||||
deleter_type,
|
||||
typename add_lvalue_reference<const deleter_type>::type>::type
|
||||
__d) noexcept
|
||||
: unique_ptr(ptr) {}
|
||||
|
||||
unique_ptr(pointer ptr,
|
||||
typename remove_reference<deleter_type>::type&& __d) noexcept
|
||||
: unique_ptr(ptr) {}
|
||||
|
||||
unique_ptr(unique_ptr&& u) noexcept {
|
||||
model_move(__cast_to_infer_ptr(this), __cast_to_infer_ptr(&u));
|
||||
}
|
||||
|
||||
template <class _Up,
|
||||
class _Ep,
|
||||
typename = typename enable_if<
|
||||
is_array<_Up>::value &&
|
||||
is_convertible<typename unique_ptr<_Up, _Ep>::pointer,
|
||||
pointer>::value &&
|
||||
is_convertible<_Ep, deleter_type>::value &&
|
||||
(!is_reference<deleter_type>::value ||
|
||||
is_same<deleter_type, _Ep>::value)>::type>
|
||||
unique_ptr(unique_ptr<_Up, _Ep>&& u) noexcept {
|
||||
model_move(__cast_to_infer_ptr(this), __cast_to_infer_ptr(&u));
|
||||
}
|
||||
|
||||
template <
|
||||
class _Up,
|
||||
typename = typename enable_if<is_convertible<_Up*, _Tp*>::value>::type>
|
||||
unique_ptr(auto_ptr<_Up>&& __p) noexcept;
|
||||
|
||||
~unique_ptr() { reset(); }
|
||||
|
||||
unique_ptr& operator=(unique_ptr&& __u) noexcept {
|
||||
model_move(__cast_to_infer_ptr(this), __cast_to_infer_ptr(&__u));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class _Up,
|
||||
class _Ep,
|
||||
typename = typename enable_if<
|
||||
is_array<_Up>::value &&
|
||||
is_convertible<typename unique_ptr<_Up, _Ep>::pointer,
|
||||
pointer>::value &&
|
||||
is_assignable<deleter_type&, _Ep&&>::value>::type>
|
||||
unique_ptr& operator=(unique_ptr<_Up, _Ep>&& __u) noexcept {
|
||||
model_move(__cast_to_infer_ptr(this), __cast_to_infer_ptr(&__u));
|
||||
return *this;
|
||||
}
|
||||
|
||||
unique_ptr& operator=(nullptr_t) noexcept {
|
||||
reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
typename add_lvalue_reference<_Tp>::type operator[](size_t i) const
|
||||
INFER_MODEL_AS_DEREF_FIRST_ARG;
|
||||
|
||||
pointer get() const INFER_MODEL_AS_DEREF_FIRST_ARG;
|
||||
typedef typename remove_reference<deleter_type>::type& _Dp_reference;
|
||||
typedef const typename remove_reference<deleter_type>::type&
|
||||
_Dp_const_reference;
|
||||
_Dp_const_reference get_deleter() const {}
|
||||
_Dp_reference get_deleter() {}
|
||||
|
||||
explicit operator bool() const {
|
||||
return !!(bool)(*__cast_to_infer_ptr(this));
|
||||
}
|
||||
pointer release() INFER_MODEL_AS_DEREF_FIRST_ARG;
|
||||
|
||||
void reset(pointer p = nullptr) { model_set(__cast_to_infer_ptr(this), p); }
|
||||
|
||||
void swap(unique_ptr& u) {
|
||||
model_swap(__cast_to_infer_ptr(this), __cast_to_infer_ptr(&u));
|
||||
}
|
||||
};
|
||||
|
||||
template <class _T1, class _D1, class _T2, class _D2>
|
||||
inline bool operator==(const unique_ptr<_T1, _D1>& __x,
|
||||
const unique_ptr<_T2, _D2>& __y) {
|
||||
return __x.get() == __y.get();
|
||||
}
|
||||
|
||||
template <class _T1, class _D1, class _T2, class _D2>
|
||||
inline bool operator!=(const unique_ptr<_T1, _D1>& __x,
|
||||
const unique_ptr<_T2, _D2>& __y) {
|
||||
return !(__x == __y);
|
||||
}
|
||||
|
||||
template <class _T1, class _D1, class _T2, class _D2>
|
||||
inline bool operator<(const unique_ptr<_T1, _D1>& __x,
|
||||
const unique_ptr<_T2, _D2>& __y) {
|
||||
/*typedef typename unique_ptr<_T1, _D1>::pointer _P1;
|
||||
typedef typename unique_ptr<_T2, _D2>::pointer _P2;
|
||||
typedef typename common_type<_P1, _P2>::type _Vp;
|
||||
return less<_Vp>()(__x.get(), __y.get());*/
|
||||
}
|
||||
|
||||
template <class _T1, class _D1, class _T2, class _D2>
|
||||
inline bool operator>(const unique_ptr<_T1, _D1>& __x,
|
||||
const unique_ptr<_T2, _D2>& __y) {
|
||||
return __y < __x;
|
||||
}
|
||||
|
||||
template <class _T1, class _D1, class _T2, class _D2>
|
||||
inline bool operator<=(const unique_ptr<_T1, _D1>& __x,
|
||||
const unique_ptr<_T2, _D2>& __y) {
|
||||
return !(__y < __x);
|
||||
}
|
||||
|
||||
template <class _T1, class _D1, class _T2, class _D2>
|
||||
inline bool operator>=(const unique_ptr<_T1, _D1>& __x,
|
||||
const unique_ptr<_T2, _D2>& __y) {
|
||||
return !(__x < __y);
|
||||
}
|
||||
|
||||
template <class _T1, class _D1>
|
||||
inline bool operator==(const unique_ptr<_T1, _D1>& __x, nullptr_t) {
|
||||
return !__x;
|
||||
}
|
||||
|
||||
template <class _T1, class _D1>
|
||||
inline bool operator==(nullptr_t, const unique_ptr<_T1, _D1>& __x) {
|
||||
return !__x;
|
||||
}
|
||||
|
||||
template <class _T1, class _D1>
|
||||
inline bool operator!=(const unique_ptr<_T1, _D1>& __x, nullptr_t) {
|
||||
return static_cast<bool>(__x);
|
||||
}
|
||||
|
||||
template <class _T1, class _D1>
|
||||
inline bool operator!=(nullptr_t, const unique_ptr<_T1, _D1>& __x) {
|
||||
return static_cast<bool>(__x);
|
||||
}
|
||||
|
||||
template <class _T1, class _D1>
|
||||
inline bool operator<(const unique_ptr<_T1, _D1>& __x, nullptr_t) {
|
||||
/*typedef typename unique_ptr<_T1, _D1>::pointer _P1;
|
||||
return less<_P1>()(__x.get(), nullptr);*/
|
||||
}
|
||||
|
||||
template <class _T1, class _D1>
|
||||
inline bool operator<(nullptr_t, const unique_ptr<_T1, _D1>& __x) {
|
||||
/*typedef typename unique_ptr<_T1, _D1>::pointer _P1;
|
||||
return less<_P1>()(nullptr, __x.get());*/
|
||||
}
|
||||
|
||||
template <class _T1, class _D1>
|
||||
inline bool operator>(const unique_ptr<_T1, _D1>& __x, nullptr_t) {
|
||||
return nullptr < __x;
|
||||
}
|
||||
|
||||
template <class _T1, class _D1>
|
||||
inline bool operator>(nullptr_t, const unique_ptr<_T1, _D1>& __x) {
|
||||
return __x < nullptr;
|
||||
}
|
||||
|
||||
template <class _T1, class _D1>
|
||||
inline bool operator<=(const unique_ptr<_T1, _D1>& __x, nullptr_t) {
|
||||
return !(nullptr < __x);
|
||||
}
|
||||
|
||||
template <class _T1, class _D1>
|
||||
inline bool operator<=(nullptr_t, const unique_ptr<_T1, _D1>& __x) {
|
||||
return !(__x < nullptr);
|
||||
}
|
||||
|
||||
template <class _T1, class _D1>
|
||||
inline bool operator>=(const unique_ptr<_T1, _D1>& __x, nullptr_t) {
|
||||
return !(__x < nullptr);
|
||||
}
|
||||
|
||||
template <class _T1, class _D1>
|
||||
inline bool operator>=(nullptr_t, const unique_ptr<_T1, _D1>& __x) {
|
||||
return !(nullptr < __x);
|
||||
}
|
||||
|
||||
template <class T, class D>
|
||||
struct hash<unique_ptr<T, D>> : public hash<std__unique_ptr<T, D>> {
|
||||
size_t operator()(const unique_ptr<T, D>& __u) const noexcept {}
|
||||
};
|
||||
|
||||
template <typename _Tp>
|
||||
struct _MakeUniq2 {
|
||||
typedef unique_ptr<_Tp> __single_object;
|
||||
};
|
||||
|
||||
template <typename _Tp>
|
||||
struct _MakeUniq2<_Tp[]> {
|
||||
typedef unique_ptr<_Tp[]> __array;
|
||||
};
|
||||
|
||||
template <typename _Tp, size_t _Bound>
|
||||
struct _MakeUniq2<_Tp[_Bound]> {
|
||||
struct __invalid_type {};
|
||||
};
|
||||
|
||||
/// std::make_unique for single objects
|
||||
template <typename _Tp, typename... _Args>
|
||||
inline typename _MakeUniq2<_Tp>::__single_object make_unique(
|
||||
_Args&&... __args) {
|
||||
return unique_ptr<_Tp>(::new _Tp(std::forward<_Args>(__args)...));
|
||||
}
|
||||
|
||||
/// std::make_unique for arrays of unknown bound
|
||||
template <typename _Tp>
|
||||
inline typename _MakeUniq2<_Tp>::__array make_unique(size_t __num) {
|
||||
return unique_ptr<_Tp>(::new typename remove_extent<_Tp>::type[__num]());
|
||||
}
|
||||
|
||||
/// Disable std::make_unique for arrays of known bound
|
||||
template <typename _Tp, typename... _Args>
|
||||
inline typename _MakeUniq2<_Tp>::__invalid_type make_unique(_Args&&...) =
|
||||
delete;
|
||||
INFER_NAMESPACE_STD_END
|
||||
|
||||
#undef __cast_to_infer_ptr
|
@ -1,650 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
#include <climits>
|
||||
#include <limits>
|
||||
#include <initializer_list>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
#include <infer_model/common.h>
|
||||
#include <infer_model/infer_traits.h>
|
||||
|
||||
#ifdef INFER_USE_LIBCPP
|
||||
// libc++ vector header includes it, but it breaks
|
||||
// compilation with stdlibc++ implementation
|
||||
#include <algorithm>
|
||||
#endif
|
||||
|
||||
INFER_NAMESPACE_STD_BEGIN
|
||||
|
||||
struct bool_ref {
|
||||
bool_ref& operator=(bool x) {}
|
||||
bool_ref& operator=(const bool_ref& x) {}
|
||||
|
||||
operator bool() const noexcept {}
|
||||
void flip() noexcept {}
|
||||
|
||||
// not part of C++ std, but required for model implementation to compile
|
||||
explicit bool_ref(bool x) {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct vector_ref {
|
||||
typedef T& ref;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct vector_ref<bool> {
|
||||
typedef bool_ref ref;
|
||||
};
|
||||
|
||||
int __infer_skip__get_int_val();
|
||||
|
||||
// this function will be treated as SKIP by infer
|
||||
template <class T>
|
||||
T* __infer_skip__get_nondet_val() {}
|
||||
|
||||
template <class T>
|
||||
void __infer_deref_first_arg(T* ptr) INFER_MODEL_AS_DEREF_FIRST_ARG;
|
||||
|
||||
#define INFER_EXCLUDE_CONDITION(cond) \
|
||||
if (cond) \
|
||||
while (1)
|
||||
|
||||
// WARNING: do not add any new fields to std::vector model. sizeof(std::vector)
|
||||
// = 24 !!
|
||||
#ifdef INFER_USE_LIBCPP
|
||||
// if using libcpp, then this template will have already a default _Allocator
|
||||
// set (see include/c++/v1/iosfwd, where vector's declaration has a template
|
||||
// with a default allocator<_Tp>, like the commented section below)
|
||||
template <class _Tp, class _Allocator /* = allocator<_Tp> */>
|
||||
#else
|
||||
template <class _Tp, class _Allocator = allocator<_Tp>>
|
||||
#endif
|
||||
class vector {
|
||||
|
||||
public:
|
||||
typedef vector __self;
|
||||
typedef _Tp value_type;
|
||||
typedef _Allocator allocator_type;
|
||||
typedef allocator_traits<allocator_type> __alloc_traits;
|
||||
typedef typename vector_ref<value_type>::ref reference;
|
||||
typedef const value_type& const_reference;
|
||||
typedef typename __alloc_traits::size_type size_type;
|
||||
typedef typename __alloc_traits::difference_type difference_type;
|
||||
typedef typename __alloc_traits::pointer pointer;
|
||||
typedef typename __alloc_traits::const_pointer const_pointer;
|
||||
|
||||
typedef STD_ITER(pointer, vector) iterator;
|
||||
typedef STD_ITER(const_pointer, vector) const_iterator;
|
||||
typedef std::reverse_iterator<iterator> reverse_iterator;
|
||||
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||
|
||||
/* INFER SPECIFIC HELPER FUNCTIONS */
|
||||
|
||||
// required to keep sizeof(std::vector) same as in standard
|
||||
value_type* beginPtr = nullptr;
|
||||
value_type* endPtr = nullptr;
|
||||
value_type* __ignore;
|
||||
|
||||
value_type* _get_begin() const {
|
||||
// we have to resort to that hack so that infer can truly dereference
|
||||
// beginPtr.
|
||||
// Another way to model that would be 'auto tmp = *beginPtr' but that will
|
||||
// trigger copy constructor that may not exist for value_type
|
||||
__infer_deref_first_arg(beginPtr);
|
||||
return beginPtr;
|
||||
}
|
||||
|
||||
value_type* _get_end() const {
|
||||
__infer_deref_first_arg(beginPtr);
|
||||
__infer_deref_first_arg(endPtr);
|
||||
return endPtr;
|
||||
}
|
||||
|
||||
value_type* _get_index(size_type __n) const {
|
||||
__infer_deref_first_arg(beginPtr);
|
||||
return __infer_skip__get_nondet_val<value_type>();
|
||||
}
|
||||
|
||||
void allocate(size_type size) {
|
||||
// assume that allocation will produce non-empty vector regardless of the
|
||||
// size
|
||||
// if (size > 0) {
|
||||
beginPtr = __infer_skip__get_nondet_val<value_type>();
|
||||
endPtr = __infer_skip__get_nondet_val<value_type>();
|
||||
//} else {
|
||||
// deallocate();
|
||||
//}
|
||||
}
|
||||
|
||||
void deallocate() { beginPtr = nullptr; }
|
||||
|
||||
template <class Iter>
|
||||
void allocate_iter(Iter begin, Iter end) {
|
||||
// very simplified implementation to avoid false positives
|
||||
allocate(1);
|
||||
// infer doesn't understand iterators well which leads to skip functions
|
||||
// they in effect lead to false positives in situations when empty vector
|
||||
// is impossible. Implemenatation should look like this:
|
||||
/*if (begin != end) {
|
||||
allocate(1);
|
||||
} else {
|
||||
deallocate();
|
||||
}*/
|
||||
}
|
||||
|
||||
/* std::vector implementation */
|
||||
|
||||
vector() noexcept(is_nothrow_default_constructible<allocator_type>::value) {
|
||||
deallocate();
|
||||
}
|
||||
|
||||
explicit vector(const allocator_type& __a) noexcept { deallocate(); }
|
||||
|
||||
explicit vector(size_type __n);
|
||||
// introduced in C++14
|
||||
explicit vector(size_type __n, const allocator_type& __a);
|
||||
vector(size_type __n, const_reference __x);
|
||||
vector(size_type __n, const_reference __x, const allocator_type& __a);
|
||||
template <class _ForwardIterator>
|
||||
vector(_ForwardIterator __first,
|
||||
typename enable_if<
|
||||
is_constructible<
|
||||
value_type,
|
||||
typename iterator_traits<_ForwardIterator>::reference>::value,
|
||||
_ForwardIterator>::type __last);
|
||||
template <class _ForwardIterator>
|
||||
vector(_ForwardIterator __first,
|
||||
_ForwardIterator __last,
|
||||
const allocator_type& __a,
|
||||
typename enable_if<is_constructible<
|
||||
value_type,
|
||||
typename iterator_traits<_ForwardIterator>::reference>::value>::
|
||||
type* = 0);
|
||||
|
||||
vector(initializer_list<value_type> __il);
|
||||
|
||||
vector(initializer_list<value_type> __il, const allocator_type& __a);
|
||||
|
||||
vector(const vector& __x);
|
||||
vector(const vector& __x, const allocator_type& __a);
|
||||
|
||||
vector& operator=(const vector& __x);
|
||||
|
||||
vector(vector&& __x) noexcept;
|
||||
|
||||
vector(vector&& __x, const allocator_type& __a);
|
||||
|
||||
vector& operator=(vector&& __x) noexcept;
|
||||
/*((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value)); */
|
||||
|
||||
vector& operator=(initializer_list<value_type> __il) {
|
||||
assign(__il.begin(), __il.end());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class _ForwardIterator>
|
||||
typename enable_if<is_constructible<value_type,
|
||||
typename iterator_traits<
|
||||
_ForwardIterator>::reference>::value,
|
||||
void>::type
|
||||
assign(_ForwardIterator __first, _ForwardIterator __last);
|
||||
|
||||
void assign(size_type __n, const_reference __u);
|
||||
|
||||
void assign(initializer_list<value_type> __il) {
|
||||
assign(__il.begin(), __il.end());
|
||||
}
|
||||
|
||||
allocator_type get_allocator() const {}
|
||||
|
||||
iterator begin() noexcept;
|
||||
const_iterator begin() const noexcept;
|
||||
iterator end() noexcept;
|
||||
const_iterator end() const noexcept;
|
||||
|
||||
reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
|
||||
|
||||
const_reverse_iterator rbegin() const noexcept {
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
|
||||
reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
|
||||
|
||||
const_reverse_iterator rend() const noexcept {
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
|
||||
const_iterator cbegin() const noexcept { return begin(); }
|
||||
|
||||
const_iterator cend() const noexcept { return end(); }
|
||||
|
||||
const_reverse_iterator crbegin() const noexcept { return rbegin(); }
|
||||
|
||||
const_reverse_iterator crend() const noexcept { return rend(); }
|
||||
|
||||
size_type size() const noexcept {
|
||||
if (empty()) {
|
||||
return 0;
|
||||
}
|
||||
return 10;
|
||||
}
|
||||
|
||||
size_type capacity() const noexcept {}
|
||||
|
||||
bool empty() const noexcept {
|
||||
if (beginPtr == nullptr) {
|
||||
// prune branch where beginPtr is nullptr and endPtr isn't
|
||||
INFER_EXCLUDE_CONDITION(endPtr != nullptr);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
size_type max_size() const noexcept;
|
||||
void reserve(size_type __n);
|
||||
void shrink_to_fit() noexcept;
|
||||
|
||||
reference operator[](size_type __n);
|
||||
const_reference operator[](size_type __n) const;
|
||||
reference at(size_type __n);
|
||||
const_reference at(size_type __n) const;
|
||||
|
||||
reference front() { return (reference)*_get_begin(); }
|
||||
const_reference front() const { return (const_reference)*_get_begin(); }
|
||||
reference back() {
|
||||
size_t last_element = __infer_skip__get_int_val();
|
||||
return (reference)*_get_index(last_element);
|
||||
}
|
||||
const_reference back() const {
|
||||
size_t last_element = __infer_skip__get_int_val();
|
||||
return (const_reference)*_get_index(last_element);
|
||||
}
|
||||
|
||||
value_type* data() noexcept { return _get_begin(); }
|
||||
|
||||
const value_type* data() const noexcept { return _get_begin(); }
|
||||
|
||||
void push_back(const_reference __x);
|
||||
void push_back(value_type&& __x);
|
||||
template <class... _Args>
|
||||
|
||||
void emplace_back(_Args&&... __args);
|
||||
|
||||
void pop_back();
|
||||
|
||||
iterator insert(const_iterator __position, const_reference __x);
|
||||
iterator insert(const_iterator __position, value_type&& __x);
|
||||
template <class... _Args>
|
||||
iterator emplace(const_iterator __position, _Args&&... __args);
|
||||
iterator insert(const_iterator __position,
|
||||
size_type __n,
|
||||
const_reference __x);
|
||||
template <class _ForwardIterator>
|
||||
typename enable_if<is_constructible<value_type,
|
||||
typename iterator_traits<
|
||||
_ForwardIterator>::reference>::value,
|
||||
iterator>::type
|
||||
insert(const_iterator __position,
|
||||
_ForwardIterator __first,
|
||||
_ForwardIterator __last);
|
||||
|
||||
iterator insert(const_iterator __position,
|
||||
initializer_list<value_type> __il) {
|
||||
return insert(__position, __il.begin(), __il.end());
|
||||
}
|
||||
|
||||
iterator erase(const_iterator __position);
|
||||
iterator erase(const_iterator __first, const_iterator __last);
|
||||
|
||||
void clear() noexcept { deallocate(); }
|
||||
|
||||
void resize(size_type __sz);
|
||||
void resize(size_type __sz, const_reference __x);
|
||||
|
||||
// NOTE c++17 adds noexcept
|
||||
void swap(vector&);
|
||||
|
||||
private:
|
||||
iterator __make_iter(pointer __p) noexcept;
|
||||
|
||||
const_iterator __make_iter(const_pointer __p) const noexcept;
|
||||
};
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
typename vector<_Tp, _Allocator>::size_type vector<_Tp, _Allocator>::max_size()
|
||||
const noexcept {}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
vector<_Tp, _Allocator>::vector(size_type __n) {
|
||||
allocate(__n);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
vector<_Tp, _Allocator>::vector(size_type __n, const allocator_type& __a) {
|
||||
allocate(__n);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
vector<_Tp, _Allocator>::vector(size_type __n, const_reference __x) {
|
||||
allocate(__n);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
vector<_Tp, _Allocator>::vector(size_type __n,
|
||||
const_reference __x,
|
||||
const allocator_type& __a) {
|
||||
allocate(__n);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
template <class _ForwardIterator>
|
||||
vector<_Tp, _Allocator>::vector(
|
||||
_ForwardIterator __first,
|
||||
typename enable_if<
|
||||
is_constructible<
|
||||
value_type,
|
||||
typename iterator_traits<_ForwardIterator>::reference>::value,
|
||||
_ForwardIterator>::type __last) {
|
||||
allocate_iter(__first, __last);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
template <class _ForwardIterator>
|
||||
vector<_Tp, _Allocator>::vector(
|
||||
_ForwardIterator __first,
|
||||
_ForwardIterator __last,
|
||||
const allocator_type& __a,
|
||||
typename enable_if<is_constructible<
|
||||
value_type,
|
||||
typename iterator_traits<_ForwardIterator>::reference>::value>::type*) {
|
||||
allocate_iter(__first, __last);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
vector<_Tp, _Allocator>::vector(const vector& __x) {
|
||||
beginPtr = __x.beginPtr;
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
vector<_Tp, _Allocator>::vector(const vector& __x, const allocator_type& __a) {
|
||||
beginPtr = __x.beginPtr;
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline vector<_Tp, _Allocator>::vector(vector&& __x) noexcept {
|
||||
beginPtr = __x.beginPtr;
|
||||
__x.beginPtr = nullptr;
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline vector<_Tp, _Allocator>::vector(vector&& __x,
|
||||
const allocator_type& __a) {
|
||||
beginPtr = __x.beginPtr;
|
||||
__x.beginPtr = nullptr;
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline vector<_Tp, _Allocator>::vector(initializer_list<value_type> __il) {
|
||||
allocate_iter(__il.begin(), __il.end());
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline vector<_Tp, _Allocator>::vector(initializer_list<value_type> __il,
|
||||
const allocator_type& __a) {
|
||||
allocate_iter(__il.begin(), __il.end());
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline vector<_Tp, _Allocator>& vector<_Tp, _Allocator>::operator=(
|
||||
vector&& __x) noexcept /*((__noexcept_move_assign_container<_Allocator,
|
||||
__alloc_traits>::value)) */
|
||||
{
|
||||
beginPtr = __x.beginPtr;
|
||||
__x.beginPtr = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline vector<_Tp, _Allocator>& vector<_Tp, _Allocator>::operator=(
|
||||
const vector& __x) {
|
||||
beginPtr = __x.beginPtr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
template <class _ForwardIterator>
|
||||
typename enable_if<is_constructible<_Tp,
|
||||
typename iterator_traits<
|
||||
_ForwardIterator>::reference>::value,
|
||||
void>::type
|
||||
vector<_Tp, _Allocator>::assign(_ForwardIterator __first,
|
||||
_ForwardIterator __last) {
|
||||
allocate_iter(__first, __last);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
void vector<_Tp, _Allocator>::assign(size_type __n, const_reference __u) {
|
||||
allocate(__n);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline typename vector<_Tp, _Allocator>::iterator
|
||||
vector<_Tp, _Allocator>::__make_iter(pointer __p) noexcept {
|
||||
return iterator(__p);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline typename vector<_Tp, _Allocator>::const_iterator
|
||||
vector<_Tp, _Allocator>::__make_iter(const_pointer __p) const noexcept {
|
||||
return const_iterator(__p);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline typename vector<_Tp, _Allocator>::iterator
|
||||
vector<_Tp, _Allocator>::begin() noexcept {
|
||||
return __make_iter(beginPtr);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline typename vector<_Tp, _Allocator>::const_iterator
|
||||
vector<_Tp, _Allocator>::begin() const noexcept {
|
||||
return __make_iter(beginPtr);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline typename vector<_Tp, _Allocator>::iterator
|
||||
vector<_Tp, _Allocator>::end() noexcept {
|
||||
return __make_iter(endPtr);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline typename vector<_Tp, _Allocator>::const_iterator
|
||||
vector<_Tp, _Allocator>::end() const noexcept {
|
||||
return __make_iter(endPtr);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline typename vector<_Tp, _Allocator>::reference vector<_Tp, _Allocator>::
|
||||
operator[](size_type __n) {
|
||||
return (reference)*_get_index(__n);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline typename vector<_Tp, _Allocator>::const_reference
|
||||
vector<_Tp, _Allocator>::operator[](size_type __n) const {
|
||||
return (const_reference)*_get_index(__n);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
typename vector<_Tp, _Allocator>::reference vector<_Tp, _Allocator>::at(
|
||||
size_type __n) {
|
||||
return (reference)*_get_index(__n);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
typename vector<_Tp, _Allocator>::const_reference vector<_Tp, _Allocator>::at(
|
||||
size_type __n) const {
|
||||
return (const_reference)*_get_index(__n);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
void vector<_Tp, _Allocator>::reserve(size_type __n) {}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
void vector<_Tp, _Allocator>::shrink_to_fit() noexcept {}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline void vector<_Tp, _Allocator>::push_back(const_reference __x) {
|
||||
allocate(1);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline void vector<_Tp, _Allocator>::push_back(value_type&& __x) {
|
||||
allocate(1);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
template <class... _Args>
|
||||
inline void vector<_Tp, _Allocator>::emplace_back(_Args&&... __args) {
|
||||
/* TODO - consider constructing the object
|
||||
__alloc_traits::construct(this->__alloc(),
|
||||
_VSTD::__to_raw_pointer(this->__end_),
|
||||
_VSTD::forward<_Args>(__args)...);
|
||||
*/
|
||||
allocate(1);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline void vector<_Tp, _Allocator>::pop_back() {
|
||||
// dereference the object
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline typename vector<_Tp, _Allocator>::iterator
|
||||
vector<_Tp, _Allocator>::erase(const_iterator __position) {
|
||||
// dereference the object
|
||||
/* TODO return __r;*/
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::erase(
|
||||
const_iterator __first, const_iterator __last) {
|
||||
// dereference the object
|
||||
/* TODO return __r;*/
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::insert(
|
||||
const_iterator __position, const_reference __x) {}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::insert(
|
||||
const_iterator __position, value_type&& __x) {}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
template <class... _Args>
|
||||
typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::emplace(
|
||||
const_iterator __position, _Args&&... __args) {
|
||||
// TODO consider constructing the object
|
||||
allocate(1);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::insert(
|
||||
const_iterator __position, size_type __n, const_reference __x) {
|
||||
if (empty()) {
|
||||
allocate(__n);
|
||||
}
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
template <class _ForwardIterator>
|
||||
typename enable_if<is_constructible<_Tp,
|
||||
typename iterator_traits<
|
||||
_ForwardIterator>::reference>::value,
|
||||
typename vector<_Tp, _Allocator>::iterator>::type
|
||||
vector<_Tp, _Allocator>::insert(const_iterator __position,
|
||||
_ForwardIterator __first,
|
||||
_ForwardIterator __last) {
|
||||
// TODO return __make_iter(__p);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
void vector<_Tp, _Allocator>::resize(size_type __sz) {
|
||||
allocate(__sz);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
void vector<_Tp, _Allocator>::resize(size_type __sz, const_reference __x) {
|
||||
allocate(__sz);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
void vector<_Tp, _Allocator>::swap(vector& __x) {
|
||||
value_type* tmp = __x.beginPtr;
|
||||
__x.beginPtr = beginPtr;
|
||||
beginPtr = tmp;
|
||||
}
|
||||
|
||||
template <class _Allocator>
|
||||
struct hash<vector<bool, _Allocator>>
|
||||
: public unary_function<vector<bool, _Allocator>, size_t> {
|
||||
|
||||
size_t operator()(const vector<bool, _Allocator>& __vec) const noexcept {}
|
||||
};
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline bool operator==(const vector<_Tp, _Allocator>& __x,
|
||||
const vector<_Tp, _Allocator>& __y) {
|
||||
const typename vector<_Tp, _Allocator>::size_type __sz = __x.size();
|
||||
return __sz == __y.size() && equal(__x.begin(), __x.end(), __y.begin());
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline bool operator!=(const vector<_Tp, _Allocator>& __x,
|
||||
const vector<_Tp, _Allocator>& __y) {
|
||||
return !(__x == __y);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline bool operator<(const vector<_Tp, _Allocator>& __x,
|
||||
const vector<_Tp, _Allocator>& __y) {
|
||||
return lexicographical_compare(
|
||||
__x.begin(), __x.end(), __y.begin(), __y.end());
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline bool operator>(const vector<_Tp, _Allocator>& __x,
|
||||
const vector<_Tp, _Allocator>& __y) {
|
||||
return __y < __x;
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline bool operator>=(const vector<_Tp, _Allocator>& __x,
|
||||
const vector<_Tp, _Allocator>& __y) {
|
||||
return !(__x < __y);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline bool operator<=(const vector<_Tp, _Allocator>& __x,
|
||||
const vector<_Tp, _Allocator>& __y) {
|
||||
return !(__y < __x);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline void swap(vector<_Tp, _Allocator>& __x, vector<_Tp, _Allocator>& __y) {
|
||||
__x.swap(__y);
|
||||
}
|
||||
|
||||
INFER_NAMESPACE_STD_END
|
@ -1,612 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
#include <climits>
|
||||
#include <limits>
|
||||
#include <initializer_list>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
#include <infer_model/common.h>
|
||||
#include <infer_model/infer_traits.h>
|
||||
|
||||
#ifdef INFER_USE_LIBCPP
|
||||
// libc++ vector header includes it, but it breaks
|
||||
// compilation with stdlibc++ implementation
|
||||
#include <algorithm>
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
int __inferbo_min(int, int);
|
||||
|
||||
void __inferbo_set_size(void* p, int size);
|
||||
}
|
||||
|
||||
bool __inferbo_empty(int* size) { return 1 - __inferbo_min(*size, 1); }
|
||||
|
||||
INFER_NAMESPACE_STD_BEGIN
|
||||
|
||||
struct bool_ref {
|
||||
bool_ref& operator=(bool x) {}
|
||||
bool_ref& operator=(const bool_ref& x) {}
|
||||
|
||||
operator bool() const noexcept {}
|
||||
void flip() noexcept {}
|
||||
|
||||
// not part of C++ std, but required for model implementation to compile
|
||||
explicit bool_ref(bool x) {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct vector_ref {
|
||||
typedef T& ref;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct vector_ref<bool> {
|
||||
typedef bool_ref ref;
|
||||
};
|
||||
|
||||
// this function will be treated as SKIP by infer
|
||||
template <class T>
|
||||
T* __infer_skip__get_nondet_val() {}
|
||||
|
||||
template <class T>
|
||||
void __infer_deref_first_arg(T* ptr) INFER_MODEL_AS_DEREF_FIRST_ARG;
|
||||
|
||||
// WARNING: do not add any new fields to std::vector model. sizeof(std::vector)
|
||||
// = 24 !!
|
||||
#ifdef INFER_USE_LIBCPP
|
||||
// if using libcpp, then this template will have already a default _Allocator
|
||||
// set (see include/c++/v1/iosfwd, where vector's declaration has a template
|
||||
// with a default allocator<_Tp>, like the commented section below)
|
||||
template <class _Tp, class _Allocator /* = allocator<_Tp> */>
|
||||
#else
|
||||
template <class _Tp, class _Allocator = allocator<_Tp>>
|
||||
#endif
|
||||
class vector {
|
||||
|
||||
public:
|
||||
typedef vector __self;
|
||||
typedef _Tp value_type;
|
||||
typedef _Allocator allocator_type;
|
||||
typedef allocator_traits<allocator_type> __alloc_traits;
|
||||
typedef typename vector_ref<value_type>::ref reference;
|
||||
typedef const value_type& const_reference;
|
||||
typedef typename __alloc_traits::size_type size_type;
|
||||
typedef typename __alloc_traits::difference_type difference_type;
|
||||
typedef typename __alloc_traits::pointer pointer;
|
||||
typedef typename __alloc_traits::const_pointer const_pointer;
|
||||
|
||||
typedef STD_ITER(pointer, vector) iterator;
|
||||
typedef STD_ITER(const_pointer, vector) const_iterator;
|
||||
typedef std::reverse_iterator<iterator> reverse_iterator;
|
||||
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||
|
||||
/* INFER SPECIFIC HELPER FUNCTIONS */
|
||||
|
||||
// required to keep sizeof(std::vector) same as in standard
|
||||
size_type infer_size = 0;
|
||||
void* _ignore1;
|
||||
void* _ignore2;
|
||||
|
||||
void access_at(size_type index) const {
|
||||
int* dummy_array = (int*)malloc(sizeof(int) * infer_size);
|
||||
int x = dummy_array[index];
|
||||
}
|
||||
|
||||
value_type* get() const {
|
||||
value_type* p = (value_type*)malloc(sizeof(value_type));
|
||||
return p;
|
||||
}
|
||||
|
||||
void allocate(size_type __n) { infer_size = __n; }
|
||||
|
||||
void deallocate() { infer_size = 0; }
|
||||
|
||||
template <class Iter>
|
||||
void allocate_iter(Iter begin, Iter end) {
|
||||
allocate(distance(begin, end));
|
||||
}
|
||||
|
||||
/* std::vector implementation */
|
||||
|
||||
vector() noexcept(is_nothrow_default_constructible<allocator_type>::value) {
|
||||
deallocate();
|
||||
}
|
||||
|
||||
explicit vector(const allocator_type& __a) noexcept { deallocate(); }
|
||||
|
||||
explicit vector(size_type __n);
|
||||
// introduced in C++14
|
||||
explicit vector(size_type __n, const allocator_type& __a);
|
||||
vector(size_type __n, const_reference __x);
|
||||
vector(size_type __n, const_reference __x, const allocator_type& __a);
|
||||
template <class _ForwardIterator>
|
||||
vector(_ForwardIterator __first,
|
||||
typename enable_if<
|
||||
is_constructible<
|
||||
value_type,
|
||||
typename iterator_traits<_ForwardIterator>::reference>::value,
|
||||
_ForwardIterator>::type __last);
|
||||
template <class _ForwardIterator>
|
||||
vector(_ForwardIterator __first,
|
||||
_ForwardIterator __last,
|
||||
const allocator_type& __a,
|
||||
typename enable_if<is_constructible<
|
||||
value_type,
|
||||
typename iterator_traits<_ForwardIterator>::reference>::value>::
|
||||
type* = 0);
|
||||
|
||||
vector(initializer_list<value_type> __il);
|
||||
|
||||
vector(initializer_list<value_type> __il, const allocator_type& __a);
|
||||
|
||||
vector(const vector& __x);
|
||||
vector(const vector& __x, const allocator_type& __a);
|
||||
|
||||
vector& operator=(const vector& __x);
|
||||
|
||||
vector(vector&& __x) noexcept;
|
||||
|
||||
vector(vector&& __x, const allocator_type& __a);
|
||||
|
||||
vector& operator=(vector&& __x) noexcept;
|
||||
/*((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value)); */
|
||||
|
||||
vector& operator=(initializer_list<value_type> __il) {
|
||||
assign(__il.begin(), __il.end());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class _ForwardIterator>
|
||||
typename enable_if<is_constructible<value_type,
|
||||
typename iterator_traits<
|
||||
_ForwardIterator>::reference>::value,
|
||||
void>::type
|
||||
assign(_ForwardIterator __first, _ForwardIterator __last);
|
||||
|
||||
void assign(size_type __n, const_reference __u);
|
||||
|
||||
void assign(initializer_list<value_type> __il) {
|
||||
assign(__il.begin(), __il.end());
|
||||
}
|
||||
|
||||
allocator_type get_allocator() const {}
|
||||
|
||||
iterator begin() noexcept;
|
||||
const_iterator begin() const noexcept;
|
||||
iterator end() noexcept;
|
||||
const_iterator end() const noexcept;
|
||||
|
||||
reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
|
||||
|
||||
const_reverse_iterator rbegin() const noexcept {
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
|
||||
reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
|
||||
|
||||
const_reverse_iterator rend() const noexcept {
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
|
||||
const_iterator cbegin() const noexcept { return begin(); }
|
||||
|
||||
const_iterator cend() const noexcept { return end(); }
|
||||
|
||||
const_reverse_iterator crbegin() const noexcept { return rbegin(); }
|
||||
|
||||
const_reverse_iterator crend() const noexcept { return rend(); }
|
||||
|
||||
size_type size() const noexcept { return infer_size; }
|
||||
|
||||
size_type capacity() const noexcept {}
|
||||
|
||||
bool empty() const noexcept { return __inferbo_empty((int*)&infer_size); }
|
||||
size_type max_size() const noexcept;
|
||||
void reserve(size_type __n);
|
||||
void shrink_to_fit() noexcept;
|
||||
|
||||
reference operator[](size_type __n);
|
||||
const_reference operator[](size_type __n) const;
|
||||
reference at(size_type __n);
|
||||
const_reference at(size_type __n) const;
|
||||
|
||||
reference front() { return (reference)*get(); }
|
||||
const_reference front() const { return (const_reference)*get(); }
|
||||
reference back() { return (reference)*get(); }
|
||||
const_reference back() const { return (const_reference)*get(); }
|
||||
|
||||
value_type* data() noexcept {
|
||||
value_type* p = get();
|
||||
__inferbo_set_size((void*)&p, infer_size);
|
||||
return p;
|
||||
}
|
||||
|
||||
const value_type* data() const noexcept {
|
||||
value_type* p = get();
|
||||
__inferbo_set_size((void*)&p, infer_size);
|
||||
return p;
|
||||
}
|
||||
|
||||
void push_back(const_reference __x);
|
||||
void push_back(value_type&& __x);
|
||||
template <class... _Args>
|
||||
|
||||
void emplace_back(_Args&&... __args);
|
||||
|
||||
void pop_back();
|
||||
|
||||
iterator insert(const_iterator __position, const_reference __x);
|
||||
iterator insert(const_iterator __position, value_type&& __x);
|
||||
template <class... _Args>
|
||||
iterator emplace(const_iterator __position, _Args&&... __args);
|
||||
iterator insert(const_iterator __position,
|
||||
size_type __n,
|
||||
const_reference __x);
|
||||
template <class _ForwardIterator>
|
||||
typename enable_if<is_constructible<value_type,
|
||||
typename iterator_traits<
|
||||
_ForwardIterator>::reference>::value,
|
||||
iterator>::type
|
||||
insert(const_iterator __position,
|
||||
_ForwardIterator __first,
|
||||
_ForwardIterator __last);
|
||||
|
||||
iterator insert(const_iterator __position,
|
||||
initializer_list<value_type> __il) {
|
||||
return insert(__position, __il.begin(), __il.end());
|
||||
}
|
||||
|
||||
iterator erase(const_iterator __position);
|
||||
iterator erase(const_iterator __first, const_iterator __last);
|
||||
|
||||
void clear() noexcept { deallocate(); }
|
||||
|
||||
void resize(size_type __sz);
|
||||
void resize(size_type __sz, const_reference __x);
|
||||
|
||||
// NOTE c++17 adds noexcept
|
||||
void swap(vector&);
|
||||
|
||||
private:
|
||||
iterator __make_iter(pointer __p) noexcept;
|
||||
|
||||
const_iterator __make_iter(const_pointer __p) const noexcept;
|
||||
};
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
typename vector<_Tp, _Allocator>::size_type vector<_Tp, _Allocator>::max_size()
|
||||
const noexcept {}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
vector<_Tp, _Allocator>::vector(size_type __n) {
|
||||
allocate(__n);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
vector<_Tp, _Allocator>::vector(size_type __n, const allocator_type& __a) {
|
||||
allocate(__n);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
vector<_Tp, _Allocator>::vector(size_type __n, const_reference __x) {
|
||||
allocate(__n);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
vector<_Tp, _Allocator>::vector(size_type __n,
|
||||
const_reference __x,
|
||||
const allocator_type& __a) {
|
||||
allocate(__n);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
template <class _ForwardIterator>
|
||||
vector<_Tp, _Allocator>::vector(
|
||||
_ForwardIterator __first,
|
||||
typename enable_if<
|
||||
is_constructible<
|
||||
value_type,
|
||||
typename iterator_traits<_ForwardIterator>::reference>::value,
|
||||
_ForwardIterator>::type __last) {
|
||||
allocate_iter(__first, __last);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
template <class _ForwardIterator>
|
||||
vector<_Tp, _Allocator>::vector(
|
||||
_ForwardIterator __first,
|
||||
_ForwardIterator __last,
|
||||
const allocator_type& __a,
|
||||
typename enable_if<is_constructible<
|
||||
value_type,
|
||||
typename iterator_traits<_ForwardIterator>::reference>::value>::type*) {
|
||||
allocate_iter(__first, __last);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
vector<_Tp, _Allocator>::vector(const vector& __x) {
|
||||
allocate(__x.size());
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
vector<_Tp, _Allocator>::vector(const vector& __x, const allocator_type& __a) {
|
||||
allocate(__x.size());
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline vector<_Tp, _Allocator>::vector(vector&& __x) noexcept {
|
||||
allocate(__x.size());
|
||||
__x.clear();
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline vector<_Tp, _Allocator>::vector(vector&& __x,
|
||||
const allocator_type& __a) {
|
||||
allocate(__x.size());
|
||||
__x.clear();
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline vector<_Tp, _Allocator>::vector(initializer_list<value_type> __il) {
|
||||
allocate_iter(__il.begin(), __il.end());
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline vector<_Tp, _Allocator>::vector(initializer_list<value_type> __il,
|
||||
const allocator_type& __a) {
|
||||
allocate_iter(__il.begin(), __il.end());
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline vector<_Tp, _Allocator>& vector<_Tp, _Allocator>::operator=(
|
||||
vector&& __x) noexcept /*((__noexcept_move_assign_container<_Allocator,
|
||||
__alloc_traits>::value)) */
|
||||
{
|
||||
allocate(__x.size());
|
||||
__x.clear();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline vector<_Tp, _Allocator>& vector<_Tp, _Allocator>::operator=(
|
||||
const vector& __x) {
|
||||
allocate(__x.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
template <class _ForwardIterator>
|
||||
typename enable_if<is_constructible<_Tp,
|
||||
typename iterator_traits<
|
||||
_ForwardIterator>::reference>::value,
|
||||
void>::type
|
||||
vector<_Tp, _Allocator>::assign(_ForwardIterator __first,
|
||||
_ForwardIterator __last) {
|
||||
allocate_iter(__first, __last);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
void vector<_Tp, _Allocator>::assign(size_type __n, const_reference __u) {
|
||||
allocate(__n);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline typename vector<_Tp, _Allocator>::iterator
|
||||
vector<_Tp, _Allocator>::__make_iter(pointer __p) noexcept {
|
||||
return iterator(__p);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline typename vector<_Tp, _Allocator>::const_iterator
|
||||
vector<_Tp, _Allocator>::__make_iter(const_pointer __p) const noexcept {
|
||||
return const_iterator(__p);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline typename vector<_Tp, _Allocator>::iterator
|
||||
vector<_Tp, _Allocator>::begin() noexcept {
|
||||
return __make_iter(get());
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline typename vector<_Tp, _Allocator>::const_iterator
|
||||
vector<_Tp, _Allocator>::begin() const noexcept {
|
||||
return __make_iter(get());
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline typename vector<_Tp, _Allocator>::iterator
|
||||
vector<_Tp, _Allocator>::end() noexcept {
|
||||
return __make_iter(get());
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline typename vector<_Tp, _Allocator>::const_iterator
|
||||
vector<_Tp, _Allocator>::end() const noexcept {
|
||||
return __make_iter(get());
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline typename vector<_Tp, _Allocator>::reference vector<_Tp, _Allocator>::
|
||||
operator[](size_type __n) {
|
||||
access_at(__n);
|
||||
return (reference)*get();
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline typename vector<_Tp, _Allocator>::const_reference
|
||||
vector<_Tp, _Allocator>::operator[](size_type __n) const {
|
||||
access_at(__n);
|
||||
return (const_reference)*get();
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
typename vector<_Tp, _Allocator>::reference vector<_Tp, _Allocator>::at(
|
||||
size_type __n) {
|
||||
access_at(__n);
|
||||
return (reference)*get();
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
typename vector<_Tp, _Allocator>::const_reference vector<_Tp, _Allocator>::at(
|
||||
size_type __n) const {
|
||||
access_at(__n);
|
||||
return (const_reference)*get();
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
void vector<_Tp, _Allocator>::reserve(size_type __n) {}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
void vector<_Tp, _Allocator>::shrink_to_fit() noexcept {}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline void vector<_Tp, _Allocator>::push_back(const_reference __x) {
|
||||
infer_size++;
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline void vector<_Tp, _Allocator>::push_back(value_type&& __x) {
|
||||
infer_size++;
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
template <class... _Args>
|
||||
inline void vector<_Tp, _Allocator>::emplace_back(_Args&&... __args) {
|
||||
infer_size++;
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline void vector<_Tp, _Allocator>::pop_back() {
|
||||
infer_size--;
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline typename vector<_Tp, _Allocator>::iterator
|
||||
vector<_Tp, _Allocator>::erase(const_iterator __position) {
|
||||
infer_size--;
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::erase(
|
||||
const_iterator __first, const_iterator __last) {
|
||||
infer_size -= distance(__first, __last);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::insert(
|
||||
const_iterator __position, const_reference __x) {
|
||||
infer_size++;
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::insert(
|
||||
const_iterator __position, value_type&& __x) {
|
||||
infer_size++;
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
template <class... _Args>
|
||||
typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::emplace(
|
||||
const_iterator __position, _Args&&... __args) {
|
||||
infer_size++;
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::insert(
|
||||
const_iterator __position, size_type __n, const_reference __x) {
|
||||
infer_size += __n;
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
template <class _ForwardIterator>
|
||||
typename enable_if<is_constructible<_Tp,
|
||||
typename iterator_traits<
|
||||
_ForwardIterator>::reference>::value,
|
||||
typename vector<_Tp, _Allocator>::iterator>::type
|
||||
vector<_Tp, _Allocator>::insert(const_iterator __position,
|
||||
_ForwardIterator __first,
|
||||
_ForwardIterator __last) {
|
||||
infer_size += distance(__first, __last);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
void vector<_Tp, _Allocator>::resize(size_type __sz) {
|
||||
infer_size = __sz;
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
void vector<_Tp, _Allocator>::resize(size_type __sz, const_reference __x) {
|
||||
infer_size = __sz;
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
void vector<_Tp, _Allocator>::swap(vector& __x) {
|
||||
auto tmp = __x.size();
|
||||
__x.resize(infer_size);
|
||||
infer_size = tmp;
|
||||
}
|
||||
|
||||
template <class _Allocator>
|
||||
struct hash<vector<bool, _Allocator>>
|
||||
: public unary_function<vector<bool, _Allocator>, size_t> {
|
||||
|
||||
size_t operator()(const vector<bool, _Allocator>& __vec) const noexcept {}
|
||||
};
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline bool operator==(const vector<_Tp, _Allocator>& __x,
|
||||
const vector<_Tp, _Allocator>& __y) {
|
||||
const typename vector<_Tp, _Allocator>::size_type __sz = __x.size();
|
||||
return __sz == __y.size() && equal(__x.begin(), __x.end(), __y.begin());
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline bool operator!=(const vector<_Tp, _Allocator>& __x,
|
||||
const vector<_Tp, _Allocator>& __y) {
|
||||
return !(__x == __y);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline bool operator<(const vector<_Tp, _Allocator>& __x,
|
||||
const vector<_Tp, _Allocator>& __y) {
|
||||
return lexicographical_compare(
|
||||
__x.begin(), __x.end(), __y.begin(), __y.end());
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline bool operator>(const vector<_Tp, _Allocator>& __x,
|
||||
const vector<_Tp, _Allocator>& __y) {
|
||||
return __y < __x;
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline bool operator>=(const vector<_Tp, _Allocator>& __x,
|
||||
const vector<_Tp, _Allocator>& __y) {
|
||||
return !(__x < __y);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline bool operator<=(const vector<_Tp, _Allocator>& __x,
|
||||
const vector<_Tp, _Allocator>& __y) {
|
||||
return !(__y < __x);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline void swap(vector<_Tp, _Allocator>& __x, vector<_Tp, _Allocator>& __y) {
|
||||
__x.swap(__y);
|
||||
}
|
||||
|
||||
INFER_NAMESPACE_STD_END
|
@ -1,174 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <infer_model/common.h>
|
||||
#include <infer_model/infer_traits.h>
|
||||
|
||||
unsigned long int __infer_nondet_unsigned_long_int();
|
||||
|
||||
INFER_NAMESPACE_STD_BEGIN
|
||||
|
||||
// forward declaration because it is used here
|
||||
template <class T>
|
||||
class shared_ptr;
|
||||
|
||||
// Ideally: : public std__weak_ptr<T>
|
||||
// use inheritance to avoid compilation errors when using
|
||||
// methods / non-member functions that are not modeled
|
||||
// Currently not inherited because it leads to Symexec_memory_error
|
||||
|
||||
template <class T>
|
||||
class weak_ptr {
|
||||
|
||||
template <class>
|
||||
friend class weak_ptr;
|
||||
|
||||
// WARNING: if sizeof(weak_ptr) becomes different than 16, it may
|
||||
// lead to compilation errors
|
||||
T* ptr;
|
||||
void* __ignore;
|
||||
|
||||
public:
|
||||
// Conversion constructors to allow implicit conversions.
|
||||
// it's here purely to avoid compilation errors
|
||||
template <class Y,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
weak_ptr(const std__weak_ptr<Y>& r) {}
|
||||
|
||||
// constructors:
|
||||
constexpr weak_ptr() noexcept { ptr = nullptr; }
|
||||
|
||||
template <class Y,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
weak_ptr(const shared_ptr<Y>& r) noexcept {
|
||||
ptr = r.get();
|
||||
}
|
||||
|
||||
weak_ptr(const weak_ptr& r) noexcept { ptr = r.ptr; }
|
||||
|
||||
template <class Y,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
weak_ptr(const weak_ptr<Y>& r) noexcept {
|
||||
ptr = r.ptr;
|
||||
}
|
||||
|
||||
weak_ptr(weak_ptr&& r) noexcept {
|
||||
ptr = r.ptr;
|
||||
r.ptr = nullptr;
|
||||
}
|
||||
|
||||
template <class Y,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
weak_ptr(weak_ptr<Y>&& r) noexcept {
|
||||
ptr = r.ptr;
|
||||
r.ptr = nullptr;
|
||||
}
|
||||
|
||||
// destructor:
|
||||
~weak_ptr() { ptr = nullptr; }
|
||||
|
||||
// assignment:
|
||||
weak_ptr& operator=(const weak_ptr& r) noexcept {
|
||||
// weak_ptr<T>(r).swap(*this);
|
||||
ptr = r.ptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Y,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
weak_ptr& operator=(const weak_ptr<Y>& r) noexcept {
|
||||
// weak_ptr<T>(r).swap(*this);
|
||||
ptr = r.ptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Y,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
weak_ptr& operator=(const shared_ptr<Y>& r) noexcept {
|
||||
// weak_ptr<T>(r).swap(*this);
|
||||
ptr = r.get();
|
||||
return *this;
|
||||
}
|
||||
|
||||
weak_ptr& operator=(weak_ptr&& r) noexcept {
|
||||
// shared_ptr<T>(std::move(r)).swap(*this);
|
||||
ptr = r.ptr;
|
||||
r.ptr = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Y,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
weak_ptr& operator=(weak_ptr<Y>&& r) {
|
||||
// weak_ptr<T>(std::move(r)).swap(*this);
|
||||
ptr = r.ptr;
|
||||
r.ptr = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// modifiers:
|
||||
void swap(weak_ptr& r) noexcept {
|
||||
T* tmp = ptr;
|
||||
ptr = r.ptr;
|
||||
r.ptr = tmp;
|
||||
}
|
||||
|
||||
void reset() noexcept {
|
||||
// weak_ptr().swap(*this);
|
||||
ptr = nullptr;
|
||||
}
|
||||
|
||||
// observers:
|
||||
long use_count() const noexcept {
|
||||
if (ptr) {
|
||||
return __infer_nondet_unsigned_long_int();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool expired() const noexcept { return use_count() <= 0; }
|
||||
|
||||
shared_ptr<T> lock() const noexcept {
|
||||
if (use_count() > 0) {
|
||||
return shared_ptr<T>(ptr);
|
||||
}
|
||||
return shared_ptr<T>();
|
||||
}
|
||||
|
||||
template <class U>
|
||||
bool owner_before(shared_ptr<U> const& b) const {
|
||||
return true; /* FIXME - use non-det*/
|
||||
}
|
||||
template <class U>
|
||||
bool owner_before(weak_ptr<U> const& b) const {
|
||||
return true; /* FIXME - use non-det */
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct owner_less;
|
||||
|
||||
template <class T>
|
||||
struct owner_less<weak_ptr<T>>
|
||||
: binary_function<weak_ptr<T>, weak_ptr<T>, bool> {
|
||||
typedef bool result_type;
|
||||
bool operator()(weak_ptr<T> const& x, weak_ptr<T> const& y) const {
|
||||
return x.owner_before(y);
|
||||
}
|
||||
|
||||
bool operator()(shared_ptr<T> const& x, weak_ptr<T> const& y) const {
|
||||
return x.owner_before(y);
|
||||
}
|
||||
|
||||
bool operator()(weak_ptr<T> const& x, shared_ptr<T> const& y) const {
|
||||
return x.owner_before(y);
|
||||
}
|
||||
};
|
||||
|
||||
INFER_NAMESPACE_STD_END
|
@ -1,30 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
|
||||
// NOTE this header shouldn't be translated by infer - it's here to disallow
|
||||
// running binaries built with infer headers
|
||||
namespace infer_model {
|
||||
// code compiled with infer headers is not supposed to be executed
|
||||
struct AbortWhenRun {
|
||||
AbortWhenRun() { __infer_skip__(); }
|
||||
// will be skipped by analyzer
|
||||
void __infer_skip__() {
|
||||
fprintf(stderr,
|
||||
"!!! This program must not be run !!!\n"
|
||||
"This code was compiled to be analyzed by Infer.\n"
|
||||
"To run this program, recompile it without Infer.\n");
|
||||
std::abort();
|
||||
}
|
||||
};
|
||||
|
||||
static AbortWhenRun a{};
|
||||
} // namespace infer_model
|
@ -1,7 +0,0 @@
|
||||
#include <infer_model/portability.h>
|
||||
|
||||
#ifdef INFER_CPP11_ON
|
||||
# include <infer_model/iostream.h>
|
||||
#else
|
||||
# include_next <iostream>
|
||||
#endif
|
@ -1,16 +0,0 @@
|
||||
|
||||
#include <infer_model/portability.h>
|
||||
|
||||
#ifdef INFER_CPP11_ON
|
||||
|
||||
#include <infer_model/begin_name_override.inc>
|
||||
#include_next <memory>
|
||||
#include <infer_model/end_name_override.inc>
|
||||
|
||||
#include<infer_model/unique_ptr.h>
|
||||
#include<infer_model/shared_ptr.h>
|
||||
|
||||
#else
|
||||
// don't model memory for pre-C++11 code
|
||||
#include_next <memory>
|
||||
#endif
|
@ -1,17 +0,0 @@
|
||||
#include <infer_model/portability.h>
|
||||
|
||||
#ifdef INFER_CPP11_ON
|
||||
|
||||
#ifdef __INFER_BUFFEROVERRUN
|
||||
// Separate model for bufferoverrun checker
|
||||
// TODO t17807570: move to a separate directory
|
||||
#include<infer_model/vector_bufferoverrun.h>
|
||||
#else
|
||||
#include<infer_model/vector.h>
|
||||
#endif
|
||||
|
||||
#else
|
||||
// don't model std::vector pre-c++11 to
|
||||
// simplify implementation
|
||||
#include_next <vector>
|
||||
#endif
|
@ -1,11 +0,0 @@
|
||||
/*
|
||||
* 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 <vector>
|
||||
#if defined(_LIBCPP_VECTOR) || defined(_GLIBCXX_VECTOR)
|
||||
#error "infer should use models headers"
|
||||
#endif
|
Loading…
Reference in new issue