diff --git a/src/benchmark.cc b/src/benchmark.cc index 91280295e..c39307d00 100644 --- a/src/benchmark.cc +++ b/src/benchmark.cc @@ -222,42 +222,19 @@ State::State(std::string name, IterationCount max_iters, } } - // Note: The use of offsetof below is technically undefined until C++17 - // because State is not a standard layout type. However, all compilers - // currently provide well-defined behavior as an extension (which is - // demonstrated since constexpr evaluation must diagnose all undefined - // behavior). However, GCC and Clang also warn about this use of offsetof, - // which must be suppressed. -#if defined(__INTEL_COMPILER) -#pragma warning push -#pragma warning(disable : 1875) -#elif defined(__GNUC__) || defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Winvalid-offsetof" -#endif -#if defined(__NVCC__) -#pragma nv_diagnostic push -#pragma nv_diag_suppress 1427 -#endif -#if defined(__NVCOMPILER) -#pragma diagnostic push -#pragma diag_suppress offset_in_non_POD_nonstandard -#endif - // Offset tests to ensure commonly accessed data is on the first cache line. - const int cache_line_size = 64; - static_assert( - offsetof(State, skipped_) <= (cache_line_size - sizeof(skipped_)), ""); -#if defined(__INTEL_COMPILER) -#pragma warning pop -#elif defined(__GNUC__) || defined(__clang__) -#pragma GCC diagnostic pop -#endif -#if defined(__NVCC__) -#pragma nv_diagnostic pop -#endif -#if defined(__NVCOMPILER) -#pragma diagnostic pop -#endif + // Ensure commonly accessed data is on the first cache line. + // + // We deliberately avoid offsetof() here: State is not a standard-layout type + // (it has non-static data members with differing access control), so + // offsetof() on it is undefined behavior and is diagnosed by + // -Winvalid-offsetof (and equivalents on other compilers), which previously + // had to be suppressed with a stack of compiler-specific pragmas. Instead we + // compute the offset from the live object, which is well defined. This runs + // only in debug builds, as BM_CHECK is a no-op under NDEBUG. + BM_CHECK_LE(reinterpret_cast(&skipped_) - + reinterpret_cast(this), + /*cache_line_size=*/64 - + static_cast(sizeof(skipped_))); } void State::PauseTiming() {