diff options
Diffstat (limited to 'absl')
68 files changed, 629 insertions, 831 deletions
diff --git a/absl/BUILD.bazel b/absl/BUILD.bazel index 42c107d23a1e..92e9059bb276 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 2e023ef23f97..4c1b50952ad9 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 c2155a4e213d..ddf44584130d 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 1f9a8102f7ec..47d4013928a0 100644 --- a/absl/base/internal/atomic_hook.h +++ b/absl/base/internal/atomic_hook.h @@ -18,28 +18,12 @@ #include <atomic> #include <cassert> +#include <cstdint> #include <utility> namespace absl { namespace base_internal { -// In current versions of MSVC (as of July 2017), a std::atomic<T> 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<void(*)()> 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 <typename T> class AtomicHook; @@ -55,7 +39,7 @@ class AtomicHook<ReturnType (*)(Args...)> { 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<ReturnType (*)(Args...)> { // 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<void>(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 <typename... CallArgs> 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<CallArgs>(args)...); - } else { - return ReturnType(); - } + return DoLoad()(std::forward<CallArgs>(args)...); } // Returns the registered callback, or nullptr if none has been registered. @@ -98,23 +70,79 @@ class AtomicHook<ReturnType (*)(Args...)> { // 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<T*>: 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<FnPtr> 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<FnPtr>(value); + } + + bool DoStore(FnPtr fn) { + assert(fn); + const auto value = reinterpret_cast<intptr_t>(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<intptr_t> 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 a01d1c03272b..e716f2b49fa1 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 4f5a0befe2f0..7165d4cbd02a 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<uintptr_t>(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 c0890614b1be..1b849abfceae 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 <unistd.h> + #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 b7560f30d793..1b6497ad8757 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 6734cc9ef05f..5f658211cc56 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 <stdint.h> #include <atomic> diff --git a/absl/base/internal/sysinfo.cc b/absl/base/internal/sysinfo.cc index 6a4c00641b1f..9e0140fadb1f 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 f21de14325c7..5bd1c500bd54 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 4c7d66b7f9c3..e0d9aab9bc2d 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 ee96a5883293..678e8568d742 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 259970fea89a..31d1c02ecfa6 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 68aafd5c5011..e52ed49f5403 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 84acf9f99e1f..7a56e4962e7b 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 037ea54c3385..30d2e71da1b3 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 <fcntl.h> #include <sys/syscall.h> #include <unistd.h> - #include <atomic> #include <cerrno> #include <cstdint> diff --git a/absl/debugging/internal/stacktrace_config.h b/absl/debugging/internal/stacktrace_config.h index c0df5bb067f1..57f0b0f2a6e2 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 e9c2d26a5fe4..000000000000 --- 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 <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT> -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<void**>( - 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 27ca2d1b7bf3..febd1ee4f928 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 <memory> +#include <string> + #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 6c1690426381..61fee6190f54 100644 --- a/absl/debugging/stacktrace.cc +++ b/absl/debugging/stacktrace.cc @@ -38,6 +38,7 @@ #include <atomic> +#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 779afd2dd143..ced66269b063 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 <stddef.h> #include <type_traits> #include "absl/base/config.h" diff --git a/absl/meta/type_traits_test.cc b/absl/meta/type_traits_test.cc index 54dcc8f4160b..15e1c28bd24b 100644 --- a/absl/meta/type_traits_test.cc +++ b/absl/meta/type_traits_test.cc @@ -17,9 +17,9 @@ #include <cstdint> #include <string> #include <type_traits> +#include <utility> #include <vector> -#include "gmock/gmock.h" #include "gtest/gtest.h" namespace { diff --git a/absl/numeric/int128.cc b/absl/numeric/int128.cc index 184041fe4a22..7debf56a62b7 100644 --- a/absl/numeric/int128.cc +++ b/absl/numeric/int128.cc @@ -14,11 +14,12 @@ #include "absl/numeric/int128.h" +#include <stddef.h> #include <cassert> -#include <cstdlib> #include <iomanip> #include <iostream> // NOLINT(readability/streams) #include <sstream> +#include <string> namespace absl { diff --git a/absl/numeric/int128.h b/absl/numeric/int128.h index e3ba238400d5..bab5e2175a7f 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 070721cc117c..da441e201aa4 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 f1576057f849..7d688ac3fac7 100644 --- a/absl/strings/escaping.cc +++ b/absl/strings/escaping.cc @@ -14,22 +14,21 @@ #include "absl/strings/escaping.h" +#include <algorithm> #include <cassert> #include <cstdint> -#include <cstdio> #include <cstring> +#include <iterator> #include <limits> #include <string> -#include <vector> #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 d464051df020..ecac9ca8c588 100644 --- a/absl/strings/escaping_test.cc +++ b/absl/strings/escaping_test.cc @@ -17,11 +17,11 @@ #include <array> #include <cstdio> #include <cstring> +#include <memory> #include <vector> #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 2167be975e7d..c3601e101e2a 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 <cstdio> -#include <cstdlib> #include <cctype> +#include <string> +#include <vector> #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 1ff60f20e0bd..09424de9a477 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 <algorithm> #include <cstdlib> #include "gtest/gtest.h" diff --git a/absl/strings/internal/ostringstream_test.cc b/absl/strings/internal/ostringstream_test.cc index 0047ec822e8b..069a0e1fbbb1 100644 --- a/absl/strings/internal/ostringstream_test.cc +++ b/absl/strings/internal/ostringstream_test.cc @@ -16,7 +16,6 @@ #include <memory> #include <ostream> -#include <sstream> #include <string> #include <type_traits> diff --git a/absl/strings/internal/utf8_test.cc b/absl/strings/internal/utf8_test.cc index 4d437427a88a..64cec70df7e1 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 <cctype> -#include <cstdlib> -#include <cstring> #include <cstdint> +#include <utility> #include "gtest/gtest.h" +#include "absl/base/port.h" namespace { diff --git a/absl/strings/match.cc b/absl/strings/match.cc index 53881bdd3f3c..25bd7f0b828b 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 4a5d1c0342cd..4ac35f192e00 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<absl::string_view::size_type>(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<absl::string_view::size_type>(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 3b093b98c6f4..ac73f5308225 100644 --- a/absl/strings/numbers.cc +++ b/absl/strings/numbers.cc @@ -3,19 +3,20 @@ #include "absl/strings/numbers.h" +#include <algorithm> #include <cassert> -#include <cctype> #include <cfloat> // for DBL_DIG and FLT_DIG #include <cmath> // for HUGE_VAL +#include <cstdint> #include <cstdio> #include <cstdlib> #include <cstring> +#include <iterator> #include <limits> #include <memory> -#include <string> +#include <utility> #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<uint32_t>(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<uint32_t>(lower64 - mul64); - uint32_t upper = static_cast<uint32_t>(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<float>::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 f17dc97b2b1c..74aebc8028ea 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 9b74d67b87c8..817604d78c7f 100644 --- a/absl/strings/numbers_test.cc +++ b/absl/strings/numbers_test.cc @@ -3,10 +3,7 @@ #include "absl/strings/numbers.h" #include <sys/types.h> -#include <algorithm> -#include <cctype> #include <cfenv> // NOLINT(build/c++11) -#include <cfloat> #include <cinttypes> #include <climits> #include <cmath> @@ -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<float> 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<double> mismatches; diff --git a/absl/strings/str_cat.cc b/absl/strings/str_cat.cc index 0c75655c993f..99eb28908c19 100644 --- a/absl/strings/str_cat.cc +++ b/absl/strings/str_cat.cc @@ -14,9 +14,9 @@ #include "absl/strings/str_cat.h" -#include <cstdarg> +#include <assert.h> +#include <algorithm> #include <cstdint> -#include <cstdio> #include <cstring> #include "absl/strings/ascii.h" diff --git a/absl/strings/str_join_test.cc b/absl/strings/str_join_test.cc index 7c2ed09b91d6..03b60f03c82e 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 <algorithm> #include <cstddef> #include <cstdint> #include <cstdio> +#include <functional> #include <initializer_list> #include <map> +#include <memory> #include <ostream> -#include <random> #include <set> #include <tuple> +#include <type_traits> #include <vector> -#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 f49c7e1c32cf..5d003a224a4f 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 <list> +#include <map> #include <tuple> #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 910a67cf2840..0207213c26ba 100644 --- a/absl/strings/str_split.cc +++ b/absl/strings/str_split.cc @@ -14,11 +14,14 @@ #include "absl/strings/str_split.h" +#include <algorithm> #include <cassert> +#include <cstdint> #include <cstdlib> #include <cstring> #include <iterator> #include <limits> +#include <memory> #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 a95a0fbd3596..22a68d0f8339 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 <climits> -#include <cstdlib> -#include <cstring> #include <deque> -#include <limits> +#include <initializer_list> #include <list> #include <map> #include <memory> #include <string> +#include <type_traits> #include <unordered_map> #include <unordered_set> #include <vector> @@ -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 4d4ba6c1741f..0e1729546a5f 100644 --- a/absl/strings/string_view.cc +++ b/absl/strings/string_view.cc @@ -20,7 +20,6 @@ #include <climits> #include <cstring> #include <ostream> -#include <string> #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 e2609f174f93..8e37acb8d870 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<size_t>(s.size())); diff --git a/absl/strings/string_view_test.cc b/absl/strings/string_view_test.cc index 439d6499730e..6be6f3b82b11 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 <algorithm> +#include <stdlib.h> #include <iomanip> #include <iterator> +#include <limits> #include <map> -#include <random> #include <sstream> +#include <stdexcept> #include <string> #include <type_traits> #include <utility> @@ -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 968c09c6fd31..adc219f16b8c 100644 --- a/absl/strings/strip.cc +++ b/absl/strings/strip.cc @@ -18,7 +18,6 @@ #include "absl/strings/strip.h" #include <algorithm> -#include <cassert> #include <cstring> #include <string> diff --git a/absl/strings/substitute.h b/absl/strings/substitute.h index 5d6bfd90c2fb..3fc4ac4cdcc4 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 <typename... Args> -// 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 <typename... Args> -// 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 48e3650da246..7e68e960bc3a 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 b4b6677234e9..e8223f841a5f 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 <functional> -#include <memory> #include <thread> // NOLINT(build/c++11) #include <vector> #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 14976347b671..0134a4399b42 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 <stdint.h> +#include <new> + // 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 <string.h> -#include <atomic> -#include <memory> #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 734f2770b26e..9a85b39074d7 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 <map> #include <random> -#include <vector> #include <unordered_set> +#include <utility> +#include <vector> #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 1d072a79e3d4..61296cfca502 100644 --- a/absl/synchronization/internal/per_thread_sem_test.cc +++ b/absl/synchronization/internal/per_thread_sem_test.cc @@ -22,13 +22,13 @@ #include <string> #include <thread> // 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 a417802677cc..8343c9c8961f 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 9cf34fce0271..cfe81096dc98 100644 --- a/absl/synchronization/mutex_test.cc +++ b/absl/synchronization/mutex_test.cc @@ -20,7 +20,6 @@ #include <algorithm> #include <atomic> -#include <cstdint> #include <cstdlib> #include <functional> #include <memory> @@ -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 eca88d88cd68..0190c300107f 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 da8167f93e4c..0d340f25ca3c 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 e2bc01bdb6a3..9ffc1c4f91d8 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 07d1082d8977..f5081955d3bd 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<std::chrono::nanoseconds>(d); +} +std::chrono::microseconds ToChronoMicroseconds(Duration d) { + return time_internal::ToChronoDuration<std::chrono::microseconds>(d); +} +std::chrono::milliseconds ToChronoMilliseconds(Duration d) { + return time_internal::ToChronoDuration<std::chrono::milliseconds>(d); +} +std::chrono::seconds ToChronoSeconds(Duration d) { + return time_internal::ToChronoDuration<std::chrono::seconds>(d); +} +std::chrono::minutes ToChronoMinutes(Duration d) { + return time_internal::ToChronoDuration<std::chrono::minutes>(d); +} +std::chrono::hours ToChronoHours(Duration d) { + return time_internal::ToChronoDuration<std::chrono::hours>(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 ec8e17f548e6..ab98b02ac38f 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 <chrono> // NOLINT(build/c++11) #include <cmath> #include <cstdint> #include <ctime> @@ -132,50 +133,50 @@ TEST(Duration, ToConversion) { #undef TEST_DURATION_CONVERSION } -template <int64_t n> +template <int64_t N> 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 <int64_t N> +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 <int64_t N> +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<kint64min>(); + TestToChrono<-1>(); + TestToChrono<0>(); + TestToChrono<1>(); + TestToChrono<kint64max>(); + + // 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 <typename T> 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 c58a886bf93a..7c88db5b00d0 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 fd5a41b15080..ee14ba306e80 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>(d); +} + } // namespace absl diff --git a/absl/time/time.h b/absl/time/time.h index 302c76037e6f..6976343708be 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 <std::intmax_t N> +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<T>(0) is true if the expression `int64_t{std::declval<T>()}` is +// valid. That is, if a T can be assigned to an int64_t without narrowing. +template <typename T> +constexpr auto IsValidRep64(int) + -> decltype(int64_t{std::declval<T>()}, bool()) { + return true; +} +template <typename T> +constexpr auto IsValidRep64(char) -> bool { + return false; +} + +// Converts a std::chrono::duration to an absl::Duration. +template <typename Rep, typename Period> +constexpr absl::Duration FromChrono( + const std::chrono::duration<Rep, Period>& d) { + static_assert(IsValidRep64<Rep>(0), "duration::rep is invalid"); + return FromInt64(int64_t{d.count()}, Period{}); +} + +template <typename Ratio> +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 <typename T> +T ToChronoDuration(absl::Duration d) { + using Rep = typename T::rep; + using Period = typename T::period; + static_assert(IsValidRep64<Rep>(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<Rep>::max()) return T::max(); + if (v < std::numeric_limits<Rep>::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<int64_t>::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 51b9e53d6905..64083880c1e0 100644 --- a/absl/time/time_test.cc +++ b/absl/time/time_test.cc @@ -14,6 +14,7 @@ #include "absl/time/time.h" +#include <chrono> // NOLINT(build/c++11) #include <cstring> #include <ctime> #include <iomanip> @@ -489,6 +490,66 @@ TEST(Time, RoundtripConversion) { #undef TEST_CONVERSION_ROUND_TRIP } +template <typename Duration> +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 8d09440ef104..f1e432d19a15 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 ab04bf5aac60..aef98f308241 100644 --- a/absl/types/any_test.cc +++ b/absl/types/any_test.cc @@ -16,7 +16,6 @@ #include <initializer_list> #include <type_traits> -#include <typeinfo> #include <utility> #include <vector> diff --git a/absl/types/optional.h b/absl/types/optional.h index 3e010bd5d0cf..8b56513fab2e 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<T> { } }; -// 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<T>, // the arguments `std::forward<Args>(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<T, Args&&...> SFINAE. + // + // TODO(absl-team): Add std::is_constructible<T, Args&&...> SFINAE. template <typename... Args> constexpr explicit optional(in_place_t, Args&&... args) : data_base(in_place_t(), absl::forward<Args>(args)...) {} diff --git a/absl/types/optional_test.cc b/absl/types/optional_test.cc index 65f43871e1c0..645f5b93cf89 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<T, Args&&...> + // TODO(absl-team): uncomment these when std::is_constructible<T, Args&&...> // 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 22ea33e0a278..5a4f0014af38 100644 --- a/absl/types/span_test.cc +++ b/absl/types/span_test.cc @@ -14,7 +14,6 @@ #include "absl/types/span.h" -#include <algorithm> #include <array> #include <initializer_list> #include <numeric> @@ -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" |