libcamera: controls: Fix strict aliasing violation

gcc 8.3.0 for ARM complains about strict aliasing violations:

../../src/libcamera/controls.cpp: In member function ‘void libcamera::ControlValue::release()’:
../../src/libcamera/controls.cpp:111:13: error: dereferencing type-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing]
   delete[] *reinterpret_cast<char **>(&storage_);

Fix it and simplify the code at the same time.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
This commit is contained in:
Laurent Pinchart 2020-03-07 22:02:35 +02:00
parent 291d4878bb
commit 4de31ccc9e
2 changed files with 14 additions and 11 deletions

View file

@ -160,7 +160,10 @@ private:
ControlType type_ : 8;
bool isArray_ : 1;
std::size_t numElements_ : 16;
uint64_t storage_;
union {
uint64_t value_;
void *storage_;
};
void release();
void set(ControlType type, bool isArray, const void *data,

View file

@ -107,9 +107,9 @@ void ControlValue::release()
{
std::size_t size = numElements_ * ControlValueSize[type_];
if (size > sizeof(storage_)) {
delete[] *reinterpret_cast<char **>(&storage_);
storage_ = 0;
if (size > sizeof(value_)) {
delete[] reinterpret_cast<uint8_t *>(storage_);
storage_ = nullptr;
}
}
@ -176,9 +176,9 @@ ControlValue &ControlValue::operator=(const ControlValue &other)
Span<const uint8_t> ControlValue::data() const
{
std::size_t size = numElements_ * ControlValueSize[type_];
const uint8_t *data = size > sizeof(storage_)
? *reinterpret_cast<const uint8_t * const *>(&storage_)
: reinterpret_cast<const uint8_t *>(&storage_);
const uint8_t *data = size > sizeof(value_)
? reinterpret_cast<const uint8_t *>(storage_)
: reinterpret_cast<const uint8_t *>(&value_);
return { data, size };
}
@ -308,11 +308,11 @@ void ControlValue::set(ControlType type, bool isArray, const void *data,
std::size_t size = elementSize * numElements;
void *storage;
if (size > sizeof(storage_)) {
storage = reinterpret_cast<void *>(new char[size]);
*reinterpret_cast<void **>(&storage_) = storage;
if (size > sizeof(value_)) {
storage_ = reinterpret_cast<void *>(new uint8_t[size]);
storage = storage_;
} else {
storage = reinterpret_cast<void *>(&storage_);
storage = reinterpret_cast<void *>(&value_);
}
memcpy(storage, data, size);