mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 22:04:26 +00:00
Fix UB in class NullOr am: cf5d7e83fd am: 24db85e33e
am: 51bbd6719b
Change-Id: I43c73744cb503c2a1e0848d84fdbc57aacf165c4
This commit is contained in:
@@ -280,39 +280,50 @@ inline KeyParameter Authorization(TypedTag<tag_type, tag> ttag, Args&&... args)
|
||||
*/
|
||||
template <typename ValueT>
|
||||
class NullOr {
|
||||
template <typename T>
|
||||
struct reference_initializer {
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wnull-dereference"
|
||||
static T&& init() { return *static_cast<std::remove_reference_t<T>*>(nullptr); }
|
||||
#pragma GCC diagnostic pop
|
||||
};
|
||||
template <typename T>
|
||||
struct pointer_initializer {
|
||||
static T init() { return nullptr; }
|
||||
};
|
||||
template <typename T>
|
||||
struct value_initializer {
|
||||
static T init() { return T(); }
|
||||
};
|
||||
template <typename T>
|
||||
using initializer_t =
|
||||
std::conditional_t<std::is_lvalue_reference<T>::value, reference_initializer<T>,
|
||||
std::conditional_t<std::is_pointer<T>::value, pointer_initializer<T>,
|
||||
value_initializer<T>>>;
|
||||
using internal_t = std::conditional_t<std::is_lvalue_reference<ValueT>::value,
|
||||
std::remove_reference_t<ValueT>*, ValueT>;
|
||||
|
||||
public:
|
||||
NullOr() : value_(initializer_t<ValueT>::init()), null_(true) {}
|
||||
NullOr(ValueT&& value) : value_(std::forward<ValueT>(value)), null_(false) {}
|
||||
struct pointer_initializer {
|
||||
static std::nullptr_t init() { return nullptr; }
|
||||
};
|
||||
struct value_initializer {
|
||||
static ValueT init() { return ValueT(); }
|
||||
};
|
||||
struct value_pointer_deref_t {
|
||||
static ValueT& deref(ValueT& v) { return v; }
|
||||
};
|
||||
struct reference_deref_t {
|
||||
static auto& deref(internal_t v) { return *v; }
|
||||
};
|
||||
using initializer_t = std::conditional_t<std::is_lvalue_reference<ValueT>::value ||
|
||||
std::is_pointer<ValueT>::value,
|
||||
pointer_initializer, value_initializer>;
|
||||
using deref_t = std::conditional_t<std::is_lvalue_reference<ValueT>::value, reference_deref_t,
|
||||
value_pointer_deref_t>;
|
||||
|
||||
public:
|
||||
NullOr() : value_(initializer_t::init()), null_(true) {}
|
||||
template <typename T>
|
||||
NullOr(T&& value, typename std::enable_if<
|
||||
!std::is_lvalue_reference<ValueT>::value &&
|
||||
std::is_same<std::decay_t<ValueT>, std::decay_t<T>>::value,
|
||||
int>::type = 0)
|
||||
: value_(std::forward<ValueT>(value)), null_(false) {}
|
||||
template <typename T>
|
||||
NullOr(T& value, typename std::enable_if<
|
||||
std::is_lvalue_reference<ValueT>::value &&
|
||||
std::is_same<std::decay_t<ValueT>, std::decay_t<T>>::value,
|
||||
int>::type = 0)
|
||||
: value_(&value), null_(false) {}
|
||||
|
||||
bool isOk() const { return !null_; }
|
||||
|
||||
const ValueT& value() const & { return value_; }
|
||||
ValueT& value() & { return value_; }
|
||||
ValueT&& value() && { return std::move(value_); }
|
||||
const ValueT& value() const& { return deref_t::deref(value_); }
|
||||
ValueT& value() & { return deref_t::deref(value_); }
|
||||
ValueT&& value() && { return std::move(deref_t::deref(value_)); }
|
||||
|
||||
private:
|
||||
ValueT value_;
|
||||
private:
|
||||
internal_t value_;
|
||||
bool null_;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user