https://github.com/aseprite/laf/pull/84 From: "Azamat H. Hackimov" Date: Sun, 14 Apr 2024 21:47:02 +0300 Subject: [PATCH] Fix strict-alias warnings reinterpret_cast on pointers break strict-aliasing rule (-Wstrict-aliasing). Implemented internal function copy_reinterpret_cast that memcpy pointer into type, that can be converted to desired type. --- a/laf/base/cfile.cpp +++ b/laf/base/cfile.cpp @@ -7,6 +7,7 @@ #ifdef HAVE_CONFIG_H #include "config.h" #endif +#include "base/mem_utils.h" #include @@ -114,7 +115,7 @@ float fgetf(FILE* file) // Little endian. int v = ((b4 << 24) | (b3 << 16) | (b2 << 8) | b1); - return *reinterpret_cast(&v); + return *copy_reinterpret_cast(&v); } // Reads a 64-bit double-precision floating point number using @@ -156,7 +157,7 @@ double fgetd(FILE* file) ((long long)b3 << 16) | ((long long)b2 << 8) | (long long)b1); - return *reinterpret_cast(&v); + return *copy_reinterpret_cast(&v); } // Writes a word using little-endian byte ordering. @@ -231,7 +232,7 @@ int fputq(long long l, FILE* file) // Returns 0 in success or -1 in error int fputf(float l, FILE* file) { - int b = *(reinterpret_cast(&l)); + int b = *(copy_reinterpret_cast(&l)); int b1, b2, b3, b4; // Little endian. @@ -254,7 +255,7 @@ int fputf(float l, FILE* file) // Returns 0 in success or -1 in error int fputd(double l, FILE* file) { - long long b = *(reinterpret_cast(&l)); + long long b = *(copy_reinterpret_cast(&l)); int b1, b2, b3, b4, b5, b6, b7, b8; // Little endian. --- a/laf/base/mem_utils.h +++ b/laf/base/mem_utils.h @@ -8,10 +8,18 @@ #define BASE_MEM_UTILS_H_INCLUDED #pragma once +#include #include namespace base { + template + T copy_reinterpret_cast(const void* ptr) { + T tmp; + std::memcpy(&tmp, ptr, sizeof(T)); + return tmp; + } + std::string get_pretty_memory_size(std::size_t memsize); } // namespace base --- a/laf/base/serialization.cpp +++ b/laf/base/serialization.cpp @@ -8,6 +8,7 @@ #include "config.h" #endif +#include "base/mem_utils.h" #include "base/serialization.h" #include @@ -57,7 +58,7 @@ std::ostream& little_endian::write64(std::ostream& os, uint64_t qword) std::ostream& little_endian::write_float(std::ostream& os, float value) { - int b = *(reinterpret_cast(&value)); + int b = *(copy_reinterpret_cast(&value)); os.put((int)((b & 0x000000ffl))); os.put((int)((b & 0x0000ff00l) >> 8)); os.put((int)((b & 0x00ff0000l) >> 16)); @@ -67,7 +68,7 @@ std::ostream& little_endian::write_float(std::ostream& os, float value) std::ostream& little_endian::write_double(std::ostream& os, double value) { - long long b = *(reinterpret_cast(&value)); + long long b = *(copy_reinterpret_cast(&value)); os.put((int)((b & 0x00000000000000ffl))); os.put((int)((b & 0x000000000000ff00l) >> 8)); os.put((int)((b & 0x0000000000ff0000l) >> 16)); @@ -126,7 +127,7 @@ float little_endian::read_float(std::istream& is) b3 = is.get(); b4 = is.get(); int v = ((b4 << 24) | (b3 << 16) | (b2 << 8) | b1); - return *reinterpret_cast(&v); + return *copy_reinterpret_cast(&v); } double little_endian::read_double(std::istream& is) @@ -148,7 +149,7 @@ double little_endian::read_double(std::istream& is) ((long long)b3 << 16) | ((long long)b2 << 8) | (long long)b1); - return *reinterpret_cast(&v); + return *copy_reinterpret_cast(&v); } std::ostream& big_endian::write16(std::ostream& os, uint16_t word) @@ -182,7 +183,7 @@ std::ostream& big_endian::write64(std::ostream& os, uint64_t qword) std::ostream& big_endian::write_float(std::ostream& os, float value) { - int b = *(reinterpret_cast(&value)); + int b = *(copy_reinterpret_cast(&value)); os.put((int)((b & 0xff000000l) >> 24)); os.put((int)((b & 0x00ff0000l) >> 16)); os.put((int)((b & 0x0000ff00l) >> 8)); @@ -192,7 +193,7 @@ std::ostream& big_endian::write_float(std::ostream& os, float value) std::ostream& big_endian::write_double(std::ostream& os, double value) { - long long b = *(reinterpret_cast(&value)); + long long b = *(copy_reinterpret_cast(&value)); os.put((int)((b & 0xff00000000000000l) >> 56)); os.put((int)((b & 0x00ff000000000000l) >> 48)); os.put((int)((b & 0x0000ff0000000000l) >> 40)); @@ -251,7 +252,7 @@ float big_endian::read_float(std::istream& is) b2 = is.get(); b1 = is.get(); int v = ((b4 << 24) | (b3 << 16) | (b2 << 8) | b1); - return *reinterpret_cast(&v); + return *copy_reinterpret_cast(&v); } double big_endian::read_double(std::istream& is) @@ -273,7 +274,7 @@ double big_endian::read_double(std::istream& is) ((long long)b3 << 16) | ((long long)b2 << 8) | (long long)b1); - return *reinterpret_cast(&v); + return *copy_reinterpret_cast(&v); }