Message ID | 20200307212530.28053-3-laurent.pinchart@ideasonboard.com |
---|---|
State | Accepted |
Commit | 4de31ccc9ef47e7b16330d226d071d5d006faa6d |
Headers | show |
Series |
|
Related | show |
Hi Laurent, On 07/03/2020 21:25, Laurent Pinchart wrote: > 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> For either kept separate, or squashed into the other patch that adds this: Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Though I wonder, could the above error also have been resolved with use of a uintptr_t? But the union does seem to make the duality of use more clear to me all the same. > --- > include/libcamera/controls.h | 5 ++++- > src/libcamera/controls.cpp | 20 ++++++++++---------- > 2 files changed, 14 insertions(+), 11 deletions(-) > > diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h > index 4767e2d3fc8c..0e111ab72bce 100644 > --- a/include/libcamera/controls.h > +++ b/include/libcamera/controls.h > @@ -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, > diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp > index 94bdbdd9c388..4326174adf86 100644 > --- a/src/libcamera/controls.cpp > +++ b/src/libcamera/controls.cpp > @@ -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); >
Hi Kieran, On Sat, Mar 07, 2020 at 11:37:21PM +0000, Kieran Bingham wrote: > On 07/03/2020 21:25, Laurent Pinchart wrote: > > 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> > > For either kept separate, or squashed into the other patch that adds this: > > Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> > > Though I wonder, could the above error also have been resolved with use > of a uintptr_t? I don't think so. Strict aliasing means, in a nutshell, that the compiler can assume that pointers to different types do not point to the same memory. There's an exception for char * that can alias anything. The aliasing rules allow for interesting optimisations, but can also create "interesting" behaviour. #include <iostream> void foo(int *i, char *c) { *i = 0x42; c[0] = 0; c[1] = 1; c[2] = 2; c[3] = 3; std::cout << std::hex << *i << std::endl; } void foo(int *i, short *s) { *i = 0x42; s[0] = 0; s[1] = 1; std::cout << std::hex << *i << std::endl; } int main(int argc __attribute__((__unused__)), char *argv[] __attribute__((__unused__))) { int i = 0; short *s = reinterpret_cast<short *>(&i); char *c = reinterpret_cast<char *>(&i); foo(&i, c); foo(&i, s); return 0; } $ g++ -W -Wall -O1 -o aliasing aliasing.cpp $ ./aliasing 3020100 10000 $ g++ -W -Wall -O2 -o aliasing aliasing.cpp $ ./aliasing 3020100 42 clang++ exhibits the same behaviour. No idea why neither prints any warning in the above example though :-S > But the union does seem to make the duality of use more clear to me all > the same. I like the union better too. > > --- > > include/libcamera/controls.h | 5 ++++- > > src/libcamera/controls.cpp | 20 ++++++++++---------- > > 2 files changed, 14 insertions(+), 11 deletions(-) > > > > diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h > > index 4767e2d3fc8c..0e111ab72bce 100644 > > --- a/include/libcamera/controls.h > > +++ b/include/libcamera/controls.h > > @@ -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, > > diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp > > index 94bdbdd9c388..4326174adf86 100644 > > --- a/src/libcamera/controls.cpp > > +++ b/src/libcamera/controls.cpp > > @@ -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);
diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h index 4767e2d3fc8c..0e111ab72bce 100644 --- a/include/libcamera/controls.h +++ b/include/libcamera/controls.h @@ -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, diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp index 94bdbdd9c388..4326174adf86 100644 --- a/src/libcamera/controls.cpp +++ b/src/libcamera/controls.cpp @@ -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);
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> --- include/libcamera/controls.h | 5 ++++- src/libcamera/controls.cpp | 20 ++++++++++---------- 2 files changed, 14 insertions(+), 11 deletions(-)