From cf6ab6bb2b800fae859ccc735f398d22a7336a00 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Sun, 24 Sep 2017 08:20:48 -0700 Subject: [PATCH] Changes imported from Abseil "staging" branch: - b527a3e4b36b644ac424e3c525b1cd393f6f6c40 Fix some typos in the usage examples by Jorg Brown - 82be4a9adf3bb0ddafc0d46274969c99afffe870 Fix typo in optional.h comment. by Abseil Team - d6ee63bf8fc51fba074c23b33cebc28c808d7f07 Remove internal-only identifiers from code. by Daniel Katz - f9c3ad2f0d73f53b21603638af8b4bed636e79f4 Use easier understandable names for absl::StartsWith and ... by Abseil Team - 7c16c14fefee89c927b8789d6043c4691bcffc9b Add -Wno-missing-prototypes back to the LLVM copts. by Derek Mauro - 2f4b7d2e50c7023240242f1e15db60ccd7e8768d IWYU | absl/strings by Juemin Yang - a99cbcc1daa34a2d6a2bb26de275e05173cc77e9 IWYU | absl/type by Juemin Yang - 12e1146d0fc76c071d7e0ebaabb62f0a984fae66 Use LLVM_FLAGS and LLVM_TEST_FLAGS when --compiler=llvm. by Derek Mauro - cd6bea616abda558d0bace5bd77455662a233688 IWYU | absl/debugging by Juemin Yang - d9a7382e59d46a8581b6b7a31cd5a48bb89326e9 IWYU | absl/synchronization by Juemin Yang - 07ec7d6d5a4a666f4183c5d0ed9c342baa7b24bc IWYU | absl/numeric by Juemin Yang - 12bfe40051f4270f8707e191af5652f83f2f750c Remove the RoundTrip{Float,Double}ToBuffer routines from ... by Jorg Brown - eeb4fd67c9d97f66cb9475c3c5e51ab132f1c810 Adds conversion functions for converting between absl/tim... by Greg Miller - 59a2108d05d4ea85dc5cc11e49b2cd2335d4295a Change Substitute to use %.6g formatting rather than 15/1... by Jorg Brown - 394becb48e0fcd161642cdaac5120d32567e0ef8 IWYU | absl/meta by Juemin Yang - 1e5da6e8da336699b2469dcf6dda025b9b0ec4c9 Rewrite atomic_hook.h to not use std::atomic under Wi... by Greg Falcon GitOrigin-RevId: b527a3e4b36b644ac424e3c525b1cd393f6f6c40 Change-Id: I14e331d91c956ef045ac7927091a9f179716de0c --- absl/BUILD.bazel | 14 - absl/base/BUILD.bazel | 5 +- absl/base/attributes.h | 2 +- absl/base/internal/atomic_hook.h | 104 +++-- absl/base/internal/low_level_scheduling.h | 4 +- absl/base/internal/malloc_hook.cc | 26 +- absl/base/internal/raw_logging.cc | 8 +- absl/base/internal/scheduling_mode.h | 4 +- absl/base/internal/spinlock_wait.h | 4 - absl/base/internal/sysinfo.cc | 5 +- absl/base/internal/sysinfo.h | 3 +- absl/base/internal/sysinfo_test.cc | 5 +- absl/base/internal/thread_identity.cc | 11 +- absl/base/macros.h | 2 +- absl/copts.bzl | 20 +- absl/debugging/BUILD.bazel | 1 - .../debugging/internal/address_is_readable.cc | 1 - absl/debugging/internal/stacktrace_config.h | 8 +- .../internal/stacktrace_libunwind-inl.inc | 128 ------ absl/debugging/leak_check_test.cc | 3 +- absl/debugging/stacktrace.cc | 12 +- absl/meta/type_traits.h | 1 + absl/meta/type_traits_test.cc | 2 +- absl/numeric/int128.cc | 3 +- absl/numeric/int128.h | 2 +- absl/strings/BUILD.bazel | 1 + absl/strings/escaping.cc | 7 +- absl/strings/escaping_test.cc | 2 +- absl/strings/internal/char_map_test.cc | 4 +- absl/strings/internal/memutil_test.cc | 1 - absl/strings/internal/ostringstream_test.cc | 1 - absl/strings/internal/utf8_test.cc | 5 +- absl/strings/match.cc | 6 +- absl/strings/match.h | 32 +- absl/strings/numbers.cc | 387 +----------------- absl/strings/numbers.h | 3 - absl/strings/numbers_test.cc | 41 -- absl/strings/str_cat.cc | 4 +- absl/strings/str_join_test.cc | 7 +- absl/strings/str_replace_test.cc | 3 +- absl/strings/str_split.cc | 3 + absl/strings/str_split_test.cc | 7 +- absl/strings/string_view.cc | 1 - absl/strings/string_view.h | 9 +- absl/strings/string_view_test.cc | 6 +- absl/strings/strip.cc | 1 - absl/strings/substitute.h | 16 +- absl/synchronization/blocking_counter.cc | 2 + absl/synchronization/blocking_counter_test.cc | 3 +- .../internal/create_thread_identity.cc | 5 +- .../internal/graphcycles_test.cc | 13 +- .../internal/per_thread_sem_test.cc | 2 +- absl/synchronization/mutex.h | 2 +- absl/synchronization/mutex_test.cc | 6 - absl/test_dependencies.bzl | 4 +- absl/time/BUILD.bazel | 13 - absl/time/clock.cc | 2 +- absl/time/duration.cc | 21 +- absl/time/duration_test.cc | 202 +++++++-- absl/time/format.cc | 4 +- absl/time/time.cc | 13 + absl/time/time.h | 164 +++++++- absl/time/time_test.cc | 61 +++ absl/types/BUILD.bazel | 4 +- absl/types/any_test.cc | 1 - absl/types/optional.h | 7 +- absl/types/optional_test.cc | 2 +- absl/types/span_test.cc | 4 +- 68 files changed, 629 insertions(+), 831 deletions(-) delete mode 100644 absl/debugging/internal/stacktrace_libunwind-inl.inc diff --git a/absl/BUILD.bazel b/absl/BUILD.bazel index 42c107d23..92e9059bb 100644 --- a/absl/BUILD.bazel +++ b/absl/BUILD.bazel @@ -25,20 +25,6 @@ config_setting( }, ) -config_setting( - name = "hybrid_compiler", - values = { - "compiler": "hybrid", - }, -) - -config_setting( - name = "llvm_warnings", - values = { - "define": "ABSL_LLVM_WARNINGS=1", - }, -) - # following configs are based on mapping defined in: https://git.io/v5Ijz config_setting( name = "ios", diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel index 2e023ef23..4c1b50952 100644 --- a/absl/base/BUILD.bazel +++ b/absl/base/BUILD.bazel @@ -30,9 +30,6 @@ package(default_visibility = ["//visibility:public"]) licenses(["notice"]) # Apache 2.0 -# Some header files in //base are directly exported for unusual use cases, -# and the ABSL versions must also be exported for those users. - exports_files(["thread_annotations.h"]) cc_library( @@ -188,7 +185,7 @@ cc_library( hdrs = ["internal/throw_delegate.h"], copts = ABSL_DEFAULT_COPTS + ABSL_EXCEPTIONS_FLAG, features = [ - "-use_header_modules", # b/33207452 + "-use_header_modules", ], deps = [ ":base", diff --git a/absl/base/attributes.h b/absl/base/attributes.h index c2155a4e2..ddf445841 100644 --- a/absl/base/attributes.h +++ b/absl/base/attributes.h @@ -526,7 +526,7 @@ // // Note that this attribute is redundant if the variable is declared constexpr. #if ABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization) -// NOLINTNEXTLINE(whitespace/braces) (b/36288871) +// NOLINTNEXTLINE(whitespace/braces) #define ABSL_CONST_INIT [[clang::require_constant_initialization]] #else #define ABSL_CONST_INIT diff --git a/absl/base/internal/atomic_hook.h b/absl/base/internal/atomic_hook.h index 1f9a8102f..47d401392 100644 --- a/absl/base/internal/atomic_hook.h +++ b/absl/base/internal/atomic_hook.h @@ -18,28 +18,12 @@ #include #include +#include #include namespace absl { namespace base_internal { -// In current versions of MSVC (as of July 2017), a std::atomic where T is a -// pointer to function cannot be constant-initialized with an address constant -// expression. That is, the following code does not compile: -// void NoOp() {} -// constexpr std::atomic ptr(NoOp); -// -// This is the only compiler we support that seems to have this issue. We -// conditionalize on MSVC here to use a fallback implementation. But we -// should revisit this occasionally. If MSVC fixes this compiler bug, we -// can then change this to be conditionalized on the value on _MSC_FULL_VER -// instead. -#ifdef _MSC_FULL_VER -#define ABSL_HAVE_FUNCTION_ADDRESS_CONSTANT_EXPRESSION 0 -#else -#define ABSL_HAVE_FUNCTION_ADDRESS_CONSTANT_EXPRESSION 1 -#endif - template class AtomicHook; @@ -55,7 +39,7 @@ class AtomicHook { public: using FnPtr = ReturnType (*)(Args...); - constexpr AtomicHook() : hook_(DummyFunction) {} + constexpr AtomicHook() : hook_(kInitialValue) {} // Stores the provided function pointer as the value for this hook. // @@ -64,28 +48,16 @@ class AtomicHook { // as a memory_order_release operation, and read accesses are implemented as // memory_order_acquire. void Store(FnPtr fn) { - assert(fn); - FnPtr expected = DummyFunction; - hook_.compare_exchange_strong(expected, fn, std::memory_order_acq_rel, - std::memory_order_acquire); - // If the compare and exchange failed, make sure that's because hook_ was - // already set to `fn` by an earlier call. Any other state reflects an API - // violation (calling Store() multiple times with different values). - // - // Avoid ABSL_RAW_CHECK, since raw logging depends on AtomicHook. - assert(expected == DummyFunction || expected == fn); + bool success = DoStore(fn); + static_cast(success); + assert(success); } // Invokes the registered callback. If no callback has yet been registered, a // default-constructed object of the appropriate type is returned instead. template ReturnType operator()(CallArgs&&... args) const { - FnPtr hook = hook_.load(std::memory_order_acquire); - if (ABSL_HAVE_FUNCTION_ADDRESS_CONSTANT_EXPRESSION || hook) { - return hook(std::forward(args)...); - } else { - return ReturnType(); - } + return DoLoad()(std::forward(args)...); } // Returns the registered callback, or nullptr if none has been registered. @@ -98,23 +70,79 @@ class AtomicHook { // Load()() unless you must conditionalize behavior on whether a hook was // registered. FnPtr Load() const { - FnPtr ptr = hook_.load(std::memory_order_acquire); + FnPtr ptr = DoLoad(); return (ptr == DummyFunction) ? nullptr : ptr; } private: -#if ABSL_HAVE_FUNCTION_ADDRESS_CONSTANT_EXPRESSION static ReturnType DummyFunction(Args...) { return ReturnType(); } + + // Current versions of MSVC (as of September 2017) have a broken + // implementation of std::atomic: Its constructor attempts to do the + // equivalent of a reinterpret_cast in a constexpr context, which is not + // allowed. + // + // This causes an issue when building with LLVM under Windows. To avoid this, + // we use a less-efficient, intptr_t-based implementation on Windows. + +#ifdef _MSC_FULL_VER +#define ABSL_HAVE_WORKING_ATOMIC_POINTER 0 #else - static constexpr FnPtr DummyFunction = nullptr; +#define ABSL_HAVE_WORKING_ATOMIC_POINTER 1 #endif +#if ABSL_HAVE_WORKING_ATOMIC_POINTER + static constexpr FnPtr kInitialValue = &DummyFunction; + + // Return the stored value, or DummyFunction if no value has been stored. + FnPtr DoLoad() const { return hook_.load(std::memory_order_acquire); } + + // Store the given value. Returns false if a different value was already + // stored to this object. + bool DoStore(FnPtr fn) { + assert(fn); + FnPtr expected = DummyFunction; + hook_.compare_exchange_strong(expected, fn, std::memory_order_acq_rel, + std::memory_order_acquire); + const bool store_succeeded = (expected == DummyFunction); + const bool same_value_already_stored = (expected == fn); + return store_succeeded || same_value_already_stored; + } + std::atomic hook_; +#else // !ABSL_HAVE_WORKING_ATOMIC_POINTER + // Use a sentinel value unlikely to be the address of an actual function. + static constexpr intptr_t kInitialValue = 0; + + static_assert(sizeof(intptr_t) >= sizeof(FnPtr), + "intptr_t can't contain a function pointer"); + + FnPtr DoLoad() const { + const intptr_t value = hook_.load(std::memory_order_acquire); + if (value == 0) { + return DummyFunction; + } + return reinterpret_cast(value); + } + + bool DoStore(FnPtr fn) { + assert(fn); + const auto value = reinterpret_cast(fn); + intptr_t expected = 0; + hook_.compare_exchange_strong(expected, value, std::memory_order_acq_rel, + std::memory_order_acquire); + const bool store_succeeded = (expected == 0); + const bool same_value_already_stored = (expected == value); + return store_succeeded || same_value_already_stored; + } + + std::atomic hook_; +#endif }; -#undef ABSL_HAVE_FUNCTION_ADDRESS_CONSTANT_EXPRESSION +#undef ABSL_HAVE_WORKING_ATOMIC_POINTER } // namespace base_internal } // namespace absl diff --git a/absl/base/internal/low_level_scheduling.h b/absl/base/internal/low_level_scheduling.h index a01d1c032..e716f2b49 100644 --- a/absl/base/internal/low_level_scheduling.h +++ b/absl/base/internal/low_level_scheduling.h @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. // -// Core interfaces and definitions used by by low-level //base interfaces such -// as SpinLock. +// Core interfaces and definitions used by by low-level interfaces such as +// SpinLock. #ifndef ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_ #define ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_ diff --git a/absl/base/internal/malloc_hook.cc b/absl/base/internal/malloc_hook.cc index 4f5a0befe..7165d4cbd 100644 --- a/absl/base/internal/malloc_hook.cc +++ b/absl/base/internal/malloc_hook.cc @@ -453,16 +453,13 @@ void MallocHook::InvokeSbrkHookSlow(const void* result, ptrdiff_t increment) { } // namespace base_internal } // namespace absl -ABSL_DEFINE_ATTRIBUTE_SECTION_VARS(google_malloc); -ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(google_malloc); -// actual functions are in debugallocation.cc or tcmalloc.cc ABSL_DEFINE_ATTRIBUTE_SECTION_VARS(malloc_hook); ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(malloc_hook); // actual functions are in this file, malloc_hook.cc, and low_level_alloc.cc +ABSL_DEFINE_ATTRIBUTE_SECTION_VARS(google_malloc); +ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(google_malloc); ABSL_DEFINE_ATTRIBUTE_SECTION_VARS(blink_malloc); ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(blink_malloc); -// actual functions are in third_party/blink_headless/.../{PartitionAlloc, -// FastMalloc}.cpp. #define ADDR_IN_ATTRIBUTE_SECTION(addr, name) \ (reinterpret_cast(ABSL_ATTRIBUTE_SECTION_START(name)) <= \ @@ -486,13 +483,6 @@ static inline bool InHookCaller(const void* caller) { static absl::once_flag in_hook_caller_once; static void InitializeInHookCaller() { - ABSL_INIT_ATTRIBUTE_SECTION_VARS(google_malloc); - if (ABSL_ATTRIBUTE_SECTION_START(google_malloc) == - ABSL_ATTRIBUTE_SECTION_STOP(google_malloc)) { - ABSL_RAW_LOG(ERROR, - "google_malloc section is missing, " - "thus InHookCaller is broken!"); - } ABSL_INIT_ATTRIBUTE_SECTION_VARS(malloc_hook); if (ABSL_ATTRIBUTE_SECTION_START(malloc_hook) == ABSL_ATTRIBUTE_SECTION_STOP(malloc_hook)) { @@ -500,9 +490,14 @@ static void InitializeInHookCaller() { "malloc_hook section is missing, " "thus InHookCaller is broken!"); } + ABSL_INIT_ATTRIBUTE_SECTION_VARS(google_malloc); + if (ABSL_ATTRIBUTE_SECTION_START(google_malloc) == + ABSL_ATTRIBUTE_SECTION_STOP(google_malloc)) { + ABSL_RAW_LOG(ERROR, + "google_malloc section is missing, " + "thus InHookCaller is broken!"); + } ABSL_INIT_ATTRIBUTE_SECTION_VARS(blink_malloc); - // The blink_malloc section is only expected to be present in binaries - // linking against the blink rendering engine in third_party/blink_headless. } // We can improve behavior/compactness of this function @@ -574,7 +569,8 @@ extern "C" int MallocHook_GetCallerStackTrace( // still allow users to disable this in special cases that can't be easily // detected during compilation, via -DABSL_MALLOC_HOOK_MMAP_DISABLE or #define // ABSL_MALLOC_HOOK_MMAP_DISABLE. -// TODO(b/62370839): Remove MALLOC_HOOK_MMAP_DISABLE in CROSSTOOL for tsan and +// +// TODO(absl-team): Remove MALLOC_HOOK_MMAP_DISABLE in CROSSTOOL for tsan and // msan config; Replace MALLOC_HOOK_MMAP_DISABLE with // ABSL_MALLOC_HOOK_MMAP_DISABLE for other special cases. #if !defined(THREAD_SANITIZER) && !defined(MEMORY_SANITIZER) && \ diff --git a/absl/base/internal/raw_logging.cc b/absl/base/internal/raw_logging.cc index c0890614b..1b849abfc 100644 --- a/absl/base/internal/raw_logging.cc +++ b/absl/base/internal/raw_logging.cc @@ -34,10 +34,10 @@ // // This preprocessor token is also defined in raw_io.cc. If you need to copy // this, consider moving both to config.h instead. -#if defined(__linux__) || defined(__APPLE__) || defined(__Fuchsia__) || \ - defined(__GENCLAVE__) +#if defined(__linux__) || defined(__APPLE__) || defined(__Fuchsia__) #include + #define ABSL_HAVE_POSIX_WRITE 1 #define ABSL_LOW_LEVEL_WRITE_SUPPORTED 1 #else @@ -110,10 +110,6 @@ namespace { // CAVEAT: vsnprintf called from *DoRawLog below has some (exotic) code paths // that invoke malloc() and getenv() that might acquire some locks. -// If this becomes a problem we should reimplement a subset of vsnprintf -// that does not need locks and malloc. -// E.g. google3/third_party/clearsilver/core/util/snprintf.c -// looks like such a reimplementation. // Helper for RawLog below. // *DoRawLog writes to *buf of *size and move them past the written portion. diff --git a/absl/base/internal/scheduling_mode.h b/absl/base/internal/scheduling_mode.h index b7560f30d..1b6497ad8 100644 --- a/absl/base/internal/scheduling_mode.h +++ b/absl/base/internal/scheduling_mode.h @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. // -// Core interfaces and definitions used by by low-level //base interfaces such -// as SpinLock. +// Core interfaces and definitions used by by low-level interfaces such as +// SpinLock. #ifndef ABSL_BASE_INTERNAL_SCHEDULING_MODE_H_ #define ABSL_BASE_INTERNAL_SCHEDULING_MODE_H_ diff --git a/absl/base/internal/spinlock_wait.h b/absl/base/internal/spinlock_wait.h index 6734cc9ef..5f658211c 100644 --- a/absl/base/internal/spinlock_wait.h +++ b/absl/base/internal/spinlock_wait.h @@ -18,10 +18,6 @@ // Operations to make atomic transitions on a word, and to allow // waiting for those transitions to become possible. -// This file is used internally in spinlock.cc and once.cc, and a few other -// places listing in //base:spinlock_wait_users. If you need to use it outside -// of //base, please request permission to be added to that list. - #include #include diff --git a/absl/base/internal/sysinfo.cc b/absl/base/internal/sysinfo.cc index 6a4c00641..9e0140fad 100644 --- a/absl/base/internal/sysinfo.cc +++ b/absl/base/internal/sysinfo.cc @@ -57,10 +57,7 @@ static int num_cpus = 0; static double nominal_cpu_frequency = 1.0; // 0.0 might be dangerous. static int GetNumCPUs() { -#if defined(__myriad2__) || defined(__GENCLAVE__) - // TODO(b/28296132): Calling std::thread::hardware_concurrency() induces a - // link error on myriad2 builds. - // TODO(b/62709537): Support std::thread::hardware_concurrency() in gEnclalve. +#if defined(__myriad2__) return 1; #else // Other possibilities: diff --git a/absl/base/internal/sysinfo.h b/absl/base/internal/sysinfo.h index f21de1432..5bd1c500b 100644 --- a/absl/base/internal/sysinfo.h +++ b/absl/base/internal/sysinfo.h @@ -40,8 +40,7 @@ namespace base_internal { // Thread-safe. double NominalCPUFrequency(); -// Number of logical processors (hyperthreads) in system. See -// //base/cpuid/cpuid.h for more CPU-related info. Thread-safe. +// Number of logical processors (hyperthreads) in system. Thread-safe. int NumCPUs(); // Return the thread id of the current thread, as told by the system. diff --git a/absl/base/internal/sysinfo_test.cc b/absl/base/internal/sysinfo_test.cc index 4c7d66b7f..e0d9aab9b 100644 --- a/absl/base/internal/sysinfo_test.cc +++ b/absl/base/internal/sysinfo_test.cc @@ -41,11 +41,10 @@ TEST(SysinfoTest, NominalCPUFrequency) { EXPECT_GE(NominalCPUFrequency(), 1000.0) << "NominalCPUFrequency() did not return a reasonable value"; #else - // TODO(b/37919252): Aarch64 cannot read the CPU frequency from sysfs, so we + // TODO(absl-team): Aarch64 cannot read the CPU frequency from sysfs, so we // get back 1.0. Fix once the value is available. EXPECT_EQ(NominalCPUFrequency(), 1.0) - << "CPU frequency detection was fixed! Please update unittest and " - "b/37919252"; + << "CPU frequency detection was fixed! Please update unittest."; #endif } diff --git a/absl/base/internal/thread_identity.cc b/absl/base/internal/thread_identity.cc index ee96a5883..678e8568d 100644 --- a/absl/base/internal/thread_identity.cc +++ b/absl/base/internal/thread_identity.cc @@ -48,12 +48,10 @@ void AllocateThreadIdentityKey(ThreadIdentityReclaimerFunction reclaimer) { ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11 // The actual TLS storage for a thread's currently associated ThreadIdentity. // This is referenced by inline accessors in the header. -// "protected" visibility ensures that if multiple copies of //base exist in a -// process (via dlopen() or similar), references to -// thread_identity_ptr from each copy of the code will refer to -// *different* instances of this ptr. See extensive discussion of this choice -// in cl/90634708 -// TODO(ahh): hard deprecate multiple copies of //base; remove this. +// "protected" visibility ensures that if multiple instances of Abseil code +// exist within a process (via dlopen() or similar), references to +// thread_identity_ptr from each instance of the code will refer to +// *different* instances of this ptr. #ifdef __GNUC__ __attribute__((visibility("protected"))) #endif // __GNUC__ @@ -70,7 +68,6 @@ void SetCurrentThreadIdentity( // NOTE: Not async-safe. But can be open-coded. absl::call_once(init_thread_identity_key_once, AllocateThreadIdentityKey, reclaimer); - // b/18366710: // We must mask signals around the call to setspecific as with current glibc, // a concurrent getspecific (needed for GetCurrentThreadIdentityIfPresent()) // may zero our value. diff --git a/absl/base/macros.h b/absl/base/macros.h index 259970fea..31d1c02ec 100644 --- a/absl/base/macros.h +++ b/absl/base/macros.h @@ -144,7 +144,7 @@ enum LinkerInitialized { // // Every usage of a deprecated entity will trigger a warning when compiled with // clang's `-Wdeprecated-declarations` option. This option is turned off by -// default, but the warnings will be reported by go/clang-tidy. +// default, but the warnings will be reported by clang-tidy. #if defined(__clang__) && __cplusplus >= 201103L && defined(__has_warning) #define ABSL_DEPRECATED(message) __attribute__((deprecated(message))) #endif diff --git a/absl/copts.bzl b/absl/copts.bzl index 68aafd5c5..e52ed49f5 100644 --- a/absl/copts.bzl +++ b/absl/copts.bzl @@ -35,6 +35,8 @@ LLVM_FLAGS = [ "-Wno-c++98-compat-pedantic", "-Wno-comma", "-Wno-conversion", + "-Wno-covered-switch-default", + "-Wno-deprecated", "-Wno-disabled-macro-expansion", "-Wno-documentation", "-Wno-documentation-unknown-command", @@ -46,10 +48,6 @@ LLVM_FLAGS = [ "-Wno-format-nonliteral", "-Wno-gcc-compat", "-Wno-global-constructors", - "-Wno-google3-inheriting-constructor", - "-Wno-google3-lambda-expression", - "-Wno-google3-rvalue-reference", - "-Wno-google3-trailing-return-type", "-Wno-nested-anon-types", "-Wno-non-modular-include-in-module", "-Wno-old-style-cast", @@ -62,9 +60,11 @@ LLVM_FLAGS = [ "-Wno-switch-enum", "-Wno-thread-safety-negative", "-Wno-undef", + "-Wno-unknown-warning-option", + "-Wno-unreachable-code", "-Wno-unused-macros", "-Wno-weak-vtables", - # flags below are also controled by -Wconversion which is disabled + # flags below are also controlled by -Wconversion which is disabled "-Wbitfield-enum-conversion", "-Wbool-conversion", "-Wconstant-conversion", @@ -111,16 +111,10 @@ MSVC_TEST_FLAGS = [ "/wd4503", # decorated name length exceeded, name was truncated ] -def _qualify_flags(scope, flags): - return [scope + x for x in flags] - -HYBRID_FLAGS = _qualify_flags("-Xgcc-only=", GCC_FLAGS) + _qualify_flags("-Xclang-only=", LLVM_FLAGS) -HYBRID_TEST_FLAGS = _qualify_flags("-Xgcc-only=", GCC_TEST_FLAGS) + _qualify_flags("-Xclang-only=", LLVM_TEST_FLAGS) - # /Wall with msvc includes unhelpful warnings such as C4711, C4710, ... ABSL_DEFAULT_COPTS = select({ "//absl:windows": MSVC_FLAGS, - "//absl:llvm_warnings": LLVM_FLAGS, + "//absl:llvm_compiler": LLVM_FLAGS, "//conditions:default": GCC_FLAGS, }) @@ -128,7 +122,7 @@ ABSL_DEFAULT_COPTS = select({ # to their (included header) dependencies and fail to build outside absl ABSL_TEST_COPTS = ABSL_DEFAULT_COPTS + select({ "//absl:windows": MSVC_TEST_FLAGS, - "//absl:llvm_warnings": LLVM_TEST_FLAGS, + "//absl:llvm_compiler": LLVM_TEST_FLAGS, "//conditions:default": GCC_TEST_FLAGS, }) diff --git a/absl/debugging/BUILD.bazel b/absl/debugging/BUILD.bazel index 84acf9f99..7a56e4962 100644 --- a/absl/debugging/BUILD.bazel +++ b/absl/debugging/BUILD.bazel @@ -53,7 +53,6 @@ cc_library( "internal/stacktrace_arm-inl.inc", "internal/stacktrace_config.h", "internal/stacktrace_generic-inl.inc", - "internal/stacktrace_libunwind-inl.inc", "internal/stacktrace_powerpc-inl.inc", "internal/stacktrace_unimplemented-inl.inc", "internal/stacktrace_win32-inl.inc", diff --git a/absl/debugging/internal/address_is_readable.cc b/absl/debugging/internal/address_is_readable.cc index 037ea54c3..30d2e71da 100644 --- a/absl/debugging/internal/address_is_readable.cc +++ b/absl/debugging/internal/address_is_readable.cc @@ -33,7 +33,6 @@ bool AddressIsReadable(const void* /* addr */) { return true; } #include #include #include - #include #include #include diff --git a/absl/debugging/internal/stacktrace_config.h b/absl/debugging/internal/stacktrace_config.h index c0df5bb06..57f0b0f2a 100644 --- a/absl/debugging/internal/stacktrace_config.h +++ b/absl/debugging/internal/stacktrace_config.h @@ -25,15 +25,13 @@ #if ABSL_STACKTRACE_INL_HEADER #error ABSL_STACKTRACE_INL_HEADER cannot be directly set #elif defined(__native_client__) || defined(__APPLE__) || \ - defined(__ANDROID__) || defined(__myriad2__) || defined(__asmjs__) || \ - defined(__Fuchsia__) || defined(__GENCLAVE__) || \ - defined(GOOGLE_UNSUPPORTED_OS_HERCULES) + defined(__ANDROID__) || defined(__myriad2__) || defined(asmjs__) || \ + defined(__Fuchsia__) #define ABSL_STACKTRACE_INL_HEADER \ "absl/debugging/internal/stacktrace_unimplemented-inl.inc" // Next, test for Mips and Windows. -// TODO(marmstrong): http://b/21334018: Mips case, remove the check for -// ABSL_STACKTRACE_INL_HEADER. +// TODO(marmstrong): Mips case, remove the check for ABSL_STACKTRACE_INL_HEADER #elif defined(__mips__) && !defined(ABSL_STACKTRACE_INL_HEADER) #define ABSL_STACKTRACE_INL_HEADER \ "absl/debugging/internal/stacktrace_unimplemented-inl.inc" diff --git a/absl/debugging/internal/stacktrace_libunwind-inl.inc b/absl/debugging/internal/stacktrace_libunwind-inl.inc deleted file mode 100644 index e9c2d26a5..000000000 --- a/absl/debugging/internal/stacktrace_libunwind-inl.inc +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 2017 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_LIBUNWIND_INL_H_ -#define ABSL_DEBUGGING_INTERNAL_STACKTRACE_LIBUNWIND_INL_H_ - -// We only need local unwinder. -#define UNW_LOCAL_ONLY - -extern "C" { -#include "third_party/libunwind/include/libunwind.h" -} -#include "absl/debugging/stacktrace.h" - -#include "absl/base/dynamic_annotations.h" -#include "absl/base/internal/raw_logging.h" - -// Sometimes, we can try to get a stack trace from within a stack -// trace, because we don't block signals inside libunwind (which would be too -// expensive: the two extra system calls per stack trace do matter here). -// That can cause a self-deadlock (as in http://b/5722312). -// Protect against such reentrant call by failing to get a stack trace. -// -// We use __thread here because the code here is extremely low level -- it is -// called while collecting stack traces from within malloc and mmap, and thus -// can not call anything which might call malloc or mmap itself. -// In particular, using PerThread or STATIC_THREAD_LOCAL_POD -// here will cause infinite recursion for at least dbg/piii builds with -// crosstool-v12. -static __thread int recursive; - -template -static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count, - const void *, int *min_dropped_frames) { - if (recursive) { - return 0; - } - ++recursive; - - int n = 0; - if (IS_STACK_FRAMES) { - void *ip; - unw_cursor_t cursor; - unw_context_t uc; - unw_word_t sp = 0, next_sp = 0; - - unw_getcontext(&uc); - ABSL_RAW_CHECK(unw_init_local(&cursor, &uc) >= 0, "unw_init_local failed"); - skip_count++; // Do not include current frame - - while (skip_count--) { - if (unw_step(&cursor) <= 0) { - goto out; - } - if (unw_get_reg(&cursor, UNW_REG_SP, &next_sp)) { - goto out; - } - } - - while (n < max_depth) { - if (unw_get_reg(&cursor, UNW_REG_IP, (unw_word_t *) &ip) < 0) { - break; - } - sizes[n] = 0; - result[n++] = ip; - if (unw_step(&cursor) <= 0) { - break; - } - sp = next_sp; - if (unw_get_reg(&cursor, UNW_REG_SP, &next_sp) , 0) { - break; - } - sizes[n - 1] = next_sp - sp; - } - if (min_dropped_frames != nullptr) { - // Implementation detail: we clamp the max of frames we are willing to - // count, so as not to spend too much time in the loop below. - const int kMaxUnwind = 200; - int j = 0; - for (; j < kMaxUnwind; j++) { - if (unw_step(&cursor) < 0) { - break; - } - } - *min_dropped_frames = j; - } - } else { - skip_count++; // Do not include current frame. - void **result_all = reinterpret_cast( - alloca(sizeof(void*) * (max_depth + skip_count))); - int rc = unw_backtrace(result_all, max_depth + skip_count); - - if (rc > 0) { - // Tell MSan that result_all has been initialized. b/34965936. - ANNOTATE_MEMORY_IS_INITIALIZED(result_all, rc * sizeof(void*)); - } - - if (rc > skip_count) { - memcpy(result, &result_all[skip_count], - sizeof(void*) * (rc - skip_count)); - n = rc - skip_count; - } else { - n = 0; - } - - if (min_dropped_frames != nullptr) { - // Not implemented. - *min_dropped_frames = 0; - } - } - - out: - --recursive; - return n; -} - -#endif // ABSL_DEBUGGING_INTERNAL_STACKTRACE_LIBUNWIND_INL_H_ diff --git a/absl/debugging/leak_check_test.cc b/absl/debugging/leak_check_test.cc index 27ca2d1b7..febd1ee4f 100644 --- a/absl/debugging/leak_check_test.cc +++ b/absl/debugging/leak_check_test.cc @@ -12,7 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include +#include + #include "gtest/gtest.h" #include "absl/base/internal/raw_logging.h" #include "absl/debugging/leak_check.h" diff --git a/absl/debugging/stacktrace.cc b/absl/debugging/stacktrace.cc index 6c1690426..61fee6190 100644 --- a/absl/debugging/stacktrace.cc +++ b/absl/debugging/stacktrace.cc @@ -38,6 +38,7 @@ #include +#include "absl/base/attributes.h" #include "absl/base/port.h" #include "absl/debugging/internal/stacktrace_config.h" @@ -45,14 +46,13 @@ #include ABSL_STACKTRACE_INL_HEADER #else # error Cannot calculate stack trace: will need to write for your environment -# include "absl/debugging/internal/stacktrace_x86-inl.inc" -# include "absl/debugging/internal/stacktrace_win32-inl.inc" -# include "absl/debugging/internal/stacktrace_unimplemented-inl.inc" -# include "absl/debugging/internal/stacktrace_libunwind-inl.inc" +# include "absl/debugging/internal/stacktrace_aarch64-inl.inc" +# include "absl/debugging/internal/stacktrace_arm-inl.inc" # include "absl/debugging/internal/stacktrace_generic-inl.inc" # include "absl/debugging/internal/stacktrace_powerpc-inl.inc" -# include "absl/debugging/internal/stacktrace_arm-inl.inc" -# include "absl/debugging/internal/stacktrace_aarch64-inl.inc" +# include "absl/debugging/internal/stacktrace_unimplemented-inl.inc" +# include "absl/debugging/internal/stacktrace_win32-inl.inc" +# include "absl/debugging/internal/stacktrace_x86-inl.inc" #endif namespace absl { diff --git a/absl/meta/type_traits.h b/absl/meta/type_traits.h index 779afd2dd..ced66269b 100644 --- a/absl/meta/type_traits.h +++ b/absl/meta/type_traits.h @@ -35,6 +35,7 @@ #ifndef ABSL_META_TYPE_TRAITS_H_ #define ABSL_META_TYPE_TRAITS_H_ +#include #include #include "absl/base/config.h" diff --git a/absl/meta/type_traits_test.cc b/absl/meta/type_traits_test.cc index 54dcc8f41..15e1c28bd 100644 --- a/absl/meta/type_traits_test.cc +++ b/absl/meta/type_traits_test.cc @@ -17,9 +17,9 @@ #include #include #include +#include #include -#include "gmock/gmock.h" #include "gtest/gtest.h" namespace { diff --git a/absl/numeric/int128.cc b/absl/numeric/int128.cc index 184041fe4..7debf56a6 100644 --- a/absl/numeric/int128.cc +++ b/absl/numeric/int128.cc @@ -14,11 +14,12 @@ #include "absl/numeric/int128.h" +#include #include -#include #include #include // NOLINT(readability/streams) #include +#include namespace absl { diff --git a/absl/numeric/int128.h b/absl/numeric/int128.h index e3ba23840..bab5e2175 100644 --- a/absl/numeric/int128.h +++ b/absl/numeric/int128.h @@ -206,7 +206,7 @@ extern std::ostream& operator<<(std::ostream& o, const uint128& b); uint64_t Uint128Low64(const uint128& v); uint64_t Uint128High64(const uint128& v); -// TODO(b/31950287): Implement signed 128-bit type +// TODO(absl-team): Implement signed 128-bit type // -------------------------------------------------------------------------- // Implementation details follow diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel index 070721cc1..da441e201 100644 --- a/absl/strings/BUILD.bazel +++ b/absl/strings/BUILD.bazel @@ -162,6 +162,7 @@ cc_test( deps = [ ":strings", ":internal", + "//absl/base:core_headers", ] + select(GUNIT_MAIN_DEPS_SELECTOR), ) diff --git a/absl/strings/escaping.cc b/absl/strings/escaping.cc index f1576057f..7d688ac3f 100644 --- a/absl/strings/escaping.cc +++ b/absl/strings/escaping.cc @@ -14,22 +14,21 @@ #include "absl/strings/escaping.h" +#include #include #include -#include #include +#include #include #include -#include #include "absl/base/internal/endian.h" #include "absl/base/internal/raw_logging.h" #include "absl/base/internal/unaligned_access.h" -#include "absl/base/macros.h" -#include "absl/base/port.h" #include "absl/strings/internal/char_map.h" #include "absl/strings/internal/resize_uninitialized.h" #include "absl/strings/internal/utf8.h" +#include "absl/strings/str_cat.h" #include "absl/strings/str_join.h" #include "absl/strings/string_view.h" diff --git a/absl/strings/escaping_test.cc b/absl/strings/escaping_test.cc index d464051df..ecac9ca8c 100644 --- a/absl/strings/escaping_test.cc +++ b/absl/strings/escaping_test.cc @@ -17,11 +17,11 @@ #include #include #include +#include #include #include "gmock/gmock.h" #include "gtest/gtest.h" -#include "absl/base/macros.h" #include "absl/container/fixed_array.h" #include "absl/strings/str_cat.h" diff --git a/absl/strings/internal/char_map_test.cc b/absl/strings/internal/char_map_test.cc index 2167be975..c3601e101 100644 --- a/absl/strings/internal/char_map_test.cc +++ b/absl/strings/internal/char_map_test.cc @@ -14,9 +14,9 @@ #include "absl/strings/internal/char_map.h" -#include -#include #include +#include +#include #include "gmock/gmock.h" #include "gtest/gtest.h" diff --git a/absl/strings/internal/memutil_test.cc b/absl/strings/internal/memutil_test.cc index 1ff60f20e..09424de9a 100644 --- a/absl/strings/internal/memutil_test.cc +++ b/absl/strings/internal/memutil_test.cc @@ -16,7 +16,6 @@ #include "absl/strings/internal/memutil.h" -#include #include #include "gtest/gtest.h" diff --git a/absl/strings/internal/ostringstream_test.cc b/absl/strings/internal/ostringstream_test.cc index 0047ec822..069a0e1fb 100644 --- a/absl/strings/internal/ostringstream_test.cc +++ b/absl/strings/internal/ostringstream_test.cc @@ -16,7 +16,6 @@ #include #include -#include #include #include diff --git a/absl/strings/internal/utf8_test.cc b/absl/strings/internal/utf8_test.cc index 4d437427a..64cec70df 100644 --- a/absl/strings/internal/utf8_test.cc +++ b/absl/strings/internal/utf8_test.cc @@ -14,12 +14,11 @@ #include "absl/strings/internal/utf8.h" -#include -#include -#include #include +#include #include "gtest/gtest.h" +#include "absl/base/port.h" namespace { diff --git a/absl/strings/match.cc b/absl/strings/match.cc index 53881bdd3..25bd7f0b8 100644 --- a/absl/strings/match.cc +++ b/absl/strings/match.cc @@ -27,9 +27,9 @@ bool CaseEqual(absl::string_view piece1, absl::string_view piece2) { } } // namespace -bool StartsWithIgnoreCase(absl::string_view text, absl::string_view preffix) { - return (text.size() >= preffix.size()) && - CaseEqual(text.substr(0, preffix.size()), preffix); +bool StartsWithIgnoreCase(absl::string_view text, absl::string_view prefix) { + return (text.size() >= prefix.size()) && + CaseEqual(text.substr(0, prefix.size()), prefix); } bool EndsWithIgnoreCase(absl::string_view text, absl::string_view suffix) { diff --git a/absl/strings/match.h b/absl/strings/match.h index 4a5d1c034..4ac35f192 100644 --- a/absl/strings/match.h +++ b/absl/strings/match.h @@ -41,40 +41,42 @@ namespace absl { // StrContains() // -// Returns whether a given std::string `s` contains the substring `x`. -inline bool StrContains(absl::string_view s, absl::string_view x) { - return static_cast(s.find(x, 0)) != s.npos; +// Returns whether a given std::string `haystack` contains the substring `needle`. +inline bool StrContains(absl::string_view haystack, absl::string_view needle) { + return static_cast(haystack.find(needle, 0)) != + haystack.npos; } // StartsWith() // -// Returns whether a given std::string `s` begins with `x`. -inline bool StartsWith(absl::string_view s, absl::string_view x) { - return x.empty() || - (s.size() >= x.size() && memcmp(s.data(), x.data(), x.size()) == 0); +// Returns whether a given std::string `text` begins with `prefix`. +inline bool StartsWith(absl::string_view text, absl::string_view prefix) { + return prefix.empty() || + (text.size() >= prefix.size() && + memcmp(text.data(), prefix.data(), prefix.size()) == 0); } // EndsWith() // -// Returns whether a given std::string `s` ends `x`. -inline bool EndsWith(absl::string_view s, absl::string_view x) { - return x.empty() || - (s.size() >= x.size() && - memcmp(s.data() + (s.size() - x.size()), x.data(), x.size()) == 0); +// Returns whether a given std::string `text` ends with `suffix`. +inline bool EndsWith(absl::string_view text, absl::string_view suffix) { + return suffix.empty() || + (text.size() >= suffix.size() && + memcmp(text.data() + (text.size() - suffix.size()), suffix.data(), + suffix.size()) == 0); } // StartsWithIgnoreCase() // // Returns whether a given std::string `text` starts with `starts_with`, ignoring // case in the comparison. -bool StartsWithIgnoreCase(absl::string_view text, - absl::string_view starts_with); +bool StartsWithIgnoreCase(absl::string_view text, absl::string_view prefix); // EndsWithIgnoreCase() // // Returns whether a given std::string `text` ends with `ends_with`, ignoring case // in the comparison. -bool EndsWithIgnoreCase(absl::string_view text, absl::string_view ends_with); +bool EndsWithIgnoreCase(absl::string_view text, absl::string_view suffix); } // namespace absl diff --git a/absl/strings/numbers.cc b/absl/strings/numbers.cc index 3b093b98c..ac73f5308 100644 --- a/absl/strings/numbers.cc +++ b/absl/strings/numbers.cc @@ -3,19 +3,20 @@ #include "absl/strings/numbers.h" +#include #include -#include #include // for DBL_DIG and FLT_DIG #include // for HUGE_VAL +#include #include #include #include +#include #include #include -#include +#include #include "absl/base/internal/raw_logging.h" -#include "absl/numeric/int128.h" #include "absl/strings/ascii.h" #include "absl/strings/internal/memutil.h" #include "absl/strings/str_cat.h" @@ -291,386 +292,6 @@ char* numbers_internal::FastInt64ToBuffer(int64_t i, char* buffer) { return numbers_internal::FastUInt64ToBuffer(u, buffer); } -// Although DBL_DIG is typically 15, DBL_MAX is normally represented with 17 -// digits of precision. When converted to a std::string value with fewer digits -// of precision using strtod(), the result can be bigger than DBL_MAX due to -// a rounding error. Converting this value back to a double will produce an -// Inf which will trigger a SIGFPE if FP exceptions are enabled. We skip -// the precision check for sufficiently large values to avoid the SIGFPE. -static const double kDoublePrecisionCheckMax = DBL_MAX / 1.000000000000001; - -char* numbers_internal::RoundTripDoubleToBuffer(double d, char* buffer) { - // DBL_DIG is 15 for IEEE-754 doubles, which are used on almost all - // platforms these days. Just in case some system exists where DBL_DIG - // is significantly larger -- and risks overflowing our buffer -- we have - // this assert. - static_assert(DBL_DIG < 20, "DBL_DIG is too big"); - - bool full_precision_needed = true; - if (std::abs(d) <= kDoublePrecisionCheckMax) { - int snprintf_result = snprintf(buffer, numbers_internal::kFastToBufferSize, - "%.*g", DBL_DIG, d); - - // The snprintf should never overflow because the buffer is significantly - // larger than the precision we asked for. - assert(snprintf_result > 0 && - snprintf_result < numbers_internal::kFastToBufferSize); - (void)snprintf_result; - - full_precision_needed = strtod(buffer, nullptr) != d; - } - - if (full_precision_needed) { - int snprintf_result = snprintf(buffer, numbers_internal::kFastToBufferSize, - "%.*g", DBL_DIG + 2, d); - - // Should never overflow; see above. - assert(snprintf_result > 0 && - snprintf_result < numbers_internal::kFastToBufferSize); - (void)snprintf_result; - } - return buffer; -} -// This table is used to quickly calculate the base-ten exponent of a given -// float, and then to provide a multiplier to bring that number into the -// range 1-999,999,999, that is, into uint32_t range. Finally, the exp -// std::string is made available so there is one less int-to-std::string conversion -// to be done. - -struct Spec { - double min_range; - double multiplier; - const char expstr[5]; -}; -const Spec neg_exp_table[] = { - {1.4e-45f, 1e+55, "e-45"}, // - {1e-44f, 1e+54, "e-44"}, // - {1e-43f, 1e+53, "e-43"}, // - {1e-42f, 1e+52, "e-42"}, // - {1e-41f, 1e+51, "e-41"}, // - {1e-40f, 1e+50, "e-40"}, // - {1e-39f, 1e+49, "e-39"}, // - {1e-38f, 1e+48, "e-38"}, // - {1e-37f, 1e+47, "e-37"}, // - {1e-36f, 1e+46, "e-36"}, // - {1e-35f, 1e+45, "e-35"}, // - {1e-34f, 1e+44, "e-34"}, // - {1e-33f, 1e+43, "e-33"}, // - {1e-32f, 1e+42, "e-32"}, // - {1e-31f, 1e+41, "e-31"}, // - {1e-30f, 1e+40, "e-30"}, // - {1e-29f, 1e+39, "e-29"}, // - {1e-28f, 1e+38, "e-28"}, // - {1e-27f, 1e+37, "e-27"}, // - {1e-26f, 1e+36, "e-26"}, // - {1e-25f, 1e+35, "e-25"}, // - {1e-24f, 1e+34, "e-24"}, // - {1e-23f, 1e+33, "e-23"}, // - {1e-22f, 1e+32, "e-22"}, // - {1e-21f, 1e+31, "e-21"}, // - {1e-20f, 1e+30, "e-20"}, // - {1e-19f, 1e+29, "e-19"}, // - {1e-18f, 1e+28, "e-18"}, // - {1e-17f, 1e+27, "e-17"}, // - {1e-16f, 1e+26, "e-16"}, // - {1e-15f, 1e+25, "e-15"}, // - {1e-14f, 1e+24, "e-14"}, // - {1e-13f, 1e+23, "e-13"}, // - {1e-12f, 1e+22, "e-12"}, // - {1e-11f, 1e+21, "e-11"}, // - {1e-10f, 1e+20, "e-10"}, // - {1e-09f, 1e+19, "e-09"}, // - {1e-08f, 1e+18, "e-08"}, // - {1e-07f, 1e+17, "e-07"}, // - {1e-06f, 1e+16, "e-06"}, // - {1e-05f, 1e+15, "e-05"}, // - {1e-04f, 1e+14, "e-04"}, // -}; - -const Spec pos_exp_table[] = { - {1e+08f, 1e+02, "e+08"}, // - {1e+09f, 1e+01, "e+09"}, // - {1e+10f, 1e+00, "e+10"}, // - {1e+11f, 1e-01, "e+11"}, // - {1e+12f, 1e-02, "e+12"}, // - {1e+13f, 1e-03, "e+13"}, // - {1e+14f, 1e-04, "e+14"}, // - {1e+15f, 1e-05, "e+15"}, // - {1e+16f, 1e-06, "e+16"}, // - {1e+17f, 1e-07, "e+17"}, // - {1e+18f, 1e-08, "e+18"}, // - {1e+19f, 1e-09, "e+19"}, // - {1e+20f, 1e-10, "e+20"}, // - {1e+21f, 1e-11, "e+21"}, // - {1e+22f, 1e-12, "e+22"}, // - {1e+23f, 1e-13, "e+23"}, // - {1e+24f, 1e-14, "e+24"}, // - {1e+25f, 1e-15, "e+25"}, // - {1e+26f, 1e-16, "e+26"}, // - {1e+27f, 1e-17, "e+27"}, // - {1e+28f, 1e-18, "e+28"}, // - {1e+29f, 1e-19, "e+29"}, // - {1e+30f, 1e-20, "e+30"}, // - {1e+31f, 1e-21, "e+31"}, // - {1e+32f, 1e-22, "e+32"}, // - {1e+33f, 1e-23, "e+33"}, // - {1e+34f, 1e-24, "e+34"}, // - {1e+35f, 1e-25, "e+35"}, // - {1e+36f, 1e-26, "e+36"}, // - {1e+37f, 1e-27, "e+37"}, // - {1e+38f, 1e-28, "e+38"}, // - {1e+39, 1e-29, "e+39"}, // -}; - -struct ExpCompare { - bool operator()(const Spec& spec, double d) const { - return spec.min_range < d; - } -}; - -// Utility routine(s) for RoundTripFloatToBuffer: -// OutputNecessaryDigits takes two 11-digit numbers, whose integer portion -// represents the fractional part of a floating-point number, and outputs a -// number that is in-between them, with the fewest digits possible. For -// instance, given 12345678900 and 12345876900, it would output "0123457". -// When there are multiple final digits that would satisfy this requirement, -// this routine attempts to use a digit that would represent the average of -// lower_double and upper_double. -// -// Although the routine works using integers, all callers use doubles, so -// for their convenience this routine accepts doubles. -static char* OutputNecessaryDigits(double lower_double, double upper_double, - char* out) { - assert(lower_double > 0); - assert(lower_double < upper_double - 10); - assert(upper_double < 100000000000.0); - - // Narrow the range a bit; without this bias, an input of lower=87654320010.0 - // and upper=87654320100.0 would produce an output of 876543201 - // - // We do this in three steps: first, we lower the upper bound and truncate it - // to an integer. Then, we increase the lower bound by exactly the amount we - // just decreased the upper bound by - at that point, the midpoint is exactly - // where it used to be. Then we truncate the lower bound. - - uint64_t upper64 = upper_double - (1.0 / 1024); - double shrink = upper_double - upper64; - uint64_t lower64 = lower_double + shrink; - - // Theory of operation: we convert the lower number to ascii representation, - // two digits at a time. As we go, we remove the same digits from the upper - // number. When we see the upper number does not share those same digits, we - // know we can stop converting. When we stop, the last digit we output is - // taken from the average of upper and lower values, rounded up. - char buf[2]; - uint32_t lodigits = - static_cast(lower64 / 1000000000); // 1,000,000,000 - uint64_t mul64 = lodigits * uint64_t{1000000000}; - - PutTwoDigits(lodigits, out); - out += 2; - if (upper64 - mul64 >= 1000000000) { // digit mismatch! - PutTwoDigits(upper64 / 1000000000, buf); - if (out[-2] != buf[0]) { - out[-2] = '0' + (upper64 + lower64 + 10000000000) / 20000000000; - --out; - } else { - PutTwoDigits((upper64 + lower64 + 1000000000) / 2000000000, out - 2); - } - *out = '\0'; - return out; - } - uint32_t lower = static_cast(lower64 - mul64); - uint32_t upper = static_cast(upper64 - mul64); - - lodigits = lower / 10000000; // 10,000,000 - uint32_t mul = lodigits * 10000000; - PutTwoDigits(lodigits, out); - out += 2; - if (upper - mul >= 10000000) { // digit mismatch! - PutTwoDigits(upper / 10000000, buf); - if (out[-2] != buf[0]) { - out[-2] = '0' + (upper + lower + 100000000) / 200000000; - --out; - } else { - PutTwoDigits((upper + lower + 10000000) / 20000000, out - 2); - } - *out = '\0'; - return out; - } - lower -= mul; - upper -= mul; - - lodigits = lower / 100000; // 100,000 - mul = lodigits * 100000; - PutTwoDigits(lodigits, out); - out += 2; - if (upper - mul >= 100000) { // digit mismatch! - PutTwoDigits(upper / 100000, buf); - if (out[-2] != buf[0]) { - out[-2] = '0' + (upper + lower + 1000000) / 2000000; - --out; - } else { - PutTwoDigits((upper + lower + 100000) / 200000, out - 2); - } - *out = '\0'; - return out; - } - lower -= mul; - upper -= mul; - - lodigits = lower / 1000; - mul = lodigits * 1000; - PutTwoDigits(lodigits, out); - out += 2; - if (upper - mul >= 1000) { // digit mismatch! - PutTwoDigits(upper / 1000, buf); - if (out[-2] != buf[0]) { - out[-2] = '0' + (upper + lower + 10000) / 20000; - --out; - } else { - PutTwoDigits((upper + lower + 1000) / 2000, out - 2); - } - *out = '\0'; - return out; - } - lower -= mul; - upper -= mul; - - PutTwoDigits(lower / 10, out); - out += 2; - PutTwoDigits(upper / 10, buf); - if (out[-2] != buf[0]) { - out[-2] = '0' + (upper + lower + 100) / 200; - --out; - } else { - PutTwoDigits((upper + lower + 10) / 20, out - 2); - } - *out = '\0'; - return out; -} - -// RoundTripFloatToBuffer converts the given float into a std::string which, if -// passed to strtof, will produce the exact same original float. It does this -// by computing the range of possible doubles which map to the given float, and -// then examining the digits of the doubles in that range. If all the doubles -// in the range start with "2.37", then clearly our float does, too. As soon as -// they diverge, only one more digit is needed. -char* numbers_internal::RoundTripFloatToBuffer(float f, char* buffer) { - static_assert(std::numeric_limits::is_iec559, - "IEEE-754/IEC-559 support only"); - - char* out = buffer; // we write data to out, incrementing as we go, but - // FloatToBuffer always returns the address of the buffer - // passed in. - - if (std::isnan(f)) { - strcpy(out, "nan"); // NOLINT(runtime/printf) - return buffer; - } - if (f == 0) { // +0 and -0 are handled here - if (std::signbit(f)) { - strcpy(out, "-0"); // NOLINT(runtime/printf) - } else { - strcpy(out, "0"); // NOLINT(runtime/printf) - } - return buffer; - } - if (f < 0) { - *out++ = '-'; - f = -f; - } - if (std::isinf(f)) { - strcpy(out, "inf"); // NOLINT(runtime/printf) - return buffer; - } - - double next_lower = nextafterf(f, 0.0f); - // For all doubles in the range lower_bound < f < upper_bound, the - // nearest float is f. - double lower_bound = (f + next_lower) * 0.5; - double upper_bound = f + (f - lower_bound); - // Note: because std::nextafter is slow, we calculate upper_bound - // assuming that it is the same distance from f as lower_bound is. - // For exact powers of two, upper_bound is actually twice as far - // from f as lower_bound is, but this turns out not to matter. - - // Most callers pass floats that are either 0 or within the - // range 0.0001 through 100,000,000, so handle those first, - // since they don't need exponential notation. - const Spec* spec = nullptr; - if (f < 1.0) { - if (f >= 0.0001f) { - // for fractional values, we set up the multiplier at the same - // time as we output the leading "0." / "0.0" / "0.00" / "0.000" - double multiplier = 1e+11; - *out++ = '0'; - *out++ = '.'; - if (f < 0.1f) { - multiplier = 1e+12; - *out++ = '0'; - if (f < 0.01f) { - multiplier = 1e+13; - *out++ = '0'; - if (f < 0.001f) { - multiplier = 1e+14; - *out++ = '0'; - } - } - } - OutputNecessaryDigits(lower_bound * multiplier, upper_bound * multiplier, - out); - return buffer; - } - spec = std::lower_bound(std::begin(neg_exp_table), std::end(neg_exp_table), - double{f}, ExpCompare()); - if (spec == std::end(neg_exp_table)) --spec; - } else if (f < 1e8) { - // Handling non-exponential format greater than 1.0 is similar to the above, - // but instead of 0.0 / 0.00 / 0.000, the prefix is simply the truncated - // integer part of f. - int32_t as_int = f; - out = numbers_internal::FastUInt32ToBuffer(as_int, out); - // Easy: if the integer part is within (lower_bound, upper_bound), then we - // are already done. - if (as_int > lower_bound && as_int < upper_bound) { - return buffer; - } - *out++ = '.'; - OutputNecessaryDigits((lower_bound - as_int) * 1e11, - (upper_bound - as_int) * 1e11, out); - return buffer; - } else { - spec = std::lower_bound(std::begin(pos_exp_table), - std::end(pos_exp_table), - double{f}, ExpCompare()); - if (spec == std::end(pos_exp_table)) --spec; - } - // Exponential notation from here on. "spec" was computed using lower_bound, - // which means it's the first spec from the table where min_range is greater - // or equal to f. - // Unfortunately that's not quite what we want; we want a min_range that is - // less or equal. So first thing, if it was greater, back up one entry. - if (spec->min_range > f) --spec; - - // The digits might be "237000123", but we want "2.37000123", - // so we output the digits one character later, and then move the first - // digit back so we can stick the "." in. - char* start = out; - out = OutputNecessaryDigits(lower_bound * spec->multiplier, - upper_bound * spec->multiplier, start + 1); - start[0] = start[1]; - start[1] = '.'; - - // If it turns out there was only one digit output, then back up over the '.' - if (out == &start[2]) --out; - - // Now add the "e+NN" part. - memcpy(out, spec->expstr, 4); - out[4] = '\0'; - return buffer; -} - // Returns the number of leading 0 bits in a 64-bit value. // TODO(jorg): Replace with builtin_clzll if available. // Are we shipping util/bits in absl? diff --git a/absl/strings/numbers.h b/absl/strings/numbers.h index f17dc97b2..74aebc802 100644 --- a/absl/strings/numbers.h +++ b/absl/strings/numbers.h @@ -92,9 +92,6 @@ char* FastUInt64ToBuffer(uint64_t i, char* buffer); static const int kFastToBufferSize = 32; static const int kSixDigitsToBufferSize = 16; -char* RoundTripDoubleToBuffer(double d, char* buffer); -char* RoundTripFloatToBuffer(float f, char* buffer); - // Helper function for fast formatting of floating-point values. // The result is the same as printf's "%g", a.k.a. "%.6g"; that is, six // significant digits are returned, trailing zeros are removed, and numbers diff --git a/absl/strings/numbers_test.cc b/absl/strings/numbers_test.cc index 9b74d67b8..817604d78 100644 --- a/absl/strings/numbers_test.cc +++ b/absl/strings/numbers_test.cc @@ -3,10 +3,7 @@ #include "absl/strings/numbers.h" #include -#include -#include #include // NOLINT(build/c++11) -#include #include #include #include @@ -25,7 +22,6 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/base/internal/raw_logging.h" -#include "absl/base/port.h" #include "absl/strings/str_cat.h" #include "absl/strings/internal/numbers_test_common.inc" @@ -42,7 +38,6 @@ using absl::numbers_internal::safe_strto32_base; using absl::numbers_internal::safe_strto64_base; using absl::numbers_internal::safe_strtou32_base; using absl::numbers_internal::safe_strtou64_base; -using absl::numbers_internal::RoundTripFloatToBuffer; using absl::numbers_internal::SixDigitsToBuffer; using absl::SimpleAtoi; using testing::Eq; @@ -776,42 +771,6 @@ void ExhaustiveFloat(uint32_t cases, R&& runnable) { } } -TEST_F(SimpleDtoaTest, ExhaustiveFloatToBuffer) { - uint64_t test_count = 0; - std::vector mismatches; - ExhaustiveFloat(kFloatNumCases, [&](float f) { - if (f != f) return; // rule out NaNs - ++test_count; - char fastbuf[kFastToBufferSize]; - RoundTripFloatToBuffer(f, fastbuf); - float round_trip = strtof(fastbuf, nullptr); - if (f != round_trip) { - mismatches.push_back(f); - if (mismatches.size() < 10) { - ABSL_RAW_LOG(ERROR, "%s", - absl::StrCat("Round-trip failure with float. ", "f=", f, - "=", ToNineDigits(f), " fast=", fastbuf, - " strtof=", ToNineDigits(round_trip)) - .c_str()); - } - } - }); - if (!mismatches.empty()) { - EXPECT_EQ(mismatches.size(), 0); - for (size_t i = 0; i < mismatches.size(); ++i) { - if (i > 100) i = mismatches.size() - 1; - float f = mismatches[i]; - std::string msg = - absl::StrCat("Mismatch #", i, " f=", f, " (", ToNineDigits(f), ")"); - char buf[kFastToBufferSize]; - absl::StrAppend(&msg, " fast='", RoundTripFloatToBuffer(f, buf), "'"); - float rt = strtof(buf, nullptr); - absl::StrAppend(&msg, " rt=", ToNineDigits(rt)); - ABSL_RAW_LOG(ERROR, "%s", msg.c_str()); - } - } -} - TEST_F(SimpleDtoaTest, ExhaustiveDoubleToSixDigits) { uint64_t test_count = 0; std::vector mismatches; diff --git a/absl/strings/str_cat.cc b/absl/strings/str_cat.cc index 0c75655c9..99eb28908 100644 --- a/absl/strings/str_cat.cc +++ b/absl/strings/str_cat.cc @@ -14,9 +14,9 @@ #include "absl/strings/str_cat.h" -#include +#include +#include #include -#include #include #include "absl/strings/ascii.h" diff --git a/absl/strings/str_join_test.cc b/absl/strings/str_join_test.cc index 7c2ed09b9..03b60f03c 100644 --- a/absl/strings/str_join_test.cc +++ b/absl/strings/str_join_test.cc @@ -16,22 +16,21 @@ #include "absl/strings/str_join.h" -#include #include #include #include +#include #include #include +#include #include -#include #include #include +#include #include -#include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/base/macros.h" -#include "absl/base/port.h" #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_split.h" diff --git a/absl/strings/str_replace_test.cc b/absl/strings/str_replace_test.cc index f49c7e1c3..5d003a224 100644 --- a/absl/strings/str_replace_test.cc +++ b/absl/strings/str_replace_test.cc @@ -15,11 +15,12 @@ #include "absl/strings/str_replace.h" #include +#include #include #include "gtest/gtest.h" -#include "absl/strings/str_split.h" #include "absl/strings/str_cat.h" +#include "absl/strings/str_split.h" TEST(StrReplaceAll, OneReplacement) { std::string s; diff --git a/absl/strings/str_split.cc b/absl/strings/str_split.cc index 910a67cf2..0207213c2 100644 --- a/absl/strings/str_split.cc +++ b/absl/strings/str_split.cc @@ -14,11 +14,14 @@ #include "absl/strings/str_split.h" +#include #include +#include #include #include #include #include +#include #include "absl/base/internal/raw_logging.h" #include "absl/strings/ascii.h" diff --git a/absl/strings/str_split_test.cc b/absl/strings/str_split_test.cc index a95a0fbd3..22a68d0f8 100644 --- a/absl/strings/str_split_test.cc +++ b/absl/strings/str_split_test.cc @@ -14,15 +14,13 @@ #include "absl/strings/str_split.h" -#include -#include -#include #include -#include +#include #include #include #include #include +#include #include #include #include @@ -31,7 +29,6 @@ #include "gtest/gtest.h" #include "absl/base/dynamic_annotations.h" // for RunningOnValgrind #include "absl/base/macros.h" -#include "absl/base/port.h" #include "absl/strings/numbers.h" namespace { diff --git a/absl/strings/string_view.cc b/absl/strings/string_view.cc index 4d4ba6c17..0e1729546 100644 --- a/absl/strings/string_view.cc +++ b/absl/strings/string_view.cc @@ -20,7 +20,6 @@ #include #include #include -#include #include "absl/strings/internal/memutil.h" #include "absl/strings/internal/resize_uninitialized.h" diff --git a/absl/strings/string_view.h b/absl/strings/string_view.h index e2609f174..8e37acb8d 100644 --- a/absl/strings/string_view.h +++ b/absl/strings/string_view.h @@ -180,9 +180,9 @@ class string_view { constexpr string_view(const char* data, size_type len) : ptr_(data), length_(CheckLengthInternal(len)) {} - // NOTE(b/36227513): harmlessly omitted to work around gdb bug. - // constexpr string_view(const string_view&) noexcept = default; - // string_view& operator=(const string_view&) noexcept = default; + // NOTE: Harmlessly omitted to work around gdb bug. + // constexpr string_view(const string_view&) noexcept = default; + // string_view& operator=(const string_view&) noexcept = default; // Iterators @@ -550,8 +550,7 @@ namespace absl { // ClippedSubstr() // // Like `s.substr(pos, n)`, but clips `pos` to an upper bound of `s.size()`. -// Provided because std::string_view::substr throws if `pos > size()`, -// to support b/37991613. +// Provided because std::string_view::substr throws if `pos > size()` inline string_view ClippedSubstr(string_view s, size_t pos, size_t n = string_view::npos) { pos = std::min(pos, static_cast(s.size())); diff --git a/absl/strings/string_view_test.cc b/absl/strings/string_view_test.cc index 439d64997..6be6f3b82 100644 --- a/absl/strings/string_view_test.cc +++ b/absl/strings/string_view_test.cc @@ -14,12 +14,13 @@ #include "absl/strings/string_view.h" -#include +#include #include #include +#include #include -#include #include +#include #include #include #include @@ -27,7 +28,6 @@ #include "gtest/gtest.h" #include "absl/base/config.h" #include "absl/base/dynamic_annotations.h" -#include "absl/base/port.h" namespace { diff --git a/absl/strings/strip.cc b/absl/strings/strip.cc index 968c09c6f..adc219f16 100644 --- a/absl/strings/strip.cc +++ b/absl/strings/strip.cc @@ -18,7 +18,6 @@ #include "absl/strings/strip.h" #include -#include #include #include diff --git a/absl/strings/substitute.h b/absl/strings/substitute.h index 5d6bfd90c..3fc4ac4cd 100644 --- a/absl/strings/substitute.h +++ b/absl/strings/substitute.h @@ -73,7 +73,7 @@ // * calls for a position argument which is not provided, // e.g. Substitute("Hello $2", "world"), or // * specifies a non-digit, non-$ character after an unescaped $ character, -// e.g. "Hello %f". +// e.g. "Hello $f". // In debug mode, i.e. #ifndef NDEBUG, such errors terminate the program. #ifndef ABSL_STRINGS_SUBSTITUTE_H_ @@ -149,9 +149,11 @@ class Arg { : piece_(scratch_, numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {} Arg(float value) // NOLINT(runtime/explicit) - : piece_(numbers_internal::RoundTripFloatToBuffer(value, scratch_)) {} + : piece_(scratch_, numbers_internal::SixDigitsToBuffer(value, scratch_)) { + } Arg(double value) // NOLINT(runtime/explicit) - : piece_(numbers_internal::RoundTripDoubleToBuffer(value, scratch_)) {} + : piece_(scratch_, numbers_internal::SixDigitsToBuffer(value, scratch_)) { + } Arg(bool value) // NOLINT(runtime/explicit) : piece_(value ? "true" : "false") {} // `void*` values, with the exception of `char*`, are printed as @@ -211,9 +213,9 @@ constexpr int PlaceholderBitmask(const char* format) { // // Example: // template -// void VarMsg(std::string* boilerplate, const std::string& format, +// void VarMsg(std::string* boilerplate, absl::string_view format, // const Args&... args) { -// std::string s = absl::SubstituteAndAppend(boilerplate, format, args...)"; +// absl::SubstituteAndAppend(boilerplate, format, args...); // } // inline void SubstituteAndAppend(std::string* output, absl::string_view format) { @@ -458,8 +460,8 @@ void SubstituteAndAppend( // // Example: // template -// void VarMsg(const std::string& format, const Args&... args) { -// std::string s = absl::Substitute(format, args...)"; +// void VarMsg(absl::string_view format, const Args&... args) { +// std::string s = absl::Substitute(format, args...); ABSL_MUST_USE_RESULT inline std::string Substitute(absl::string_view format) { std::string result; diff --git a/absl/synchronization/blocking_counter.cc b/absl/synchronization/blocking_counter.cc index 48e3650da..7e68e960b 100644 --- a/absl/synchronization/blocking_counter.cc +++ b/absl/synchronization/blocking_counter.cc @@ -14,6 +14,8 @@ #include "absl/synchronization/blocking_counter.h" +#include "absl/base/internal/raw_logging.h" + namespace absl { // Return whether int *arg is zero. diff --git a/absl/synchronization/blocking_counter_test.cc b/absl/synchronization/blocking_counter_test.cc index b4b667723..e8223f841 100644 --- a/absl/synchronization/blocking_counter_test.cc +++ b/absl/synchronization/blocking_counter_test.cc @@ -14,13 +14,12 @@ #include "absl/synchronization/blocking_counter.h" -#include -#include #include // NOLINT(build/c++11) #include #include "gtest/gtest.h" #include "absl/time/clock.h" +#include "absl/time/time.h" namespace absl { namespace { diff --git a/absl/synchronization/internal/create_thread_identity.cc b/absl/synchronization/internal/create_thread_identity.cc index 14976347b..0134a4399 100644 --- a/absl/synchronization/internal/create_thread_identity.cc +++ b/absl/synchronization/internal/create_thread_identity.cc @@ -12,13 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include +#include + // This file is a no-op if the required LowLevelAlloc support is missing. #include "absl/base/internal/low_level_alloc.h" #ifndef ABSL_LOW_LEVEL_ALLOC_MISSING #include -#include -#include #include "absl/base/internal/spinlock.h" #include "absl/base/internal/thread_identity.h" diff --git a/absl/synchronization/internal/graphcycles_test.cc b/absl/synchronization/internal/graphcycles_test.cc index 734f2770b..9a85b3907 100644 --- a/absl/synchronization/internal/graphcycles_test.cc +++ b/absl/synchronization/internal/graphcycles_test.cc @@ -12,22 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Copyright 2007 Google, Inc. -// All rights reserved. - -// Author: Mike Burrows - -// A test for the GraphCycles interface. - -// This test is testing a component of //third_party/absl. As written it -// heavily uses logging, including VLOG, so this test can't ship with Abseil. -// We're leaving it here until Abseil gets base/logging.h in a future release. #include "absl/synchronization/internal/graphcycles.h" #include #include -#include #include +#include +#include #include "gtest/gtest.h" #include "absl/base/internal/raw_logging.h" diff --git a/absl/synchronization/internal/per_thread_sem_test.cc b/absl/synchronization/internal/per_thread_sem_test.cc index 1d072a79e..61296cfca 100644 --- a/absl/synchronization/internal/per_thread_sem_test.cc +++ b/absl/synchronization/internal/per_thread_sem_test.cc @@ -22,13 +22,13 @@ #include #include // NOLINT(build/c++11) +#include "gtest/gtest.h" #include "absl/base/internal/cycleclock.h" #include "absl/base/internal/malloc_extension.h" #include "absl/base/internal/thread_identity.h" #include "absl/strings/str_cat.h" #include "absl/time/clock.h" #include "absl/time/time.h" -#include "gtest/gtest.h" // In this test we explicitly avoid the use of synchronization // primitives which might use PerThreadSem, most notably absl::Mutex. diff --git a/absl/synchronization/mutex.h b/absl/synchronization/mutex.h index a41780267..8343c9c89 100644 --- a/absl/synchronization/mutex.h +++ b/absl/synchronization/mutex.h @@ -81,8 +81,8 @@ namespace absl { -struct SynchWaitParams; class Condition; +struct SynchWaitParams; // ----------------------------------------------------------------------------- // Mutex diff --git a/absl/synchronization/mutex_test.cc b/absl/synchronization/mutex_test.cc index 9cf34fce0..cfe81096d 100644 --- a/absl/synchronization/mutex_test.cc +++ b/absl/synchronization/mutex_test.cc @@ -20,7 +20,6 @@ #include #include -#include #include #include #include @@ -32,8 +31,6 @@ #include "gtest/gtest.h" #include "absl/base/internal/raw_logging.h" #include "absl/base/internal/sysinfo.h" -#include "absl/base/macros.h" -#include "absl/base/thread_annotations.h" #include "absl/memory/memory.h" #include "absl/synchronization/internal/thread_pool.h" #include "absl/time/clock.h" @@ -713,7 +710,6 @@ static void LockWhenTestWaitForIsCond(LockWhenTestStruct* s) { TEST(Mutex, LockWhen) { LockWhenTestStruct s; - // Don't use ThreadPool for this test. See b/65107115. std::thread t(LockWhenTestWaitForIsCond, &s); s.mu2.LockWhen(absl::Condition(&s.waiting)); s.mu2.Unlock(); @@ -1041,8 +1037,6 @@ TEST(Mutex, DeadlockDetector) { m2.Unlock(); m4.Unlock(); m1.Unlock(); - // Pre b/7636708 the thread local cache remembered that ID1 is assigned to m1. - // So, we had a cycle ID1=>ID1=>ID1. } // Bazel has a test "warning" file that programs can write to if the diff --git a/absl/test_dependencies.bzl b/absl/test_dependencies.bzl index eca88d88c..0190c3001 100644 --- a/absl/test_dependencies.bzl +++ b/absl/test_dependencies.bzl @@ -2,7 +2,7 @@ # pylint: disable=pointless-std::string-statement -# TODO(catlyons): Clean up below selectors when possible. Hold on to them for +# TODO(absl-team): Clean up below selectors when possible. Hold on to them for # now as we may still need our own gunit_main selectors that do not bring in any # heapchecker-related deps, and possibly to deal with benchmark dependencies. @@ -20,7 +20,7 @@ GUNIT_MAIN_DEPS_SELECTOR = { ], } -# TODO(b/30141238): In order to set up absl deps on leak checking +# TODO(absl-team): In order to set up absl deps on leak checking # without base, we'll need gunit_main without either # base:heapcheck or base:noheapcheck. GUNIT_MAIN_NO_LEAK_CHECK_DEPS = [ diff --git a/absl/time/BUILD.bazel b/absl/time/BUILD.bazel index da8167f93..0d340f25c 100644 --- a/absl/time/BUILD.bazel +++ b/absl/time/BUILD.bazel @@ -97,16 +97,3 @@ cc_test( "@com_googlesource_code_cctz//:time_zone", ], ) - -# Used by get_current_time_test, which, due to a dependency on commandlineflags -# and some required cleanup, is staying back in //base for now. -cc_library( - name = "get_current_time_for_test", - testonly = 1, - copts = ABSL_DEFAULT_COPTS, - textual_hdrs = [ - "clock.cc", - "clock.h", - ], - deps = ["//absl/base"], -) diff --git a/absl/time/clock.cc b/absl/time/clock.cc index e2bc01bdb..9ffc1c4f9 100644 --- a/absl/time/clock.cc +++ b/absl/time/clock.cc @@ -368,7 +368,7 @@ static uint64_t UpdateLastSample( // into the fast past. That causes lots of register spills and reloads that // are unnecessary unless the slow path is taken. // -// TODO(b/36012148) Remove this attribute when our compiler is smart enough +// TODO(absl-team) Remove this attribute when our compiler is smart enough // to do the right thing. ABSL_ATTRIBUTE_NOINLINE static int64_t GetCurrentTimeNanosSlowPath() LOCKS_EXCLUDED(lock) { diff --git a/absl/time/duration.cc b/absl/time/duration.cc index 07d1082d8..f5081955d 100644 --- a/absl/time/duration.cc +++ b/absl/time/duration.cc @@ -641,6 +641,25 @@ timeval ToTimeval(Duration d) { return tv; } +std::chrono::nanoseconds ToChronoNanoseconds(Duration d) { + return time_internal::ToChronoDuration(d); +} +std::chrono::microseconds ToChronoMicroseconds(Duration d) { + return time_internal::ToChronoDuration(d); +} +std::chrono::milliseconds ToChronoMilliseconds(Duration d) { + return time_internal::ToChronoDuration(d); +} +std::chrono::seconds ToChronoSeconds(Duration d) { + return time_internal::ToChronoDuration(d); +} +std::chrono::minutes ToChronoMinutes(Duration d) { + return time_internal::ToChronoDuration(d); +} +std::chrono::hours ToChronoHours(Duration d) { + return time_internal::ToChronoDuration(d); +} + // // To/From std::string formatting. // @@ -852,7 +871,7 @@ bool ParseDuration(const std::string& dur_string, Duration* d) { return true; } -// TODO(b/63899288) copybara strip once dependencies are removed. +// TODO(absl-team): Remove once dependencies are removed. bool ParseFlag(const std::string& text, Duration* dst, std::string* /* err */) { return ParseDuration(text, dst); } diff --git a/absl/time/duration_test.cc b/absl/time/duration_test.cc index ec8e17f54..ab98b02ac 100644 --- a/absl/time/duration_test.cc +++ b/absl/time/duration_test.cc @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include // NOLINT(build/c++11) #include #include #include @@ -132,50 +133,50 @@ TEST(Duration, ToConversion) { #undef TEST_DURATION_CONVERSION } -template +template void TestToConversion() { - constexpr absl::Duration nano = absl::Nanoseconds(n); - EXPECT_EQ(n, absl::ToInt64Nanoseconds(nano)); + constexpr absl::Duration nano = absl::Nanoseconds(N); + EXPECT_EQ(N, absl::ToInt64Nanoseconds(nano)); EXPECT_EQ(0, absl::ToInt64Microseconds(nano)); EXPECT_EQ(0, absl::ToInt64Milliseconds(nano)); EXPECT_EQ(0, absl::ToInt64Seconds(nano)); EXPECT_EQ(0, absl::ToInt64Minutes(nano)); EXPECT_EQ(0, absl::ToInt64Hours(nano)); - const absl::Duration micro = absl::Microseconds(n); - EXPECT_EQ(n * 1000, absl::ToInt64Nanoseconds(micro)); - EXPECT_EQ(n, absl::ToInt64Microseconds(micro)); + const absl::Duration micro = absl::Microseconds(N); + EXPECT_EQ(N * 1000, absl::ToInt64Nanoseconds(micro)); + EXPECT_EQ(N, absl::ToInt64Microseconds(micro)); EXPECT_EQ(0, absl::ToInt64Milliseconds(micro)); EXPECT_EQ(0, absl::ToInt64Seconds(micro)); EXPECT_EQ(0, absl::ToInt64Minutes(micro)); EXPECT_EQ(0, absl::ToInt64Hours(micro)); - const absl::Duration milli = absl::Milliseconds(n); - EXPECT_EQ(n * 1000 * 1000, absl::ToInt64Nanoseconds(milli)); - EXPECT_EQ(n * 1000, absl::ToInt64Microseconds(milli)); - EXPECT_EQ(n, absl::ToInt64Milliseconds(milli)); + const absl::Duration milli = absl::Milliseconds(N); + EXPECT_EQ(N * 1000 * 1000, absl::ToInt64Nanoseconds(milli)); + EXPECT_EQ(N * 1000, absl::ToInt64Microseconds(milli)); + EXPECT_EQ(N, absl::ToInt64Milliseconds(milli)); EXPECT_EQ(0, absl::ToInt64Seconds(milli)); EXPECT_EQ(0, absl::ToInt64Minutes(milli)); EXPECT_EQ(0, absl::ToInt64Hours(milli)); - const absl::Duration sec = absl::Seconds(n); - EXPECT_EQ(n * 1000 * 1000 * 1000, absl::ToInt64Nanoseconds(sec)); - EXPECT_EQ(n * 1000 * 1000, absl::ToInt64Microseconds(sec)); - EXPECT_EQ(n * 1000, absl::ToInt64Milliseconds(sec)); - EXPECT_EQ(n, absl::ToInt64Seconds(sec)); + const absl::Duration sec = absl::Seconds(N); + EXPECT_EQ(N * 1000 * 1000 * 1000, absl::ToInt64Nanoseconds(sec)); + EXPECT_EQ(N * 1000 * 1000, absl::ToInt64Microseconds(sec)); + EXPECT_EQ(N * 1000, absl::ToInt64Milliseconds(sec)); + EXPECT_EQ(N, absl::ToInt64Seconds(sec)); EXPECT_EQ(0, absl::ToInt64Minutes(sec)); EXPECT_EQ(0, absl::ToInt64Hours(sec)); - const absl::Duration min = absl::Minutes(n); - EXPECT_EQ(n * 60 * 1000 * 1000 * 1000, absl::ToInt64Nanoseconds(min)); - EXPECT_EQ(n * 60 * 1000 * 1000, absl::ToInt64Microseconds(min)); - EXPECT_EQ(n * 60 * 1000, absl::ToInt64Milliseconds(min)); - EXPECT_EQ(n * 60, absl::ToInt64Seconds(min)); - EXPECT_EQ(n, absl::ToInt64Minutes(min)); + const absl::Duration min = absl::Minutes(N); + EXPECT_EQ(N * 60 * 1000 * 1000 * 1000, absl::ToInt64Nanoseconds(min)); + EXPECT_EQ(N * 60 * 1000 * 1000, absl::ToInt64Microseconds(min)); + EXPECT_EQ(N * 60 * 1000, absl::ToInt64Milliseconds(min)); + EXPECT_EQ(N * 60, absl::ToInt64Seconds(min)); + EXPECT_EQ(N, absl::ToInt64Minutes(min)); EXPECT_EQ(0, absl::ToInt64Hours(min)); - const absl::Duration hour = absl::Hours(n); - EXPECT_EQ(n * 60 * 60 * 1000 * 1000 * 1000, absl::ToInt64Nanoseconds(hour)); - EXPECT_EQ(n * 60 * 60 * 1000 * 1000, absl::ToInt64Microseconds(hour)); - EXPECT_EQ(n * 60 * 60 * 1000, absl::ToInt64Milliseconds(hour)); - EXPECT_EQ(n * 60 * 60, absl::ToInt64Seconds(hour)); - EXPECT_EQ(n * 60, absl::ToInt64Minutes(hour)); - EXPECT_EQ(n, absl::ToInt64Hours(hour)); + const absl::Duration hour = absl::Hours(N); + EXPECT_EQ(N * 60 * 60 * 1000 * 1000 * 1000, absl::ToInt64Nanoseconds(hour)); + EXPECT_EQ(N * 60 * 60 * 1000 * 1000, absl::ToInt64Microseconds(hour)); + EXPECT_EQ(N * 60 * 60 * 1000, absl::ToInt64Milliseconds(hour)); + EXPECT_EQ(N * 60 * 60, absl::ToInt64Seconds(hour)); + EXPECT_EQ(N * 60, absl::ToInt64Minutes(hour)); + EXPECT_EQ(N, absl::ToInt64Hours(hour)); } TEST(Duration, ToConversionDeprecated) { @@ -186,6 +187,149 @@ TEST(Duration, ToConversionDeprecated) { TestToConversion<-43>(); } +template +void TestFromChronoBasicEquality() { + using std::chrono::nanoseconds; + using std::chrono::microseconds; + using std::chrono::milliseconds; + using std::chrono::seconds; + using std::chrono::minutes; + using std::chrono::hours; + + static_assert(absl::Nanoseconds(N) == absl::FromChrono(nanoseconds(N)), ""); + static_assert(absl::Microseconds(N) == absl::FromChrono(microseconds(N)), ""); + static_assert(absl::Milliseconds(N) == absl::FromChrono(milliseconds(N)), ""); + static_assert(absl::Seconds(N) == absl::FromChrono(seconds(N)), ""); + static_assert(absl::Minutes(N) == absl::FromChrono(minutes(N)), ""); + static_assert(absl::Hours(N) == absl::FromChrono(hours(N)), ""); +} + +TEST(Duration, FromChrono) { + TestFromChronoBasicEquality<-123>(); + TestFromChronoBasicEquality<-1>(); + TestFromChronoBasicEquality<0>(); + TestFromChronoBasicEquality<1>(); + TestFromChronoBasicEquality<123>(); + + // Minutes (might, depending on the platform) saturate at +inf. + const auto chrono_minutes_max = std::chrono::minutes::max(); + const auto minutes_max = absl::FromChrono(chrono_minutes_max); + const int64_t minutes_max_count = chrono_minutes_max.count(); + if (minutes_max_count > kint64max / 60) { + EXPECT_EQ(absl::InfiniteDuration(), minutes_max); + } else { + EXPECT_EQ(absl::Minutes(minutes_max_count), minutes_max); + } + + // Minutes (might, depending on the platform) saturate at -inf. + const auto chrono_minutes_min = std::chrono::minutes::min(); + const auto minutes_min = absl::FromChrono(chrono_minutes_min); + const int64_t minutes_min_count = chrono_minutes_min.count(); + if (minutes_min_count < kint64min / 60) { + EXPECT_EQ(-absl::InfiniteDuration(), minutes_min); + } else { + EXPECT_EQ(absl::Minutes(minutes_min_count), minutes_min); + } + + // Hours (might, depending on the platform) saturate at +inf. + const auto chrono_hours_max = std::chrono::hours::max(); + const auto hours_max = absl::FromChrono(chrono_hours_max); + const int64_t hours_max_count = chrono_hours_max.count(); + if (hours_max_count > kint64max / 3600) { + EXPECT_EQ(absl::InfiniteDuration(), hours_max); + } else { + EXPECT_EQ(absl::Hours(hours_max_count), hours_max); + } + + // Hours (might, depending on the platform) saturate at -inf. + const auto chrono_hours_min = std::chrono::hours::min(); + const auto hours_min = absl::FromChrono(chrono_hours_min); + const int64_t hours_min_count = chrono_hours_min.count(); + if (hours_min_count < kint64min / 3600) { + EXPECT_EQ(-absl::InfiniteDuration(), hours_min); + } else { + EXPECT_EQ(absl::Hours(hours_min_count), hours_min); + } +} + +template +void TestToChrono() { + using std::chrono::nanoseconds; + using std::chrono::microseconds; + using std::chrono::milliseconds; + using std::chrono::seconds; + using std::chrono::minutes; + using std::chrono::hours; + + EXPECT_EQ(nanoseconds(N), absl::ToChronoNanoseconds(absl::Nanoseconds(N))); + EXPECT_EQ(microseconds(N), absl::ToChronoMicroseconds(absl::Microseconds(N))); + EXPECT_EQ(milliseconds(N), absl::ToChronoMilliseconds(absl::Milliseconds(N))); + EXPECT_EQ(seconds(N), absl::ToChronoSeconds(absl::Seconds(N))); + + constexpr auto absl_minutes = absl::Minutes(N); + auto chrono_minutes = minutes(N); + if (absl_minutes == -absl::InfiniteDuration()) { + chrono_minutes = minutes::min(); + } else if (absl_minutes == absl::InfiniteDuration()) { + chrono_minutes = minutes::max(); + } + EXPECT_EQ(chrono_minutes, absl::ToChronoMinutes(absl_minutes)); + + constexpr auto absl_hours = absl::Hours(N); + auto chrono_hours = hours(N); + if (absl_hours == -absl::InfiniteDuration()) { + chrono_hours = hours::min(); + } else if (absl_hours == absl::InfiniteDuration()) { + chrono_hours = hours::max(); + } + EXPECT_EQ(chrono_hours, absl::ToChronoHours(absl_hours)); +} + +TEST(Duration, ToChrono) { + using std::chrono::nanoseconds; + using std::chrono::microseconds; + using std::chrono::milliseconds; + using std::chrono::seconds; + using std::chrono::minutes; + using std::chrono::hours; + + TestToChrono(); + TestToChrono<-1>(); + TestToChrono<0>(); + TestToChrono<1>(); + TestToChrono(); + + // Verify truncation toward zero. + const auto tick = absl::Nanoseconds(1) / 4; + EXPECT_EQ(nanoseconds(0), absl::ToChronoNanoseconds(tick)); + EXPECT_EQ(nanoseconds(0), absl::ToChronoNanoseconds(-tick)); + EXPECT_EQ(microseconds(0), absl::ToChronoMicroseconds(tick)); + EXPECT_EQ(microseconds(0), absl::ToChronoMicroseconds(-tick)); + EXPECT_EQ(milliseconds(0), absl::ToChronoMilliseconds(tick)); + EXPECT_EQ(milliseconds(0), absl::ToChronoMilliseconds(-tick)); + EXPECT_EQ(seconds(0), absl::ToChronoSeconds(tick)); + EXPECT_EQ(seconds(0), absl::ToChronoSeconds(-tick)); + EXPECT_EQ(minutes(0), absl::ToChronoMinutes(tick)); + EXPECT_EQ(minutes(0), absl::ToChronoMinutes(-tick)); + EXPECT_EQ(hours(0), absl::ToChronoHours(tick)); + EXPECT_EQ(hours(0), absl::ToChronoHours(-tick)); + + // Verifies +/- infinity saturation at max/min. + constexpr auto inf = absl::InfiniteDuration(); + EXPECT_EQ(nanoseconds::min(), absl::ToChronoNanoseconds(-inf)); + EXPECT_EQ(nanoseconds::max(), absl::ToChronoNanoseconds(inf)); + EXPECT_EQ(microseconds::min(), absl::ToChronoMicroseconds(-inf)); + EXPECT_EQ(microseconds::max(), absl::ToChronoMicroseconds(inf)); + EXPECT_EQ(milliseconds::min(), absl::ToChronoMilliseconds(-inf)); + EXPECT_EQ(milliseconds::max(), absl::ToChronoMilliseconds(inf)); + EXPECT_EQ(seconds::min(), absl::ToChronoSeconds(-inf)); + EXPECT_EQ(seconds::max(), absl::ToChronoSeconds(inf)); + EXPECT_EQ(minutes::min(), absl::ToChronoMinutes(-inf)); + EXPECT_EQ(minutes::max(), absl::ToChronoMinutes(inf)); + EXPECT_EQ(hours::min(), absl::ToChronoHours(-inf)); + EXPECT_EQ(hours::max(), absl::ToChronoHours(inf)); +} + // Used for testing the factory overloads. template struct ImplicitlyConvertible { @@ -248,7 +392,7 @@ TEST(Duration, FactoryOverloads) { } TEST(Duration, InfinityExamples) { - // These examples are used in the documentation in //base/time.h. They are + // These examples are used in the documentation in time.h. They are // written so that they can be copy-n-pasted easily. constexpr absl::Duration inf = absl::InfiniteDuration(); diff --git a/absl/time/format.cc b/absl/time/format.cc index c58a886bf..7c88db5b0 100644 --- a/absl/time/format.cc +++ b/absl/time/format.cc @@ -127,8 +127,8 @@ bool ParseTime(const std::string& format, const std::string& input, absl::TimeZo return b; } -// TODO(b/63899288) copybara strip once dependencies are removed. -// Functions required to support absl::Time flags. See go/flags. +// TODO(absl-team): Remove once dependencies are removed. +// Functions required to support absl::Time flags. bool ParseFlag(const std::string& text, absl::Time* t, std::string* error) { return absl::ParseTime(RFC3339_full, text, absl::UTCTimeZone(), t, error); } diff --git a/absl/time/time.cc b/absl/time/time.cc index fd5a41b15..ee14ba306 100644 --- a/absl/time/time.cc +++ b/absl/time/time.cc @@ -367,4 +367,17 @@ int64_t ToUniversal(absl::Time t) { return absl::FloorToUnit(t - absl::UniversalEpoch(), absl::Nanoseconds(100)); } +Time FromChrono(const std::chrono::system_clock::time_point& tp) { + return time_internal::FromUnixDuration(time_internal::FromChrono( + tp - std::chrono::system_clock::from_time_t(0))); +} + +std::chrono::system_clock::time_point ToChronoTime(absl::Time t) { + using D = std::chrono::system_clock::duration; + auto d = time_internal::ToUnixDuration(t); + if (d < ZeroDuration()) d = Floor(d, FromChrono(D{1})); + return std::chrono::system_clock::from_time_t(0) + + time_internal::ToChronoDuration(d); +} + } // namespace absl diff --git a/absl/time/time.h b/absl/time/time.h index 302c76037..697634370 100644 --- a/absl/time/time.h +++ b/absl/time/time.h @@ -361,7 +361,7 @@ Duration Hours(T n) { // Example: // // absl::Duration d = absl::Milliseconds(1500); -// int64_t isec = ToInt64Seconds(d); // isec == 1 +// int64_t isec = ToInt64Seconds(d); // isec == 1 int64_t ToInt64Nanoseconds(Duration d); int64_t ToInt64Microseconds(Duration d); int64_t ToInt64Milliseconds(Duration d); @@ -391,6 +391,46 @@ double ToDoubleSeconds(Duration d); double ToDoubleMinutes(Duration d); double ToDoubleHours(Duration d); +// FromChrono() +// +// Converts any of the pre-defined std::chrono durations to an absl::Duration. +// +// Example: +// +// std::chrono::milliseconds ms(123); +// absl::Duration d = absl::FromChrono(ms); +constexpr Duration FromChrono(const std::chrono::nanoseconds& d); +constexpr Duration FromChrono(const std::chrono::microseconds& d); +constexpr Duration FromChrono(const std::chrono::milliseconds& d); +constexpr Duration FromChrono(const std::chrono::seconds& d); +constexpr Duration FromChrono(const std::chrono::minutes& d); +constexpr Duration FromChrono(const std::chrono::hours& d); + +// ToChronoNanoseconds() +// ToChronoMicroseconds() +// ToChronoMilliseconds() +// ToChronoSeconds() +// ToChronoMinutes() +// ToChronoHours() +// +// Converts an absl::Duration to any of the pre-defined std::chrono durations. +// If overflow would occur, the returned value will saturate at the min/max +// chrono duration value instead. +// +// Example: +// +// absl::Duration d = absl::Microseconds(123); +// auto x = absl::ToChronoMicroseconds(d); +// auto y = absl::ToChronoNanoseconds(d); // x == y +// auto z = absl::ToChronoSeconds(absl::InfiniteDuration()); +// // z == std::chrono::seconds::max() +std::chrono::nanoseconds ToChronoNanoseconds(Duration d); +std::chrono::microseconds ToChronoMicroseconds(Duration d); +std::chrono::milliseconds ToChronoMilliseconds(Duration d); +std::chrono::seconds ToChronoSeconds(Duration d); +std::chrono::minutes ToChronoMinutes(Duration d); +std::chrono::hours ToChronoHours(Duration d); + // InfiniteDuration() // // Returns an infinite `Duration`. To get a `Duration` representing negative @@ -445,7 +485,7 @@ inline std::ostream& operator<<(std::ostream& os, Duration d) { bool ParseDuration(const std::string& dur_string, Duration* d); // Flag Support -// TODO(b/63899288) copybara strip once dependencies are removed. +// TODO(absl-team): Remove once dependencies are removed. // ParseFlag() // @@ -790,6 +830,30 @@ Time TimeFromTimeval(timeval tv); timespec ToTimespec(Time t); timeval ToTimeval(Time t); +// FromChrono() +// +// Converts a std::chrono::system_clock::time_point to an absl::Time. +// +// Example: +// +// auto tp = std::chrono::system_clock::from_time_t(123); +// absl::Time t = absl::FromChrono(tp); +// // t == absl::FromTimeT(123) +Time FromChrono(const std::chrono::system_clock::time_point& tp); + +// ToChronoTime() +// +// Converts an absl::Time to a std::chrono::system_clock::time_point. If +// overflow would occur, the returned value will saturate at the min/max time +// point value instead. +// +// Example: +// +// absl::Time t = absl::FromTimeT(123); +// auto tp = absl::ToChronoTime(t); +// // tp == std::chrono::system_clock::from_time_t(123); +std::chrono::system_clock::time_point ToChronoTime(absl::Time); + // RFC3339_full // RFC3339_sec // @@ -917,7 +981,7 @@ bool ParseTime(const std::string& format, const std::string& input, bool ParseTime(const std::string& format, const std::string& input, TimeZone tz, Time* time, std::string* err); -// TODO(b/63899288) copybara strip once dependencies are removed. +// TODO(absl-team): Remove once dependencies are removed. // ParseFlag() // UnparseFlag() @@ -1072,6 +1136,81 @@ constexpr int64_t NegateAndSubtractOne(int64_t n) { // knowledge, we would need to add-in/subtract-out UnixEpoch() respectively. constexpr Time FromUnixDuration(Duration d) { return Time(d); } constexpr Duration ToUnixDuration(Time t) { return t.rep_; } + +template +constexpr absl::Duration FromInt64(int64_t v, std::ratio<1, N>) { + static_assert(0 < N && N <= 1000 * 1000 * 1000, "Unsupported ratio"); + // Subsecond ratios cannot overflow. + return MakeNormalizedDuration( + v / N, v % N * kTicksPerNanosecond * 1000 * 1000 * 1000 / N); +} +constexpr absl::Duration FromInt64(int64_t v, std::ratio<60>) { + return Minutes(v); +} +constexpr absl::Duration FromInt64(int64_t v, std::ratio<3600>) { + return Hours(v); +} + +// IsValidRep64(0) is true if the expression `int64_t{std::declval()}` is +// valid. That is, if a T can be assigned to an int64_t without narrowing. +template +constexpr auto IsValidRep64(int) + -> decltype(int64_t{std::declval()}, bool()) { + return true; +} +template +constexpr auto IsValidRep64(char) -> bool { + return false; +} + +// Converts a std::chrono::duration to an absl::Duration. +template +constexpr absl::Duration FromChrono( + const std::chrono::duration& d) { + static_assert(IsValidRep64(0), "duration::rep is invalid"); + return FromInt64(int64_t{d.count()}, Period{}); +} + +template +int64_t ToInt64(absl::Duration d, Ratio) { + // Note: This may be used on MSVC, which may have a system_clock period of + // std::ratio<1, 10 * 1000 * 1000> + return ToInt64Seconds(d * Ratio::den / Ratio::num); +} +// Fastpath implementations for the 6 common duration units. +inline int64_t ToInt64(absl::Duration d, std::nano) { + return ToInt64Nanoseconds(d); +} +inline int64_t ToInt64(absl::Duration d, std::micro) { + return ToInt64Microseconds(d); +} +inline int64_t ToInt64(absl::Duration d, std::milli) { + return ToInt64Milliseconds(d); +} +inline int64_t ToInt64(absl::Duration d, std::ratio<1>) { + return ToInt64Seconds(d); +} +inline int64_t ToInt64(absl::Duration d, std::ratio<60>) { + return ToInt64Minutes(d); +} +inline int64_t ToInt64(absl::Duration d, std::ratio<3600>) { + return ToInt64Hours(d); +} + +// Converts an absl::Duration to a chrono duration of type T. +template +T ToChronoDuration(absl::Duration d) { + using Rep = typename T::rep; + using Period = typename T::period; + static_assert(IsValidRep64(0), "duration::rep is invalid"); + if (time_internal::IsInfiniteDuration(d)) + return d < ZeroDuration() ? T::min() : T::max(); + const auto v = ToInt64(d, Period{}); + if (v > std::numeric_limits::max()) return T::max(); + if (v < std::numeric_limits::min()) return T::min(); + return T{v}; +} + } // namespace time_internal constexpr bool operator<(Duration lhs, Duration rhs) { @@ -1156,6 +1295,25 @@ constexpr Duration InfiniteDuration() { return time_internal::MakeDuration(std::numeric_limits::max(), ~0U); } +constexpr Duration FromChrono(const std::chrono::nanoseconds& d) { + return time_internal::FromChrono(d); +} +constexpr Duration FromChrono(const std::chrono::microseconds& d) { + return time_internal::FromChrono(d); +} +constexpr Duration FromChrono(const std::chrono::milliseconds& d) { + return time_internal::FromChrono(d); +} +constexpr Duration FromChrono(const std::chrono::seconds& d) { + return time_internal::FromChrono(d); +} +constexpr Duration FromChrono(const std::chrono::minutes& d) { + return time_internal::FromChrono(d); +} +constexpr Duration FromChrono(const std::chrono::hours& d) { + return time_internal::FromChrono(d); +} + constexpr Time FromUnixNanos(int64_t ns) { return time_internal::FromUnixDuration(Nanoseconds(ns)); } diff --git a/absl/time/time_test.cc b/absl/time/time_test.cc index 51b9e53d6..64083880c 100644 --- a/absl/time/time_test.cc +++ b/absl/time/time_test.cc @@ -14,6 +14,7 @@ #include "absl/time/time.h" +#include // NOLINT(build/c++11) #include #include #include @@ -489,6 +490,66 @@ TEST(Time, RoundtripConversion) { #undef TEST_CONVERSION_ROUND_TRIP } +template +std::chrono::system_clock::time_point MakeChronoUnixTime(const Duration& d) { + return std::chrono::system_clock::from_time_t(0) + d; +} + +TEST(Time, FromChrono) { + EXPECT_EQ(absl::FromTimeT(-1), + absl::FromChrono(std::chrono::system_clock::from_time_t(-1))); + EXPECT_EQ(absl::FromTimeT(0), + absl::FromChrono(std::chrono::system_clock::from_time_t(0))); + EXPECT_EQ(absl::FromTimeT(1), + absl::FromChrono(std::chrono::system_clock::from_time_t(1))); + + EXPECT_EQ( + absl::FromUnixMillis(-1), + absl::FromChrono(MakeChronoUnixTime(std::chrono::milliseconds(-1)))); + EXPECT_EQ(absl::FromUnixMillis(0), + absl::FromChrono(MakeChronoUnixTime(std::chrono::milliseconds(0)))); + EXPECT_EQ(absl::FromUnixMillis(1), + absl::FromChrono(MakeChronoUnixTime(std::chrono::milliseconds(1)))); + + // Chrono doesn't define exactly its range and precision (neither does + // absl::Time), so let's simply test +/- ~100 years to make sure things work. + const auto century_sec = 60 * 60 * 24 * 365 * int64_t{100}; + const auto century = std::chrono::seconds(century_sec); + const auto chrono_future = MakeChronoUnixTime(century); + const auto chrono_past = MakeChronoUnixTime(-century); + EXPECT_EQ(absl::FromUnixSeconds(century_sec), + absl::FromChrono(chrono_future)); + EXPECT_EQ(absl::FromUnixSeconds(-century_sec), absl::FromChrono(chrono_past)); + + // Roundtrip them both back to chrono. + EXPECT_EQ(chrono_future, + absl::ToChronoTime(absl::FromUnixSeconds(century_sec))); + EXPECT_EQ(chrono_past, + absl::ToChronoTime(absl::FromUnixSeconds(-century_sec))); +} + +TEST(Time, ToChronoTime) { + EXPECT_EQ(std::chrono::system_clock::from_time_t(-1), + absl::ToChronoTime(absl::FromTimeT(-1))); + EXPECT_EQ(std::chrono::system_clock::from_time_t(0), + absl::ToChronoTime(absl::FromTimeT(0))); + EXPECT_EQ(std::chrono::system_clock::from_time_t(1), + absl::ToChronoTime(absl::FromTimeT(1))); + + EXPECT_EQ(MakeChronoUnixTime(std::chrono::milliseconds(-1)), + absl::ToChronoTime(absl::FromUnixMillis(-1))); + EXPECT_EQ(MakeChronoUnixTime(std::chrono::milliseconds(0)), + absl::ToChronoTime(absl::FromUnixMillis(0))); + EXPECT_EQ(MakeChronoUnixTime(std::chrono::milliseconds(1)), + absl::ToChronoTime(absl::FromUnixMillis(1))); + + // Time before the Unix epoch should floor, not trunc. + const auto tick = absl::Nanoseconds(1) / 4; + EXPECT_EQ(std::chrono::system_clock::from_time_t(0) - + std::chrono::system_clock::duration(1), + absl::ToChronoTime(absl::UnixEpoch() - tick)); +} + TEST(Time, ConvertDateTime) { const absl::TimeZone utc = absl::UTCTimeZone(); const absl::TimeZone goog = diff --git a/absl/types/BUILD.bazel b/absl/types/BUILD.bazel index 8d09440ef..f1e432d19 100644 --- a/absl/types/BUILD.bazel +++ b/absl/types/BUILD.bazel @@ -48,7 +48,7 @@ cc_library( hdrs = ["bad_any_cast.h"], copts = ABSL_EXCEPTIONS_FLAG + ABSL_DEFAULT_COPTS, features = [ - "-use_header_modules", # b/33207452 + "-use_header_modules", ], deps = [ "//absl/base", @@ -153,7 +153,7 @@ cc_library( hdrs = ["bad_optional_access.h"], copts = ABSL_DEFAULT_COPTS + ABSL_EXCEPTIONS_FLAG, features = [ - "-use_header_modules", # b/33207452 + "-use_header_modules", ], deps = [ "//absl/base", diff --git a/absl/types/any_test.cc b/absl/types/any_test.cc index ab04bf5aa..aef98f308 100644 --- a/absl/types/any_test.cc +++ b/absl/types/any_test.cc @@ -16,7 +16,6 @@ #include #include -#include #include #include diff --git a/absl/types/optional.h b/absl/types/optional.h index 3e010bd5d..8b56513fa 100644 --- a/absl/types/optional.h +++ b/absl/types/optional.h @@ -17,7 +17,7 @@ // optional.h // ----------------------------------------------------------------------------- // -// This header file define the `absl::optional` type for holding a value which +// This header file defines the `absl::optional` type for holding a value which // may or may not be present. This type is useful for providing value semantics // for operations that may either wish to return or hold "something-or-nothing". // @@ -246,7 +246,7 @@ class optional_data_base : public optional_data_dtor_base { } }; -// TODO(b/34201852): Add another base class using +// TODO(absl-team) Add another class using // std::is_trivially_move_constructible trait when available to match // http://cplusplus.github.io/LWG/lwg-defects.html#2900, for types that // have trivial move but nontrivial copy. @@ -502,7 +502,8 @@ class optional : private optional_internal::optional_data, // the arguments `std::forward(args)...` within the `optional`. // (The `in_place_t` is a tag used to indicate that the contained object // should be constructed in-place.) - // TODO(b/34201852): Add std::is_constructible SFINAE. + // + // TODO(absl-team): Add std::is_constructible SFINAE. template constexpr explicit optional(in_place_t, Args&&... args) : data_base(in_place_t(), absl::forward(args)...) {} diff --git a/absl/types/optional_test.cc b/absl/types/optional_test.cc index 65f43871e..645f5b93c 100644 --- a/absl/types/optional_test.cc +++ b/absl/types/optional_test.cc @@ -328,7 +328,7 @@ TEST(optionalTest, InPlaceConstructor) { static_assert(opt2->x == ConstexprType::kCtorInitializerList, ""); #endif - // TODO(b/34201852): uncomment these when std::is_constructible + // TODO(absl-team): uncomment these when std::is_constructible // SFINAE is added to optional::optional(absl::in_place_t, Args&&...). // struct I { // I(absl::in_place_t); diff --git a/absl/types/span_test.cc b/absl/types/span_test.cc index 22ea33e0a..5a4f0014a 100644 --- a/absl/types/span_test.cc +++ b/absl/types/span_test.cc @@ -14,7 +14,6 @@ #include "absl/types/span.h" -#include #include #include #include @@ -25,10 +24,9 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +#include "absl/base/attributes.h" #include "absl/base/config.h" #include "absl/base/internal/exception_testing.h" -#include "absl/base/macros.h" -#include "absl/base/port.h" #include "absl/container/fixed_array.h" #include "absl/container/inlined_vector.h" #include "absl/strings/str_cat.h"