diff options
33 files changed, 108 insertions, 67 deletions
diff --git a/base/BUILD.gn b/base/BUILD.gn index 589af08..5d8510f 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn @@ -213,6 +213,7 @@ component("base") { "bind_helpers.h", "bind_internal.h", "bind_internal_win.h", + "bit_cast.h", "bits.h", "build_time.cc", "build_time.h", diff --git a/base/base.gypi b/base/base.gypi index 5e90823..bb028bd 100644 --- a/base/base.gypi +++ b/base/base.gypi @@ -120,6 +120,7 @@ 'bind_helpers.h', 'bind_internal.h', 'bind_internal_win.h', + 'bit_cast.h', 'bits.h', 'build_time.cc', 'build_time.h', diff --git a/base/bit_cast.h b/base/bit_cast.h new file mode 100644 index 0000000..b548467 --- /dev/null +++ b/base/bit_cast.h @@ -0,0 +1,71 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_BIT_CAST_H_ +#define BASE_BIT_CAST_H_ + +#include <string.h> + +// bit_cast<Dest,Source> is a template function that implements the equivalent +// of "*reinterpret_cast<Dest*>(&source)". We need this in very low-level +// functions like the protobuf library and fast math support. +// +// float f = 3.14159265358979; +// int i = bit_cast<int32_t>(f); +// // i = 0x40490fdb +// +// The classical address-casting method is: +// +// // WRONG +// float f = 3.14159265358979; // WRONG +// int i = * reinterpret_cast<int*>(&f); // WRONG +// +// The address-casting method actually produces undefined behavior according to +// the ISO C++98 specification, section 3.10 ("basic.lval"), paragraph 15. +// (This did not substantially change in C++11.) Roughly, this section says: if +// an object in memory has one type, and a program accesses it with a different +// type, then the result is undefined behavior for most values of "different +// type". +// +// This is true for any cast syntax, either *(int*)&f or +// *reinterpret_cast<int*>(&f). And it is particularly true for conversions +// between integral lvalues and floating-point lvalues. +// +// The purpose of this paragraph is to allow optimizing compilers to assume that +// expressions with different types refer to different memory. Compilers are +// known to take advantage of this. So a non-conforming program quietly +// produces wildly incorrect output. +// +// The problem is not the use of reinterpret_cast. The problem is type punning: +// holding an object in memory of one type and reading its bits back using a +// different type. +// +// The C++ standard is more subtle and complex than this, but that is the basic +// idea. +// +// Anyways ... +// +// bit_cast<> calls memcpy() which is blessed by the standard, especially by the +// example in section 3.9 . Also, of course, bit_cast<> wraps up the nasty +// logic in one place. +// +// Fortunately memcpy() is very fast. In optimized mode, compilers replace +// calls to memcpy() with inline object code when the size argument is a +// compile-time constant. On a 32-bit system, memcpy(d,s,4) compiles to one +// load and one store, and memcpy(d,s,8) compiles to two loads and two stores. +// +// WARNING: if Dest or Source is a non-POD type, the result of the memcpy +// is likely to surprise you. + +template <class Dest, class Source> +inline Dest bit_cast(const Source& source) { + static_assert(sizeof(Dest) == sizeof(Source), + "bit_cast requires source and destination to be the same size"); + + Dest dest; + memcpy(&dest, &source, sizeof(dest)); + return dest; +} + +#endif // BASE_BIT_CAST_H_ diff --git a/base/macros.h b/base/macros.h index fa12dd2..46ee1da 100644 --- a/base/macros.h +++ b/base/macros.h @@ -11,7 +11,6 @@ #define BASE_MACROS_H_ #include <stddef.h> // For size_t. -#include <string.h> // For memcpy. // Put this in the declarations for a class to be uncopyable. #define DISALLOW_COPY(TypeName) \ @@ -49,70 +48,6 @@ template <typename T, size_t N> char (&ArraySizeHelper(T (&array)[N]))[N]; #define arraysize(array) (sizeof(ArraySizeHelper(array))) -// bit_cast<Dest,Source> is a template function that implements the -// equivalent of "*reinterpret_cast<Dest*>(&source)". We need this in -// very low-level functions like the protobuf library and fast math -// support. -// -// float f = 3.14159265358979; -// int i = bit_cast<int32_t>(f); -// // i = 0x40490fdb -// -// The classical address-casting method is: -// -// // WRONG -// float f = 3.14159265358979; // WRONG -// int i = * reinterpret_cast<int*>(&f); // WRONG -// -// The address-casting method actually produces undefined behavior -// according to ISO C++ specification section 3.10 -15 -. Roughly, this -// section says: if an object in memory has one type, and a program -// accesses it with a different type, then the result is undefined -// behavior for most values of "different type". -// -// This is true for any cast syntax, either *(int*)&f or -// *reinterpret_cast<int*>(&f). And it is particularly true for -// conversions between integral lvalues and floating-point lvalues. -// -// The purpose of 3.10 -15- is to allow optimizing compilers to assume -// that expressions with different types refer to different memory. gcc -// 4.0.1 has an optimizer that takes advantage of this. So a -// non-conforming program quietly produces wildly incorrect output. -// -// The problem is not the use of reinterpret_cast. The problem is type -// punning: holding an object in memory of one type and reading its bits -// back using a different type. -// -// The C++ standard is more subtle and complex than this, but that -// is the basic idea. -// -// Anyways ... -// -// bit_cast<> calls memcpy() which is blessed by the standard, -// especially by the example in section 3.9 . Also, of course, -// bit_cast<> wraps up the nasty logic in one place. -// -// Fortunately memcpy() is very fast. In optimized mode, with a -// constant size, gcc 2.95.3, gcc 4.0.1, and msvc 7.1 produce inline -// code with the minimal amount of data movement. On a 32-bit system, -// memcpy(d,s,4) compiles to one load and one store, and memcpy(d,s,8) -// compiles to two loads and two stores. -// -// I tested this code with gcc 2.95.3, gcc 4.0.1, icc 8.1, and msvc 7.1. -// -// WARNING: if Dest or Source is a non-POD type, the result of the memcpy -// is likely to surprise you. - -template <class Dest, class Source> -inline Dest bit_cast(const Source& source) { - static_assert(sizeof(Dest) == sizeof(Source), - "bit_cast requires source and destination to be the same size"); - - Dest dest; - memcpy(&dest, &source, sizeof(dest)); - return dest; -} - // Used to explicitly mark the return value of a function as unused. If you are // really sure you don't want to do anything with the return value of a function // that has been marked WARN_UNUSED_RESULT, wrap it with this. Example: diff --git a/base/time/time_win.cc b/base/time/time_win.cc index b2d9c76..dc968ad 100644 --- a/base/time/time_win.cc +++ b/base/time/time_win.cc @@ -38,6 +38,7 @@ #include <mmsystem.h> #include <stdint.h> +#include "base/bit_cast.h" #include "base/cpu.h" #include "base/lazy_instance.h" #include "base/logging.h" diff --git a/chrome/browser/profile_resetter/triggered_profile_resetter_win_unittest.cc b/chrome/browser/profile_resetter/triggered_profile_resetter_win_unittest.cc index 1db72be..565f1b4 100644 --- a/chrome/browser/profile_resetter/triggered_profile_resetter_win_unittest.cc +++ b/chrome/browser/profile_resetter/triggered_profile_resetter_win_unittest.cc @@ -6,6 +6,7 @@ #include <stdint.h> +#include "base/bit_cast.h" #include "base/memory/scoped_ptr.h" #include "base/metrics/field_trial.h" #include "base/prefs/pref_service.h" diff --git a/chromeos/hugepage_text/hugepage_text.cc b/chromeos/hugepage_text/hugepage_text.cc index a14a2d1..ccae53f 100644 --- a/chromeos/hugepage_text/hugepage_text.cc +++ b/chromeos/hugepage_text/hugepage_text.cc @@ -10,6 +10,7 @@ #include <link.h> #include <sys/mman.h> +#include "base/bit_cast.h" #include "base/logging.h" namespace chromeos { diff --git a/components/compression/compression_utils.cc b/components/compression/compression_utils.cc index dfc1664..aedfc8e 100644 --- a/components/compression/compression_utils.cc +++ b/components/compression/compression_utils.cc @@ -10,6 +10,7 @@ #include <vector> +#include "base/bit_cast.h" #include "base/logging.h" #include "base/sys_byteorder.h" #include "third_party/zlib/zlib.h" diff --git a/components/visitedlink/common/visitedlink_common.cc b/components/visitedlink/common/visitedlink_common.cc index b052142..1703cac 100644 --- a/components/visitedlink/common/visitedlink_common.cc +++ b/components/visitedlink/common/visitedlink_common.cc @@ -6,6 +6,7 @@ #include <string.h> // for memset() +#include "base/bit_cast.h" #include "base/logging.h" #include "base/md5.h" #include "url/gurl.h" diff --git a/components/webcrypto/algorithms/rsa_oaep.cc b/components/webcrypto/algorithms/rsa_oaep.cc index 8e4452e..27e834b 100644 --- a/components/webcrypto/algorithms/rsa_oaep.cc +++ b/components/webcrypto/algorithms/rsa_oaep.cc @@ -5,6 +5,7 @@ #include <openssl/evp.h> #include <stddef.h> #include <stdint.h> +#include <string.h> #include "components/webcrypto/algorithms/rsa.h" #include "components/webcrypto/algorithms/util.h" diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.cc b/content/renderer/pepper/pepper_plugin_instance_impl.cc index 172c3b7..de1cdaf 100644 --- a/content/renderer/pepper/pepper_plugin_instance_impl.cc +++ b/content/renderer/pepper/pepper_plugin_instance_impl.cc @@ -7,6 +7,7 @@ #include <utility> #include "base/bind.h" +#include "base/bit_cast.h" #include "base/callback_helpers.h" #include "base/location.h" #include "base/logging.h" diff --git a/courgette/difference_estimator.cc b/courgette/difference_estimator.cc index 8b7aa29..ac9f0d4 100644 --- a/courgette/difference_estimator.cc +++ b/courgette/difference_estimator.cc @@ -10,6 +10,7 @@ #include <stddef.h> #include <stdint.h> +#include <string.h> #include "base/containers/hash_tables.h" #include "base/macros.h" diff --git a/gpu/command_buffer/tests/gl_readback_unittest.cc b/gpu/command_buffer/tests/gl_readback_unittest.cc index d629564..eaaa1bb 100644 --- a/gpu/command_buffer/tests/gl_readback_unittest.cc +++ b/gpu/command_buffer/tests/gl_readback_unittest.cc @@ -11,6 +11,7 @@ #include <cmath> #include "base/bind.h" +#include "base/bit_cast.h" #include "base/location.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" diff --git a/media/cdm/ppapi/ppapi_cdm_adapter.cc b/media/cdm/ppapi/ppapi_cdm_adapter.cc index 40b0bae..d3a143a 100644 --- a/media/cdm/ppapi/ppapi_cdm_adapter.cc +++ b/media/cdm/ppapi/ppapi_cdm_adapter.cc @@ -4,6 +4,8 @@ #include "media/cdm/ppapi/ppapi_cdm_adapter.h" +#include <string.h> + #include "base/macros.h" #include "build/build_config.h" #include "media/base/limits.h" diff --git a/net/disk_cache/blockfile/bitmap.h b/net/disk_cache/blockfile/bitmap.h index 54e4162..59a987a 100644 --- a/net/disk_cache/blockfile/bitmap.h +++ b/net/disk_cache/blockfile/bitmap.h @@ -6,6 +6,7 @@ #define NET_DISK_CACHE_BLOCKFILE_BITMAP_H_ #include <stdint.h> +#include <string.h> #include "base/macros.h" #include "net/base/net_export.h" diff --git a/net/disk_cache/blockfile/disk_format_v3.h b/net/disk_cache/blockfile/disk_format_v3.h index 3ec43e8..da873ed 100644 --- a/net/disk_cache/blockfile/disk_format_v3.h +++ b/net/disk_cache/blockfile/disk_format_v3.h @@ -46,6 +46,7 @@ #define NET_DISK_CACHE_BLOCKFILE_DISK_FORMAT_V3_H_ #include <stdint.h> +#include <string.h> #include "net/disk_cache/blockfile/disk_format_base.h" diff --git a/net/disk_cache/blockfile/index_table_v3.cc b/net/disk_cache/blockfile/index_table_v3.cc index 426d683..9c24e80 100644 --- a/net/disk_cache/blockfile/index_table_v3.cc +++ b/net/disk_cache/blockfile/index_table_v3.cc @@ -9,6 +9,7 @@ #include <set> #include <utility> +#include "base/bit_cast.h" #include "base/bits.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" diff --git a/net/filter/brotli_filter.cc b/net/filter/brotli_filter.cc index 66e778a..939a6f7 100644 --- a/net/filter/brotli_filter.cc +++ b/net/filter/brotli_filter.cc @@ -4,6 +4,7 @@ #include "net/filter/brotli_filter.h" +#include "base/bit_cast.h" #include "base/macros.h" #include "base/numerics/safe_conversions.h" #include "base/numerics/safe_math.h" diff --git a/net/filter/gzip_filter.cc b/net/filter/gzip_filter.cc index 6d15ee9..209e3c4 100644 --- a/net/filter/gzip_filter.cc +++ b/net/filter/gzip_filter.cc @@ -4,6 +4,7 @@ #include "net/filter/gzip_filter.h" +#include "base/bit_cast.h" #include "base/logging.h" #include "net/filter/gzip_header.h" #include "third_party/zlib/zlib.h" diff --git a/net/filter/gzip_filter_unittest.cc b/net/filter/gzip_filter_unittest.cc index 2f11e28a..e25cc1c 100644 --- a/net/filter/gzip_filter_unittest.cc +++ b/net/filter/gzip_filter_unittest.cc @@ -5,6 +5,7 @@ #include <fstream> #include <ostream> +#include "base/bit_cast.h" #include "base/files/file_util.h" #include "base/memory/scoped_ptr.h" #include "base/path_service.h" diff --git a/net/filter/sdch_filter_unittest.cc b/net/filter/sdch_filter_unittest.cc index cbb85a8..701aba0 100644 --- a/net/filter/sdch_filter_unittest.cc +++ b/net/filter/sdch_filter_unittest.cc @@ -8,6 +8,7 @@ #include <string> #include <vector> +#include "base/bit_cast.h" #include "base/logging.h" #include "base/macros.h" #include "base/memory/scoped_ptr.h" diff --git a/net/quic/test_tools/mock_random.cc b/net/quic/test_tools/mock_random.cc index 87977be..f1bc024 100644 --- a/net/quic/test_tools/mock_random.cc +++ b/net/quic/test_tools/mock_random.cc @@ -4,6 +4,8 @@ #include "net/quic/test_tools/mock_random.h" +#include <string.h> + namespace net { namespace test { diff --git a/pdf/out_of_process_instance.h b/pdf/out_of_process_instance.h index f210d0a5..bdd0e68 100644 --- a/pdf/out_of_process_instance.h +++ b/pdf/out_of_process_instance.h @@ -6,6 +6,7 @@ #define PDF_OUT_OF_PROCESS_INSTANCE_H_ #include <stdint.h> +#include <string.h> #include <queue> #include <set> diff --git a/ppapi/shared_impl/ppb_view_shared.cc b/ppapi/shared_impl/ppb_view_shared.cc index 36c047d..5c1ab97 100644 --- a/ppapi/shared_impl/ppb_view_shared.cc +++ b/ppapi/shared_impl/ppb_view_shared.cc @@ -4,6 +4,8 @@ #include "ppapi/shared_impl/ppb_view_shared.h" +#include <string.h> + namespace { bool IsRectNonempty(const PP_Rect& rect) { diff --git a/remoting/client/plugin/pepper_util.cc b/remoting/client/plugin/pepper_util.cc index 0e575c8..0315382 100644 --- a/remoting/client/plugin/pepper_util.cc +++ b/remoting/client/plugin/pepper_util.cc @@ -4,6 +4,7 @@ #include "remoting/client/plugin/pepper_util.h" +#include "base/bit_cast.h" #include "base/callback.h" #include "base/logging.h" #include "base/sys_byteorder.h" diff --git a/sandbox/win/src/Wow64.cc b/sandbox/win/src/Wow64.cc index d07d72f..c5984d6 100644 --- a/sandbox/win/src/Wow64.cc +++ b/sandbox/win/src/Wow64.cc @@ -8,6 +8,7 @@ #include <sstream> +#include "base/bit_cast.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/win/scoped_process_information.h" diff --git a/sandbox/win/src/service_resolver_32.cc b/sandbox/win/src/service_resolver_32.cc index 4fc96d3..f809227 100644 --- a/sandbox/win/src/service_resolver_32.cc +++ b/sandbox/win/src/service_resolver_32.cc @@ -6,6 +6,7 @@ #include <stddef.h> +#include "base/bit_cast.h" #include "base/memory/scoped_ptr.h" #include "sandbox/win/src/win_utils.h" diff --git a/sandbox/win/src/service_resolver_unittest.cc b/sandbox/win/src/service_resolver_unittest.cc index 421b814..25d0875 100644 --- a/sandbox/win/src/service_resolver_unittest.cc +++ b/sandbox/win/src/service_resolver_unittest.cc @@ -6,6 +6,7 @@ #include <stddef.h> +#include "base/bit_cast.h" #include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "base/win/windows_version.h" diff --git a/sandbox/win/wow_helper/service64_resolver.cc b/sandbox/win/wow_helper/service64_resolver.cc index b5b67cc..0424d9f 100644 --- a/sandbox/win/wow_helper/service64_resolver.cc +++ b/sandbox/win/wow_helper/service64_resolver.cc @@ -7,6 +7,7 @@ #include <limits.h> #include <stddef.h> +#include "base/bit_cast.h" #include "base/memory/scoped_ptr.h" #include "sandbox/win/wow_helper/target_code.h" diff --git a/sync/internal_api/http_bridge.cc b/sync/internal_api/http_bridge.cc index b8d57cc..b02ede8 100644 --- a/sync/internal_api/http_bridge.cc +++ b/sync/internal_api/http_bridge.cc @@ -9,6 +9,7 @@ #include <vector> +#include "base/bit_cast.h" #include "base/message_loop/message_loop.h" #include "base/metrics/field_trial.h" #include "base/metrics/histogram_macros.h" diff --git a/sync/internal_api/http_bridge_unittest.cc b/sync/internal_api/http_bridge_unittest.cc index d61f644..206adcb 100644 --- a/sync/internal_api/http_bridge_unittest.cc +++ b/sync/internal_api/http_bridge_unittest.cc @@ -5,6 +5,7 @@ #include <stddef.h> #include <stdint.h> +#include "base/bit_cast.h" #include "base/metrics/field_trial.h" #include "base/strings/stringprintf.h" #include "base/synchronization/waitable_event.h" diff --git a/third_party/crashpad/README.chromium b/third_party/crashpad/README.chromium index 9ada866..92bdd99 100644 --- a/third_party/crashpad/README.chromium +++ b/third_party/crashpad/README.chromium @@ -35,4 +35,4 @@ $ cd "${CRASHPAD_DIR}" $ git am --3way --message-id -p4 /tmp/patchdir Local Modifications: -None. +- Move bit_cast from base/macros.h to its own header. diff --git a/third_party/crashpad/crashpad/util/numeric/int128_test.cc b/third_party/crashpad/crashpad/util/numeric/int128_test.cc index c0ad74e..61a6d82 100644 --- a/third_party/crashpad/crashpad/util/numeric/int128_test.cc +++ b/third_party/crashpad/crashpad/util/numeric/int128_test.cc @@ -14,7 +14,10 @@ #include "util/numeric/int128.h" -#include "base/macros.h" +#include <stdint.h> + +#include "base/bit_cast.h" +#include "build/build_config.h" #include "gtest/gtest.h" namespace crashpad { |