summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--CMake/AbseilConfigureCopts.cmake145
-rw-r--r--CMake/AbseilHelpers.cmake4
-rw-r--r--CMakeLists.txt44
-rw-r--r--absl/algorithm/BUILD.bazel2
-rw-r--r--absl/base/BUILD.bazel32
-rw-r--r--absl/base/CMakeLists.txt7
-rw-r--r--absl/base/call_once_test.cc5
-rw-r--r--absl/base/const_init.h73
-rw-r--r--absl/base/internal/spinlock.h4
-rw-r--r--absl/base/internal/spinlock_benchmark.cc52
-rw-r--r--absl/container/BUILD.bazel13
-rw-r--r--absl/container/CMakeLists.txt23
-rw-r--r--absl/container/flat_hash_set.h6
-rw-r--r--absl/container/inlined_vector.h979
-rw-r--r--absl/container/internal/compressed_tuple.h28
-rw-r--r--absl/container/internal/compressed_tuple_test.cc43
-rw-r--r--absl/container/internal/hashtable_debug.h2
-rw-r--r--absl/container/internal/have_sse.h49
-rw-r--r--absl/container/internal/layout.h4
-rw-r--r--absl/container/internal/layout_test.cc28
-rw-r--r--absl/container/internal/raw_hash_set.cc3
-rw-r--r--absl/container/internal/raw_hash_set.h33
-rw-r--r--absl/container/node_hash_set.h6
-rw-r--r--absl/copts.bzl170
-rw-r--r--absl/copts/AbseilConfigureCopts.cmake34
-rw-r--r--absl/copts/GENERATED_AbseilCopts.cmake131
-rw-r--r--absl/copts/GENERATED_copts.bzl132
-rw-r--r--absl/copts/configure_copts.bzl42
-rw-r--r--absl/copts/copts.py157
-rwxr-xr-xabsl/copts/generate_copts.py108
-rw-r--r--absl/debugging/BUILD.bazel20
-rw-r--r--absl/debugging/CMakeLists.txt413
-rw-r--r--absl/debugging/internal/demangle.cc9
-rw-r--r--absl/hash/BUILD.bazel2
-rw-r--r--absl/hash/CMakeLists.txt116
-rw-r--r--absl/memory/BUILD.bazel2
-rw-r--r--absl/memory/CMakeLists.txt76
-rw-r--r--absl/memory/memory_test.cc39
-rw-r--r--absl/meta/BUILD.bazel2
-rw-r--r--absl/meta/CMakeLists.txt58
-rw-r--r--absl/numeric/BUILD.bazel2
-rw-r--r--absl/numeric/CMakeLists.txt74
-rw-r--r--absl/numeric/int128.h25
-rw-r--r--absl/numeric/int128_have_intrinsic.inc2
-rw-r--r--absl/numeric/int128_no_intrinsic.inc2
-rw-r--r--absl/strings/BUILD.bazel25
-rw-r--r--absl/strings/CMakeLists.txt780
-rw-r--r--absl/strings/charconv_test.cc14
-rw-r--r--absl/strings/internal/charconv_bigint.h14
-rw-r--r--absl/strings/internal/pow10_helper.cc120
-rw-r--r--absl/strings/internal/pow10_helper.h36
-rw-r--r--absl/strings/internal/pow10_helper_test.cc120
-rw-r--r--absl/strings/internal/resize_uninitialized.h35
-rw-r--r--absl/strings/internal/resize_uninitialized_test.cc24
-rw-r--r--absl/strings/internal/str_format/arg.h2
-rw-r--r--absl/strings/match.cc13
-rw-r--r--absl/strings/numbers_test.cc3
-rw-r--r--absl/strings/string_view.h8
-rw-r--r--absl/synchronization/BUILD.bazel25
-rw-r--r--absl/synchronization/CMakeLists.txt268
-rw-r--r--absl/synchronization/internal/kernel_timeout.h4
-rw-r--r--absl/synchronization/internal/mutex_nonprod.inc3
-rw-r--r--absl/synchronization/lifetime_test.cc48
-rw-r--r--absl/synchronization/mutex.cc2
-rw-r--r--absl/synchronization/mutex.h22
-rw-r--r--absl/synchronization/mutex_benchmark.cc151
-rw-r--r--absl/synchronization/notification.h1
-rw-r--r--absl/time/BUILD.bazel2
-rw-r--r--absl/time/CMakeLists.txt161
-rw-r--r--absl/time/duration.cc8
-rw-r--r--absl/time/duration_test.cc34
-rw-r--r--absl/time/internal/cctz/include/cctz/civil_time_detail.h10
-rw-r--r--absl/time/time.h11
-rw-r--r--absl/types/BUILD.bazel2
-rw-r--r--absl/types/CMakeLists.txt436
-rw-r--r--absl/types/internal/variant.h31
-rw-r--r--absl/types/variant.h8
-rw-r--r--absl/utility/BUILD.bazel2
-rw-r--r--absl/utility/CMakeLists.txt54
80 files changed, 3510 insertions, 2171 deletions
diff --git a/.gitignore b/.gitignore
index 7175c4f8..31f33741 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,6 @@ build
CMakeLists.txt.user
# Ignore VS Code files
.vscode/*
+# Ignore generated python artifacts
+copts/copts.pyc
+copts/__pycache__/
diff --git a/CMake/AbseilConfigureCopts.cmake b/CMake/AbseilConfigureCopts.cmake
deleted file mode 100644
index 96e0390b..00000000
--- a/CMake/AbseilConfigureCopts.cmake
+++ /dev/null
@@ -1,145 +0,0 @@
-# Abseil-specific compiler flags. See absl/copts.bzl for description.
-# DO NOT CHANGE THIS FILE WITHOUT THE CORRESPONDING CHANGE TO absl/copts.bzl
-
-list(APPEND GCC_FLAGS
- -Wall
- -Wextra
- -Wcast-qual
- -Wconversion-null
- -Wmissing-declarations
- -Woverlength-strings
- -Wpointer-arith
- -Wunused-local-typedefs
- -Wunused-result
- -Wvarargs
- -Wwrite-strings
- -Wno-sign-compare
-)
-
-list(APPEND GCC_TEST_FLAGS
- -Wno-conversion-null
- -Wno-missing-declarations
- -Wno-sign-compare
- -Wno-unused-function
- -Wno-unused-parameter
- -Wno-unused-private-field
-)
-
-list(APPEND LLVM_FLAGS
- -Wall
- -Wextra
- -Weverything
- -Wno-c++98-compat-pedantic
- -Wno-conversion
- -Wno-covered-switch-default
- -Wno-deprecated
- -Wno-disabled-macro-expansion
- -Wno-double-promotion
- -Wno-comma
- -Wno-extra-semi
- -Wno-packed
- -Wno-padded
- -Wno-sign-compare
- -Wno-float-conversion
- -Wno-float-equal
- -Wno-format-nonliteral
- -Wno-gcc-compat
- -Wno-global-constructors
- -Wno-exit-time-destructors
- -Wno-nested-anon-types
- -Wno-non-modular-include-in-module
- -Wno-old-style-cast
- -Wno-range-loop-analysis
- -Wno-reserved-id-macro
- -Wno-shorten-64-to-32
- -Wno-switch-enum
- -Wno-thread-safety-negative
- -Wno-undef
- -Wno-unknown-warning-option
- -Wno-unreachable-code
- -Wno-unused-macros
- -Wno-weak-vtables
- -Wbitfield-enum-conversion
- -Wbool-conversion
- -Wconstant-conversion
- -Wenum-conversion
- -Wint-conversion
- -Wliteral-conversion
- -Wnon-literal-null-conversion
- -Wnull-conversion
- -Wobjc-literal-conversion
- -Wno-sign-conversion
- -Wstring-conversion
-)
-
-list(APPEND LLVM_TEST_FLAGS
- -Wno-c99-extensions
- -Wno-missing-noreturn
- -Wno-missing-prototypes
- -Wno-missing-variable-declarations
- -Wno-null-conversion
- -Wno-shadow
- -Wno-shift-sign-overflow
- -Wno-sign-compare
- -Wno-unused-function
- -Wno-unused-member-function
- -Wno-unused-parameter
- -Wno-unused-private-field
- -Wno-unused-template
- -Wno-used-but-marked-unused
- -Wno-zero-as-null-pointer-constant
- -Wno-gnu-zero-variadic-macro-arguments
-)
-
-list(APPEND MSVC_FLAGS
- /W3
- /wd4005
- /wd4018
- /wd4068
- /wd4180
- /wd4244
- /wd4267
- /wd4800
- /DNOMINMAX
- /DWIN32_LEAN_AND_MEAN
- /D_CRT_SECURE_NO_WARNINGS
- /D_SCL_SECURE_NO_WARNINGS
- /D_ENABLE_EXTENDED_ALIGNED_STORAGE
-)
-
-list(APPEND MSVC_TEST_FLAGS
- /wd4101
- /wd4503
-)
-
-if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
- set(ABSL_DEFAULT_COPTS "${GCC_FLAGS}")
- set(ABSL_TEST_COPTS "${GCC_FLAGS};${GCC_TEST_FLAGS}")
- set(ABSL_EXCEPTIONS_FLAG "-fexceptions")
-elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
- # MATCHES so we get both Clang and AppleClang
- set(ABSL_DEFAULT_COPTS "${LLVM_FLAGS}")
- set(ABSL_TEST_COPTS "${LLVM_FLAGS};${LLVM_TEST_FLAGS}")
- set(ABSL_EXCEPTIONS_FLAG "-fexceptions")
-elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
- set(ABSL_DEFAULT_COPTS "${MSVC_FLAGS}")
- set(ABSL_TEST_COPTS "${MSVC_FLAGS};${MSVC_TEST_FLAGS}")
- set(ABSL_EXCEPTIONS_FLAG "/U_HAS_EXCEPTIONS;/D_HAS_EXCEPTIONS=1;/EHsc")
-else()
- message(WARNING "Unknown compiler: ${CMAKE_CXX_COMPILER}. Building with no default flags")
- set(ABSL_DEFAULT_COPTS "")
- set(ABSL_TEST_COPTS "")
- set(ABSL_EXCEPTIONS_FLAG "")
-endif()
-
-# This flag is used internally for Bazel builds and is kept here for consistency
-set(ABSL_EXCEPTIONS_FLAG_LINKOPTS "")
-
-if("${CMAKE_CXX_STANDARD}" EQUAL 98)
- message(FATAL_ERROR "Abseil requires at least C++11")
-elseif(NOT "${CMAKE_CXX_STANDARD}")
- message(STATUS "No CMAKE_CXX_STANDARD set, assuming 11")
- set(ABSL_CXX_STANDARD 11)
-else()
- set(ABSL_CXX_STANDARD "${CMAKE_CXX_STANDARD}")
-endif()
diff --git a/CMake/AbseilHelpers.cmake b/CMake/AbseilHelpers.cmake
index 5402bf51..e4289c11 100644
--- a/CMake/AbseilHelpers.cmake
+++ b/CMake/AbseilHelpers.cmake
@@ -135,7 +135,9 @@ function(absl_cc_library)
endif()
# Check if this is a header-only library
- if ("${ABSL_CC_LIB_SRCS}" STREQUAL "")
+ set(ABSL_CC_SRCS "${ABSL_CC_LIB_SRCS}")
+ list(FILTER ABSL_CC_SRCS EXCLUDE REGEX ".*\\.h")
+ if ("${ABSL_CC_SRCS}" STREQUAL "")
set(ABSL_CC_LIB_IS_INTERFACE 1)
else()
set(ABSL_CC_LIB_IS_INTERFACE 0)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 77ae631d..380ed74f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -17,37 +17,23 @@
# We require 3.0 for modern, target-based CMake. We require 3.1 for the use of
# CXX_STANDARD in our targets.
cmake_minimum_required(VERSION 3.1)
+
+# Compiler id for Apple Clang is now AppleClang.
+if (POLICY CMP0025)
+ cmake_policy(SET CMP0025 NEW)
+endif()
+
project(absl)
-list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/CMake)
+list(APPEND CMAKE_MODULE_PATH
+ ${CMAKE_CURRENT_LIST_DIR}/CMake
+ ${CMAKE_CURRENT_LIST_DIR}/absl/copts
+)
include(GNUInstallDirs)
include(AbseilHelpers)
-# config options
-if (MSVC)
- # /wd4005 macro-redefinition
- # /wd4068 unknown pragma
- # /wd4244 conversion from 'type1' to 'type2'
- # /wd4267 conversion from 'size_t' to 'type2'
- # /wd4800 force value to bool 'true' or 'false' (performance warning)
- add_compile_options(/W3 /wd4005 /wd4068 /wd4244 /wd4267 /wd4800)
- # /D_ENABLE_EXTENDED_ALIGNED_STORAGE Introduced in VS 2017 15.8, before the
- # member type would non-conformingly have an alignment of only alignof(max_align_t).
- add_definitions(
- /DNOMINMAX
- /DWIN32_LEAN_AND_MEAN=1
- /D_CRT_SECURE_NO_WARNINGS
- /D_SCL_SECURE_NO_WARNINGS
- /D_ENABLE_EXTENDED_ALIGNED_STORAGE
- )
-else()
- set(ABSL_STD_CXX_FLAG "-std=c++11" CACHE STRING "c++ std flag (default: c++11)")
-endif()
-
-
-
##
## Using absl targets
##
@@ -62,11 +48,11 @@ endif()
# include current path
list(APPEND ABSL_COMMON_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR})
-# -std=X
-set(CMAKE_CXX_FLAGS "${ABSL_STD_CXX_FLAG} ${CMAKE_CXX_FLAGS}")
-
-# -fexceptions
-set(ABSL_EXCEPTIONS_FLAG "${CMAKE_CXX_EXCEPTIONS}")
+if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
+ set(ABSL_USING_CLANG ON)
+else()
+ set(ABSL_USING_CLANG OFF)
+endif()
# find dependencies
## pthread
diff --git a/absl/algorithm/BUILD.bazel b/absl/algorithm/BUILD.bazel
index d04dc712..4314ee86 100644
--- a/absl/algorithm/BUILD.bazel
+++ b/absl/algorithm/BUILD.bazel
@@ -15,7 +15,7 @@
#
load(
- "//absl:copts.bzl",
+ "//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
"ABSL_TEST_COPTS",
)
diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel
index 44de05e3..2717df0c 100644
--- a/absl/base/BUILD.bazel
+++ b/absl/base/BUILD.bazel
@@ -15,7 +15,7 @@
#
load(
- "//absl:copts.bzl",
+ "//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
"ABSL_TEST_COPTS",
"ABSL_EXCEPTIONS_FLAG",
@@ -67,6 +67,7 @@ cc_library(
name = "core_headers",
hdrs = [
"attributes.h",
+ "const_init.h",
"macros.h",
"optimization.h",
"port.h",
@@ -107,6 +108,7 @@ cc_library(
"internal/identity.h",
"internal/inline_variable.h",
"internal/invoke.h",
+ "internal/scheduling_mode.h",
],
copts = ABSL_DEFAULT_COPTS,
visibility = [
@@ -229,7 +231,6 @@ cc_library(
copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
deps = [
- ":base",
":config",
":pretty_function",
"//absl/memory",
@@ -314,6 +315,33 @@ cc_test(
)
cc_library(
+ name = "spinlock_benchmark_common",
+ testonly = 1,
+ srcs = ["internal/spinlock_benchmark.cc"],
+ copts = ABSL_DEFAULT_COPTS,
+ visibility = [
+ "//absl/base:__pkg__",
+ ],
+ deps = [
+ ":base",
+ ":base_internal",
+ "//absl/synchronization",
+ "@com_github_google_benchmark//:benchmark_main",
+ ],
+ alwayslink = 1,
+)
+
+cc_binary(
+ name = "spinlock_benchmark",
+ testonly = 1,
+ copts = ABSL_DEFAULT_COPTS,
+ visibility = ["//visibility:private"],
+ deps = [
+ ":spinlock_benchmark_common",
+ ],
+)
+
+cc_library(
name = "endian",
hdrs = [
"internal/endian.h",
diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt
index 212dd083..1016a665 100644
--- a/absl/base/CMakeLists.txt
+++ b/absl/base/CMakeLists.txt
@@ -60,6 +60,7 @@ absl_cc_library(
core_headers
HDRS
"attributes.h"
+ "const_init.h"
"macros.h"
"optimization.h"
"port.h"
@@ -180,10 +181,11 @@ absl_cc_library(
SRCS
"internal/exception_safety_testing.cc"
COPTS
- ${ABSL_DEFAULT_COPTS}
+ ${ABSL_TEST_COPTS}
${ABSL_EXCEPTIONS_FLAG}
+ LINKOPTS
+ ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
DEPS
- absl::base
absl::config
absl::pretty_function
absl::memory
@@ -200,6 +202,7 @@ absl_cc_test(
SRCS
"exception_safety_testing_test.cc"
COPTS
+ ${ABSL_TEST_COPTS}
${ABSL_EXCEPTIONS_FLAG}
LINKOPTS
${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
diff --git a/absl/base/call_once_test.cc b/absl/base/call_once_test.cc
index cd58ee19..183b92ef 100644
--- a/absl/base/call_once_test.cc
+++ b/absl/base/call_once_test.cc
@@ -18,6 +18,8 @@
#include <vector>
#include "gtest/gtest.h"
+#include "absl/base/attributes.h"
+#include "absl/base/const_init.h"
#include "absl/base/thread_annotations.h"
#include "absl/synchronization/mutex.h"
@@ -25,7 +27,8 @@ namespace absl {
namespace {
absl::once_flag once;
-Mutex counters_mu;
+
+ABSL_CONST_INIT Mutex counters_mu(absl::kConstInit);
int running_thread_count GUARDED_BY(counters_mu) = 0;
int call_once_invoke_count GUARDED_BY(counters_mu) = 0;
diff --git a/absl/base/const_init.h b/absl/base/const_init.h
new file mode 100644
index 00000000..fc88b267
--- /dev/null
+++ b/absl/base/const_init.h
@@ -0,0 +1,73 @@
+// 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.
+//
+// -----------------------------------------------------------------------------
+// kConstInit
+// -----------------------------------------------------------------------------
+//
+// A constructor tag used to mark an object as safe for use as a global
+// variable, avoiding the usual lifetime issues that can affect globals.
+
+#ifndef ABSL_BASE_CONST_INIT_H_
+#define ABSL_BASE_CONST_INIT_H_
+
+// In general, objects with static storage duration (such as global variables)
+// can trigger tricky object lifetime situations. Attempting to access them
+// from the constructors or destructors of other global objects can result in
+// undefined behavior, unless their constructors and destructors are designed
+// with this issue in mind.
+//
+// The normal way to deal with this issue in C++11 is to use constant
+// initialization and trivial destructors.
+//
+// Constant initialization is guaranteed to occur before any other code
+// executes. Constructors that are declared 'constexpr' are eligible for
+// constant initialization. You can annotate a variable declaration with the
+// ABSL_CONST_INIT macro to express this intent. For compilers that support
+// it, this annotation will cause a compilation error for declarations that
+// aren't subject to constant initialization (perhaps because a runtime value
+// was passed as a constructor argument).
+//
+// On program shutdown, lifetime issues can be avoided on global objects by
+// ensuring that they contain trivial destructors. A class has a trivial
+// destructor unless it has a user-defined destructor, a virtual method or base
+// class, or a data member or base class with a non-trivial destructor of its
+// own. Objects with static storage duration and a trivial destructor are not
+// cleaned up on program shutdown, and are thus safe to access from other code
+// running during shutdown.
+//
+// For a few core Abseil classes, we make a best effort to allow for safe global
+// instances, even though these classes have non-trivial destructors. These
+// objects can be created with the absl::kConstInit tag. For example:
+// ABSL_CONST_INIT absl::Mutex global_mutex(absl::kConstInit);
+//
+// The line above declares a global variable of type absl::Mutex which can be
+// accessed at any point during startup or shutdown. global_mutex's destructor
+// will still run, but will not invalidate the object. Note that C++ specifies
+// that accessing an object after its destructor has run results in undefined
+// behavior, but this pattern works on the toolchains we support.
+//
+// The absl::kConstInit tag should only be used to define objects with static
+// or thread_local storage duration.
+//
+
+namespace absl {
+
+enum ConstInitType {
+ kConstInit,
+};
+
+} // namespace absl
+
+#endif // ABSL_BASE_CONST_INIT_H_
diff --git a/absl/base/internal/spinlock.h b/absl/base/internal/spinlock.h
index dcce0109..eb3eec9c 100644
--- a/absl/base/internal/spinlock.h
+++ b/absl/base/internal/spinlock.h
@@ -101,8 +101,8 @@ class LOCKABLE SpinLock {
inline void Unlock() UNLOCK_FUNCTION() {
ABSL_TSAN_MUTEX_PRE_UNLOCK(this, 0);
uint32_t lock_value = lockword_.load(std::memory_order_relaxed);
- lockword_.store(lock_value & kSpinLockCooperative,
- std::memory_order_release);
+ lock_value = lockword_.exchange(lock_value & kSpinLockCooperative,
+ std::memory_order_release);
if ((lock_value & kSpinLockDisabledScheduling) != 0) {
base_internal::SchedulingGuard::EnableRescheduling(true);
diff --git a/absl/base/internal/spinlock_benchmark.cc b/absl/base/internal/spinlock_benchmark.cc
new file mode 100644
index 00000000..907d3e27
--- /dev/null
+++ b/absl/base/internal/spinlock_benchmark.cc
@@ -0,0 +1,52 @@
+// Copyright 2018 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.
+
+// See also //absl/synchronization:mutex_benchmark for a comparison of SpinLock
+// and Mutex performance under varying levels of contention.
+
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/internal/scheduling_mode.h"
+#include "absl/base/internal/spinlock.h"
+#include "absl/synchronization/internal/create_thread_identity.h"
+#include "benchmark/benchmark.h"
+
+namespace {
+
+template <absl::base_internal::SchedulingMode scheduling_mode>
+static void BM_SpinLock(benchmark::State& state) {
+ // Ensure a ThreadIdentity is installed.
+ ABSL_INTERNAL_CHECK(
+ absl::synchronization_internal::GetOrCreateCurrentThreadIdentity() !=
+ nullptr,
+ "GetOrCreateCurrentThreadIdentity() failed");
+
+ static auto* spinlock = new absl::base_internal::SpinLock(scheduling_mode);
+ for (auto _ : state) {
+ absl::base_internal::SpinLockHolder holder(spinlock);
+ }
+}
+
+BENCHMARK_TEMPLATE(BM_SpinLock,
+ absl::base_internal::SCHEDULE_KERNEL_ONLY)
+ ->UseRealTime()
+ ->Threads(1)
+ ->ThreadPerCpu();
+
+BENCHMARK_TEMPLATE(BM_SpinLock,
+ absl::base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL)
+ ->UseRealTime()
+ ->Threads(1)
+ ->ThreadPerCpu();
+
+} // namespace
diff --git a/absl/container/BUILD.bazel b/absl/container/BUILD.bazel
index afc869f4..55aea397 100644
--- a/absl/container/BUILD.bazel
+++ b/absl/container/BUILD.bazel
@@ -15,11 +15,11 @@
#
load(
- "//absl:copts.bzl",
+ "//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
- "ABSL_TEST_COPTS",
"ABSL_EXCEPTIONS_FLAG",
"ABSL_EXCEPTIONS_FLAG_LINKOPTS",
+ "ABSL_TEST_COPTS",
)
package(default_visibility = ["//visibility:public"])
@@ -41,6 +41,8 @@ cc_test(
copts = ABSL_TEST_COPTS,
deps = [
":compressed_tuple",
+ "//absl/memory",
+ "//absl/utility",
"@com_google_googletest//:gtest_main",
],
)
@@ -462,6 +464,12 @@ cc_library(
)
cc_library(
+ name = "have_sse",
+ hdrs = ["internal/have_sse.h"],
+ copts = ABSL_DEFAULT_COPTS,
+)
+
+cc_library(
name = "raw_hash_set",
srcs = ["internal/raw_hash_set.cc"],
hdrs = ["internal/raw_hash_set.h"],
@@ -471,6 +479,7 @@ cc_library(
":container_memory",
":hash_policy_traits",
":hashtable_debug_hooks",
+ ":have_sse",
":layout",
"//absl/base:bits",
"//absl/base:config",
diff --git a/absl/container/CMakeLists.txt b/absl/container/CMakeLists.txt
index 7cddd84b..9f781004 100644
--- a/absl/container/CMakeLists.txt
+++ b/absl/container/CMakeLists.txt
@@ -30,7 +30,7 @@ absl_cc_library(
absl_cc_library(
NAME
compressed_tuple
- SRCS
+ HDRS
"internal/compressed_tuple.h"
DEPS
absl::utility
@@ -44,6 +44,8 @@ absl_cc_test(
"internal/compressed_tuple_test.cc"
DEPS
absl::compressed_tuple
+ absl::memory
+ absl::utility
gmock_main
)
@@ -452,6 +454,16 @@ absl_cc_library(
absl_cc_library(
NAME
+ have_sse
+ HDRS
+ "internal/have_sse.h"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ PUBLIC
+)
+
+absl_cc_library(
+ NAME
node_hash_policy
HDRS
"internal/node_hash_policy.h"
@@ -494,15 +506,16 @@ absl_cc_library(
COPTS
${ABSL_DEFAULT_COPTS}
DEPS
+ absl::bits
absl::compressed_tuple
+ absl::config
absl::container_memory
+ absl::core_headers
+ absl::endian
absl::hash_policy_traits
absl::hashtable_debug_hooks
+ absl::have_sse
absl::layout
- absl::bits
- absl::config
- absl::core_headers
- absl::endian
absl::memory
absl::meta
absl::optional
diff --git a/absl/container/flat_hash_set.h b/absl/container/flat_hash_set.h
index 5ea6a816..84984cc4 100644
--- a/absl/container/flat_hash_set.h
+++ b/absl/container/flat_hash_set.h
@@ -279,8 +279,7 @@ class flat_hash_set
//
// The element may be constructed even if there already is an element with the
// key in the container, in which case the newly constructed element will be
- // destroyed immediately. Prefer `try_emplace()` unless your key is not
- // copyable or moveable.
+ // destroyed immediately.
//
// If rehashing occurs due to the insertion, all iterators are invalidated.
using Base::emplace;
@@ -294,8 +293,7 @@ class flat_hash_set
//
// The element may be constructed even if there already is an element with the
// key in the container, in which case the newly constructed element will be
- // destroyed immediately. Prefer `try_emplace()` unless your key is not
- // copyable or moveable.
+ // destroyed immediately.
//
// If rehashing occurs due to the insertion, all iterators are invalidated.
using Base::emplace_hint;
diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h
index 642dae6c..fe228001 100644
--- a/absl/container/inlined_vector.h
+++ b/absl/container/inlined_vector.h
@@ -66,12 +66,11 @@ namespace absl {
// designed to cover the same API footprint as covered by `std::vector`.
template <typename T, size_t N, typename A = std::allocator<T>>
class InlinedVector {
+ static_assert(N > 0, "InlinedVector requires inline capacity greater than 0");
constexpr static typename A::size_type inlined_capacity() {
return static_cast<typename A::size_type>(N);
}
- static_assert(inlined_capacity() > 0, "InlinedVector needs inlined capacity");
-
template <typename Iterator>
using DisableIfIntegral =
absl::enable_if_t<!std::is_integral<Iterator>::value>;
@@ -131,7 +130,8 @@ class InlinedVector {
InlinedVector(std::initializer_list<value_type> init_list,
const allocator_type& alloc = allocator_type())
: allocator_and_tag_(alloc) {
- AppendRange(init_list.begin(), init_list.end());
+ AppendRange(init_list.begin(), init_list.end(),
+ IteratorCategory<decltype(init_list.begin())>{});
}
// Creates an inlined vector with elements constructed from the provided
@@ -144,14 +144,25 @@ class InlinedVector {
InlinedVector(InputIterator first, InputIterator last,
const allocator_type& alloc = allocator_type())
: allocator_and_tag_(alloc) {
- AppendRange(first, last);
+ AppendRange(first, last, IteratorCategory<InputIterator>{});
}
// Creates a copy of `other` using `other`'s allocator.
- InlinedVector(const InlinedVector& other);
+ InlinedVector(const InlinedVector& other)
+ : InlinedVector(other, other.get_allocator()) {}
// Creates a copy of `other` but with a specified allocator.
- InlinedVector(const InlinedVector& other, const allocator_type& alloc);
+ InlinedVector(const InlinedVector& other, const allocator_type& alloc)
+ : allocator_and_tag_(alloc) {
+ reserve(other.size());
+ if (allocated()) {
+ UninitializedCopy(other.begin(), other.end(), allocated_space());
+ tag().set_allocated_size(other.size());
+ } else {
+ UninitializedCopy(other.begin(), other.end(), inlined_space());
+ tag().set_inline_size(other.size());
+ }
+ }
// Creates an inlined vector by moving in the contents of `other`.
//
@@ -163,9 +174,22 @@ class InlinedVector {
// allocation function as the `InlinedVector`'s allocator, so the move
// constructor is non-throwing if the allocator is non-throwing or
// `value_type`'s move constructor is specified as `noexcept`.
- InlinedVector(InlinedVector&& v) noexcept(
+ InlinedVector(InlinedVector&& other) noexcept(
absl::allocator_is_nothrow<allocator_type>::value ||
- std::is_nothrow_move_constructible<value_type>::value);
+ std::is_nothrow_move_constructible<value_type>::value)
+ : allocator_and_tag_(other.allocator_and_tag_) {
+ if (other.allocated()) {
+ // We can just steal the underlying buffer from the source.
+ // That leaves the source empty, so we clear its size.
+ init_allocation(other.allocation());
+ other.tag() = Tag();
+ } else {
+ UninitializedCopy(
+ std::make_move_iterator(other.inlined_space()),
+ std::make_move_iterator(other.inlined_space() + other.size()),
+ inlined_space());
+ }
+ }
// Creates an inlined vector by moving in the contents of `other`.
//
@@ -175,8 +199,31 @@ class InlinedVector {
// same assumptions as above, the `noexcept` specification is dominated by
// whether the allocation can throw regardless of whether `value_type`'s move
// constructor is specified as `noexcept`.
- InlinedVector(InlinedVector&& v, const allocator_type& alloc) noexcept(
- absl::allocator_is_nothrow<allocator_type>::value);
+ InlinedVector(InlinedVector&& other, const allocator_type& alloc) noexcept(
+ absl::allocator_is_nothrow<allocator_type>::value)
+ : allocator_and_tag_(alloc) {
+ if (other.allocated()) {
+ if (alloc == other.allocator()) {
+ // We can just steal the allocation from the source.
+ tag() = other.tag();
+ init_allocation(other.allocation());
+ other.tag() = Tag();
+ } else {
+ // We need to use our own allocator
+ reserve(other.size());
+ UninitializedCopy(std::make_move_iterator(other.begin()),
+ std::make_move_iterator(other.end()),
+ allocated_space());
+ tag().set_allocated_size(other.size());
+ }
+ } else {
+ UninitializedCopy(
+ std::make_move_iterator(other.inlined_space()),
+ std::make_move_iterator(other.inlined_space() + other.size()),
+ inlined_space());
+ tag().set_inline_size(other.size());
+ }
+ }
~InlinedVector() { clear(); }
@@ -255,7 +302,7 @@ class InlinedVector {
reference at(size_type i) {
if (ABSL_PREDICT_FALSE(i >= size())) {
base_internal::ThrowStdOutOfRange(
- "InlinedVector::at() failed bounds check");
+ "`InlinedVector::at(size_type)` failed bounds check");
}
return data()[i];
}
@@ -265,7 +312,7 @@ class InlinedVector {
const_reference at(size_type i) const {
if (ABSL_PREDICT_FALSE(i >= size())) {
base_internal::ThrowStdOutOfRange(
- "InlinedVector::at() failed bounds check");
+ "`InlinedVector::at(size_type) const` failed bounds check");
}
return data()[i];
}
@@ -366,7 +413,6 @@ class InlinedVector {
// Returns a copy of the allocator of the inlined vector.
allocator_type get_allocator() const { return allocator(); }
-
// ---------------------------------------------------------------------------
// InlinedVector Member Mutators
// ---------------------------------------------------------------------------
@@ -376,7 +422,8 @@ class InlinedVector {
// Replaces the contents of the inlined vector with copies of the elements in
// the provided `std::initializer_list`.
InlinedVector& operator=(std::initializer_list<value_type> init_list) {
- AssignRange(init_list.begin(), init_list.end());
+ AssignRange(init_list.begin(), init_list.end(),
+ IteratorCategory<decltype(init_list.begin())>{});
return *this;
}
@@ -453,14 +500,15 @@ class InlinedVector {
// inlined vector with copies of the values in the provided
// `std::initializer_list`.
void assign(std::initializer_list<value_type> init_list) {
- AssignRange(init_list.begin(), init_list.end());
+ AssignRange(init_list.begin(), init_list.end(),
+ IteratorCategory<decltype(init_list.begin())>{});
}
// Overload of `InlinedVector::assign()` to replace the contents of the
// inlined vector with values constructed from the range [`first`, `last`).
template <typename InputIterator, DisableIfIntegral<InputIterator>* = nullptr>
void assign(InputIterator first, InputIterator last) {
- AssignRange(first, last);
+ AssignRange(first, last, IteratorCategory<InputIterator>{});
}
// `InlinedVector::resize()`
@@ -468,12 +516,46 @@ class InlinedVector {
// Resizes the inlined vector to contain `n` elements. If `n` is smaller than
// the inlined vector's current size, extra elements are destroyed. If `n` is
// larger than the initial size, new elements are value-initialized.
- void resize(size_type n);
+ void resize(size_type n) {
+ size_type s = size();
+ if (n < s) {
+ erase(begin() + n, end());
+ return;
+ }
+ reserve(n);
+ assert(capacity() >= n);
+
+ // Fill new space with elements constructed in-place.
+ if (allocated()) {
+ UninitializedFill(allocated_space() + s, allocated_space() + n);
+ tag().set_allocated_size(n);
+ } else {
+ UninitializedFill(inlined_space() + s, inlined_space() + n);
+ tag().set_inline_size(n);
+ }
+ }
// Overload of `InlinedVector::resize()` to resize the inlined vector to
// contain `n` elements where, if `n` is larger than `size()`, the new values
// will be copy-constructed from `v`.
- void resize(size_type n, const_reference v);
+ void resize(size_type n, const_reference v) {
+ size_type s = size();
+ if (n < s) {
+ erase(begin() + n, end());
+ return;
+ }
+ reserve(n);
+ assert(capacity() >= n);
+
+ // Fill new space with copies of `v`.
+ if (allocated()) {
+ UninitializedFill(allocated_space() + s, allocated_space() + n, v);
+ tag().set_allocated_size(n);
+ } else {
+ UninitializedFill(inlined_space() + s, inlined_space() + n, v);
+ tag().set_inline_size(n);
+ }
+ }
// `InlinedVector::insert()`
//
@@ -523,7 +605,27 @@ class InlinedVector {
// Constructs and inserts an object in the inlined vector at the given
// `position`, returning an `iterator` pointing to the newly emplaced element.
template <typename... Args>
- iterator emplace(const_iterator position, Args&&... args);
+ iterator emplace(const_iterator position, Args&&... args) {
+ assert(position >= begin());
+ assert(position <= end());
+ if (ABSL_PREDICT_FALSE(position == end())) {
+ emplace_back(std::forward<Args>(args)...);
+ return end() - 1;
+ }
+
+ T new_t = T(std::forward<Args>(args)...);
+
+ auto range = ShiftRight(position, 1);
+ if (range.first == range.second) {
+ // constructing into uninitialized memory
+ Construct(range.first, std::move(new_t));
+ } else {
+ // assigning into moved-from object
+ *range.first = T(std::move(new_t));
+ }
+
+ return range.first;
+ }
// `InlinedVector::emplace_back()`
//
@@ -596,7 +698,30 @@ class InlinedVector {
// range [`from`, `to`) in the inlined vector. Returns an `iterator` pointing
// to the first element following the range erased or the end iterator if `to`
// was the end iterator.
- iterator erase(const_iterator from, const_iterator to);
+ iterator erase(const_iterator from, const_iterator to) {
+ assert(begin() <= from);
+ assert(from <= to);
+ assert(to <= end());
+
+ iterator range_start = const_cast<iterator>(from);
+ iterator range_end = const_cast<iterator>(to);
+
+ size_type s = size();
+ ptrdiff_t erase_gap = std::distance(range_start, range_end);
+ if (erase_gap > 0) {
+ pointer space;
+ if (allocated()) {
+ space = allocated_space();
+ tag().set_allocated_size(s - erase_gap);
+ } else {
+ space = inlined_space();
+ tag().set_inline_size(s - erase_gap);
+ }
+ std::move(range_end, space + s, range_start);
+ Destroy(space + s - erase_gap, space + s);
+ }
+ return range_start;
+ }
// `InlinedVector::clear()`
//
@@ -667,16 +792,88 @@ class InlinedVector {
// `InlinedVector::swap()`
//
// Swaps the contents of this inlined vector with the contents of `other`.
- void swap(InlinedVector& other);
+ void swap(InlinedVector& other) {
+ if (ABSL_PREDICT_FALSE(this == &other)) return;
+
+ using std::swap; // Augment ADL with `std::swap`.
+ if (allocated() && other.allocated()) {
+ // Both out of line, so just swap the tag, allocation, and allocator.
+ swap(tag(), other.tag());
+ swap(allocation(), other.allocation());
+ swap(allocator(), other.allocator());
+ return;
+ }
+ if (!allocated() && !other.allocated()) {
+ // Both inlined: swap up to smaller size, then move remaining elements.
+ InlinedVector* a = this;
+ InlinedVector* b = &other;
+ if (size() < other.size()) {
+ swap(a, b);
+ }
- template <typename Hash>
- friend Hash AbslHashValue(Hash hash, const InlinedVector& inlined_vector) {
- const_pointer p = inlined_vector.data();
- size_type n = inlined_vector.size();
- return Hash::combine(Hash::combine_contiguous(std::move(hash), p, n), n);
+ const size_type a_size = a->size();
+ const size_type b_size = b->size();
+ assert(a_size >= b_size);
+ // `a` is larger. Swap the elements up to the smaller array size.
+ std::swap_ranges(a->inlined_space(), a->inlined_space() + b_size,
+ b->inlined_space());
+
+ // Move the remaining elements:
+ // [`b_size`, `a_size`) from `a` -> [`b_size`, `a_size`) from `b`
+ b->UninitializedCopy(a->inlined_space() + b_size,
+ a->inlined_space() + a_size,
+ b->inlined_space() + b_size);
+ a->Destroy(a->inlined_space() + b_size, a->inlined_space() + a_size);
+
+ swap(a->tag(), b->tag());
+ swap(a->allocator(), b->allocator());
+ assert(b->size() == a_size);
+ assert(a->size() == b_size);
+ return;
+ }
+
+ // One is out of line, one is inline.
+ // We first move the elements from the inlined vector into the
+ // inlined space in the other vector. We then put the other vector's
+ // pointer/capacity into the originally inlined vector and swap
+ // the tags.
+ InlinedVector* a = this;
+ InlinedVector* b = &other;
+ if (a->allocated()) {
+ swap(a, b);
+ }
+ assert(!a->allocated());
+ assert(b->allocated());
+ const size_type a_size = a->size();
+ const size_type b_size = b->size();
+ // In an optimized build, `b_size` would be unused.
+ static_cast<void>(b_size);
+
+ // Made Local copies of `size()`, don't need `tag()` accurate anymore
+ swap(a->tag(), b->tag());
+
+ // Copy `b_allocation` out before `b`'s union gets clobbered by
+ // `inline_space`
+ Allocation b_allocation = b->allocation();
+
+ b->UninitializedCopy(a->inlined_space(), a->inlined_space() + a_size,
+ b->inlined_space());
+ a->Destroy(a->inlined_space(), a->inlined_space() + a_size);
+
+ a->allocation() = b_allocation;
+
+ if (a->allocator() != b->allocator()) {
+ swap(a->allocator(), b->allocator());
+ }
+
+ assert(b->size() == a_size);
+ assert(a->size() == b_size);
}
private:
+ template <typename Hash, typename OtherT, size_t OtherN, typename OtherA>
+ friend Hash AbslHashValue(Hash, const InlinedVector<OtherT, OtherN, OtherA>&);
+
// Holds whether the vector is allocated or not in the lowest bit and the size
// in the high bits:
// `size_ = (size << 1) | is_allocated;`
@@ -773,10 +970,76 @@ class InlinedVector {
bool allocated() const { return tag().allocated(); }
+ void ResetAllocation(Allocation new_allocation, size_type new_size) {
+ if (allocated()) {
+ Destroy(allocated_space(), allocated_space() + size());
+ assert(begin() == allocated_space());
+ allocation().Dealloc(allocator());
+ allocation() = new_allocation;
+ } else {
+ Destroy(inlined_space(), inlined_space() + size());
+ init_allocation(new_allocation); // bug: only init once
+ }
+ tag().set_allocated_size(new_size);
+ }
+
+ template <typename... Args>
+ reference Construct(pointer p, Args&&... args) {
+ std::allocator_traits<allocator_type>::construct(
+ allocator(), p, std::forward<Args>(args)...);
+ return *p;
+ }
+
+ template <typename Iterator>
+ void UninitializedCopy(Iterator src, Iterator src_last, pointer dst) {
+ for (; src != src_last; ++dst, ++src) Construct(dst, *src);
+ }
+
+ template <typename... Args>
+ void UninitializedFill(pointer dst, pointer dst_last, const Args&... args) {
+ for (; dst != dst_last; ++dst) Construct(dst, args...);
+ }
+
+ // Destroy [`from`, `to`) in place.
+ void Destroy(pointer from, pointer to) {
+ for (pointer cur = from; cur != to; ++cur) {
+ std::allocator_traits<allocator_type>::destroy(allocator(), cur);
+ }
+#if !defined(NDEBUG)
+ // Overwrite unused memory with `0xab` so we can catch uninitialized usage.
+ // Cast to `void*` to tell the compiler that we don't care that we might be
+ // scribbling on a vtable pointer.
+ if (from != to) {
+ auto len = sizeof(value_type) * std::distance(from, to);
+ std::memset(reinterpret_cast<void*>(from), 0xab, len);
+ }
+#endif // !defined(NDEBUG)
+ }
+
// Enlarge the underlying representation so we can store `size_ + delta` elems
// in allocated space. The size is not changed, and any newly added memory is
// not initialized.
- void EnlargeBy(size_type delta);
+ void EnlargeBy(size_type delta) {
+ const size_type s = size();
+ assert(s <= capacity());
+
+ size_type target = (std::max)(inlined_capacity(), s + delta);
+
+ // Compute new capacity by repeatedly doubling current capacity
+ // TODO(psrc): Check and avoid overflow?
+ size_type new_capacity = capacity();
+ while (new_capacity < target) {
+ new_capacity <<= 1;
+ }
+
+ Allocation new_allocation(allocator(), new_capacity);
+
+ UninitializedCopy(std::make_move_iterator(data()),
+ std::make_move_iterator(data() + s),
+ new_allocation.buffer());
+
+ ResetAllocation(new_allocation, s);
+ }
// Shift all elements from `position` to `end()` by `n` places to the right.
// If the vector needs to be enlarged, memory will be allocated.
@@ -787,19 +1050,61 @@ class InlinedVector {
//
// Updates the size of the InlinedVector internally.
std::pair<iterator, iterator> ShiftRight(const_iterator position,
- size_type n);
+ size_type n) {
+ iterator start_used = const_cast<iterator>(position);
+ iterator start_raw = const_cast<iterator>(position);
+ size_type s = size();
+ size_type required_size = s + n;
- void ResetAllocation(Allocation new_allocation, size_type new_size) {
- if (allocated()) {
- Destroy(allocated_space(), allocated_space() + size());
- assert(begin() == allocated_space());
- allocation().Dealloc(allocator());
- allocation() = new_allocation;
+ if (required_size > capacity()) {
+ // Compute new capacity by repeatedly doubling current capacity
+ size_type new_capacity = capacity();
+ while (new_capacity < required_size) {
+ new_capacity <<= 1;
+ }
+ // Move everyone into the new allocation, leaving a gap of `n` for the
+ // requested shift.
+ Allocation new_allocation(allocator(), new_capacity);
+ size_type index = position - begin();
+ UninitializedCopy(std::make_move_iterator(data()),
+ std::make_move_iterator(data() + index),
+ new_allocation.buffer());
+ UninitializedCopy(std::make_move_iterator(data() + index),
+ std::make_move_iterator(data() + s),
+ new_allocation.buffer() + index + n);
+ ResetAllocation(new_allocation, s);
+
+ // New allocation means our iterator is invalid, so we'll recalculate.
+ // Since the entire gap is in new space, there's no used space to reuse.
+ start_raw = begin() + index;
+ start_used = start_raw;
} else {
- Destroy(inlined_space(), inlined_space() + size());
- init_allocation(new_allocation); // bug: only init once
+ // If we had enough space, it's a two-part move. Elements going into
+ // previously-unoccupied space need an `UninitializedCopy()`. Elements
+ // going into a previously-occupied space are just a `std::move()`.
+ iterator pos = const_cast<iterator>(position);
+ iterator raw_space = end();
+ size_type slots_in_used_space = raw_space - pos;
+ size_type new_elements_in_used_space = (std::min)(n, slots_in_used_space);
+ size_type new_elements_in_raw_space = n - new_elements_in_used_space;
+ size_type old_elements_in_used_space =
+ slots_in_used_space - new_elements_in_used_space;
+
+ UninitializedCopy(
+ std::make_move_iterator(pos + old_elements_in_used_space),
+ std::make_move_iterator(raw_space),
+ raw_space + new_elements_in_raw_space);
+ std::move_backward(pos, pos + old_elements_in_used_space, raw_space);
+
+ // If the gap is entirely in raw space, the used space starts where the
+ // raw space starts, leaving no elements in used space. If the gap is
+ // entirely in used space, the raw space starts at the end of the gap,
+ // leaving all elements accounted for within the used space.
+ start_used = pos;
+ start_raw = pos + new_elements_in_used_space;
}
- tag().set_allocated_size(new_size);
+ tag().add_size(n);
+ return std::make_pair(start_used, start_raw);
}
template <typename... Args>
@@ -820,64 +1125,118 @@ class InlinedVector {
return new_element;
}
- void InitAssign(size_type n);
-
- void InitAssign(size_type n, const_reference v);
-
- template <typename... Args>
- reference Construct(pointer p, Args&&... args) {
- std::allocator_traits<allocator_type>::construct(
- allocator(), p, std::forward<Args>(args)...);
- return *p;
+ void InitAssign(size_type n) {
+ if (n > inlined_capacity()) {
+ Allocation new_allocation(allocator(), n);
+ init_allocation(new_allocation);
+ UninitializedFill(allocated_space(), allocated_space() + n);
+ tag().set_allocated_size(n);
+ } else {
+ UninitializedFill(inlined_space(), inlined_space() + n);
+ tag().set_inline_size(n);
+ }
}
- template <typename Iterator>
- void UninitializedCopy(Iterator src, Iterator src_last, pointer dst) {
- for (; src != src_last; ++dst, ++src) Construct(dst, *src);
+ void InitAssign(size_type n, const_reference v) {
+ if (n > inlined_capacity()) {
+ Allocation new_allocation(allocator(), n);
+ init_allocation(new_allocation);
+ UninitializedFill(allocated_space(), allocated_space() + n, v);
+ tag().set_allocated_size(n);
+ } else {
+ UninitializedFill(inlined_space(), inlined_space() + n, v);
+ tag().set_inline_size(n);
+ }
}
- template <typename... Args>
- void UninitializedFill(pointer dst, pointer dst_last, const Args&... args) {
- for (; dst != dst_last; ++dst) Construct(dst, args...);
+ template <typename Iterator>
+ void AssignRange(Iterator first, Iterator last, std::forward_iterator_tag) {
+ auto length = std::distance(first, last);
+ // Prefer reassignment to copy construction for elements.
+ if (static_cast<size_type>(length) <= size()) {
+ erase(std::copy(first, last, begin()), end());
+ return;
+ }
+ reserve(length);
+ iterator out = begin();
+ for (; out != end(); ++first, ++out) *out = *first;
+ if (allocated()) {
+ UninitializedCopy(first, last, out);
+ tag().set_allocated_size(length);
+ } else {
+ UninitializedCopy(first, last, out);
+ tag().set_inline_size(length);
+ }
}
- // Destroy [`from`, `to`) in place.
- void Destroy(pointer from, pointer to);
-
template <typename Iterator>
- void AppendRange(Iterator first, Iterator last, std::input_iterator_tag) {
+ void AssignRange(Iterator first, Iterator last, std::input_iterator_tag) {
+ // Optimized to avoid reallocation.
+ // Prefer reassignment to copy construction for elements.
+ iterator out = begin();
+ for (; first != last && out != end(); ++first, ++out) {
+ *out = *first;
+ }
+ erase(out, end());
std::copy(first, last, std::back_inserter(*this));
}
template <typename Iterator>
- void AppendRange(Iterator first, Iterator last, std::forward_iterator_tag);
+ void AppendRange(Iterator first, Iterator last, std::forward_iterator_tag) {
+ auto length = std::distance(first, last);
+ reserve(size() + length);
+ if (allocated()) {
+ UninitializedCopy(first, last, allocated_space() + size());
+ tag().set_allocated_size(size() + length);
+ } else {
+ UninitializedCopy(first, last, inlined_space() + size());
+ tag().set_inline_size(size() + length);
+ }
+ }
template <typename Iterator>
- void AppendRange(Iterator first, Iterator last) {
- AppendRange(first, last, IteratorCategory<Iterator>());
+ void AppendRange(Iterator first, Iterator last, std::input_iterator_tag) {
+ std::copy(first, last, std::back_inserter(*this));
}
- template <typename Iterator>
- void AssignRange(Iterator first, Iterator last, std::input_iterator_tag);
+ iterator InsertWithCount(const_iterator position, size_type n,
+ const_reference v) {
+ assert(position >= begin() && position <= end());
+ if (ABSL_PREDICT_FALSE(n == 0)) return const_cast<iterator>(position);
- template <typename Iterator>
- void AssignRange(Iterator first, Iterator last, std::forward_iterator_tag);
+ value_type copy = v;
+ std::pair<iterator, iterator> it_pair = ShiftRight(position, n);
+ std::fill(it_pair.first, it_pair.second, copy);
+ UninitializedFill(it_pair.second, it_pair.first + n, copy);
- template <typename Iterator>
- void AssignRange(Iterator first, Iterator last) {
- AssignRange(first, last, IteratorCategory<Iterator>());
+ return it_pair.first;
}
- iterator InsertWithCount(const_iterator position, size_type n,
- const_reference v);
+ template <typename ForwardIterator>
+ iterator InsertWithRange(const_iterator position, ForwardIterator first,
+ ForwardIterator last, std::forward_iterator_tag) {
+ assert(position >= begin() && position <= end());
+ if (ABSL_PREDICT_FALSE(first == last))
+ return const_cast<iterator>(position);
+
+ auto n = std::distance(first, last);
+ std::pair<iterator, iterator> it_pair = ShiftRight(position, n);
+ size_type used_spots = it_pair.second - it_pair.first;
+ ForwardIterator open_spot = std::next(first, used_spots);
+ std::copy(first, open_spot, it_pair.first);
+ UninitializedCopy(open_spot, last, it_pair.second);
+ return it_pair.first;
+ }
template <typename InputIterator>
iterator InsertWithRange(const_iterator position, InputIterator first,
- InputIterator last, std::input_iterator_tag);
-
- template <typename ForwardIterator>
- iterator InsertWithRange(const_iterator position, ForwardIterator first,
- ForwardIterator last, std::forward_iterator_tag);
+ InputIterator last, std::input_iterator_tag) {
+ assert(position >= begin() && position <= end());
+ size_type index = position - cbegin();
+ size_type i = index;
+ while (first != last) insert(begin() + i++, *first++);
+ return begin() + index;
+ }
// Stores either the inlined or allocated representation
union Rep {
@@ -889,7 +1248,7 @@ class InlinedVector {
// Structs wrap the buffers to perform indirection that solves a bizarre
// compilation error on Visual Studio (all known versions).
struct InlinedRep {
- ValueTypeBuffer inlined[inlined_capacity()];
+ ValueTypeBuffer inlined[N];
};
struct AllocatedRep {
AllocationBuffer allocation;
@@ -975,477 +1334,19 @@ bool operator>=(const InlinedVector<T, N, A>& a,
return !(a < b);
}
+template <typename Hash, typename T, size_t N, typename A>
+Hash AbslHashValue(Hash hash, const InlinedVector<T, N, A>& inlined_vector) {
+ auto p = inlined_vector.data();
+ auto n = inlined_vector.size();
+ return Hash::combine(Hash::combine_contiguous(std::move(hash), p, n), n);
+}
+
// -----------------------------------------------------------------------------
// Implementation of InlinedVector
//
// Do not depend on any below implementation details!
// -----------------------------------------------------------------------------
-template <typename T, size_t N, typename A>
-InlinedVector<T, N, A>::InlinedVector(const InlinedVector& other)
- : allocator_and_tag_(other.allocator()) {
- reserve(other.size());
- if (allocated()) {
- UninitializedCopy(other.begin(), other.end(), allocated_space());
- tag().set_allocated_size(other.size());
- } else {
- UninitializedCopy(other.begin(), other.end(), inlined_space());
- tag().set_inline_size(other.size());
- }
-}
-
-template <typename T, size_t N, typename A>
-InlinedVector<T, N, A>::InlinedVector(const InlinedVector& other,
- const allocator_type& alloc)
- : allocator_and_tag_(alloc) {
- reserve(other.size());
- if (allocated()) {
- UninitializedCopy(other.begin(), other.end(), allocated_space());
- tag().set_allocated_size(other.size());
- } else {
- UninitializedCopy(other.begin(), other.end(), inlined_space());
- tag().set_inline_size(other.size());
- }
-}
-
-template <typename T, size_t N, typename A>
-InlinedVector<T, N, A>::InlinedVector(InlinedVector&& other) noexcept(
- absl::allocator_is_nothrow<allocator_type>::value ||
- std::is_nothrow_move_constructible<value_type>::value)
- : allocator_and_tag_(other.allocator_and_tag_) {
- if (other.allocated()) {
- // We can just steal the underlying buffer from the source.
- // That leaves the source empty, so we clear its size.
- init_allocation(other.allocation());
- other.tag() = Tag();
- } else {
- UninitializedCopy(
- std::make_move_iterator(other.inlined_space()),
- std::make_move_iterator(other.inlined_space() + other.size()),
- inlined_space());
- }
-}
-
-template <typename T, size_t N, typename A>
-InlinedVector<T, N, A>::InlinedVector(InlinedVector&& other,
- const allocator_type& alloc) noexcept( //
- absl::allocator_is_nothrow<allocator_type>::value)
- : allocator_and_tag_(alloc) {
- if (other.allocated()) {
- if (alloc == other.allocator()) {
- // We can just steal the allocation from the source.
- tag() = other.tag();
- init_allocation(other.allocation());
- other.tag() = Tag();
- } else {
- // We need to use our own allocator
- reserve(other.size());
- UninitializedCopy(std::make_move_iterator(other.begin()),
- std::make_move_iterator(other.end()),
- allocated_space());
- tag().set_allocated_size(other.size());
- }
- } else {
- UninitializedCopy(
- std::make_move_iterator(other.inlined_space()),
- std::make_move_iterator(other.inlined_space() + other.size()),
- inlined_space());
- tag().set_inline_size(other.size());
- }
-}
-
-template <typename T, size_t N, typename A>
-void InlinedVector<T, N, A>::InitAssign(size_type n, const_reference v) {
- if (n > inlined_capacity()) {
- Allocation new_allocation(allocator(), n);
- init_allocation(new_allocation);
- UninitializedFill(allocated_space(), allocated_space() + n, v);
- tag().set_allocated_size(n);
- } else {
- UninitializedFill(inlined_space(), inlined_space() + n, v);
- tag().set_inline_size(n);
- }
-}
-
-template <typename T, size_t N, typename A>
-void InlinedVector<T, N, A>::InitAssign(size_type n) {
- if (n > inlined_capacity()) {
- Allocation new_allocation(allocator(), n);
- init_allocation(new_allocation);
- UninitializedFill(allocated_space(), allocated_space() + n);
- tag().set_allocated_size(n);
- } else {
- UninitializedFill(inlined_space(), inlined_space() + n);
- tag().set_inline_size(n);
- }
-}
-
-template <typename T, size_t N, typename A>
-void InlinedVector<T, N, A>::resize(size_type n) {
- size_type s = size();
- if (n < s) {
- erase(begin() + n, end());
- return;
- }
- reserve(n);
- assert(capacity() >= n);
-
- // Fill new space with elements constructed in-place.
- if (allocated()) {
- UninitializedFill(allocated_space() + s, allocated_space() + n);
- tag().set_allocated_size(n);
- } else {
- UninitializedFill(inlined_space() + s, inlined_space() + n);
- tag().set_inline_size(n);
- }
-}
-
-template <typename T, size_t N, typename A>
-void InlinedVector<T, N, A>::resize(size_type n, const_reference v) {
- size_type s = size();
- if (n < s) {
- erase(begin() + n, end());
- return;
- }
- reserve(n);
- assert(capacity() >= n);
-
- // Fill new space with copies of 'v'.
- if (allocated()) {
- UninitializedFill(allocated_space() + s, allocated_space() + n, v);
- tag().set_allocated_size(n);
- } else {
- UninitializedFill(inlined_space() + s, inlined_space() + n, v);
- tag().set_inline_size(n);
- }
-}
-
-template <typename T, size_t N, typename A>
-template <typename... Args>
-auto InlinedVector<T, N, A>::emplace(const_iterator position, Args&&... args)
- -> iterator {
- assert(position >= begin());
- assert(position <= end());
- if (ABSL_PREDICT_FALSE(position == end())) {
- emplace_back(std::forward<Args>(args)...);
- return end() - 1;
- }
-
- T new_t = T(std::forward<Args>(args)...);
-
- auto range = ShiftRight(position, 1);
- if (range.first == range.second) {
- // constructing into uninitialized memory
- Construct(range.first, std::move(new_t));
- } else {
- // assigning into moved-from object
- *range.first = T(std::move(new_t));
- }
-
- return range.first;
-}
-
-template <typename T, size_t N, typename A>
-auto InlinedVector<T, N, A>::erase(const_iterator from, const_iterator to)
- -> iterator {
- assert(begin() <= from);
- assert(from <= to);
- assert(to <= end());
-
- iterator range_start = const_cast<iterator>(from);
- iterator range_end = const_cast<iterator>(to);
-
- size_type s = size();
- ptrdiff_t erase_gap = std::distance(range_start, range_end);
- if (erase_gap > 0) {
- pointer space;
- if (allocated()) {
- space = allocated_space();
- tag().set_allocated_size(s - erase_gap);
- } else {
- space = inlined_space();
- tag().set_inline_size(s - erase_gap);
- }
- std::move(range_end, space + s, range_start);
- Destroy(space + s - erase_gap, space + s);
- }
- return range_start;
-}
-
-template <typename T, size_t N, typename A>
-void InlinedVector<T, N, A>::swap(InlinedVector& other) {
- using std::swap; // Augment ADL with `std::swap`.
- if (ABSL_PREDICT_FALSE(this == &other)) return;
-
- if (allocated() && other.allocated()) {
- // Both out of line, so just swap the tag, allocation, and allocator.
- swap(tag(), other.tag());
- swap(allocation(), other.allocation());
- swap(allocator(), other.allocator());
- return;
- }
- if (!allocated() && !other.allocated()) {
- // Both inlined: swap up to smaller size, then move remaining elements.
- InlinedVector* a = this;
- InlinedVector* b = &other;
- if (size() < other.size()) {
- swap(a, b);
- }
-
- const size_type a_size = a->size();
- const size_type b_size = b->size();
- assert(a_size >= b_size);
- // `a` is larger. Swap the elements up to the smaller array size.
- std::swap_ranges(a->inlined_space(), a->inlined_space() + b_size,
- b->inlined_space());
-
- // Move the remaining elements:
- // [`b_size`, `a_size`) from `a` -> [`b_size`, `a_size`) from `b`
- b->UninitializedCopy(a->inlined_space() + b_size,
- a->inlined_space() + a_size,
- b->inlined_space() + b_size);
- a->Destroy(a->inlined_space() + b_size, a->inlined_space() + a_size);
-
- swap(a->tag(), b->tag());
- swap(a->allocator(), b->allocator());
- assert(b->size() == a_size);
- assert(a->size() == b_size);
- return;
- }
-
- // One is out of line, one is inline.
- // We first move the elements from the inlined vector into the
- // inlined space in the other vector. We then put the other vector's
- // pointer/capacity into the originally inlined vector and swap
- // the tags.
- InlinedVector* a = this;
- InlinedVector* b = &other;
- if (a->allocated()) {
- swap(a, b);
- }
- assert(!a->allocated());
- assert(b->allocated());
- const size_type a_size = a->size();
- const size_type b_size = b->size();
- // In an optimized build, `b_size` would be unused.
- static_cast<void>(b_size);
-
- // Made Local copies of `size()`, don't need `tag()` accurate anymore
- swap(a->tag(), b->tag());
-
- // Copy `b_allocation` out before `b`'s union gets clobbered by `inline_space`
- Allocation b_allocation = b->allocation();
-
- b->UninitializedCopy(a->inlined_space(), a->inlined_space() + a_size,
- b->inlined_space());
- a->Destroy(a->inlined_space(), a->inlined_space() + a_size);
-
- a->allocation() = b_allocation;
-
- if (a->allocator() != b->allocator()) {
- swap(a->allocator(), b->allocator());
- }
-
- assert(b->size() == a_size);
- assert(a->size() == b_size);
-}
-
-template <typename T, size_t N, typename A>
-void InlinedVector<T, N, A>::EnlargeBy(size_type delta) {
- const size_type s = size();
- assert(s <= capacity());
-
- size_type target = std::max(inlined_capacity(), s + delta);
-
- // Compute new capacity by repeatedly doubling current capacity
- // TODO(psrc): Check and avoid overflow?
- size_type new_capacity = capacity();
- while (new_capacity < target) {
- new_capacity <<= 1;
- }
-
- Allocation new_allocation(allocator(), new_capacity);
-
- UninitializedCopy(std::make_move_iterator(data()),
- std::make_move_iterator(data() + s),
- new_allocation.buffer());
-
- ResetAllocation(new_allocation, s);
-}
-
-template <typename T, size_t N, typename A>
-auto InlinedVector<T, N, A>::ShiftRight(const_iterator position, size_type n)
- -> std::pair<iterator, iterator> {
- iterator start_used = const_cast<iterator>(position);
- iterator start_raw = const_cast<iterator>(position);
- size_type s = size();
- size_type required_size = s + n;
-
- if (required_size > capacity()) {
- // Compute new capacity by repeatedly doubling current capacity
- size_type new_capacity = capacity();
- while (new_capacity < required_size) {
- new_capacity <<= 1;
- }
- // Move everyone into the new allocation, leaving a gap of `n` for the
- // requested shift.
- Allocation new_allocation(allocator(), new_capacity);
- size_type index = position - begin();
- UninitializedCopy(std::make_move_iterator(data()),
- std::make_move_iterator(data() + index),
- new_allocation.buffer());
- UninitializedCopy(std::make_move_iterator(data() + index),
- std::make_move_iterator(data() + s),
- new_allocation.buffer() + index + n);
- ResetAllocation(new_allocation, s);
-
- // New allocation means our iterator is invalid, so we'll recalculate.
- // Since the entire gap is in new space, there's no used space to reuse.
- start_raw = begin() + index;
- start_used = start_raw;
- } else {
- // If we had enough space, it's a two-part move. Elements going into
- // previously-unoccupied space need an `UninitializedCopy()`. Elements
- // going into a previously-occupied space are just a `std::move()`.
- iterator pos = const_cast<iterator>(position);
- iterator raw_space = end();
- size_type slots_in_used_space = raw_space - pos;
- size_type new_elements_in_used_space = std::min(n, slots_in_used_space);
- size_type new_elements_in_raw_space = n - new_elements_in_used_space;
- size_type old_elements_in_used_space =
- slots_in_used_space - new_elements_in_used_space;
-
- UninitializedCopy(std::make_move_iterator(pos + old_elements_in_used_space),
- std::make_move_iterator(raw_space),
- raw_space + new_elements_in_raw_space);
- std::move_backward(pos, pos + old_elements_in_used_space, raw_space);
-
- // If the gap is entirely in raw space, the used space starts where the raw
- // space starts, leaving no elements in used space. If the gap is entirely
- // in used space, the raw space starts at the end of the gap, leaving all
- // elements accounted for within the used space.
- start_used = pos;
- start_raw = pos + new_elements_in_used_space;
- }
- tag().add_size(n);
- return std::make_pair(start_used, start_raw);
-}
-
-template <typename T, size_t N, typename A>
-void InlinedVector<T, N, A>::Destroy(pointer from, pointer to) {
- for (pointer cur = from; cur != to; ++cur) {
- std::allocator_traits<allocator_type>::destroy(allocator(), cur);
- }
-#ifndef NDEBUG
- // Overwrite unused memory with `0xab` so we can catch uninitialized usage.
- // Cast to `void*` to tell the compiler that we don't care that we might be
- // scribbling on a vtable pointer.
- if (from != to) {
- auto len = sizeof(value_type) * std::distance(from, to);
- std::memset(reinterpret_cast<void*>(from), 0xab, len);
- }
-#endif
-}
-
-template <typename T, size_t N, typename A>
-template <typename Iterator>
-void InlinedVector<T, N, A>::AppendRange(Iterator first, Iterator last,
- std::forward_iterator_tag) {
- auto length = std::distance(first, last);
- reserve(size() + length);
- if (allocated()) {
- UninitializedCopy(first, last, allocated_space() + size());
- tag().set_allocated_size(size() + length);
- } else {
- UninitializedCopy(first, last, inlined_space() + size());
- tag().set_inline_size(size() + length);
- }
-}
-
-template <typename T, size_t N, typename A>
-template <typename Iterator>
-void InlinedVector<T, N, A>::AssignRange(Iterator first, Iterator last,
- std::input_iterator_tag) {
- // Optimized to avoid reallocation.
- // Prefer reassignment to copy construction for elements.
- iterator out = begin();
- for (; first != last && out != end(); ++first, ++out) {
- *out = *first;
- }
- erase(out, end());
- std::copy(first, last, std::back_inserter(*this));
-}
-
-template <typename T, size_t N, typename A>
-template <typename Iterator>
-void InlinedVector<T, N, A>::AssignRange(Iterator first, Iterator last,
- std::forward_iterator_tag) {
- auto length = std::distance(first, last);
- // Prefer reassignment to copy construction for elements.
- if (static_cast<size_type>(length) <= size()) {
- erase(std::copy(first, last, begin()), end());
- return;
- }
- reserve(length);
- iterator out = begin();
- for (; out != end(); ++first, ++out) *out = *first;
- if (allocated()) {
- UninitializedCopy(first, last, out);
- tag().set_allocated_size(length);
- } else {
- UninitializedCopy(first, last, out);
- tag().set_inline_size(length);
- }
-}
-
-template <typename T, size_t N, typename A>
-auto InlinedVector<T, N, A>::InsertWithCount(const_iterator position,
- size_type n, const_reference v)
- -> iterator {
- assert(position >= begin() && position <= end());
- if (ABSL_PREDICT_FALSE(n == 0)) return const_cast<iterator>(position);
-
- value_type copy = v;
- std::pair<iterator, iterator> it_pair = ShiftRight(position, n);
- std::fill(it_pair.first, it_pair.second, copy);
- UninitializedFill(it_pair.second, it_pair.first + n, copy);
-
- return it_pair.first;
-}
-
-template <typename T, size_t N, typename A>
-template <typename InputIterator>
-auto InlinedVector<T, N, A>::InsertWithRange(const_iterator position,
- InputIterator first,
- InputIterator last,
- std::input_iterator_tag)
- -> iterator {
- assert(position >= begin() && position <= end());
- size_type index = position - cbegin();
- size_type i = index;
- while (first != last) insert(begin() + i++, *first++);
- return begin() + index;
-}
-
-template <typename T, size_t N, typename A>
-template <typename ForwardIterator>
-auto InlinedVector<T, N, A>::InsertWithRange(const_iterator position,
- ForwardIterator first,
- ForwardIterator last,
- std::forward_iterator_tag)
- -> iterator {
- assert(position >= begin() && position <= end());
- if (ABSL_PREDICT_FALSE(first == last)) return const_cast<iterator>(position);
-
- auto n = std::distance(first, last);
- std::pair<iterator, iterator> it_pair = ShiftRight(position, n);
- size_type used_spots = it_pair.second - it_pair.first;
- ForwardIterator open_spot = std::next(first, used_spots);
- std::copy(first, open_spot, it_pair.first);
- UninitializedCopy(open_spot, last, it_pair.second);
- return it_pair.first;
-}
-
} // namespace absl
#endif // ABSL_CONTAINER_INLINED_VECTOR_H_
diff --git a/absl/container/internal/compressed_tuple.h b/absl/container/internal/compressed_tuple.h
index cc52614f..b883ae26 100644
--- a/absl/container/internal/compressed_tuple.h
+++ b/absl/container/internal/compressed_tuple.h
@@ -89,8 +89,10 @@ struct Storage {
T value;
constexpr Storage() = default;
explicit constexpr Storage(T&& v) : value(absl::forward<T>(v)) {}
- constexpr const T& get() const { return value; }
- T& get() { return value; }
+ constexpr const T& get() const& { return value; }
+ T& get() & { return value; }
+ constexpr const T&& get() const&& { return absl::move(*this).value; }
+ T&& get() && { return std::move(*this).value; }
};
template <typename D, size_t I>
@@ -99,8 +101,10 @@ struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC Storage<D, I, true>
using T = internal_compressed_tuple::ElemT<D, I>;
constexpr Storage() = default;
explicit constexpr Storage(T&& v) : T(absl::forward<T>(v)) {}
- constexpr const T& get() const { return *this; }
- T& get() { return *this; }
+ constexpr const T& get() const& { return *this; }
+ T& get() & { return *this; }
+ constexpr const T&& get() const&& { return absl::move(*this); }
+ T&& get() && { return std::move(*this); }
};
template <typename D, typename I>
@@ -152,14 +156,26 @@ class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple
: CompressedTuple::CompressedTupleImpl(absl::forward<Ts>(base)...) {}
template <int I>
- ElemT<I>& get() {
+ ElemT<I>& get() & {
return internal_compressed_tuple::Storage<CompressedTuple, I>::get();
}
template <int I>
- constexpr const ElemT<I>& get() const {
+ constexpr const ElemT<I>& get() const& {
return internal_compressed_tuple::Storage<CompressedTuple, I>::get();
}
+
+ template <int I>
+ ElemT<I>&& get() && {
+ return std::move(*this)
+ .internal_compressed_tuple::template Storage<CompressedTuple, I>::get();
+ }
+
+ template <int I>
+ constexpr const ElemT<I>&& get() const&& {
+ return absl::move(*this)
+ .internal_compressed_tuple::template Storage<CompressedTuple, I>::get();
+ }
};
// Explicit specialization for a zero-element tuple
diff --git a/absl/container/internal/compressed_tuple_test.cc b/absl/container/internal/compressed_tuple_test.cc
index 45030c67..04ead100 100644
--- a/absl/container/internal/compressed_tuple_test.cc
+++ b/absl/container/internal/compressed_tuple_test.cc
@@ -14,17 +14,25 @@
#include "absl/container/internal/compressed_tuple.h"
+#include <memory>
#include <string>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
+#include "absl/memory/memory.h"
+#include "absl/utility/utility.h"
namespace absl {
namespace container_internal {
namespace {
+enum class CallType { kConstRef, kConstMove };
+
template <int>
-struct Empty {};
+struct Empty {
+ constexpr CallType value() const& { return CallType::kConstRef; }
+ constexpr CallType value() const&& { return CallType::kConstMove; }
+};
template <typename T>
struct NotEmpty {
@@ -140,15 +148,44 @@ TEST(CompressedTupleTest, NoElements) {
EXPECT_TRUE(std::is_empty<CompressedTuple<>>::value);
}
+TEST(CompressedTupleTest, MoveOnlyElements) {
+ CompressedTuple<std::unique_ptr<std::string>> str_tup(
+ absl::make_unique<std::string>("str"));
+
+ CompressedTuple<CompressedTuple<std::unique_ptr<std::string>>,
+ std::unique_ptr<int>>
+ x(std::move(str_tup), absl::make_unique<int>(5));
+
+ EXPECT_EQ(*x.get<0>().get<0>(), "str");
+ EXPECT_EQ(*x.get<1>(), 5);
+
+ std::unique_ptr<std::string> x0 = std::move(x.get<0>()).get<0>();
+ std::unique_ptr<int> x1 = std::move(x).get<1>();
+
+ EXPECT_EQ(*x0, "str");
+ EXPECT_EQ(*x1, 5);
+}
+
TEST(CompressedTupleTest, Constexpr) {
- constexpr CompressedTuple<int, double, CompressedTuple<int>> x(
- 7, 1.25, CompressedTuple<int>(5));
+ constexpr CompressedTuple<int, double, CompressedTuple<int>, Empty<0>> x(
+ 7, 1.25, CompressedTuple<int>(5), {});
constexpr int x0 = x.get<0>();
constexpr double x1 = x.get<1>();
constexpr int x2 = x.get<2>().get<0>();
+ constexpr CallType x3 = x.get<3>().value();
+
EXPECT_EQ(x0, 7);
EXPECT_EQ(x1, 1.25);
EXPECT_EQ(x2, 5);
+ EXPECT_EQ(x3, CallType::kConstRef);
+
+#if defined(__clang__)
+ // An apparent bug in earlier versions of gcc claims these are ambiguous.
+ constexpr int x2m = absl::move(x.get<2>()).get<0>();
+ constexpr CallType x3m = absl::move(x).get<3>().value();
+ EXPECT_EQ(x2m, 5);
+ EXPECT_EQ(x3m, CallType::kConstMove);
+#endif
}
#if defined(__clang__) || defined(__GNUC__)
diff --git a/absl/container/internal/hashtable_debug.h b/absl/container/internal/hashtable_debug.h
index c3bd65c9..38050c69 100644
--- a/absl/container/internal/hashtable_debug.h
+++ b/absl/container/internal/hashtable_debug.h
@@ -60,7 +60,7 @@ std::vector<size_t> GetHashtableDebugNumProbesHistogram(const C& container) {
size_t num_probes = GetHashtableDebugNumProbes(
container,
absl::container_internal::hashtable_debug_internal::GetKey<C>(*it, 0));
- v.resize(std::max(v.size(), num_probes + 1));
+ v.resize((std::max)(v.size(), num_probes + 1));
v[num_probes]++;
}
return v;
diff --git a/absl/container/internal/have_sse.h b/absl/container/internal/have_sse.h
new file mode 100644
index 00000000..29347889
--- /dev/null
+++ b/absl/container/internal/have_sse.h
@@ -0,0 +1,49 @@
+// Copyright 2018 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.
+//
+// Shared config probing for SSE instructions used in Swiss tables.
+#ifndef ABSL_CONTAINER_INTERNAL_HAVE_SSE_H_
+#define ABSL_CONTAINER_INTERNAL_HAVE_SSE_H_
+
+#ifndef SWISSTABLE_HAVE_SSE2
+#if defined(__SSE2__) || \
+ (defined(_MSC_VER) && \
+ (defined(_M_X64) || (defined(_M_IX86) && _M_IX86_FP >= 2)))
+#define SWISSTABLE_HAVE_SSE2 1
+#else
+#define SWISSTABLE_HAVE_SSE2 0
+#endif
+#endif
+
+#ifndef SWISSTABLE_HAVE_SSSE3
+#ifdef __SSSE3__
+#define SWISSTABLE_HAVE_SSSE3 1
+#else
+#define SWISSTABLE_HAVE_SSSE3 0
+#endif
+#endif
+
+#if SWISSTABLE_HAVE_SSSE3 && !SWISSTABLE_HAVE_SSE2
+#error "Bad configuration!"
+#endif
+
+#if SWISSTABLE_HAVE_SSE2
+#include <emmintrin.h>
+#endif
+
+#if SWISSTABLE_HAVE_SSSE3
+#include <tmmintrin.h>
+#endif
+
+#endif // ABSL_CONTAINER_INTERNAL_HAVE_SSE_H_
diff --git a/absl/container/internal/layout.h b/absl/container/internal/layout.h
index a9c1244a..3d21ac96 100644
--- a/absl/container/internal/layout.h
+++ b/absl/container/internal/layout.h
@@ -253,8 +253,10 @@ template <class From, class To>
using CopyConst =
typename std::conditional<std::is_const<From>::value, const To, To>::type;
+// Note: We're not qualifying this with absl:: because it doesn't compile under
+// MSVC.
template <class T>
-using SliceType = absl::Span<T>;
+using SliceType = Span<T>;
// This namespace contains no types. It prevents functions defined in it from
// being found by ADL.
diff --git a/absl/container/internal/layout_test.cc b/absl/container/internal/layout_test.cc
index 224f741a..301e9f78 100644
--- a/absl/container/internal/layout_test.cc
+++ b/absl/container/internal/layout_test.cc
@@ -45,7 +45,7 @@ Expected Type(Actual val) {
return val;
}
-// Helper class to test different size and alignments.
+// Helper classes to test different size and alignments.
struct alignas(8) Int128 {
uint64_t a, b;
friend bool operator==(Int128 lhs, Int128 rhs) {
@@ -57,6 +57,14 @@ struct alignas(8) Int128 {
}
};
+// int64_t is *not* 8-byte aligned on all platforms!
+struct alignas(8) Int64 {
+ int64_t a;
+ friend bool operator==(Int64 lhs, Int64 rhs) {
+ return lhs.a == rhs.a;
+ }
+};
+
// Properties of types that this test relies on.
static_assert(sizeof(int8_t) == 1, "");
static_assert(alignof(int8_t) == 1, "");
@@ -64,6 +72,8 @@ static_assert(sizeof(int16_t) == 2, "");
static_assert(alignof(int16_t) == 2, "");
static_assert(sizeof(int32_t) == 4, "");
static_assert(alignof(int32_t) == 4, "");
+static_assert(sizeof(Int64) == 8, "");
+static_assert(alignof(Int64) == 8, "");
static_assert(sizeof(Int128) == 16, "");
static_assert(alignof(Int128) == 8, "");
@@ -1281,14 +1291,14 @@ TEST(Layout, OverAligned) {
TEST(Layout, Alignment) {
static_assert(Layout<int8_t>::Alignment() == 1, "");
static_assert(Layout<int32_t>::Alignment() == 4, "");
- static_assert(Layout<int64_t>::Alignment() == 8, "");
+ static_assert(Layout<Int64>::Alignment() == 8, "");
static_assert(Layout<Aligned<int8_t, 64>>::Alignment() == 64, "");
- static_assert(Layout<int8_t, int32_t, int64_t>::Alignment() == 8, "");
- static_assert(Layout<int8_t, int64_t, int32_t>::Alignment() == 8, "");
- static_assert(Layout<int32_t, int8_t, int64_t>::Alignment() == 8, "");
- static_assert(Layout<int32_t, int64_t, int8_t>::Alignment() == 8, "");
- static_assert(Layout<int64_t, int8_t, int32_t>::Alignment() == 8, "");
- static_assert(Layout<int64_t, int32_t, int8_t>::Alignment() == 8, "");
+ static_assert(Layout<int8_t, int32_t, Int64>::Alignment() == 8, "");
+ static_assert(Layout<int8_t, Int64, int32_t>::Alignment() == 8, "");
+ static_assert(Layout<int32_t, int8_t, Int64>::Alignment() == 8, "");
+ static_assert(Layout<int32_t, Int64, int8_t>::Alignment() == 8, "");
+ static_assert(Layout<Int64, int8_t, int32_t>::Alignment() == 8, "");
+ static_assert(Layout<Int64, int32_t, int8_t>::Alignment() == 8, "");
}
TEST(Layout, ConstexprPartial) {
@@ -1323,7 +1333,7 @@ void ExpectPoisoned(const unsigned char (&buf)[N],
}
TEST(Layout, PoisonPadding) {
- using L = Layout<int8_t, int64_t, int32_t, Int128>;
+ using L = Layout<int8_t, Int64, int32_t, Int128>;
constexpr size_t n = L::Partial(1, 2, 3, 4).AllocSize();
{
diff --git a/absl/container/internal/raw_hash_set.cc b/absl/container/internal/raw_hash_set.cc
index 10153129..180d3fe5 100644
--- a/absl/container/internal/raw_hash_set.cc
+++ b/absl/container/internal/raw_hash_set.cc
@@ -14,6 +14,7 @@
#include "absl/container/internal/raw_hash_set.h"
+#include <atomic>
#include <cstddef>
#include "absl/base/config.h"
@@ -29,7 +30,7 @@ inline size_t RandomSeed() {
static thread_local size_t counter = 0;
size_t value = ++counter;
#else // ABSL_HAVE_THREAD_LOCAL
- static std::atomic<size_t> counter;
+ static std::atomic<size_t> counter(0);
size_t value = counter.fetch_add(1, std::memory_order_relaxed);
#endif // ABSL_HAVE_THREAD_LOCAL
return value ^ static_cast<size_t>(reinterpret_cast<uintptr_t>(&counter));
diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h
index 575f1b00..b7b5ef8c 100644
--- a/absl/container/internal/raw_hash_set.h
+++ b/absl/container/internal/raw_hash_set.h
@@ -91,36 +91,6 @@
#ifndef ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_
#define ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_
-#ifndef SWISSTABLE_HAVE_SSE2
-#if defined(__SSE2__) || \
- (defined(_MSC_VER) && \
- (defined(_M_X64) || (defined(_M_IX86) && _M_IX86_FP >= 2)))
-#define SWISSTABLE_HAVE_SSE2 1
-#else
-#define SWISSTABLE_HAVE_SSE2 0
-#endif
-#endif
-
-#ifndef SWISSTABLE_HAVE_SSSE3
-#ifdef __SSSE3__
-#define SWISSTABLE_HAVE_SSSE3 1
-#else
-#define SWISSTABLE_HAVE_SSSE3 0
-#endif
-#endif
-
-#if SWISSTABLE_HAVE_SSSE3 && !SWISSTABLE_HAVE_SSE2
-#error "Bad configuration!"
-#endif
-
-#if SWISSTABLE_HAVE_SSE2
-#include <emmintrin.h>
-#endif
-
-#if SWISSTABLE_HAVE_SSSE3
-#include <tmmintrin.h>
-#endif
-
#include <algorithm>
#include <cmath>
#include <cstdint>
@@ -139,6 +109,7 @@
#include "absl/container/internal/container_memory.h"
#include "absl/container/internal/hash_policy_traits.h"
#include "absl/container/internal/hashtable_debug_hooks.h"
+#include "absl/container/internal/have_sse.h"
#include "absl/container/internal/layout.h"
#include "absl/memory/memory.h"
#include "absl/meta/type_traits.h"
@@ -1363,7 +1334,7 @@ class raw_hash_set {
void rehash(size_t n) {
if (n == 0 && capacity_ == 0) return;
if (n == 0 && size_ == 0) return destroy_slots();
- auto m = NormalizeCapacity(std::max(n, NumSlotsFast(size())));
+ auto m = NormalizeCapacity((std::max)(n, NumSlotsFast(size())));
// n == 0 unconditionally rehashes as per the standard.
if (n == 0 || m > capacity_) {
resize(m);
diff --git a/absl/container/node_hash_set.h b/absl/container/node_hash_set.h
index e4034461..843b11aa 100644
--- a/absl/container/node_hash_set.h
+++ b/absl/container/node_hash_set.h
@@ -273,8 +273,7 @@ class node_hash_set
//
// The element may be constructed even if there already is an element with the
// key in the container, in which case the newly constructed element will be
- // destroyed immediately. Prefer `try_emplace()` unless your key is not
- // copyable or moveable.
+ // destroyed immediately.
//
// If rehashing occurs due to the insertion, all iterators are invalidated.
using Base::emplace;
@@ -288,8 +287,7 @@ class node_hash_set
//
// The element may be constructed even if there already is an element with the
// key in the container, in which case the newly constructed element will be
- // destroyed immediately. Prefer `try_emplace()` unless your key is not
- // copyable or moveable.
+ // destroyed immediately.
//
// If rehashing occurs due to the insertion, all iterators are invalidated.
using Base::emplace_hint;
diff --git a/absl/copts.bzl b/absl/copts.bzl
deleted file mode 100644
index 49c4c9e0..00000000
--- a/absl/copts.bzl
+++ /dev/null
@@ -1,170 +0,0 @@
-"""absl specific copts.
-
-Flags specified here must not impact ABI. Code compiled with and without these
-opts will be linked together, and in some cases headers compiled with and
-without these options will be part of the same program.
-
-DO NOT CHANGE THIS FILE WITHOUT CHANGING THE SAME FLAG IN absl/CMake/AbseilConfigureCopts.cmake!!
-"""
-GCC_FLAGS = [
- "-Wall",
- "-Wextra",
- "-Wcast-qual",
- "-Wconversion-null",
- "-Wmissing-declarations",
- "-Woverlength-strings",
- "-Wpointer-arith",
- "-Wunused-local-typedefs",
- "-Wunused-result",
- "-Wvarargs",
- "-Wvla", # variable-length array
- "-Wwrite-strings",
- # Google style does not use unsigned integers, though STL containers
- # have unsigned types.
- "-Wno-sign-compare",
-]
-
-GCC_TEST_FLAGS = [
- "-Wno-conversion-null",
- "-Wno-missing-declarations",
- "-Wno-sign-compare",
- "-Wno-unused-function",
- "-Wno-unused-parameter",
- "-Wno-unused-private-field",
-]
-
-# Docs on single flags is preceded by a comment.
-# Docs on groups of flags is preceded by ###.
-
-LLVM_FLAGS = [
- "-Wall",
- "-Wextra",
- "-Weverything",
- # Abseil does not support C++98
- "-Wno-c++98-compat-pedantic",
- # Turns off all implicit conversion warnings. Most are re-enabled below.
- "-Wno-conversion",
- "-Wno-covered-switch-default",
- "-Wno-deprecated",
- "-Wno-disabled-macro-expansion",
- "-Wno-double-promotion",
- ###
- # Turned off as they include valid C++ code.
- "-Wno-comma",
- "-Wno-extra-semi",
- "-Wno-packed",
- "-Wno-padded",
- ###
- # Google style does not use unsigned integers, though STL containers
- # have unsigned types.
- "-Wno-sign-compare",
- ###
- "-Wno-float-conversion",
- "-Wno-float-equal",
- "-Wno-format-nonliteral",
- # Too aggressive: warns on Clang extensions enclosed in Clang-only
- # compilation paths.
- "-Wno-gcc-compat",
- ###
- # Some internal globals are necessary. Don't do this at home.
- "-Wno-global-constructors",
- "-Wno-exit-time-destructors",
- ###
- "-Wno-nested-anon-types",
- "-Wno-non-modular-include-in-module",
- "-Wno-old-style-cast",
- # Warns on preferred usage of non-POD types such as string_view
- "-Wno-range-loop-analysis",
- "-Wno-reserved-id-macro",
- "-Wno-shorten-64-to-32",
- "-Wno-switch-enum",
- "-Wno-thread-safety-negative",
- "-Wno-undef",
- "-Wno-unknown-warning-option",
- "-Wno-unreachable-code",
- # Causes warnings on include guards
- "-Wno-unused-macros",
- "-Wno-weak-vtables",
- ###
- # Implicit conversion warnings turned off by -Wno-conversion
- # which are re-enabled below.
- "-Wbitfield-enum-conversion",
- "-Wbool-conversion",
- "-Wconstant-conversion",
- "-Wenum-conversion",
- "-Wint-conversion",
- "-Wliteral-conversion",
- "-Wnon-literal-null-conversion",
- "-Wnull-conversion",
- "-Wobjc-literal-conversion",
- "-Wno-sign-conversion",
- "-Wstring-conversion",
- ###
-]
-
-LLVM_TEST_FLAGS = [
- "-Wno-c99-extensions",
- "-Wno-missing-noreturn",
- "-Wno-missing-prototypes",
- "-Wno-missing-variable-declarations",
- "-Wno-null-conversion",
- "-Wno-shadow",
- "-Wno-shift-sign-overflow",
- "-Wno-sign-compare",
- "-Wno-unused-function",
- "-Wno-unused-member-function",
- "-Wno-unused-parameter",
- "-Wno-unused-private-field",
- "-Wno-unused-template",
- "-Wno-used-but-marked-unused",
- "-Wno-zero-as-null-pointer-constant",
- # gtest depends on this GNU extension being offered.
- "-Wno-gnu-zero-variadic-macro-arguments",
-]
-
-MSVC_FLAGS = [
- "/W3",
- "/wd4005", # macro-redefinition
- "/wd4068", # unknown pragma
- "/wd4180", # qualifier applied to function type has no meaning; ignored
- "/wd4244", # conversion from 'type1' to 'type2', possible loss of data
- "/wd4267", # conversion from 'size_t' to 'type', possible loss of data
- "/wd4800", # forcing value to bool 'true' or 'false' (performance warning)
- "/DNOMINMAX", # Don't define min and max macros (windows.h)
- "/DWIN32_LEAN_AND_MEAN", # Don't bloat namespace with incompatible winsock versions.
- "/D_CRT_SECURE_NO_WARNINGS", # Don't warn about usage of insecure C functions.
- "/D_SCL_SECURE_NO_WARNINGS", # Don't warm when the compiler encounters a function or
- # variable that is marked as deprecated (same as /wd4996).
- "/D_ENABLE_EXTENDED_ALIGNED_STORAGE", # Introduced in VS 2017 15.8,
- # before the member type would non-conformingly have an alignment of only alignof(max_align_t).
-]
-
-MSVC_TEST_FLAGS = [
- "/wd4018", # signed/unsigned mismatch
- "/wd4101", # unreferenced local variable
- "/wd4503", # decorated name length exceeded, name was truncated
-]
-
-# /Wall with msvc includes unhelpful warnings such as C4711, C4710, ...
-ABSL_DEFAULT_COPTS = select({
- "//absl:windows": MSVC_FLAGS,
- "//absl:llvm_compiler": LLVM_FLAGS,
- "//conditions:default": GCC_FLAGS,
-})
-
-# in absence of modules (--compiler=gcc or -c opt), cc_tests leak their copts
-# 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_compiler": LLVM_TEST_FLAGS,
- "//conditions:default": GCC_TEST_FLAGS,
-})
-
-ABSL_EXCEPTIONS_FLAG = select({
- "//absl:windows": ["/U_HAS_EXCEPTIONS", "/D_HAS_EXCEPTIONS=1", "/EHsc"],
- "//conditions:default": ["-fexceptions"],
-})
-
-ABSL_EXCEPTIONS_FLAG_LINKOPTS = select({
- "//conditions:default": [],
-})
diff --git a/absl/copts/AbseilConfigureCopts.cmake b/absl/copts/AbseilConfigureCopts.cmake
new file mode 100644
index 00000000..6fde7754
--- /dev/null
+++ b/absl/copts/AbseilConfigureCopts.cmake
@@ -0,0 +1,34 @@
+# See absl/copts/copts.py and absl/copts/generate_copts.py
+include(GENERATED_AbseilCopts)
+
+if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
+ set(ABSL_DEFAULT_COPTS "${GCC_FLAGS}")
+ set(ABSL_TEST_COPTS "${GCC_FLAGS};${GCC_TEST_FLAGS}")
+ set(ABSL_EXCEPTIONS_FLAG "${GCC_EXCEPTIONS_FLAGS}")
+elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
+ # MATCHES so we get both Clang and AppleClang
+ set(ABSL_DEFAULT_COPTS "${LLVM_FLAGS}")
+ set(ABSL_TEST_COPTS "${LLVM_FLAGS};${LLVM_TEST_FLAGS}")
+ set(ABSL_EXCEPTIONS_FLAG "${LLVM_EXCEPTIONS_FLAGS}")
+elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
+ set(ABSL_DEFAULT_COPTS "${MSVC_FLAGS}")
+ set(ABSL_TEST_COPTS "${MSVC_FLAGS};${MSVC_TEST_FLAGS}")
+ set(ABSL_EXCEPTIONS_FLAG "${MSVC_EXCEPTIONS_FLAGS}")
+else()
+ message(WARNING "Unknown compiler: ${CMAKE_CXX_COMPILER}. Building with no default flags")
+ set(ABSL_DEFAULT_COPTS "")
+ set(ABSL_TEST_COPTS "")
+ set(ABSL_EXCEPTIONS_FLAG "")
+endif()
+
+# This flag is used internally for Bazel builds and is kept here for consistency
+set(ABSL_EXCEPTIONS_FLAG_LINKOPTS "")
+
+if("${CMAKE_CXX_STANDARD}" EQUAL 98)
+ message(FATAL_ERROR "Abseil requires at least C++11")
+elseif(NOT "${CMAKE_CXX_STANDARD}")
+ message(STATUS "No CMAKE_CXX_STANDARD set, assuming 11")
+ set(ABSL_CXX_STANDARD 11)
+else()
+ set(ABSL_CXX_STANDARD "${CMAKE_CXX_STANDARD}")
+endif() \ No newline at end of file
diff --git a/absl/copts/GENERATED_AbseilCopts.cmake b/absl/copts/GENERATED_AbseilCopts.cmake
new file mode 100644
index 00000000..80c98193
--- /dev/null
+++ b/absl/copts/GENERATED_AbseilCopts.cmake
@@ -0,0 +1,131 @@
+# GENERATED! DO NOT MANUALLY EDIT THIS FILE.
+#
+# (1) Edit absl/copts/copts.py.
+# (2) Run `python <path_to_absl>/copts/generate_copts.py`.
+
+list(APPEND GCC_EXCEPTIONS_FLAGS
+ "-fexceptions"
+)
+
+list(APPEND GCC_FLAGS
+ "-Wall"
+ "-Wextra"
+ "-Wcast-qual"
+ "-Wconversion-null"
+ "-Wmissing-declarations"
+ "-Woverlength-strings"
+ "-Wpointer-arith"
+ "-Wunused-local-typedefs"
+ "-Wunused-result"
+ "-Wvarargs"
+ "-Wvla"
+ "-Wwrite-strings"
+ "-Wno-sign-compare"
+)
+
+list(APPEND GCC_TEST_FLAGS
+ "-Wno-conversion-null"
+ "-Wno-missing-declarations"
+ "-Wno-sign-compare"
+ "-Wno-unused-function"
+ "-Wno-unused-parameter"
+ "-Wno-unused-private-field"
+)
+
+list(APPEND LLVM_EXCEPTIONS_FLAGS
+ "-fexceptions"
+)
+
+list(APPEND LLVM_FLAGS
+ "-Wall"
+ "-Wextra"
+ "-Weverything"
+ "-Wno-c++98-compat-pedantic"
+ "-Wno-conversion"
+ "-Wno-covered-switch-default"
+ "-Wno-deprecated"
+ "-Wno-disabled-macro-expansion"
+ "-Wno-double-promotion"
+ "-Wno-comma"
+ "-Wno-extra-semi"
+ "-Wno-extra-semi-stmt"
+ "-Wno-packed"
+ "-Wno-padded"
+ "-Wno-sign-compare"
+ "-Wno-float-conversion"
+ "-Wno-float-equal"
+ "-Wno-format-nonliteral"
+ "-Wno-gcc-compat"
+ "-Wno-global-constructors"
+ "-Wno-exit-time-destructors"
+ "-Wno-nested-anon-types"
+ "-Wno-non-modular-include-in-module"
+ "-Wno-old-style-cast"
+ "-Wno-range-loop-analysis"
+ "-Wno-reserved-id-macro"
+ "-Wno-shorten-64-to-32"
+ "-Wno-switch-enum"
+ "-Wno-thread-safety-negative"
+ "-Wno-undef"
+ "-Wno-unknown-warning-option"
+ "-Wno-unreachable-code"
+ "-Wno-unused-macros"
+ "-Wno-weak-vtables"
+ "-Wbitfield-enum-conversion"
+ "-Wbool-conversion"
+ "-Wconstant-conversion"
+ "-Wenum-conversion"
+ "-Wint-conversion"
+ "-Wliteral-conversion"
+ "-Wnon-literal-null-conversion"
+ "-Wnull-conversion"
+ "-Wobjc-literal-conversion"
+ "-Wno-sign-conversion"
+ "-Wstring-conversion"
+)
+
+list(APPEND LLVM_TEST_FLAGS
+ "-Wno-c99-extensions"
+ "-Wno-missing-noreturn"
+ "-Wno-missing-prototypes"
+ "-Wno-missing-variable-declarations"
+ "-Wno-null-conversion"
+ "-Wno-shadow"
+ "-Wno-shift-sign-overflow"
+ "-Wno-sign-compare"
+ "-Wno-unused-function"
+ "-Wno-unused-member-function"
+ "-Wno-unused-parameter"
+ "-Wno-unused-private-field"
+ "-Wno-unused-template"
+ "-Wno-used-but-marked-unused"
+ "-Wno-zero-as-null-pointer-constant"
+ "-Wno-gnu-zero-variadic-macro-arguments"
+)
+
+list(APPEND MSVC_EXCEPTIONS_FLAGS
+ "/U_HAS_EXCEPTIONS"
+ "/D_HAS_EXCEPTIONS=1"
+ "/EHsc"
+)
+
+list(APPEND MSVC_FLAGS
+ "/W3"
+ "/wd4005"
+ "/wd4068"
+ "/wd4180"
+ "/wd4244"
+ "/wd4267"
+ "/wd4800"
+ "/DNOMINMAX"
+ "/DWIN32_LEAN_AND_MEAN"
+ "/D_CRT_SECURE_NO_WARNINGS"
+ "/D_SCL_SECURE_NO_WARNINGS"
+ "/D_ENABLE_EXTENDED_ALIGNED_STORAGE"
+)
+
+list(APPEND MSVC_TEST_FLAGS
+ "/wd4018"
+ "/wd4101"
+ "/wd4503"
+)
diff --git a/absl/copts/GENERATED_copts.bzl b/absl/copts/GENERATED_copts.bzl
new file mode 100644
index 00000000..a001347d
--- /dev/null
+++ b/absl/copts/GENERATED_copts.bzl
@@ -0,0 +1,132 @@
+"""GENERATED! DO NOT MANUALLY EDIT THIS FILE.
+
+(1) Edit absl/copts/copts.py.
+(2) Run `python <path_to_absl>/copts/generate_copts.py`.
+"""
+
+GCC_EXCEPTIONS_FLAGS = [
+ "-fexceptions",
+]
+
+GCC_FLAGS = [
+ "-Wall",
+ "-Wextra",
+ "-Wcast-qual",
+ "-Wconversion-null",
+ "-Wmissing-declarations",
+ "-Woverlength-strings",
+ "-Wpointer-arith",
+ "-Wunused-local-typedefs",
+ "-Wunused-result",
+ "-Wvarargs",
+ "-Wvla",
+ "-Wwrite-strings",
+ "-Wno-sign-compare",
+]
+
+GCC_TEST_FLAGS = [
+ "-Wno-conversion-null",
+ "-Wno-missing-declarations",
+ "-Wno-sign-compare",
+ "-Wno-unused-function",
+ "-Wno-unused-parameter",
+ "-Wno-unused-private-field",
+]
+
+LLVM_EXCEPTIONS_FLAGS = [
+ "-fexceptions",
+]
+
+LLVM_FLAGS = [
+ "-Wall",
+ "-Wextra",
+ "-Weverything",
+ "-Wno-c++98-compat-pedantic",
+ "-Wno-conversion",
+ "-Wno-covered-switch-default",
+ "-Wno-deprecated",
+ "-Wno-disabled-macro-expansion",
+ "-Wno-double-promotion",
+ "-Wno-comma",
+ "-Wno-extra-semi",
+ "-Wno-extra-semi-stmt",
+ "-Wno-packed",
+ "-Wno-padded",
+ "-Wno-sign-compare",
+ "-Wno-float-conversion",
+ "-Wno-float-equal",
+ "-Wno-format-nonliteral",
+ "-Wno-gcc-compat",
+ "-Wno-global-constructors",
+ "-Wno-exit-time-destructors",
+ "-Wno-nested-anon-types",
+ "-Wno-non-modular-include-in-module",
+ "-Wno-old-style-cast",
+ "-Wno-range-loop-analysis",
+ "-Wno-reserved-id-macro",
+ "-Wno-shorten-64-to-32",
+ "-Wno-switch-enum",
+ "-Wno-thread-safety-negative",
+ "-Wno-undef",
+ "-Wno-unknown-warning-option",
+ "-Wno-unreachable-code",
+ "-Wno-unused-macros",
+ "-Wno-weak-vtables",
+ "-Wbitfield-enum-conversion",
+ "-Wbool-conversion",
+ "-Wconstant-conversion",
+ "-Wenum-conversion",
+ "-Wint-conversion",
+ "-Wliteral-conversion",
+ "-Wnon-literal-null-conversion",
+ "-Wnull-conversion",
+ "-Wobjc-literal-conversion",
+ "-Wno-sign-conversion",
+ "-Wstring-conversion",
+]
+
+LLVM_TEST_FLAGS = [
+ "-Wno-c99-extensions",
+ "-Wno-missing-noreturn",
+ "-Wno-missing-prototypes",
+ "-Wno-missing-variable-declarations",
+ "-Wno-null-conversion",
+ "-Wno-shadow",
+ "-Wno-shift-sign-overflow",
+ "-Wno-sign-compare",
+ "-Wno-unused-function",
+ "-Wno-unused-member-function",
+ "-Wno-unused-parameter",
+ "-Wno-unused-private-field",
+ "-Wno-unused-template",
+ "-Wno-used-but-marked-unused",
+ "-Wno-zero-as-null-pointer-constant",
+ "-Wno-gnu-zero-variadic-macro-arguments",
+]
+
+MSVC_EXCEPTIONS_FLAGS = [
+ "/U_HAS_EXCEPTIONS",
+ "/D_HAS_EXCEPTIONS=1",
+ "/EHsc",
+]
+
+MSVC_FLAGS = [
+ "/W3",
+ "/wd4005",
+ "/wd4068",
+ "/wd4180",
+ "/wd4244",
+ "/wd4267",
+ "/wd4800",
+ "/DNOMINMAX",
+ "/DWIN32_LEAN_AND_MEAN",
+ "/D_CRT_SECURE_NO_WARNINGS",
+ "/D_SCL_SECURE_NO_WARNINGS",
+ "/D_ENABLE_EXTENDED_ALIGNED_STORAGE",
+]
+
+MSVC_TEST_FLAGS = [
+ "/wd4018",
+ "/wd4101",
+ "/wd4503",
+]
diff --git a/absl/copts/configure_copts.bzl b/absl/copts/configure_copts.bzl
new file mode 100644
index 00000000..57cd3f62
--- /dev/null
+++ b/absl/copts/configure_copts.bzl
@@ -0,0 +1,42 @@
+"""absl specific copts.
+
+This file simply selects the correct options from the generated files. To
+change Abseil copts, edit absl/copts/copts.py
+"""
+
+load(
+ "//absl:copts/GENERATED_copts.bzl",
+ "GCC_EXCEPTIONS_FLAGS",
+ "GCC_FLAGS",
+ "GCC_TEST_FLAGS",
+ "LLVM_EXCEPTIONS_FLAGS",
+ "LLVM_FLAGS",
+ "LLVM_TEST_FLAGS",
+ "MSVC_EXCEPTIONS_FLAGS",
+ "MSVC_FLAGS",
+ "MSVC_TEST_FLAGS",
+)
+
+ABSL_DEFAULT_COPTS = select({
+ "//absl:windows": MSVC_FLAGS,
+ "//absl:llvm_compiler": LLVM_FLAGS,
+ "//conditions:default": GCC_FLAGS,
+})
+
+# in absence of modules (--compiler=gcc or -c opt), cc_tests leak their copts
+# 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_compiler": LLVM_TEST_FLAGS,
+ "//conditions:default": GCC_TEST_FLAGS,
+})
+
+ABSL_EXCEPTIONS_FLAG = select({
+ "//absl:windows": MSVC_EXCEPTIONS_FLAGS,
+ "//absl:llvm_compiler": LLVM_EXCEPTIONS_FLAGS,
+ "//conditions:default": GCC_EXCEPTIONS_FLAGS,
+})
+
+ABSL_EXCEPTIONS_FLAG_LINKOPTS = select({
+ "//conditions:default": [],
+})
diff --git a/absl/copts/copts.py b/absl/copts/copts.py
new file mode 100644
index 00000000..40a8062f
--- /dev/null
+++ b/absl/copts/copts.py
@@ -0,0 +1,157 @@
+"""Abseil compiler options.
+
+This is the source of truth for Abseil compiler options. To modify Abseil
+compilation options:
+
+ (1) Edit the appropriate list in this file based on the platform the flag is
+ needed on.
+ (2) Run `<path_to_absl>/copts/generate_copts.py`.
+
+The generated copts are consumed by configure_copts.bzl and
+AbseilConfigureCopts.cmake.
+"""
+
+import collections # absl:google-only(used for internal flags)
+COPT_VARS = {
+ "GCC_FLAGS": [
+ "-Wall",
+ "-Wextra",
+ "-Wcast-qual",
+ "-Wconversion-null",
+ "-Wmissing-declarations",
+ "-Woverlength-strings",
+ "-Wpointer-arith",
+ "-Wunused-local-typedefs",
+ "-Wunused-result",
+ "-Wvarargs",
+ "-Wvla", # variable-length array
+ "-Wwrite-strings",
+ # Google style does not use unsigned integers, though STL containers
+ # have unsigned types.
+ "-Wno-sign-compare",
+ ],
+ "GCC_TEST_FLAGS": [
+ "-Wno-conversion-null",
+ "-Wno-missing-declarations",
+ "-Wno-sign-compare",
+ "-Wno-unused-function",
+ "-Wno-unused-parameter",
+ "-Wno-unused-private-field",
+ ],
+ "GCC_EXCEPTIONS_FLAGS": ["-fexceptions"],
+
+ # Docs on single flags is preceded by a comment.
+ # Docs on groups of flags is preceded by ###.
+ "LLVM_FLAGS": [
+ "-Wall",
+ "-Wextra",
+ "-Weverything",
+ # Abseil does not support C++98
+ "-Wno-c++98-compat-pedantic",
+ # Turns off all implicit conversion warnings. Most are re-enabled below.
+ "-Wno-conversion",
+ "-Wno-covered-switch-default",
+ "-Wno-deprecated",
+ "-Wno-disabled-macro-expansion",
+ "-Wno-double-promotion",
+ ###
+ # Turned off as they include valid C++ code.
+ "-Wno-comma",
+ "-Wno-extra-semi",
+ "-Wno-extra-semi-stmt",
+ "-Wno-packed",
+ "-Wno-padded",
+ ###
+ # Google style does not use unsigned integers, though STL containers
+ # have unsigned types.
+ "-Wno-sign-compare",
+ ###
+ "-Wno-float-conversion",
+ "-Wno-float-equal",
+ "-Wno-format-nonliteral",
+ # Too aggressive: warns on Clang extensions enclosed in Clang-only
+ # compilation paths.
+ "-Wno-gcc-compat",
+ ###
+ # Some internal globals are necessary. Don't do this at home.
+ "-Wno-global-constructors",
+ "-Wno-exit-time-destructors",
+ ###
+ "-Wno-nested-anon-types",
+ "-Wno-non-modular-include-in-module",
+ "-Wno-old-style-cast",
+ # Warns on preferred usage of non-POD types such as string_view
+ "-Wno-range-loop-analysis",
+ "-Wno-reserved-id-macro",
+ "-Wno-shorten-64-to-32",
+ "-Wno-switch-enum",
+ "-Wno-thread-safety-negative",
+ "-Wno-undef",
+ "-Wno-unknown-warning-option",
+ "-Wno-unreachable-code",
+ # Causes warnings on include guards
+ "-Wno-unused-macros",
+ "-Wno-weak-vtables",
+ ###
+ # Implicit conversion warnings turned off by -Wno-conversion
+ # which are re-enabled below.
+ "-Wbitfield-enum-conversion",
+ "-Wbool-conversion",
+ "-Wconstant-conversion",
+ "-Wenum-conversion",
+ "-Wint-conversion",
+ "-Wliteral-conversion",
+ "-Wnon-literal-null-conversion",
+ "-Wnull-conversion",
+ "-Wobjc-literal-conversion",
+ "-Wno-sign-conversion",
+ "-Wstring-conversion",
+ ],
+ "LLVM_TEST_FLAGS": [
+ "-Wno-c99-extensions",
+ "-Wno-missing-noreturn",
+ "-Wno-missing-prototypes",
+ "-Wno-missing-variable-declarations",
+ "-Wno-null-conversion",
+ "-Wno-shadow",
+ "-Wno-shift-sign-overflow",
+ "-Wno-sign-compare",
+ "-Wno-unused-function",
+ "-Wno-unused-member-function",
+ "-Wno-unused-parameter",
+ "-Wno-unused-private-field",
+ "-Wno-unused-template",
+ "-Wno-used-but-marked-unused",
+ "-Wno-zero-as-null-pointer-constant",
+ # gtest depends on this GNU extension being offered.
+ "-Wno-gnu-zero-variadic-macro-arguments",
+ ],
+ "LLVM_EXCEPTIONS_FLAGS": ["-fexceptions"],
+ # /Wall with msvc includes unhelpful warnings such as C4711, C4710, ...
+ "MSVC_FLAGS": [
+ "/W3",
+ "/wd4005", # macro-redefinition
+ "/wd4068", # unknown pragma
+ "/wd4180", # qualifier applied to function type has no meaning; ignored
+ "/wd4244", # conversion from 'type1' to 'type2', possible loss of data
+ "/wd4267", # conversion from 'size_t' to 'type', possible loss of data
+ # forcing value to bool 'true' or 'false' (performance warning)
+ "/wd4800",
+ "/DNOMINMAX", # Don't define min and max macros (windows.h)
+ # Don't bloat namespace with incompatible winsock versions.
+ "/DWIN32_LEAN_AND_MEAN",
+ # Don't warn about usage of insecure C functions.
+ "/D_CRT_SECURE_NO_WARNINGS",
+ "/D_SCL_SECURE_NO_WARNINGS",
+ # Introduced in VS 2017 15.8, allow overaligned types in aligned_storage
+ "/D_ENABLE_EXTENDED_ALIGNED_STORAGE",
+ ],
+ "MSVC_TEST_FLAGS": [
+ "/wd4018", # signed/unsigned mismatch
+ "/wd4101", # unreferenced local variable
+ "/wd4503", # decorated name length exceeded, name was truncated
+ ],
+ "MSVC_EXCEPTIONS_FLAGS": [
+ "/U_HAS_EXCEPTIONS", "/D_HAS_EXCEPTIONS=1", "/EHsc"
+ ]
+}
diff --git a/absl/copts/generate_copts.py b/absl/copts/generate_copts.py
new file mode 100755
index 00000000..28b677e0
--- /dev/null
+++ b/absl/copts/generate_copts.py
@@ -0,0 +1,108 @@
+#!/usr/bin/python
+"""Generate Abseil compile compile option configs.
+
+Usage: <path_to_absl>/copts/generate_copts.py
+
+The configs are generated from copts.py.
+"""
+
+from os import path
+import sys
+from copts import COPT_VARS
+
+
+# Helper functions
+def file_header_lines():
+ return [
+ "GENERATED! DO NOT MANUALLY EDIT THIS FILE.", "",
+ "(1) Edit absl/copts/copts.py.",
+ "(2) Run `python <path_to_absl>/copts/generate_copts.py`."
+ ]
+
+
+def flatten(*lists):
+ return [item for sublist in lists for item in sublist]
+
+
+def relative_filename(filename):
+ return path.join(path.dirname(__file__), filename)
+
+
+# Style classes. These contain all the syntactic styling needed to generate a
+# copt file for different build tools.
+class CMakeStyle(object):
+ """Style object for CMake copts file."""
+
+ def separator(self):
+ return ""
+
+ def list_introducer(self, name):
+ return "list(APPEND " + name
+
+ def list_closer(self):
+ return ")\n"
+
+ def docstring(self):
+ return "\n".join((("# " + line).strip() for line in file_header_lines()))
+
+ def filename(self):
+ return "GENERATED_AbseilCopts.cmake"
+
+
+class StarlarkStyle(object):
+ """Style object for Starlark copts file."""
+
+ def separator(self):
+ return ","
+
+ def list_introducer(self, name):
+ return name + " = ["
+
+ def list_closer(self):
+ return "]\n"
+
+ def docstring(self):
+ docstring_quotes = "\"\"\""
+ return docstring_quotes + "\n".join(
+ flatten(file_header_lines(), [docstring_quotes]))
+
+ def filename(self):
+ return "GENERATED_copts.bzl"
+
+
+# Copt file generation
+def copt_list(name, arg_list, style):
+ make_line = lambda s: " \"" + s + "\"" + style.separator()
+ external_str_list = [make_line(s) for s in arg_list]
+
+ return "\n".join(
+ flatten(
+ [style.list_introducer(name)],
+ external_str_list,
+ [style.list_closer()]))
+
+
+def generate_copt_file(style):
+ """Creates a generated copt file using the given style object.
+
+ Args:
+ style: either StarlarkStyle() or CMakeStyle()
+ """
+ with open(relative_filename(style.filename()), "w") as f:
+ f.write(style.docstring())
+ f.write("\n")
+ for var_name, arg_list in sorted(COPT_VARS.items()):
+ f.write("\n")
+ f.write(copt_list(var_name, arg_list, style))
+
+
+def main(argv):
+ if len(argv) > 1:
+ raise RuntimeError("generate_copts needs no command line args")
+
+ generate_copt_file(StarlarkStyle())
+ generate_copt_file(CMakeStyle())
+
+
+if __name__ == "__main__":
+ main(sys.argv)
diff --git a/absl/debugging/BUILD.bazel b/absl/debugging/BUILD.bazel
index a8ebaea4..84b994da 100644
--- a/absl/debugging/BUILD.bazel
+++ b/absl/debugging/BUILD.bazel
@@ -15,7 +15,7 @@
#
load(
- "//absl:copts.bzl",
+ "//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
"ABSL_TEST_COPTS",
)
@@ -181,22 +181,8 @@ cc_test(
cc_library(
name = "leak_check",
- srcs = select({
- # The leak checking interface depends on weak function
- # declarations that may not necessarily have definitions.
- # Windows doesn't support this, and ios requires
- # guaranteed definitions for weak symbols.
- "//absl:ios": [],
- "//absl:windows": [],
- "//conditions:default": [
- "leak_check.cc",
- ],
- }),
- hdrs = select({
- "//absl:ios": [],
- "//absl:windows": [],
- "//conditions:default": ["leak_check.h"],
- }),
+ srcs = ["leak_check.cc"],
+ hdrs = ["leak_check.h"],
deps = ["//absl/base:core_headers"],
)
diff --git a/absl/debugging/CMakeLists.txt b/absl/debugging/CMakeLists.txt
index c28eb14b..4c1fc508 100644
--- a/absl/debugging/CMakeLists.txt
+++ b/absl/debugging/CMakeLists.txt
@@ -14,204 +14,297 @@
# limitations under the License.
#
-list(APPEND DEBUGGING_PUBLIC_HEADERS
- "failure_signal_handler.h"
- "leak_check.h"
- "stacktrace.h"
- "symbolize.h"
-)
-
-# TODO(cohenjon) The below is all kinds of wrong. Make this match what we do in
-# Bazel
-list(APPEND DEBUGGING_INTERNAL_HEADERS
- "internal/address_is_readable.h"
- "internal/demangle.h"
- "internal/elf_mem_image.h"
- "internal/examine_stack.h"
- "internal/stacktrace_config.h"
- "internal/symbolize.h"
- "internal/vdso_support.h"
-)
-
-list(APPEND DEBUGGING_INTERNAL_SRC
- "internal/address_is_readable.cc"
- "internal/elf_mem_image.cc"
- "internal/vdso_support.cc"
-)
-
-
-list(APPEND STACKTRACE_SRC
- "stacktrace.cc"
- ${DEBUGGING_INTERNAL_SRC}
- ${DEBUGGING_PUBLIC_HEADERS}
- ${DEBUGGING_INTERNAL_HEADERS}
+absl_cc_library(
+ NAME
+ stacktrace
+ HDRS
+ "stacktrace.h"
+ SRCS
+ "stacktrace.cc"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::debugging_internal
+ absl::base
+ absl::core_headers
+ PUBLIC
)
-list(APPEND SYMBOLIZE_SRC
- "symbolize.cc"
- "symbolize_elf.inc"
- "symbolize_unimplemented.inc"
- "symbolize_win32.inc"
- "internal/demangle.cc"
- ${DEBUGGING_PUBLIC_HEADERS}
- ${DEBUGGING_INTERNAL_HEADERS}
- ${DEBUGGING_INTERNAL_SRC}
+absl_cc_library(
+ NAME
+ symbolize
+ HDRS
+ "symbolize.h"
+ "internal/symbolize.h"
+ SRCS
+ "symbolize.cc"
+ "symbolize_elf.inc"
+ "symbolize_unimplemented.inc"
+ "symbolize_win32.inc"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::debugging_internal
+ absl::demangle_internal
+ absl::base
+ absl::core_headers
+ absl::malloc_internal
+ PUBLIC
)
-list(APPEND FAILURE_SIGNAL_HANDLER_SRC
- "failure_signal_handler.cc"
- ${DEBUGGING_PUBLIC_HEADERS}
+absl_cc_test(
+ NAME
+ symbolize_test
+ SRCS
+ "symbolize_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::stack_consumption
+ absl::symbolize
+ absl::base
+ absl::core_headers
+ absl::memory
+ gmock
)
-list(APPEND EXAMINE_STACK_SRC
- "internal/examine_stack.cc"
- ${DEBUGGING_PUBLIC_HEADERS}
- ${DEBUGGING_INTERNAL_HEADERS}
+absl_cc_library(
+ NAME
+ examine_stack
+ HDRS
+ "internal/examine_stack.h"
+ SRCS
+ "internal/examine_stack.cc"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::stacktrace
+ absl::symbolize
+ absl::base
+ absl::core_headers
)
-absl_library(
- TARGET
- absl_stacktrace
- SOURCES
- ${STACKTRACE_SRC}
- EXPORT_NAME
- stacktrace
+absl_cc_library(
+ NAME
+ failure_signal_handler
+ HDRS
+ "failure_signal_handler.h"
+ SRCS
+ "failure_signal_handler.cc"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::examine_stack
+ absl::stacktrace
+ absl::base
+ absl::config
+ absl::core_headers
+ PUBLIC
)
-absl_library(
- TARGET
- absl_symbolize
- SOURCES
- ${SYMBOLIZE_SRC}
- PUBLIC_LIBRARIES
+absl_cc_test(
+ NAME
+ failure_signal_handler_test
+ SRCS
+ "failure_signal_handler_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::failure_signal_handler
+ absl::stacktrace
+ absl::symbolize
absl::base
- absl::malloc_internal
- EXPORT_NAME
- symbolize
+ absl::strings
+ Threads::Threads
+ gmock
)
-absl_library(
- TARGET
- absl_failure_signal_handler
- SOURCES
- ${FAILURE_SIGNAL_HANDLER_SRC}
- PUBLIC_LIBRARIES
- absl_base absl::examine_stack absl::stacktrace absl_synchronization
- EXPORT_NAME
- failure_signal_handler
+absl_cc_library(
+ NAME
+ debugging_internal
+ HDRS
+ "internal/address_is_readable.h"
+ "internal/elf_mem_image.h"
+ "internal/stacktrace_aarch64-inl.inc"
+ "internal/stacktrace_arm-inl.inc"
+ "internal/stacktrace_config.h"
+ "internal/stacktrace_generic-inl.inc"
+ "internal/stacktrace_powerpc-inl.inc"
+ "internal/stacktrace_unimplemented-inl.inc"
+ "internal/stacktrace_win32-inl.inc"
+ "internal/stacktrace_x86-inl.inc"
+ "internal/vdso_support.h"
+ SRCS
+ "internal/address_is_readable.cc"
+ "internal/elf_mem_image.cc"
+ "internal/vdso_support.cc"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::base
+ absl::core_headers
+ absl::dynamic_annotations
)
-# Internal-only. Projects external to Abseil should not depend
-# directly on this library.
-absl_library(
- TARGET
- absl_examine_stack
- SOURCES
- ${EXAMINE_STACK_SRC}
- EXPORT_NAME
- examine_stack
+absl_cc_library(
+ NAME
+ demangle_internal
+ HDRS
+ "internal/demangle.h"
+ SRCS
+ "internal/demangle.cc"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::base
+ absl::core_headers
+ PUBLIC
)
-list(APPEND LEAK_CHECK_SRC
- "leak_check.cc"
+absl_cc_test(
+ NAME
+ demangle_test
+ SRCS
+ "internal/demangle_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::demangle_internal
+ absl::stack_consumption
+ absl::base
+ absl::core_headers
+ absl::memory
+ gmock_main
)
-
-# leak_check library
-absl_library(
- TARGET
- absl_leak_check
- SOURCES
- ${LEAK_CHECK_SRC}
- PUBLIC_LIBRARIES
- absl_base
- EXPORT_NAME
+absl_cc_library(
+ NAME
leak_check
+ HDRS
+ "leak_check.h"
+ SRCS
+ "leak_check.cc"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::core_headers
+ PUBLIC
)
-
-# component target
-absl_header_library(
- TARGET
- absl_debugging
- PUBLIC_LIBRARIES
- absl_stacktrace absl_leak_check
- EXPORT_NAME
- debugging
+absl_cc_library(
+ NAME
+ leak_check_disable
+ SRCS
+ "leak_check_disable.cc"
+ PUBLIC
)
-#
-## TESTS
-#
+# TODO(cohenjon) Move into the copts code.
+if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+ set(ABSL_LSAN_LINKOPTS "-fsanitize=leak")
+endif()
-list(APPEND STACK_CONSUMPTION_SRC
- "internal/stack_consumption.cc"
- "internal/stack_consumption.h"
+absl_cc_library(
+ NAME
+ leak_check_api_enabled_for_testing
+ HDRS
+ "leak_check.h"
+ SRCS
+ "leak_check.cc"
+ COPTS
+ $<$<BOOL:${ABSL_USING_CLANG}>:-DLEAK_SANITIZER>
+ TESTONLY
)
-absl_library(
- TARGET
- absl_stack_consumption
- SOURCES
- ${STACK_CONSUMPTION_SRC}
+absl_cc_library(
+ NAME
+ leak_check_api_disabled_for_testing
+ HDRS
+ "leak_check.h"
+ SRCS
+ "leak_check.cc"
+ COPTS
+ "-ULEAK_SANITIZER"
+ TESTONLY
)
-absl_test(
- TARGET
- absl_stack_consumption_test
- SOURCES
- "internal/stack_consumption_test.cc"
- PUBLIC_LIBRARIES
- absl_stack_consumption
+absl_cc_test(
+ NAME
+ leak_check_test
+ SRCS
+ "leak_check_test.cc"
+ COPTS
+ "$<$<CXX_COMPILER_ID:Clang>:-DABSL_EXPECT_LEAK_SANITIZER>"
+ LINKOPTS
+ "${ABSL_LSAN_LINKOPTS}"
+ DEPS
+ absl::leak_check_api_enabled_for_testing
absl::base
+ gmock_main
)
-list(APPEND DEMANGLE_TEST_SRC "internal/demangle_test.cc")
-
-absl_test(
- TARGET
- demangle_test
- SOURCES
- ${DEMANGLE_TEST_SRC}
- PUBLIC_LIBRARIES
- absl_symbolize absl_stack_consumption
+absl_cc_test(
+ NAME
+ leak_check_no_lsan_test
+ SRCS
+ "leak_check_test.cc"
+ COPTS
+ "-UABSL_EXPECT_LEAK_SANITIZER"
+ DEPS
+ absl::leak_check_api_disabled_for_testing
+ absl::base
+ gmock_main
)
-list(APPEND SYMBOLIZE_TEST_SRC "symbolize_test.cc")
-
-absl_test(
- TARGET
- symbolize_test
- SOURCES
- ${SYMBOLIZE_TEST_SRC}
- PUBLIC_LIBRARIES
- absl::base absl::memory absl_symbolize absl_stack_consumption
+absl_cc_test(
+ NAME
+ disabled_leak_check_test
+ SRCS
+ "leak_check_fail_test.cc"
+ LINKOPTS
+ "${ABSL_LSAN_LINKOPTS}"
+ DEPS
+ absl::leak_check_api_enabled_for_testing
+ absl::leak_check_disable
+ absl::base
+ gmock_main
)
-list(APPEND FAILURE_SIGNAL_HANDLER_TEST_SRC "failure_signal_handler_test.cc")
-
-absl_test(
- TARGET
- failure_signal_handler_test
- SOURCES
- ${FAILURE_SIGNAL_HANDLER_TEST_SRC}
- PUBLIC_LIBRARIES
- absl_examine_stack
- absl_failure_signal_handler
- absl_stacktrace
- absl_symbolize
+absl_cc_library(
+ NAME
+ stack_consumption
+ HDRS
+ "internal/stack_consumption.h"
+ SRCS
+ "internal/stack_consumption.cc"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
absl::base
- absl::strings
+ absl::core_headers
+ TESTONLY
)
-# test leak_check_test
-list(APPEND LEAK_CHECK_TEST_SRC "leak_check_test.cc")
+absl_cc_test(
+ NAME
+ stack_consumption_test
+ SRCS
+ "internal/stack_consumption_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::stack_consumption
+ absl::base
+ absl::core_headers
+ gmock_main
+)
-absl_test(
- TARGET
- leak_check_test
- SOURCES
- ${LEAK_CHECK_TEST_SRC}
- PUBLIC_LIBRARIES
- absl_leak_check
+# component target
+absl_cc_library(
+ NAME
+ debugging
+ DEPS
+ absl::stacktrace
+ absl::leak_check
+ PUBLIC
)
diff --git a/absl/debugging/internal/demangle.cc b/absl/debugging/internal/demangle.cc
index 48354459..3ee3df51 100644
--- a/absl/debugging/internal/demangle.cc
+++ b/absl/debugging/internal/demangle.cc
@@ -1636,6 +1636,15 @@ static bool ParseExpression(State *state) {
}
state->parse_state = copy;
+ // Pointer-to-member access expressions. This parses the same as a binary
+ // operator, but it's implemented separately because "ds" shouldn't be
+ // accepted in other contexts that parse an operator name.
+ if (ParseTwoCharToken(state, "ds") && ParseExpression(state) &&
+ ParseExpression(state)) {
+ return true;
+ }
+ state->parse_state = copy;
+
// Parameter pack expansion
if (ParseTwoCharToken(state, "sp") && ParseExpression(state)) {
return true;
diff --git a/absl/hash/BUILD.bazel b/absl/hash/BUILD.bazel
index 4f7c94ce..5f24b999 100644
--- a/absl/hash/BUILD.bazel
+++ b/absl/hash/BUILD.bazel
@@ -15,7 +15,7 @@
#
load(
- "//absl:copts.bzl",
+ "//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
"ABSL_TEST_COPTS",
)
diff --git a/absl/hash/CMakeLists.txt b/absl/hash/CMakeLists.txt
index a0d59b0b..8f97d7cc 100644
--- a/absl/hash/CMakeLists.txt
+++ b/absl/hash/CMakeLists.txt
@@ -14,40 +14,30 @@
# limitations under the License.
#
-list(APPEND HASH_PUBLIC_HEADERS
- "hash.h"
-)
-
-list(APPEND HASH_INTERNAL_HEADERS
- "internal/city.h"
- "internal/hash.h"
-)
-
-# absl_hash library
-list(APPEND HASH_SRC
- "internal/city.cc"
- "internal/hash.cc"
- ${HASH_PUBLIC_HEADERS}
- ${HASH_INTERNAL_HEADERS}
-)
-
-set(HASH_PUBLIC_LIBRARIES absl::hash absl::fixed_array absl::strings absl::str_format absl::utility)
-
-absl_library(
- TARGET
- absl_hash
- SOURCES
- ${HASH_SRC}
- PUBLIC_LIBRARIES
- ${HASH_PUBLIC_LIBRARIES}
- EXPORT_NAME
+absl_cc_library(
+ NAME
hash
+ HDRS
+ "hash.h"
+ SRCS
+ "internal/hash.cc"
+ "internal/hash.h"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::core_headers
+ absl::endian
+ absl::fixed_array
+ absl::meta
+ absl::int128
+ absl::strings
+ absl::optional
+ absl::variant
+ absl::utility
+ absl::city
+ PUBLIC
)
-#
-## TESTS
-#
-
absl_cc_library(
NAME
hash_testing
@@ -62,11 +52,29 @@ absl_cc_library(
TESTONLY
)
+absl_cc_test(
+ NAME
+ hash_test
+ SRCS
+ "hash_test.cc"
+ DEPS
+ absl::hash
+ absl::hash_testing
+ absl::core_headers
+ absl::flat_hash_set
+ absl::spy_hash_state
+ absl::meta
+ absl::int128
+ gmock_main
+)
+
absl_cc_library(
NAME
spy_hash_state
HDRS
"internal/spy_hash_state.h"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
DEPS
absl::hash
absl::strings
@@ -74,32 +82,30 @@ absl_cc_library(
TESTONLY
)
-# testing support
-set(HASH_TEST_HEADERS hash_testing.h internal/spy_hash_state.h)
-set(HASH_TEST_PUBLIC_LIBRARIES absl::hash absl::flat_hash_set absl::numeric absl::strings absl::str_format)
-
-# hash_test
-set(HASH_TEST_SRC "hash_test.cc" ${HASH_TEST_HEADERS})
-
-absl_test(
- TARGET
- hash_test
- SOURCES
- ${HASH_TEST_SRC}
- PUBLIC_LIBRARIES
- ${HASH_TEST_PUBLIC_LIBRARIES}
+absl_cc_library(
+ NAME
+ city
+ HDRS
+ "internal/city.h"
+ SRCS
+ "internal/city.cc"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::config
+ absl::core_headers
+ absl::endian
)
-# hash_test
-set(CITY_TEST_SRC "internal/city_test.cc")
-
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
city_test
- SOURCES
- ${CITY_TEST_SRC}
- PUBLIC_LIBRARIES
- ${HASH_TEST_PUBLIC_LIBRARIES}
+ SRCS
+ "internal/city_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::city
+ gmock_main
)
-
diff --git a/absl/memory/BUILD.bazel b/absl/memory/BUILD.bazel
index 89a312ea..c0da9ce1 100644
--- a/absl/memory/BUILD.bazel
+++ b/absl/memory/BUILD.bazel
@@ -15,7 +15,7 @@
#
load(
- "//absl:copts.bzl",
+ "//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
"ABSL_TEST_COPTS",
"ABSL_EXCEPTIONS_FLAG",
diff --git a/absl/memory/CMakeLists.txt b/absl/memory/CMakeLists.txt
index 8f9e731f..4b494dc0 100644
--- a/absl/memory/CMakeLists.txt
+++ b/absl/memory/CMakeLists.txt
@@ -14,55 +14,45 @@
# limitations under the License.
#
-list(APPEND MEMORY_PUBLIC_HEADERS
- "memory.h"
-)
-
-
-absl_header_library(
- TARGET
- absl_memory
- EXPORT_NAME
+absl_cc_library(
+ NAME
memory
+ HDRS
+ "memory.h"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::core_headers
+ absl::meta
+ PUBLIC
)
-#
-## TESTS
-#
-
-# test memory_test
-list(APPEND MEMORY_TEST_SRC
- "memory_test.cc"
- ${MEMORY_PUBLIC_HEADERS}
-)
-set(MEMORY_TEST_PUBLIC_LIBRARIES absl::base absl::memory)
-
-
-
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
memory_test
- SOURCES
- ${MEMORY_TEST_SRC}
- PUBLIC_LIBRARIES
- ${MEMORY_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test memory_exception_safety_test
-set(MEMORY_EXCEPTION_SAFETY_TEST_SRC "memory_exception_safety_test.cc")
-set(MEMORY_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES
- absl::memory
- absl_internal_exception_safety_testing
+ SRCS
+ "memory_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::memory
+ absl::base
+ absl::core_headers
+ gmock_main
)
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
memory_exception_safety_test
- SOURCES
- ${MEMORY_EXCEPTION_SAFETY_TEST_SRC}
- PUBLIC_LIBRARIES
- ${MEMORY_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES}
- PRIVATE_COMPILE_FLAGS
+ SRCS
+ "memory_exception_safety_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
${ABSL_EXCEPTIONS_FLAG}
+ LINKOPTS
+ ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+ DEPS
+ absl::memory
+ absl::exception_safety_testing
+ gmock_main
)
diff --git a/absl/memory/memory_test.cc b/absl/memory/memory_test.cc
index 54f920b5..21fe32f9 100644
--- a/absl/memory/memory_test.cc
+++ b/absl/memory/memory_test.cc
@@ -69,6 +69,45 @@ TEST(MakeUniqueTest, Basic) {
EXPECT_EQ("hi", *p);
}
+// InitializationVerifier fills in a pattern when allocated so we can
+// distinguish between its default and value initialized states (without
+// accessing truly uninitialized memory).
+struct InitializationVerifier {
+ static constexpr int kDefaultScalar = 0x43;
+ static constexpr int kDefaultArray = 0x4B;
+
+ static void* operator new(size_t n) {
+ void* ret = ::operator new(n);
+ memset(ret, kDefaultScalar, n);
+ return ret;
+ }
+
+ static void* operator new[](size_t n) {
+ void* ret = ::operator new[](n);
+ memset(ret, kDefaultArray, n);
+ return ret;
+ }
+
+ int a;
+ int b;
+};
+
+TEST(Initialization, MakeUnique) {
+ auto p = absl::make_unique<InitializationVerifier>();
+
+ EXPECT_EQ(0, p->a);
+ EXPECT_EQ(0, p->b);
+}
+
+TEST(Initialization, MakeUniqueArray) {
+ auto p = absl::make_unique<InitializationVerifier[]>(2);
+
+ EXPECT_EQ(0, p[0].a);
+ EXPECT_EQ(0, p[0].b);
+ EXPECT_EQ(0, p[1].a);
+ EXPECT_EQ(0, p[1].b);
+}
+
struct MoveOnly {
MoveOnly() = default;
explicit MoveOnly(int i1) : ip1{new int{i1}} {}
diff --git a/absl/meta/BUILD.bazel b/absl/meta/BUILD.bazel
index dbc9717d..1c39fa98 100644
--- a/absl/meta/BUILD.bazel
+++ b/absl/meta/BUILD.bazel
@@ -1,5 +1,5 @@
load(
- "//absl:copts.bzl",
+ "//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
"ABSL_TEST_COPTS",
)
diff --git a/absl/meta/CMakeLists.txt b/absl/meta/CMakeLists.txt
index adb0ceb7..4358db57 100644
--- a/absl/meta/CMakeLists.txt
+++ b/absl/meta/CMakeLists.txt
@@ -14,39 +14,37 @@
# limitations under the License.
#
-list(APPEND META_PUBLIC_HEADERS
- "type_traits.h"
+absl_cc_library(
+ NAME
+ type_traits
+ HDRS
+ "type_traits.h"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::config
+ PUBLIC
)
-
-#
-## TESTS
-#
-
-# test type_traits_test
-list(APPEND TYPE_TRAITS_TEST_SRC
- "type_traits_test.cc"
- ${META_PUBLIC_HEADERS}
-)
-
-absl_header_library(
- TARGET
- absl_meta
- PUBLIC_LIBRARIES
- absl::base
- EXPORT_NAME
- meta
- )
-
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
type_traits_test
- SOURCES
- ${TYPE_TRAITS_TEST_SRC}
- PUBLIC_LIBRARIES
+ SRCS
+ "type_traits_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::type_traits
absl::base
- absl::meta
+ absl::core_headers
+ gmock_main
)
-
-
+# component target
+absl_cc_library(
+ NAME
+ meta
+ DEPS
+ absl::type_traits
+ PUBLIC
+)
diff --git a/absl/numeric/BUILD.bazel b/absl/numeric/BUILD.bazel
index 324ce669..c906b8d7 100644
--- a/absl/numeric/BUILD.bazel
+++ b/absl/numeric/BUILD.bazel
@@ -13,7 +13,7 @@
# limitations under the License.
load(
- "//absl:copts.bzl",
+ "//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
"ABSL_TEST_COPTS",
)
diff --git a/absl/numeric/CMakeLists.txt b/absl/numeric/CMakeLists.txt
index 3360b2ee..42468a6a 100644
--- a/absl/numeric/CMakeLists.txt
+++ b/absl/numeric/CMakeLists.txt
@@ -14,49 +14,45 @@
# limitations under the License.
#
-list(APPEND NUMERIC_PUBLIC_HEADERS
- "int128.h"
-)
-
-
-# library 128
-list(APPEND INT128_SRC
- "int128.cc"
- ${NUMERIC_PUBLIC_HEADERS}
-)
-absl_library(
- TARGET
- absl_int128
- SOURCES
- ${INT128_SRC}
- PUBLIC_LIBRARIES
- ${INT128_PUBLIC_LIBRARIES}
- EXPORT_NAME
+absl_cc_library(
+ NAME
int128
+ HDRS
+ "int128.h"
+ SRCS
+ "int128.cc"
+ "int128_have_intrinsic.inc"
+ "int128_no_intrinsic.inc"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::config
+ absl::core_headers
+ PUBLIC
)
-
-absl_header_library(
- TARGET
- absl_numeric
- PUBLIC_LIBRARIES
+absl_cc_test(
+ NAME
+ int128_test
+ SRCS
+ "int128_stream_test.cc"
+ "int128_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
absl::int128
- EXPORT_NAME
- numeric
+ absl::base
+ absl::core_headers
+ absl::hash_testing
+ absl::type_traits
+ gmock_main
)
-# test int128_test
-set(INT128_TEST_SRC "int128_test.cc")
-set(INT128_TEST_PUBLIC_LIBRARIES absl::numeric absl::base)
-
-absl_test(
- TARGET
- int128_test
- SOURCES
- ${INT128_TEST_SRC}
- PUBLIC_LIBRARIES
- ${INT128_TEST_PUBLIC_LIBRARIES}
+# component target
+absl_cc_library(
+ NAME
+ numeric
+ DEPS
+ absl::int128
+ PUBLIC
)
-
-
-
diff --git a/absl/numeric/int128.h b/absl/numeric/int128.h
index 9c2e00f6..9c36c571 100644
--- a/absl/numeric/int128.h
+++ b/absl/numeric/int128.h
@@ -37,10 +37,19 @@
#include "absl/base/macros.h"
#include "absl/base/port.h"
-#if defined(_MSC_VER) && defined(_WIN64)
+#if defined(_MSC_VER)
+// In very old versions of MSVC and when the /Zc:wchar_t flag is off, wchar_t is
+// a typedef for unsigned short. Otherwise wchar_t is mapped to the __wchar_t
+// builtin type. We need to make sure not to define operator wchar_t()
+// alongside operator unsigned short() in these instances.
+#define ABSL_INTERNAL_WCHAR_T __wchar_t
+#if defined(_WIN64)
#include <intrin.h>
#pragma intrinsic(_umul128)
-#endif // defined(_MSC_VER) && defined(_WIN64)
+#endif // defined(_WIN64)
+#else // defined(_MSC_VER)
+#define ABSL_INTERNAL_WCHAR_T wchar_t
+#endif // defined(_MSC_VER)
namespace absl {
@@ -131,7 +140,7 @@ class
constexpr explicit operator unsigned char() const;
constexpr explicit operator char16_t() const;
constexpr explicit operator char32_t() const;
- constexpr explicit operator wchar_t() const;
+ constexpr explicit operator ABSL_INTERNAL_WCHAR_T() const;
constexpr explicit operator short() const; // NOLINT(runtime/int)
// NOLINTNEXTLINE(runtime/int)
constexpr explicit operator unsigned short() const;
@@ -271,9 +280,9 @@ class numeric_limits<absl::uint128> {
#endif // ABSL_HAVE_INTRINSIC_INT128
static constexpr bool tinyness_before = false;
- static constexpr absl::uint128 min() { return 0; }
+ static constexpr absl::uint128 (min)() { return 0; }
static constexpr absl::uint128 lowest() { return 0; }
- static constexpr absl::uint128 max() { return absl::Uint128Max(); }
+ static constexpr absl::uint128 (max)() { return absl::Uint128Max(); }
static constexpr absl::uint128 epsilon() { return 0; }
static constexpr absl::uint128 round_error() { return 0; }
static constexpr absl::uint128 infinity() { return 0; }
@@ -468,8 +477,8 @@ constexpr uint128::operator char32_t() const {
return static_cast<char32_t>(lo_);
}
-constexpr uint128::operator wchar_t() const {
- return static_cast<wchar_t>(lo_);
+constexpr uint128::operator ABSL_INTERNAL_WCHAR_T() const {
+ return static_cast<ABSL_INTERNAL_WCHAR_T>(lo_);
}
// NOLINTNEXTLINE(runtime/int)
@@ -719,4 +728,6 @@ inline uint128& uint128::operator--() {
} // namespace absl
+#undef ABSL_INTERNAL_WCHAR_T
+
#endif // ABSL_NUMERIC_INT128_H_
diff --git a/absl/numeric/int128_have_intrinsic.inc b/absl/numeric/int128_have_intrinsic.inc
index ee2a0930..0c8164a5 100644
--- a/absl/numeric/int128_have_intrinsic.inc
+++ b/absl/numeric/int128_have_intrinsic.inc
@@ -15,4 +15,4 @@
// This file contains :int128 implementation details that depend on internal
// representation when ABSL_HAVE_INTRINSIC_INT128 is defined. This file is
-// included by int128.h.
+// included by int128.h and relies on ABSL_INTERNAL_WCHAR_T being defined.
diff --git a/absl/numeric/int128_no_intrinsic.inc b/absl/numeric/int128_no_intrinsic.inc
index 0d0b3cfd..08d68ac3 100644
--- a/absl/numeric/int128_no_intrinsic.inc
+++ b/absl/numeric/int128_no_intrinsic.inc
@@ -15,4 +15,4 @@
// This file contains :int128 implementation details that depend on internal
// representation when ABSL_HAVE_INTRINSIC_INT128 is *not* defined. This file
-// is included by int128.h.
+// is included by int128.h and relies on ABSL_INTERNAL_WCHAR_T being defined.
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel
index 6d7c2619..7635a619 100644
--- a/absl/strings/BUILD.bazel
+++ b/absl/strings/BUILD.bazel
@@ -15,7 +15,7 @@
#
load(
- "//absl:copts.bzl",
+ "//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
"ABSL_TEST_COPTS",
"ABSL_EXCEPTIONS_FLAG",
@@ -413,6 +413,7 @@ cc_test(
copts = ABSL_TEST_COPTS,
visibility = ["//visibility:private"],
deps = [
+ ":pow10_helper",
":strings",
"//absl/base",
"//absl/base:core_headers",
@@ -471,6 +472,8 @@ cc_test(
srcs = ["charconv_test.cc"],
copts = ABSL_TEST_COPTS,
deps = [
+ ":pow10_helper",
+ ":str_format",
":strings",
"//absl/base",
"@com_google_googletest//:gtest_main",
@@ -659,3 +662,23 @@ cc_test(
"@com_google_googletest//:gtest_main",
],
)
+
+cc_library(
+ name = "pow10_helper",
+ testonly = True,
+ srcs = ["internal/pow10_helper.cc"],
+ hdrs = ["internal/pow10_helper.h"],
+ visibility = ["//visibility:private"],
+)
+
+cc_test(
+ name = "pow10_helper_test",
+ srcs = ["internal/pow10_helper_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ visibility = ["//visibility:private"],
+ deps = [
+ ":pow10_helper",
+ ":str_format",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt
index a6574c17..aed54dc4 100644
--- a/absl/strings/CMakeLists.txt
+++ b/absl/strings/CMakeLists.txt
@@ -14,449 +14,505 @@
# limitations under the License.
#
-
-list(APPEND STRINGS_PUBLIC_HEADERS
- "ascii.h"
- "charconv.h"
- "escaping.h"
- "match.h"
- "numbers.h"
- "str_cat.h"
- "string_view.h"
- "strip.h"
- "str_join.h"
- "str_replace.h"
- "str_split.h"
- "substitute.h"
-)
-
-
-list(APPEND STRINGS_INTERNAL_HEADERS
- "internal/char_map.h"
- "internal/charconv_bigint.h"
- "internal/charconv_parse.h"
- "internal/memutil.h"
- "internal/ostringstream.h"
- "internal/resize_uninitialized.h"
- "internal/stl_type_traits.h"
- "internal/str_join_internal.h"
- "internal/str_split_internal.h"
- "internal/utf8.h"
-)
-
-
-
-# add string library
-list(APPEND STRINGS_SRC
- "ascii.cc"
- "charconv.cc"
- "escaping.cc"
- "internal/charconv_bigint.cc"
- "internal/charconv_parse.cc"
- "internal/memutil.cc"
- "internal/memutil.h"
- "internal/utf8.cc"
- "internal/ostringstream.cc"
- "match.cc"
- "numbers.cc"
- "str_cat.cc"
- "str_replace.cc"
- "str_split.cc"
- "string_view.cc"
- "substitute.cc"
- ${STRINGS_PUBLIC_HEADERS}
- ${STRINGS_INTERNAL_HEADERS}
-)
-set(STRINGS_PUBLIC_LIBRARIES absl::base absl_internal_throw_delegate)
-
-absl_library(
- TARGET
- absl_strings
- SOURCES
- ${STRINGS_SRC}
- PUBLIC_LIBRARIES
- ${STRINGS_PUBLIC_LIBRARIES}
- EXPORT_NAME
+absl_cc_library(
+ NAME
strings
-)
-
-# add str_format library
-absl_header_library(
- TARGET
- absl_str_format
- PUBLIC_LIBRARIES
- str_format_internal
- EXPORT_NAME
- str_format
-)
-
-# str_format_internal
-absl_library(
- TARGET
- str_format_internal
- SOURCES
- "internal/str_format/arg.cc"
- "internal/str_format/bind.cc"
- "internal/str_format/extension.cc"
- "internal/str_format/float_conversion.cc"
- "internal/str_format/output.cc"
- "internal/str_format/parser.cc"
- "internal/str_format/arg.h"
- "internal/str_format/bind.h"
- "internal/str_format/checker.h"
- "internal/str_format/extension.h"
- "internal/str_format/float_conversion.h"
- "internal/str_format/output.h"
- "internal/str_format/parser.h"
- PUBLIC_LIBRARIES
- str_format_extension_internal
- absl::strings
- absl::base
- absl::numeric
- absl::inlined_vector
- absl::span
-)
-
-# str_format_extension_internal
-absl_library(
- TARGET
- str_format_extension_internal
- SOURCES
- "internal/str_format/extension.cc"
- "internal/str_format/extension.h"
- "internal/str_format/output.cc"
- "internal/str_format/output.h"
- PUBLIC_LIBRARIES
+ HDRS
+ "ascii.h"
+ "charconv.h"
+ "escaping.h"
+ "match.h"
+ "numbers.h"
+ "str_cat.h"
+ "str_join.h"
+ "str_replace.h"
+ "str_split.h"
+ "string_view.h"
+ "strip.h"
+ "substitute.h"
+ SRCS
+ "ascii.cc"
+ "charconv.cc"
+ "escaping.cc"
+ "internal/charconv_bigint.cc"
+ "internal/charconv_bigint.h"
+ "internal/charconv_parse.cc"
+ "internal/charconv_parse.h"
+ "internal/memutil.cc"
+ "internal/memutil.h"
+ "internal/stl_type_traits.h"
+ "internal/str_join_internal.h"
+ "internal/str_split_internal.h"
+ "match.cc"
+ "numbers.cc"
+ "str_cat.cc"
+ "str_replace.cc"
+ "str_split.cc"
+ "string_view.cc"
+ "substitute.cc"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::strings_internal
absl::base
- absl::strings
-)
-
-#
-## TESTS
-#
-
-# test match_test
-set(MATCH_TEST_SRC "match_test.cc")
-set(MATCH_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
- TARGET
+ absl::bits
+ absl::config
+ absl::core_headers
+ absl::endian
+ absl::throw_delegate
+ absl::memory
+ absl::type_traits
+ absl::int128
+ PUBLIC
+)
+
+absl_cc_library(
+ NAME
+ strings_internal
+ HDRS
+ "internal/char_map.h"
+ "internal/ostringstream.h"
+ "internal/resize_uninitialized.h"
+ "internal/utf8.h"
+ SRCS
+ "internal/ostringstream.cc"
+ "internal/utf8.cc"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::core_headers
+ absl::endian
+ absl::type_traits
+)
+
+absl_cc_test(
+ NAME
match_test
- SOURCES
- ${MATCH_TEST_SRC}
- PUBLIC_LIBRARIES
- ${MATCH_TEST_PUBLIC_LIBRARIES}
+ SRCS
+ "match_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::strings
+ absl::base
+ gmock_main
)
-
-# test escaping_test
-set(ESCAPING_TEST_SRC "escaping_test.cc")
-set(ESCAPING_TEST_PUBLIC_LIBRARIES absl::strings absl::base)
-
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
escaping_test
- SOURCES
- ${ESCAPING_TEST_SRC}
- PUBLIC_LIBRARIES
- ${ESCAPING_TEST_PUBLIC_LIBRARIES}
+ SRCS
+ "escaping_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::strings
+ absl::core_headers
+ absl::fixed_array
+ gmock_main
)
-
-# test ascii_test
-set(ASCII_TEST_SRC "ascii_test.cc")
-set(ASCII_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
ascii_test
- SOURCES
- ${ASCII_TEST_SRC}
- PUBLIC_LIBRARIES
- ${ASCII_TEST_PUBLIC_LIBRARIES}
+ SRCS
+ "ascii_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::strings
+ absl::core_headers
+ gmock_main
)
-
-# test memutil_test
-set(MEMUTIL_TEST_SRC "internal/memutil_test.cc")
-set(MEMUTIL_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
memutil_test
- SOURCES
- ${MEMUTIL_TEST_SRC}
- PUBLIC_LIBRARIES
- ${MEMUTIL_TEST_PUBLIC_LIBRARIES}
+ SRCS
+ "internal/memutil.h"
+ "internal/memutil_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::strings
+ absl::core_headers
+ gmock_main
)
-
-# test utf8_test
-set(UTF8_TEST_SRC "internal/utf8_test.cc")
-set(UTF8_TEST_PUBLIC_LIBRARIES absl::strings absl::base)
-
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
utf8_test
- SOURCES
- ${UTF8_TEST_SRC}
- PUBLIC_LIBRARIES
- ${UTF8_TEST_PUBLIC_LIBRARIES}
+ SRCS
+ "internal/utf8_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::strings_internal
+ absl::base
+ absl::core_headers
+ gmock_main
)
-
-# test string_view_test
-set(STRING_VIEW_TEST_SRC "string_view_test.cc")
-set(STRING_VIEW_TEST_PUBLIC_LIBRARIES absl::strings absl_internal_throw_delegate absl::base)
-
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
string_view_test
- SOURCES
- ${STRING_VIEW_TEST_SRC}
- PUBLIC_LIBRARIES
- ${STRING_VIEW_TEST_PUBLIC_LIBRARIES}
+ SRCS
+ "string_view_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ ${ABSL_EXCEPTIONS_FLAG}
+ LINKOPTS
+ ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+ DEPS
+ absl::strings
+ absl::config
+ absl::core_headers
+ absl::dynamic_annotations
+ gmock_main
)
-
-# test substitute_test
-set(SUBSTITUTE_TEST_SRC "substitute_test.cc")
-set(SUBSTITUTE_TEST_PUBLIC_LIBRARIES absl::strings absl::base)
-
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
substitute_test
- SOURCES
- ${SUBSTITUTE_TEST_SRC}
- PUBLIC_LIBRARIES
- ${SUBSTITUTE_TEST_PUBLIC_LIBRARIES}
+ SRCS
+ "substitute_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::strings
+ absl::core_headers
+ gmock_main
)
-
-# test str_replace_test
-set(STR_REPLACE_TEST_SRC "str_replace_test.cc")
-set(STR_REPLACE_TEST_PUBLIC_LIBRARIES absl::strings absl::base absl_internal_throw_delegate)
-
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
str_replace_test
- SOURCES
- ${STR_REPLACE_TEST_SRC}
- PUBLIC_LIBRARIES
- ${STR_REPLACE_TEST_PUBLIC_LIBRARIES}
+ SRCS
+ "str_replace_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::strings
+ gmock_main
)
-
-# test str_split_test
-set(STR_SPLIT_TEST_SRC "str_split_test.cc")
-set(STR_SPLIT_TEST_PUBLIC_LIBRARIES absl::strings absl::base absl_internal_throw_delegate)
-
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
str_split_test
- SOURCES
- ${STR_SPLIT_TEST_SRC}
- PUBLIC_LIBRARIES
- ${STR_SPLIT_TEST_PUBLIC_LIBRARIES}
+ SRCS
+ "str_split_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::strings
+ absl::base
+ absl::core_headers
+ absl::dynamic_annotations
+ gmock_main
)
-
-# test ostringstream_test
-set(OSTRINGSTREAM_TEST_SRC "internal/ostringstream_test.cc")
-set(OSTRINGSTREAM_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
ostringstream_test
- SOURCES
- ${OSTRINGSTREAM_TEST_SRC}
- PUBLIC_LIBRARIES
- ${OSTRINGSTREAM_TEST_PUBLIC_LIBRARIES}
+ SRCS
+ "internal/ostringstream_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::strings_internal
+ gmock_main
)
-
-# test resize_uninitialized_test
-set(RESIZE_UNINITIALIZED_TEST_SRC "internal/resize_uninitialized_test.cc")
-
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
resize_uninitialized_test
- SOURCES
- ${RESIZE_UNINITIALIZED_TEST_SRC}
+ SRCS
+ "internal/resize_uninitialized.h"
+ "internal/resize_uninitialized_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::base
+ absl::core_headers
+ absl::type_traits
+ gmock_main
)
-
-# test str_join_test
-set(STR_JOIN_TEST_SRC "str_join_test.cc")
-set(STR_JOIN_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
str_join_test
- SOURCES
- ${STR_JOIN_TEST_SRC}
- PUBLIC_LIBRARIES
- ${STR_JOIN_TEST_PUBLIC_LIBRARIES}
+ SRCS
+ "str_join_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::strings
+ absl::base
+ absl::core_headers
+ absl::memory
+ gmock_main
)
-
-# test str_cat_test
-set(STR_CAT_TEST_SRC "str_cat_test.cc")
-set(STR_CAT_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
str_cat_test
- SOURCES
- ${STR_CAT_TEST_SRC}
- PUBLIC_LIBRARIES
- ${STR_CAT_TEST_PUBLIC_LIBRARIES}
+ SRCS
+ "str_cat_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::strings
+ absl::core_headers
+ gmock_main
)
-
-# test numbers_test
-set(NUMBERS_TEST_SRC "numbers_test.cc")
-set(NUMBERS_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
numbers_test
- SOURCES
- ${NUMBERS_TEST_SRC}
- PUBLIC_LIBRARIES
- ${NUMBERS_TEST_PUBLIC_LIBRARIES}
+ SRCS
+ "internal/numbers_test_common.h"
+ "numbers_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::strings
+ absl::base
+ absl::core_headers
+ absl::pow10_helper
+ gmock_main
)
-
-# test strip_test
-set(STRIP_TEST_SRC "strip_test.cc")
-set(STRIP_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
strip_test
- SOURCES
- ${STRIP_TEST_SRC}
- PUBLIC_LIBRARIES
- ${STRIP_TEST_PUBLIC_LIBRARIES}
+ SRCS
+ "strip_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::strings
+ absl::base
+ gmock_main
)
-
-# test char_map_test
-set(CHAR_MAP_TEST_SRC "internal/char_map_test.cc")
-set(CHAR_MAP_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
char_map_test
- SOURCES
- ${CHAR_MAP_TEST_SRC}
- PUBLIC_LIBRARIES
- ${CHAR_MAP_TEST_PUBLIC_LIBRARIES}
+ SRCS
+ "internal/char_map_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::strings_internal
+ gmock_main
)
-
-# test charconv_test
-set(CHARCONV_TEST_SRC "charconv_test.cc")
-set(CHARCONV_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
charconv_test
- SOURCES
- ${CHARCONV_TEST_SRC}
- PUBLIC_LIBRARIES
- ${CHARCONV_TEST_PUBLIC_LIBRARIES}
+ SRCS
+ "charconv_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::strings
+ absl::str_format
+ absl::base
+ absl::pow10_helper
+ gmock_main
)
-
-# test charconv_parse_test
-set(CHARCONV_PARSE_TEST_SRC "internal/charconv_parse_test.cc")
-set(CHARCONV_PARSE_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
charconv_parse_test
- SOURCES
- ${CHARCONV_PARSE_TEST_SRC}
- PUBLIC_LIBRARIES
- ${CHARCONV_PARSE_TEST_PUBLIC_LIBRARIES}
+ SRCS
+ "internal/charconv_parse.h"
+ "internal/charconv_parse_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::strings
+ absl::base
+ gmock_main
)
+absl_cc_test(
+ NAME
+ charconv_bigint_test
+ SRCS
+ "internal/charconv_bigint.h"
+ "internal/charconv_bigint_test.cc"
+ "internal/charconv_parse.h"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::strings
+ absl::base
+ gmock_main
+)
-# test charconv_bigint_test
-set(CHARCONV_BIGINT_TEST_SRC "internal/charconv_bigint_test.cc")
-set(CHARCONV_BIGINT_TEST_PUBLIC_LIBRARIES absl::strings)
+absl_cc_library(
+ NAME
+ str_format
+ HDRS
+ "str_format.h"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::str_format_internal
+ PUBLIC
+)
-absl_test(
- TARGET
- charconv_bigint_test
- SOURCES
- ${CHARCONV_BIGINT_TEST_SRC}
- PUBLIC_LIBRARIES
- ${CHARCONV_BIGINT_TEST_PUBLIC_LIBRARIES}
-)
-# test str_format_test
-absl_test(
- TARGET
+absl_cc_library(
+ NAME
+ str_format_internal
+ HDRS
+ "internal/str_format/arg.h"
+ "internal/str_format/bind.h"
+ "internal/str_format/checker.h"
+ "internal/str_format/extension.h"
+ "internal/str_format/float_conversion.h"
+ "internal/str_format/output.h"
+ "internal/str_format/parser.h"
+ SRCS
+ "internal/str_format/arg.cc"
+ "internal/str_format/bind.cc"
+ "internal/str_format/extension.cc"
+ "internal/str_format/float_conversion.cc"
+ "internal/str_format/output.cc"
+ "internal/str_format/parser.cc"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::strings
+ absl::core_headers
+ absl::inlined_vector
+ absl::type_traits
+ absl::int128
+ absl::span
+)
+
+absl_cc_test(
+ NAME
str_format_test
- SOURCES
+ SRCS
"str_format_test.cc"
- PUBLIC_LIBRARIES
- absl::base
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
absl::str_format
absl::strings
+ absl::core_headers
+ gmock_main
+)
+
+absl_cc_test(
+ NAME
+ str_format_extension_test
+ SRCS
+ "internal/str_format/extension_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::str_format
+ absl::str_format_internal
+ gmock_main
+)
+
+absl_cc_test(
+ NAME
+ str_format_arg_test
+ SRCS
+ "internal/str_format/arg_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::str_format
+ absl::str_format_internal
+ gmock_main
)
-# test str_format_bind_test
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
str_format_bind_test
- SOURCES
+ SRCS
"internal/str_format/bind_test.cc"
- PUBLIC_LIBRARIES
- str_format_internal
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::str_format_internal
+ gmock_main
)
-# test str_format_checker_test
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
str_format_checker_test
- SOURCES
+ SRCS
"internal/str_format/checker_test.cc"
- PUBLIC_LIBRARIES
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
absl::str_format
+ gmock_main
)
-# test str_format_convert_test
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
str_format_convert_test
- SOURCES
+ SRCS
"internal/str_format/convert_test.cc"
- PUBLIC_LIBRARIES
- str_format_internal
- absl::numeric
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::str_format_internal
+ absl::int128
+ gmock_main
)
-# test str_format_output_test
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
str_format_output_test
- SOURCES
+ SRCS
"internal/str_format/output_test.cc"
- PUBLIC_LIBRARIES
- str_format_extension_internal
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::str_format_internal
+ gmock_main
)
-# test str_format_parser_test
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
str_format_parser_test
- SOURCES
+ SRCS
"internal/str_format/parser_test.cc"
- PUBLIC_LIBRARIES
- str_format_internal
- absl::base
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::str_format_internal
+ absl::core_headers
+ gmock_main
+)
+
+absl_cc_library(
+ NAME
+ pow10_helper
+ HDRS
+ "internal/pow10_helper.h"
+ SRCS
+ "internal/pow10_helper.cc"
+ TESTONLY
+)
+
+absl_cc_test(
+ NAME
+ pow10_helper_test
+ SRCS
+ "internal/pow10_helper_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::pow10_helper
+ absl::str_format
+ gmock_main
)
-
diff --git a/absl/strings/charconv_test.cc b/absl/strings/charconv_test.cc
index 89418fe9..d07537eb 100644
--- a/absl/strings/charconv_test.cc
+++ b/absl/strings/charconv_test.cc
@@ -19,7 +19,9 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
+#include "absl/strings/internal/pow10_helper.h"
#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
#ifdef _MSC_FULL_VER
#define ABSL_COMPILER_DOES_EXACT_ROUNDING 0
@@ -31,6 +33,8 @@
namespace {
+using absl::strings_internal::Pow10;
+
#if ABSL_COMPILER_DOES_EXACT_ROUNDING
// Tests that the given string is accepted by absl::from_chars, and that it
@@ -678,7 +682,8 @@ void TestOverflowAndUnderflow(
auto result =
absl::from_chars(input.data(), input.data() + input.size(), actual);
EXPECT_EQ(result.ec, std::errc());
- EXPECT_EQ(expected, actual);
+ EXPECT_EQ(expected, actual)
+ << absl::StrFormat("%a vs %a", expected, actual);
}
// test legal values near upper_bound
for (index = upper_bound, step = 1; index > lower_bound;
@@ -690,7 +695,8 @@ void TestOverflowAndUnderflow(
auto result =
absl::from_chars(input.data(), input.data() + input.size(), actual);
EXPECT_EQ(result.ec, std::errc());
- EXPECT_EQ(expected, actual);
+ EXPECT_EQ(expected, actual)
+ << absl::StrFormat("%a vs %a", expected, actual);
}
// Test underflow values below lower_bound
for (index = lower_bound - 1, step = 1; index > -1000000;
@@ -747,7 +753,7 @@ TEST(FromChars, HexdecimalFloatLimits) {
// acceptable exponents in this test.
TEST(FromChars, DecimalDoubleLimits) {
auto input_gen = [](int index) { return absl::StrCat("1.0e", index); };
- auto expected_gen = [](int index) { return std::pow(10.0, index); };
+ auto expected_gen = [](int index) { return Pow10(index); };
TestOverflowAndUnderflow<double>(input_gen, expected_gen, -323, 308);
}
@@ -759,7 +765,7 @@ TEST(FromChars, DecimalDoubleLimits) {
// acceptable exponents in this test.
TEST(FromChars, DecimalFloatLimits) {
auto input_gen = [](int index) { return absl::StrCat("1.0e", index); };
- auto expected_gen = [](int index) { return std::pow(10.0, index); };
+ auto expected_gen = [](int index) { return Pow10(index); };
TestOverflowAndUnderflow<float>(input_gen, expected_gen, -45, 38);
}
diff --git a/absl/strings/internal/charconv_bigint.h b/absl/strings/internal/charconv_bigint.h
index 5c579437..9d1a1bff 100644
--- a/absl/strings/internal/charconv_bigint.h
+++ b/absl/strings/internal/charconv_bigint.h
@@ -103,12 +103,12 @@ class BigUnsigned {
SetToZero();
return;
}
- size_ = std::min(size_ + word_shift, max_words);
+ size_ = (std::min)(size_ + word_shift, max_words);
count %= 32;
if (count == 0) {
std::copy_backward(words_, words_ + size_ - word_shift, words_ + size_);
} else {
- for (int i = std::min(size_, max_words - 1); i > word_shift; --i) {
+ for (int i = (std::min)(size_, max_words - 1); i > word_shift; --i) {
words_[i] = (words_[i - word_shift] << count) |
(words_[i - word_shift - 1] >> (32 - count));
}
@@ -267,7 +267,7 @@ class BigUnsigned {
void MultiplyBy(int other_size, const uint32_t* other_words) {
const int original_size = size_;
const int first_step =
- std::min(original_size + other_size - 2, max_words - 1);
+ (std::min)(original_size + other_size - 2, max_words - 1);
for (int step = first_step; step >= 0; --step) {
MultiplyStep(original_size, other_words, other_size, step);
}
@@ -286,7 +286,7 @@ class BigUnsigned {
value = 0;
}
}
- size_ = std::min(max_words, std::max(index + 1, size_));
+ size_ = (std::min)(max_words, (std::max)(index + 1, size_));
}
}
@@ -309,7 +309,7 @@ class BigUnsigned {
} else {
// Normally 32-bit AddWithCarry() sets size_, but since we don't call
// it when `high` is 0, do it ourselves here.
- size_ = std::min(max_words, std::max(index + 1, size_));
+ size_ = (std::min)(max_words, (std::max)(index + 1, size_));
}
}
}
@@ -348,7 +348,7 @@ class BigUnsigned {
// Returns -1 if lhs < rhs, 0 if lhs == rhs, and 1 if lhs > rhs.
template <int N, int M>
int Compare(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
- int limit = std::max(lhs.size(), rhs.size());
+ int limit = (std::max)(lhs.size(), rhs.size());
for (int i = limit - 1; i >= 0; --i) {
const uint32_t lhs_word = lhs.GetWord(i);
const uint32_t rhs_word = rhs.GetWord(i);
@@ -363,7 +363,7 @@ int Compare(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
template <int N, int M>
bool operator==(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
- int limit = std::max(lhs.size(), rhs.size());
+ int limit = (std::max)(lhs.size(), rhs.size());
for (int i = 0; i < limit; ++i) {
if (lhs.GetWord(i) != rhs.GetWord(i)) {
return false;
diff --git a/absl/strings/internal/pow10_helper.cc b/absl/strings/internal/pow10_helper.cc
new file mode 100644
index 00000000..66be163f
--- /dev/null
+++ b/absl/strings/internal/pow10_helper.cc
@@ -0,0 +1,120 @@
+// Copyright 2018 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.
+
+#include "absl/strings/internal/pow10_helper.h"
+
+#include <cmath>
+
+namespace absl {
+namespace strings_internal {
+
+namespace {
+
+// The exact value of 1e23 falls precisely halfway between two representable
+// doubles. Furthermore, the rounding rules we prefer (break ties by rounding
+// to the nearest even) dictate in this case that the number should be rounded
+// down, but this is not completely specified for floating-point literals in
+// C++. (It just says to use the default rounding mode of the standard
+// library.) We ensure the result we want by using a number that has an
+// unambiguous correctly rounded answer.
+constexpr double k1e23 = 9999999999999999e7;
+
+constexpr double kPowersOfTen[] = {
+ 0.0, 1e-323, 1e-322, 1e-321, 1e-320, 1e-319, 1e-318, 1e-317, 1e-316,
+ 1e-315, 1e-314, 1e-313, 1e-312, 1e-311, 1e-310, 1e-309, 1e-308, 1e-307,
+ 1e-306, 1e-305, 1e-304, 1e-303, 1e-302, 1e-301, 1e-300, 1e-299, 1e-298,
+ 1e-297, 1e-296, 1e-295, 1e-294, 1e-293, 1e-292, 1e-291, 1e-290, 1e-289,
+ 1e-288, 1e-287, 1e-286, 1e-285, 1e-284, 1e-283, 1e-282, 1e-281, 1e-280,
+ 1e-279, 1e-278, 1e-277, 1e-276, 1e-275, 1e-274, 1e-273, 1e-272, 1e-271,
+ 1e-270, 1e-269, 1e-268, 1e-267, 1e-266, 1e-265, 1e-264, 1e-263, 1e-262,
+ 1e-261, 1e-260, 1e-259, 1e-258, 1e-257, 1e-256, 1e-255, 1e-254, 1e-253,
+ 1e-252, 1e-251, 1e-250, 1e-249, 1e-248, 1e-247, 1e-246, 1e-245, 1e-244,
+ 1e-243, 1e-242, 1e-241, 1e-240, 1e-239, 1e-238, 1e-237, 1e-236, 1e-235,
+ 1e-234, 1e-233, 1e-232, 1e-231, 1e-230, 1e-229, 1e-228, 1e-227, 1e-226,
+ 1e-225, 1e-224, 1e-223, 1e-222, 1e-221, 1e-220, 1e-219, 1e-218, 1e-217,
+ 1e-216, 1e-215, 1e-214, 1e-213, 1e-212, 1e-211, 1e-210, 1e-209, 1e-208,
+ 1e-207, 1e-206, 1e-205, 1e-204, 1e-203, 1e-202, 1e-201, 1e-200, 1e-199,
+ 1e-198, 1e-197, 1e-196, 1e-195, 1e-194, 1e-193, 1e-192, 1e-191, 1e-190,
+ 1e-189, 1e-188, 1e-187, 1e-186, 1e-185, 1e-184, 1e-183, 1e-182, 1e-181,
+ 1e-180, 1e-179, 1e-178, 1e-177, 1e-176, 1e-175, 1e-174, 1e-173, 1e-172,
+ 1e-171, 1e-170, 1e-169, 1e-168, 1e-167, 1e-166, 1e-165, 1e-164, 1e-163,
+ 1e-162, 1e-161, 1e-160, 1e-159, 1e-158, 1e-157, 1e-156, 1e-155, 1e-154,
+ 1e-153, 1e-152, 1e-151, 1e-150, 1e-149, 1e-148, 1e-147, 1e-146, 1e-145,
+ 1e-144, 1e-143, 1e-142, 1e-141, 1e-140, 1e-139, 1e-138, 1e-137, 1e-136,
+ 1e-135, 1e-134, 1e-133, 1e-132, 1e-131, 1e-130, 1e-129, 1e-128, 1e-127,
+ 1e-126, 1e-125, 1e-124, 1e-123, 1e-122, 1e-121, 1e-120, 1e-119, 1e-118,
+ 1e-117, 1e-116, 1e-115, 1e-114, 1e-113, 1e-112, 1e-111, 1e-110, 1e-109,
+ 1e-108, 1e-107, 1e-106, 1e-105, 1e-104, 1e-103, 1e-102, 1e-101, 1e-100,
+ 1e-99, 1e-98, 1e-97, 1e-96, 1e-95, 1e-94, 1e-93, 1e-92, 1e-91,
+ 1e-90, 1e-89, 1e-88, 1e-87, 1e-86, 1e-85, 1e-84, 1e-83, 1e-82,
+ 1e-81, 1e-80, 1e-79, 1e-78, 1e-77, 1e-76, 1e-75, 1e-74, 1e-73,
+ 1e-72, 1e-71, 1e-70, 1e-69, 1e-68, 1e-67, 1e-66, 1e-65, 1e-64,
+ 1e-63, 1e-62, 1e-61, 1e-60, 1e-59, 1e-58, 1e-57, 1e-56, 1e-55,
+ 1e-54, 1e-53, 1e-52, 1e-51, 1e-50, 1e-49, 1e-48, 1e-47, 1e-46,
+ 1e-45, 1e-44, 1e-43, 1e-42, 1e-41, 1e-40, 1e-39, 1e-38, 1e-37,
+ 1e-36, 1e-35, 1e-34, 1e-33, 1e-32, 1e-31, 1e-30, 1e-29, 1e-28,
+ 1e-27, 1e-26, 1e-25, 1e-24, 1e-23, 1e-22, 1e-21, 1e-20, 1e-19,
+ 1e-18, 1e-17, 1e-16, 1e-15, 1e-14, 1e-13, 1e-12, 1e-11, 1e-10,
+ 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1,
+ 1e+0, 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8,
+ 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17,
+ 1e+18, 1e+19, 1e+20, 1e+21, 1e+22, k1e23, 1e+24, 1e+25, 1e+26,
+ 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35,
+ 1e+36, 1e+37, 1e+38, 1e+39, 1e+40, 1e+41, 1e+42, 1e+43, 1e+44,
+ 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53,
+ 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60, 1e+61, 1e+62,
+ 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71,
+ 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80,
+ 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89,
+ 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98,
+ 1e+99, 1e+100, 1e+101, 1e+102, 1e+103, 1e+104, 1e+105, 1e+106, 1e+107,
+ 1e+108, 1e+109, 1e+110, 1e+111, 1e+112, 1e+113, 1e+114, 1e+115, 1e+116,
+ 1e+117, 1e+118, 1e+119, 1e+120, 1e+121, 1e+122, 1e+123, 1e+124, 1e+125,
+ 1e+126, 1e+127, 1e+128, 1e+129, 1e+130, 1e+131, 1e+132, 1e+133, 1e+134,
+ 1e+135, 1e+136, 1e+137, 1e+138, 1e+139, 1e+140, 1e+141, 1e+142, 1e+143,
+ 1e+144, 1e+145, 1e+146, 1e+147, 1e+148, 1e+149, 1e+150, 1e+151, 1e+152,
+ 1e+153, 1e+154, 1e+155, 1e+156, 1e+157, 1e+158, 1e+159, 1e+160, 1e+161,
+ 1e+162, 1e+163, 1e+164, 1e+165, 1e+166, 1e+167, 1e+168, 1e+169, 1e+170,
+ 1e+171, 1e+172, 1e+173, 1e+174, 1e+175, 1e+176, 1e+177, 1e+178, 1e+179,
+ 1e+180, 1e+181, 1e+182, 1e+183, 1e+184, 1e+185, 1e+186, 1e+187, 1e+188,
+ 1e+189, 1e+190, 1e+191, 1e+192, 1e+193, 1e+194, 1e+195, 1e+196, 1e+197,
+ 1e+198, 1e+199, 1e+200, 1e+201, 1e+202, 1e+203, 1e+204, 1e+205, 1e+206,
+ 1e+207, 1e+208, 1e+209, 1e+210, 1e+211, 1e+212, 1e+213, 1e+214, 1e+215,
+ 1e+216, 1e+217, 1e+218, 1e+219, 1e+220, 1e+221, 1e+222, 1e+223, 1e+224,
+ 1e+225, 1e+226, 1e+227, 1e+228, 1e+229, 1e+230, 1e+231, 1e+232, 1e+233,
+ 1e+234, 1e+235, 1e+236, 1e+237, 1e+238, 1e+239, 1e+240, 1e+241, 1e+242,
+ 1e+243, 1e+244, 1e+245, 1e+246, 1e+247, 1e+248, 1e+249, 1e+250, 1e+251,
+ 1e+252, 1e+253, 1e+254, 1e+255, 1e+256, 1e+257, 1e+258, 1e+259, 1e+260,
+ 1e+261, 1e+262, 1e+263, 1e+264, 1e+265, 1e+266, 1e+267, 1e+268, 1e+269,
+ 1e+270, 1e+271, 1e+272, 1e+273, 1e+274, 1e+275, 1e+276, 1e+277, 1e+278,
+ 1e+279, 1e+280, 1e+281, 1e+282, 1e+283, 1e+284, 1e+285, 1e+286, 1e+287,
+ 1e+288, 1e+289, 1e+290, 1e+291, 1e+292, 1e+293, 1e+294, 1e+295, 1e+296,
+ 1e+297, 1e+298, 1e+299, 1e+300, 1e+301, 1e+302, 1e+303, 1e+304, 1e+305,
+ 1e+306, 1e+307, 1e+308,
+};
+
+} // namespace
+
+double Pow10(int exp) {
+ if (exp < -324) {
+ return 0.0;
+ } else if (exp > 308) {
+ return INFINITY;
+ } else {
+ return kPowersOfTen[exp + 324];
+ }
+}
+
+} // namespace strings_internal
+} // namespace absl
diff --git a/absl/strings/internal/pow10_helper.h b/absl/strings/internal/pow10_helper.h
new file mode 100644
index 00000000..fe7e735a
--- /dev/null
+++ b/absl/strings/internal/pow10_helper.h
@@ -0,0 +1,36 @@
+//
+// Copyright 2018 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.
+//
+// This test helper library contains a table of powers of 10, to guarantee
+// precise values are computed across the full range of doubles. We can't rely
+// on the pow() function, because not all standard libraries ship a version
+// that is precise.
+#ifndef ABSL_STRINGS_INTERNAL_POW10_HELPER_H_
+#define ABSL_STRINGS_INTERNAL_POW10_HELPER_H_
+
+#include <vector>
+
+namespace absl {
+namespace strings_internal {
+
+// Computes the precise value of 10^exp. (I.e. the nearest representable
+// double to the exact value, rounding to nearest-even in the (single) case of
+// being exactly halfway between.)
+double Pow10(int exp);
+
+} // namespace strings_internal
+} // namespace absl
+
+#endif // ABSL_STRINGS_INTERNAL_POW10_HELPER_H_
diff --git a/absl/strings/internal/pow10_helper_test.cc b/absl/strings/internal/pow10_helper_test.cc
new file mode 100644
index 00000000..9a13d524
--- /dev/null
+++ b/absl/strings/internal/pow10_helper_test.cc
@@ -0,0 +1,120 @@
+// Copyright 2018 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.
+
+#include "absl/strings/internal/pow10_helper.h"
+
+#include <cmath>
+
+#include "gtest/gtest.h"
+#include "absl/strings/str_format.h"
+
+namespace absl {
+namespace strings_internal {
+
+namespace {
+
+struct TestCase {
+ int power; // Testing Pow10(power)
+ uint64_t significand; // Raw bits of the expected value
+ int radix; // significand is adjusted by 2^radix
+};
+
+TEST(Pow10HelperTest, Works) {
+ // The logic in pow10_helper.cc is so simple that theoretically we don't even
+ // need a test. However, we're paranoid and believe that there may be
+ // compilers that don't round floating-point literals correctly, even though
+ // it is specified by the standard. We check various edge cases, just to be
+ // sure.
+ constexpr TestCase kTestCases[] = {
+ // Subnormals
+ {-323, 0x2, -1074},
+ {-322, 0x14, -1074},
+ {-321, 0xca, -1074},
+ {-320, 0x7e8, -1074},
+ {-319, 0x4f10, -1074},
+ {-318, 0x316a2, -1074},
+ {-317, 0x1ee257, -1074},
+ {-316, 0x134d761, -1074},
+ {-315, 0xc1069cd, -1074},
+ {-314, 0x78a42205, -1074},
+ {-313, 0x4b6695433, -1074},
+ {-312, 0x2f201d49fb, -1074},
+ {-311, 0x1d74124e3d1, -1074},
+ {-310, 0x12688b70e62b, -1074},
+ {-309, 0xb8157268fdaf, -1074},
+ {-308, 0x730d67819e8d2, -1074},
+ // Values that are very close to rounding the other way.
+ // Comment shows difference of significand from the true value.
+ {-307, 0x11fa182c40c60d, -1072}, // -.4588
+ {-290, 0x18f2b061aea072, -1016}, // .4854
+ {-276, 0x11BA03F5B21000, -969}, // .4709
+ {-259, 0x1899C2F6732210, -913}, // .4830
+ {-252, 0x1D53844EE47DD1, -890}, // -.4743
+ {-227, 0x1E5297287C2F45, -807}, // -.4708
+ {-198, 0x1322E220A5B17E, -710}, // -.4714
+ {-195, 0x12B010D3E1CF56, -700}, // .4928
+ {-192, 0x123FF06EEA847A, -690}, // .4968
+ {-163, 0x1708D0F84D3DE7, -594}, // -.4977
+ {-145, 0x13FAAC3E3FA1F3, -534}, // -.4785
+ {-111, 0x133D4032C2C7F5, -421}, // .4774
+ {-106, 0x1D5B561574765B, -405}, // -.4869
+ {-104, 0x16EF5B40C2FC77, -398}, // -.4741
+ {-88, 0x197683DF2F268D, -345}, // -.4738
+ {-86, 0x13E497065CD61F, -338}, // .4736
+ {-76, 0x17288E1271F513, -305}, // -.4761
+ {-63, 0x1A53FC9631D10D, -262}, // .4929
+ {-30, 0x14484BFEEBC2A0, -152}, // .4758
+ {-21, 0x12E3B40A0E9B4F, -122}, // -.4916
+ {-5, 0x14F8B588E368F1, -69}, // .4829
+ {23, 0x152D02C7E14AF6, 24}, // -.5000 (exactly, round-to-even)
+ {29, 0x1431E0FAE6D721, 44}, // -.4870
+ {34, 0x1ED09BEAD87C03, 60}, // -.4721
+ {70, 0x172EBAD6DDC73D, 180}, // .4733
+ {105, 0x1BE7ABD3781ECA, 296}, // -.4850
+ {126, 0x17A2ECC414A03F, 366}, // -.4999
+ {130, 0x1CDA62055B2D9E, 379}, // .4855
+ {165, 0x115D847AD00087, 496}, // -.4913
+ {172, 0x14B378469B6732, 519}, // .4818
+ {187, 0x1262DFEEBBB0F9, 569}, // -.4805
+ {210, 0x18557F31326BBB, 645}, // -.4992
+ {212, 0x1302CB5E6F642A, 652}, // -.4838
+ {215, 0x1290BA9A38C7D1, 662}, // -.4881
+ {236, 0x1F736F9B3494E9, 731}, // .4707
+ {244, 0x176EC98994F489, 758}, // .4924
+ {250, 0x1658E3AB795204, 778}, // -.4963
+ {252, 0x117571DDF6C814, 785}, // .4873
+ {254, 0x1B4781EAD1989E, 791}, // -.4887
+ {260, 0x1A03FDE214CAF1, 811}, // .4784
+ {284, 0x1585041B2C477F, 891}, // .4798
+ {304, 0x1D2A1BE4048F90, 957}, // -.4987
+ // Out-of-range values
+ {-324, 0x0, 0},
+ {-325, 0x0, 0},
+ {-326, 0x0, 0},
+ {309, 1, 2000},
+ {310, 1, 2000},
+ {311, 1, 2000},
+ };
+ for (const TestCase& test_case : kTestCases) {
+ EXPECT_EQ(Pow10(test_case.power),
+ std::ldexp(test_case.significand, test_case.radix))
+ << absl::StrFormat("Failure for Pow10(%d): %a vs %a", test_case.power,
+ Pow10(test_case.power),
+ std::ldexp(test_case.significand, test_case.radix));
+ }
+}
+
+} // namespace
+} // namespace strings_internal
+} // namespace absl
diff --git a/absl/strings/internal/resize_uninitialized.h b/absl/strings/internal/resize_uninitialized.h
index a94e0547..c2da0da9 100644
--- a/absl/strings/internal/resize_uninitialized.h
+++ b/absl/strings/internal/resize_uninitialized.h
@@ -18,6 +18,7 @@
#define ABSL_STRINGS_INTERNAL_RESIZE_UNINITIALIZED_H_
#include <string>
+#include <type_traits>
#include <utility>
#include "absl/base/port.h"
@@ -27,22 +28,24 @@ namespace absl {
namespace strings_internal {
// Is a subclass of true_type or false_type, depending on whether or not
-// T has a resize_uninitialized member.
-template <typename T, typename = void>
-struct HasResizeUninitialized : std::false_type {};
-template <typename T>
-struct HasResizeUninitialized<
- T, absl::void_t<decltype(std::declval<T>().resize_uninitialized(237))>>
- : std::true_type {};
+// T has a __resize_default_init member.
+template <typename string_type, typename = void>
+struct ResizeUninitializedTraits {
+ using HasMember = std::false_type;
+ static void Resize(string_type* s, size_t new_size) { s->resize(new_size); }
+};
+// __resize_default_init is provided by libc++ >= 8.0 and by Google's internal
+// ::string implementation.
template <typename string_type>
-void ResizeUninit(string_type* s, size_t new_size, std::true_type) {
- s->resize_uninitialized(new_size);
-}
-template <typename string_type>
-void ResizeUninit(string_type* s, size_t new_size, std::false_type) {
- s->resize(new_size);
-}
+struct ResizeUninitializedTraits<
+ string_type, absl::void_t<decltype(std::declval<string_type&>()
+ .__resize_default_init(237))> > {
+ using HasMember = std::true_type;
+ static void Resize(string_type* s, size_t new_size) {
+ s->__resize_default_init(new_size);
+ }
+};
// Returns true if the string implementation supports a resize where
// the new characters added to the string are left untouched.
@@ -51,7 +54,7 @@ void ResizeUninit(string_type* s, size_t new_size, std::false_type) {
// the previous function.)
template <typename string_type>
inline constexpr bool STLStringSupportsNontrashingResize(string_type*) {
- return HasResizeUninitialized<string_type>();
+ return ResizeUninitializedTraits<string_type>::HasMember::value;
}
// Like str->resize(new_size), except any new characters added to "*str" as a
@@ -60,7 +63,7 @@ inline constexpr bool STLStringSupportsNontrashingResize(string_type*) {
// store of the string with known data. Uses a Google extension to ::string.
template <typename string_type, typename = void>
inline void STLStringResizeUninitialized(string_type* s, size_t new_size) {
- ResizeUninit(s, new_size, HasResizeUninitialized<string_type>());
+ ResizeUninitializedTraits<string_type>::Resize(s, new_size);
}
} // namespace strings_internal
diff --git a/absl/strings/internal/resize_uninitialized_test.cc b/absl/strings/internal/resize_uninitialized_test.cc
index ad282efc..43aece8d 100644
--- a/absl/strings/internal/resize_uninitialized_test.cc
+++ b/absl/strings/internal/resize_uninitialized_test.cc
@@ -24,44 +24,44 @@ struct resizable_string {
void resize(size_t) { resize_call_count += 1; }
};
-int resize_uninitialized_call_count = 0;
+int resize_default_init_call_count = 0;
-struct resize_uninitializable_string {
+struct resize_default_init_string {
void resize(size_t) { resize_call_count += 1; }
- void resize_uninitialized(size_t) { resize_uninitialized_call_count += 1; }
+ void __resize_default_init(size_t) { resize_default_init_call_count += 1; }
};
TEST(ResizeUninit, WithAndWithout) {
resize_call_count = 0;
- resize_uninitialized_call_count = 0;
+ resize_default_init_call_count = 0;
{
resizable_string rs;
EXPECT_EQ(resize_call_count, 0);
- EXPECT_EQ(resize_uninitialized_call_count, 0);
+ EXPECT_EQ(resize_default_init_call_count, 0);
EXPECT_FALSE(
absl::strings_internal::STLStringSupportsNontrashingResize(&rs));
EXPECT_EQ(resize_call_count, 0);
- EXPECT_EQ(resize_uninitialized_call_count, 0);
+ EXPECT_EQ(resize_default_init_call_count, 0);
absl::strings_internal::STLStringResizeUninitialized(&rs, 237);
EXPECT_EQ(resize_call_count, 1);
- EXPECT_EQ(resize_uninitialized_call_count, 0);
+ EXPECT_EQ(resize_default_init_call_count, 0);
}
resize_call_count = 0;
- resize_uninitialized_call_count = 0;
+ resize_default_init_call_count = 0;
{
- resize_uninitializable_string rus;
+ resize_default_init_string rus;
EXPECT_EQ(resize_call_count, 0);
- EXPECT_EQ(resize_uninitialized_call_count, 0);
+ EXPECT_EQ(resize_default_init_call_count, 0);
EXPECT_TRUE(
absl::strings_internal::STLStringSupportsNontrashingResize(&rus));
EXPECT_EQ(resize_call_count, 0);
- EXPECT_EQ(resize_uninitialized_call_count, 0);
+ EXPECT_EQ(resize_default_init_call_count, 0);
absl::strings_internal::STLStringResizeUninitialized(&rus, 237);
EXPECT_EQ(resize_call_count, 0);
- EXPECT_EQ(resize_uninitialized_call_count, 1);
+ EXPECT_EQ(resize_default_init_call_count, 1);
}
}
diff --git a/absl/strings/internal/str_format/arg.h b/absl/strings/internal/str_format/arg.h
index ec9e6f00..ebd40adc 100644
--- a/absl/strings/internal/str_format/arg.h
+++ b/absl/strings/internal/str_format/arg.h
@@ -80,7 +80,7 @@ ConvertResult<Conv::s> FormatConvertImpl(const AbslCord& value,
int precision = conv.precision();
if (precision >= 0)
- to_write = std::min(to_write, static_cast<size_t>(precision));
+ to_write = (std::min)(to_write, static_cast<size_t>(precision));
space_remaining = Excess(to_write, space_remaining);
diff --git a/absl/strings/match.cc b/absl/strings/match.cc
index 3d10c577..a2e9064c 100644
--- a/absl/strings/match.cc
+++ b/absl/strings/match.cc
@@ -18,15 +18,6 @@
namespace absl {
-namespace {
-bool CaseEqual(absl::string_view piece1, absl::string_view piece2) {
- return (piece1.size() == piece2.size() &&
- 0 == strings_internal::memcasecmp(piece1.data(), piece2.data(),
- piece1.size()));
- // memcasecmp uses ascii_tolower().
-}
-} // namespace
-
bool EqualsIgnoreCase(absl::string_view piece1, absl::string_view piece2) {
return (piece1.size() == piece2.size() &&
0 == absl::strings_internal::memcasecmp(piece1.data(), piece2.data(),
@@ -36,12 +27,12 @@ bool EqualsIgnoreCase(absl::string_view piece1, absl::string_view piece2) {
bool StartsWithIgnoreCase(absl::string_view text, absl::string_view prefix) {
return (text.size() >= prefix.size()) &&
- CaseEqual(text.substr(0, prefix.size()), prefix);
+ EqualsIgnoreCase(text.substr(0, prefix.size()), prefix);
}
bool EndsWithIgnoreCase(absl::string_view text, absl::string_view suffix) {
return (text.size() >= suffix.size()) &&
- CaseEqual(text.substr(text.size() - suffix.size()), suffix);
+ EqualsIgnoreCase(text.substr(text.size() - suffix.size()), suffix);
}
} // namespace absl
diff --git a/absl/strings/numbers_test.cc b/absl/strings/numbers_test.cc
index 36fc0d64..099326c2 100644
--- a/absl/strings/numbers_test.cc
+++ b/absl/strings/numbers_test.cc
@@ -39,6 +39,7 @@
#include "absl/strings/str_cat.h"
#include "absl/strings/internal/numbers_test_common.h"
+#include "absl/strings/internal/pow10_helper.h"
namespace {
@@ -871,7 +872,7 @@ TEST_F(SimpleDtoaTest, ExhaustiveDoubleToSixDigits) {
}
for (int exponent = -324; exponent <= 308; ++exponent) {
- double powten = pow(10.0, exponent);
+ double powten = absl::strings_internal::Pow10(exponent);
if (powten == 0) powten = 5e-324;
if (kFloatNumCases >= 1e9) {
// The exhaustive test takes a very long time, so log progress.
diff --git a/absl/strings/string_view.h b/absl/strings/string_view.h
index 2cc10f52..8cd4fa24 100644
--- a/absl/strings/string_view.h
+++ b/absl/strings/string_view.h
@@ -355,7 +355,7 @@ class string_view {
string_view substr(size_type pos, size_type n = npos) const {
if (ABSL_PREDICT_FALSE(pos > length_))
base_internal::ThrowStdOutOfRange("absl::string_view::substr");
- n = std::min(n, length_ - pos);
+ n = (std::min)(n, length_ - pos);
return string_view(ptr_ + pos, n);
}
@@ -368,7 +368,7 @@ class string_view {
// on the respective sizes of the two `string_view`s to determine which is
// smaller, equal, or greater.
int compare(string_view x) const noexcept {
- auto min_length = std::min(length_, x.length_);
+ auto min_length = (std::min)(length_, x.length_);
if (min_length > 0) {
int r = memcmp(ptr_, x.ptr_, min_length);
if (r < 0) return -1;
@@ -517,7 +517,7 @@ inline bool operator!=(string_view x, string_view y) noexcept {
}
inline bool operator<(string_view x, string_view y) noexcept {
- auto min_size = std::min(x.size(), y.size());
+ auto min_size = (std::min)(x.size(), y.size());
const int r = min_size == 0 ? 0 : memcmp(x.data(), y.data(), min_size);
return (r < 0) || (r == 0 && x.size() < y.size());
}
@@ -547,7 +547,7 @@ namespace absl {
// 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()));
+ pos = (std::min)(pos, static_cast<size_t>(s.size()));
return s.substr(pos, n);
}
diff --git a/absl/synchronization/BUILD.bazel b/absl/synchronization/BUILD.bazel
index f52e9d41..53e79884 100644
--- a/absl/synchronization/BUILD.bazel
+++ b/absl/synchronization/BUILD.bazel
@@ -15,7 +15,7 @@
#
load(
- "//absl:copts.bzl",
+ "//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
"ABSL_TEST_COPTS",
)
@@ -170,18 +170,31 @@ cc_test(
],
)
-cc_test(
- name = "mutex_benchmark",
+cc_library(
+ name = "mutex_benchmark_common",
+ testonly = 1,
srcs = ["mutex_benchmark.cc"],
- copts = ABSL_TEST_COPTS,
- tags = ["benchmark"],
- visibility = ["//visibility:private"],
+ copts = ABSL_DEFAULT_COPTS,
+ visibility = [
+ "//absl/synchronization:__pkg__",
+ ],
deps = [
":synchronization",
":thread_pool",
"//absl/base",
"@com_github_google_benchmark//:benchmark_main",
],
+ alwayslink = 1,
+)
+
+cc_binary(
+ name = "mutex_benchmark",
+ testonly = 1,
+ copts = ABSL_DEFAULT_COPTS,
+ visibility = ["//visibility:private"],
+ deps = [
+ ":mutex_benchmark_common",
+ ],
)
cc_test(
diff --git a/absl/synchronization/CMakeLists.txt b/absl/synchronization/CMakeLists.txt
index de0d7b7d..cb77b685 100644
--- a/absl/synchronization/CMakeLists.txt
+++ b/absl/synchronization/CMakeLists.txt
@@ -14,142 +14,182 @@
# limitations under the License.
#
-list(APPEND SYNCHRONIZATION_PUBLIC_HEADERS
- "barrier.h"
- "blocking_counter.h"
- "mutex.h"
- "notification.h"
+absl_cc_library(
+ NAME
+ graphcycles_internal
+ HDRS
+ "internal/graphcycles.h"
+ SRCS
+ "internal/graphcycles.cc"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::base
+ absl::base_internal
+ absl::core_headers
+ absl::malloc_internal
)
-
-list(APPEND SYNCHRONIZATION_INTERNAL_HEADERS
- "internal/create_thread_identity.h"
- "internal/graphcycles.h"
- "internal/kernel_timeout.h"
- "internal/per_thread_sem.h"
- "internal/thread_pool.h"
- "internal/waiter.h"
-)
-
-
-
-# synchronization library
-list(APPEND SYNCHRONIZATION_SRC
- "barrier.cc"
- "blocking_counter.cc"
- "internal/create_thread_identity.cc"
- "internal/per_thread_sem.cc"
- "internal/waiter.cc"
- "internal/graphcycles.cc"
- "notification.cc"
- "mutex.cc"
-)
-
-set(SYNCHRONIZATION_PUBLIC_LIBRARIES absl::base absl::stacktrace absl::symbolize absl::time)
-
-absl_library(
- TARGET
- absl_synchronization
- SOURCES
- ${SYNCHRONIZATION_SRC}
- PUBLIC_LIBRARIES
- ${SYNCHRONIZATION_PUBLIC_LIBRARIES}
- EXPORT_NAME
+absl_cc_library(
+ NAME
synchronization
+ HDRS
+ "barrier.h"
+ "blocking_counter.h"
+ "internal/create_thread_identity.h"
+ "internal/kernel_timeout.h"
+ "internal/mutex_nonprod.inc"
+ "internal/per_thread_sem.h"
+ "internal/waiter.h"
+ "mutex.h"
+ "notification.h"
+ SRCS
+ "barrier.cc"
+ "blocking_counter.cc"
+ "internal/create_thread_identity.cc"
+ "internal/per_thread_sem.cc"
+ "internal/waiter.cc"
+ "notification.cc"
+ "mutex.cc"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::graphcycles_internal
+ absl::base
+ absl::base_internal
+ absl::config
+ absl::core_headers
+ absl::dynamic_annotations
+ absl::malloc_internal
+ absl::stacktrace
+ absl::symbolize
+ absl::time
+ PUBLIC
)
-
-#
-## TESTS
-#
-
-
-# test barrier_test
-set(BARRIER_TEST_SRC "barrier_test.cc")
-set(BARRIER_TEST_PUBLIC_LIBRARIES absl::synchronization)
-
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
barrier_test
- SOURCES
- ${BARRIER_TEST_SRC}
- PUBLIC_LIBRARIES
- ${BARRIER_TEST_PUBLIC_LIBRARIES}
+ SRCS
+ "barrier_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::synchronization
+ absl::time
+ gmock_main
)
-
-# test blocking_counter_test
-set(BLOCKING_COUNTER_TEST_SRC "blocking_counter_test.cc")
-set(BLOCKING_COUNTER_TEST_PUBLIC_LIBRARIES absl::synchronization)
-
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
blocking_counter_test
- SOURCES
- ${BLOCKING_COUNTER_TEST_SRC}
- PUBLIC_LIBRARIES
- ${BLOCKING_COUNTER_TEST_PUBLIC_LIBRARIES}
+ SRCS
+ "blocking_counter_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::synchronization
+ absl::time
+ gmock_main
)
-
-# test graphcycles_test
-set(GRAPHCYCLES_TEST_SRC "internal/graphcycles_test.cc")
-set(GRAPHCYCLES_TEST_PUBLIC_LIBRARIES absl::synchronization)
-
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
graphcycles_test
- SOURCES
- ${GRAPHCYCLES_TEST_SRC}
- PUBLIC_LIBRARIES
- ${GRAPHCYCLES_TEST_PUBLIC_LIBRARIES}
+ SRCS
+ "internal/graphcycles_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::graphcycles_internal
+ absl::base
+ absl::core_headers
+ gmock_main
)
+absl_cc_library(
+ NAME
+ thread_pool
+ HDRS
+ "internal/thread_pool.h"
+ DEPS
+ absl::synchronization
+ absl::core_headers
+ TESTONLY
+)
-# test mutex_test
-set(MUTEX_TEST_SRC "mutex_test.cc")
-set(MUTEX_TEST_PUBLIC_LIBRARIES absl::synchronization)
-
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
mutex_test
- SOURCES
- ${MUTEX_TEST_SRC}
- PUBLIC_LIBRARIES
- ${MUTEX_TEST_PUBLIC_LIBRARIES}
+ SRCS
+ "mutex_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::synchronization
+ absl::thread_pool
+ absl::base
+ absl::core_headers
+ absl::memory
+ absl::time
+ gmock_main
)
-
-# test notification_test
-set(NOTIFICATION_TEST_SRC "notification_test.cc")
-set(NOTIFICATION_TEST_PUBLIC_LIBRARIES absl::synchronization)
-
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
notification_test
- SOURCES
- ${NOTIFICATION_TEST_SRC}
- PUBLIC_LIBRARIES
- ${NOTIFICATION_TEST_PUBLIC_LIBRARIES}
+ SRCS
+ "notification_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::synchronization
+ absl::time
+ gmock_main
)
-
-# test per_thread_sem_test_common
-set(PER_THREAD_SEM_TEST_COMMON_SRC "internal/per_thread_sem_test.cc")
-set(PER_THREAD_SEM_TEST_COMMON_PUBLIC_LIBRARIES absl::synchronization absl::strings)
-
-absl_test(
- TARGET
+absl_cc_library(
+ NAME
per_thread_sem_test_common
- SOURCES
- ${PER_THREAD_SEM_TEST_COMMON_SRC}
- PUBLIC_LIBRARIES
- ${PER_THREAD_SEM_TEST_COMMON_PUBLIC_LIBRARIES}
+ SRCS
+ "internal/per_thread_sem_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::synchronization
+ absl::base
+ absl::strings
+ absl::time
+ gmock
+ TESTONLY
)
+absl_cc_test(
+ NAME
+ per_thread_sem_test
+ SRCS
+ "internal/per_thread_sem_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::per_thread_sem_test_common
+ absl::synchronization
+ absl::base
+ absl::strings
+ absl::time
+ gmock_main
+)
-
-
-
-
-
+absl_cc_test(
+ NAME
+ lifetime_test
+ SRCS
+ "lifetime_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::synchronization
+ absl::base
+ absl::core_headers
+ Threads::Threads
+)
diff --git a/absl/synchronization/internal/kernel_timeout.h b/absl/synchronization/internal/kernel_timeout.h
index 76e7983a..9e1eed75 100644
--- a/absl/synchronization/internal/kernel_timeout.h
+++ b/absl/synchronization/internal/kernel_timeout.h
@@ -100,8 +100,8 @@ class KernelTimeout {
if (n < 0) n = 0;
struct timespec abstime;
- int64_t seconds = std::min(n / kNanosPerSecond,
- int64_t{(std::numeric_limits<time_t>::max)()});
+ int64_t seconds = (std::min)(n / kNanosPerSecond,
+ int64_t{(std::numeric_limits<time_t>::max)()});
abstime.tv_sec = static_cast<time_t>(seconds);
abstime.tv_nsec =
static_cast<decltype(abstime.tv_nsec)>(n % kNanosPerSecond);
diff --git a/absl/synchronization/internal/mutex_nonprod.inc b/absl/synchronization/internal/mutex_nonprod.inc
index 0aab3d13..b8d5af79 100644
--- a/absl/synchronization/internal/mutex_nonprod.inc
+++ b/absl/synchronization/internal/mutex_nonprod.inc
@@ -214,6 +214,9 @@ class SynchronizationStorage {
// stack) should use this constructor.
explicit SynchronizationStorage(base_internal::LinkerInitialized) {}
+ constexpr explicit SynchronizationStorage(absl::ConstInitType)
+ : is_dynamic_(false), once_(), space_{{0}} {}
+
SynchronizationStorage(SynchronizationStorage&) = delete;
SynchronizationStorage& operator=(SynchronizationStorage&) = delete;
diff --git a/absl/synchronization/lifetime_test.cc b/absl/synchronization/lifetime_test.cc
index b7360c29..8b168e21 100644
--- a/absl/synchronization/lifetime_test.cc
+++ b/absl/synchronization/lifetime_test.cc
@@ -17,6 +17,7 @@
#include <type_traits>
#include "absl/base/attributes.h"
+#include "absl/base/const_init.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/base/thread_annotations.h"
#include "absl/synchronization/mutex.h"
@@ -95,6 +96,10 @@ void TestLocals() {
RunTests(&mutex, &condvar);
}
+// Normal kConstInit usage
+ABSL_CONST_INIT absl::Mutex const_init_mutex(absl::kConstInit);
+void TestConstInitGlobal() { RunTests(&const_init_mutex, nullptr); }
+
// Global variables during start and termination
//
// In a translation unit, static storage duration variables are initialized in
@@ -117,10 +122,53 @@ class OnDestruction {
Function fn_;
};
+// kConstInit
+// Test early usage. (Declaration comes first; definitions must appear after
+// the test runner.)
+extern absl::Mutex early_const_init_mutex;
+// (Normally I'd write this +[], to make the cast-to-function-pointer explicit,
+// but in some MSVC setups we support, lambdas provide conversion operators to
+// different flavors of function pointers, making this trick ambiguous.)
+OnConstruction test_early_const_init([] {
+ RunTests(&early_const_init_mutex, nullptr);
+});
+// This definition appears before test_early_const_init, but it should be
+// initialized first (due to constant initialization). Test that the object
+// actually works when constructed this way.
+ABSL_CONST_INIT absl::Mutex early_const_init_mutex(absl::kConstInit);
+
+// Furthermore, test that the const-init c'tor doesn't stomp over the state of
+// a Mutex. Really, this is a test that the platform under test correctly
+// supports C++11 constant initialization. (The constant-initialization
+// constructors of globals "happen at link time"; memory is pre-initialized,
+// before the constructors of either grab_lock or check_still_locked are run.)
+extern absl::Mutex const_init_sanity_mutex;
+OnConstruction grab_lock([]() NO_THREAD_SAFETY_ANALYSIS {
+ const_init_sanity_mutex.Lock();
+});
+ABSL_CONST_INIT absl::Mutex const_init_sanity_mutex(absl::kConstInit);
+OnConstruction check_still_locked([]() NO_THREAD_SAFETY_ANALYSIS {
+ const_init_sanity_mutex.AssertHeld();
+ const_init_sanity_mutex.Unlock();
+});
+
+// Test shutdown usage. (Declarations come first; definitions must appear after
+// the test runner.)
+extern absl::Mutex late_const_init_mutex;
+// OnDestruction is being used here as a global variable, even though it has a
+// non-trivial destructor. This is against the style guide. We're violating
+// that rule here to check that the exception we allow for kConstInit is safe.
+// NOLINTNEXTLINE
+OnDestruction test_late_const_init([] {
+ RunTests(&late_const_init_mutex, nullptr);
+});
+ABSL_CONST_INIT absl::Mutex late_const_init_mutex(absl::kConstInit);
+
} // namespace
int main() {
TestLocals();
+ TestConstInitGlobal();
// Explicitly call exit(0) here, to make it clear that we intend for the
// above global object destructors to run.
std::exit(0);
diff --git a/absl/synchronization/mutex.cc b/absl/synchronization/mutex.cc
index 81219798..f1b42db1 100644
--- a/absl/synchronization/mutex.cc
+++ b/absl/synchronization/mutex.cc
@@ -1079,7 +1079,7 @@ void Mutex::TryRemove(PerThreadSynch *s) {
// if the wait extends past the absolute time specified, even if "s" is still
// on the mutex queue. In this case, remove "s" from the queue and return
// true, otherwise return false.
-void Mutex::Block(PerThreadSynch *s) {
+ABSL_XRAY_LOG_ARGS(1) void Mutex::Block(PerThreadSynch *s) {
while (s->state.load(std::memory_order_acquire) == PerThreadSynch::kQueued) {
if (!DecrementSynchSem(this, s, s->waitp->timeout)) {
// After a timeout, we go into a spin loop until we remove ourselves
diff --git a/absl/synchronization/mutex.h b/absl/synchronization/mutex.h
index aeef3c95..4b65e92c 100644
--- a/absl/synchronization/mutex.h
+++ b/absl/synchronization/mutex.h
@@ -61,6 +61,7 @@
#include <cstdint>
#include <string>
+#include "absl/base/const_init.h"
#include "absl/base/internal/identity.h"
#include "absl/base/internal/low_level_alloc.h"
#include "absl/base/internal/thread_identity.h"
@@ -136,7 +137,26 @@ struct SynchWaitParams;
class LOCKABLE Mutex {
public:
+ // Creates a `Mutex` that is not held by anyone. This constructor is
+ // typically used for Mutexes allocated on the heap or the stack.
+ //
+ // To create `Mutex` instances with static storage duration
+ // (e.g. a namespace-scoped or global variable), see
+ // `Mutex::Mutex(absl::kConstInit)` below instead.
Mutex();
+
+ // Creates a mutex with static storage duration. A global variable
+ // constructed this way avoids the lifetime issues that can occur on program
+ // startup and shutdown. (See absl/base/const_init.h.)
+ //
+ // For Mutexes allocated on the heap and stack, instead use the default
+ // constructor, which can interact more fully with the thread sanitizer.
+ //
+ // Example usage:
+ // namespace foo {
+ // ABSL_CONST_INIT Mutex mu(absl::kConstInit);
+ // }
+ explicit constexpr Mutex(absl::ConstInitType);
~Mutex();
// Mutex::Lock()
@@ -879,10 +899,12 @@ class SCOPED_LOCKABLE ReleasableMutexLock {
};
#ifdef ABSL_INTERNAL_USE_NONPROD_MUTEX
+inline constexpr Mutex::Mutex(absl::ConstInitType) : impl_(absl::kConstInit) {}
#else
inline Mutex::Mutex() : mu_(0) {
ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static);
}
+inline constexpr Mutex::Mutex(absl::ConstInitType) : mu_(0) {}
inline CondVar::CondVar() : cv_(0) {}
#endif
diff --git a/absl/synchronization/mutex_benchmark.cc b/absl/synchronization/mutex_benchmark.cc
index 1e019e00..2652bb97 100644
--- a/absl/synchronization/mutex_benchmark.cc
+++ b/absl/synchronization/mutex_benchmark.cc
@@ -12,16 +12,154 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include <cstdint>
+#include <mutex> // NOLINT(build/c++11)
#include <vector>
-#include "benchmark/benchmark.h"
-#include "absl/base/internal/sysinfo.h"
+#include "absl/base/internal/cycleclock.h"
+#include "absl/base/internal/spinlock.h"
#include "absl/synchronization/blocking_counter.h"
#include "absl/synchronization/internal/thread_pool.h"
#include "absl/synchronization/mutex.h"
+#include "benchmark/benchmark.h"
namespace {
+void BM_Mutex(benchmark::State& state) {
+ static absl::Mutex* mu = new absl::Mutex;
+ for (auto _ : state) {
+ absl::MutexLock lock(mu);
+ }
+}
+BENCHMARK(BM_Mutex)->UseRealTime()->Threads(1)->ThreadPerCpu();
+
+static void DelayNs(int64_t ns, int* data) {
+ int64_t end = absl::base_internal::CycleClock::Now() +
+ ns * absl::base_internal::CycleClock::Frequency() / 1e9;
+ while (absl::base_internal::CycleClock::Now() < end) {
+ ++(*data);
+ benchmark::DoNotOptimize(*data);
+ }
+}
+
+template <typename MutexType>
+class RaiiLocker {
+ public:
+ explicit RaiiLocker(MutexType* mu) : mu_(mu) { mu_->Lock(); }
+ ~RaiiLocker() { mu_->Unlock(); }
+ private:
+ MutexType* mu_;
+};
+
+template <>
+class RaiiLocker<std::mutex> {
+ public:
+ explicit RaiiLocker(std::mutex* mu) : mu_(mu) { mu_->lock(); }
+ ~RaiiLocker() { mu_->unlock(); }
+ private:
+ std::mutex* mu_;
+};
+
+template <typename MutexType>
+void BM_Contended(benchmark::State& state) {
+ struct Shared {
+ MutexType mu;
+ int data = 0;
+ };
+ static auto* shared = new Shared;
+ int local = 0;
+ for (auto _ : state) {
+ // Here we model both local work outside of the critical section as well as
+ // some work inside of the critical section. The idea is to capture some
+ // more or less realisitic contention levels.
+ // If contention is too low, the benchmark won't measure anything useful.
+ // If contention is unrealistically high, the benchmark will favor
+ // bad mutex implementations that block and otherwise distract threads
+ // from the mutex and shared state for as much as possible.
+ // To achieve this amount of local work is multiplied by number of threads
+ // to keep ratio between local work and critical section approximately
+ // equal regardless of number of threads.
+ DelayNs(100 * state.threads, &local);
+ RaiiLocker<MutexType> locker(&shared->mu);
+ DelayNs(state.range(0), &shared->data);
+ }
+}
+
+BENCHMARK_TEMPLATE(BM_Contended, absl::Mutex)
+ ->UseRealTime()
+ // ThreadPerCpu poorly handles non-power-of-two CPU counts.
+ ->Threads(1)
+ ->Threads(2)
+ ->Threads(4)
+ ->Threads(6)
+ ->Threads(8)
+ ->Threads(12)
+ ->Threads(16)
+ ->Threads(24)
+ ->Threads(32)
+ ->Threads(48)
+ ->Threads(64)
+ ->Threads(96)
+ ->Threads(128)
+ ->Threads(192)
+ ->Threads(256)
+ // Some empirically chosen amounts of work in critical section.
+ // 1 is low contention, 200 is high contention and few values in between.
+ ->Arg(1)
+ ->Arg(20)
+ ->Arg(50)
+ ->Arg(200);
+
+BENCHMARK_TEMPLATE(BM_Contended, absl::base_internal::SpinLock)
+ ->UseRealTime()
+ // ThreadPerCpu poorly handles non-power-of-two CPU counts.
+ ->Threads(1)
+ ->Threads(2)
+ ->Threads(4)
+ ->Threads(6)
+ ->Threads(8)
+ ->Threads(12)
+ ->Threads(16)
+ ->Threads(24)
+ ->Threads(32)
+ ->Threads(48)
+ ->Threads(64)
+ ->Threads(96)
+ ->Threads(128)
+ ->Threads(192)
+ ->Threads(256)
+ // Some empirically chosen amounts of work in critical section.
+ // 1 is low contention, 200 is high contention and few values in between.
+ ->Arg(1)
+ ->Arg(20)
+ ->Arg(50)
+ ->Arg(200);
+
+BENCHMARK_TEMPLATE(BM_Contended, std::mutex)
+ ->UseRealTime()
+ // ThreadPerCpu poorly handles non-power-of-two CPU counts.
+ ->Threads(1)
+ ->Threads(2)
+ ->Threads(4)
+ ->Threads(6)
+ ->Threads(8)
+ ->Threads(12)
+ ->Threads(16)
+ ->Threads(24)
+ ->Threads(32)
+ ->Threads(48)
+ ->Threads(64)
+ ->Threads(96)
+ ->Threads(128)
+ ->Threads(192)
+ ->Threads(256)
+ // Some empirically chosen amounts of work in critical section.
+ // 1 is low contention, 200 is high contention and few values in between.
+ ->Arg(1)
+ ->Arg(20)
+ ->Arg(50)
+ ->Arg(200);
+
// Measure the overhead of conditions on mutex release (when they must be
// evaluated). Mutex has (some) support for equivalence classes allowing
// Conditions with the same function/argument to potentially not be multiply
@@ -82,13 +220,4 @@ constexpr int kMaxConditionWaiters = 1024;
#endif
BENCHMARK(BM_ConditionWaiters)->RangePair(0, 2, 1, kMaxConditionWaiters);
-void BM_ContendedMutex(benchmark::State& state) {
- static absl::Mutex* mu = new absl::Mutex;
- for (auto _ : state) {
- absl::MutexLock lock(mu);
- }
-}
-BENCHMARK(BM_ContendedMutex)->Threads(1);
-BENCHMARK(BM_ContendedMutex)->ThreadPerCpu();
-
} // namespace
diff --git a/absl/synchronization/notification.h b/absl/synchronization/notification.h
index 107932f2..f95f4d14 100644
--- a/absl/synchronization/notification.h
+++ b/absl/synchronization/notification.h
@@ -52,6 +52,7 @@
#include <atomic>
+#include "absl/base/macros.h"
#include "absl/synchronization/mutex.h"
#include "absl/time/time.h"
diff --git a/absl/time/BUILD.bazel b/absl/time/BUILD.bazel
index 4d9c01c4..2082f52c 100644
--- a/absl/time/BUILD.bazel
+++ b/absl/time/BUILD.bazel
@@ -15,7 +15,7 @@
#
load(
- "//absl:copts.bzl",
+ "//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
"ABSL_TEST_COPTS",
)
diff --git a/absl/time/CMakeLists.txt b/absl/time/CMakeLists.txt
index 53216cda..db60e712 100644
--- a/absl/time/CMakeLists.txt
+++ b/absl/time/CMakeLists.txt
@@ -14,85 +14,108 @@
# limitations under the License.
#
-list(APPEND TIME_PUBLIC_HEADERS
- "civil_time.h"
- "clock.h"
- "time.h"
-)
-
-
-list(APPEND TIME_INTERNAL_HEADERS
- "internal/test_util.h"
- "internal/cctz/include/cctz/civil_time.h"
- "internal/cctz/include/cctz/civil_time_detail.h"
- "internal/cctz/include/cctz/time_zone.h"
- "internal/cctz/include/cctz/zone_info_source.h"
-)
-
-list(APPEND TIME_SRC
+absl_cc_library(
+ NAME
+ time
+ HDRS
+ "civil_time.h"
+ "clock.h"
+ "time.h"
+ SRCS
"civil_time.cc"
- "time.cc"
"clock.cc"
"duration.cc"
"format.cc"
- "internal/cctz/src/civil_time_detail.cc"
- "internal/cctz/src/time_zone_fixed.cc"
- "internal/cctz/src/time_zone_fixed.h"
- "internal/cctz/src/time_zone_format.cc"
- "internal/cctz/src/time_zone_if.cc"
- "internal/cctz/src/time_zone_if.h"
- "internal/cctz/src/time_zone_impl.cc"
- "internal/cctz/src/time_zone_impl.h"
- "internal/cctz/src/time_zone_info.cc"
- "internal/cctz/src/time_zone_info.h"
- "internal/cctz/src/time_zone_libc.cc"
- "internal/cctz/src/time_zone_libc.h"
- "internal/cctz/src/time_zone_lookup.cc"
- "internal/cctz/src/time_zone_posix.cc"
- "internal/cctz/src/time_zone_posix.h"
- "internal/cctz/src/tzfile.h"
- "internal/cctz/src/zone_info_source.cc"
- ${TIME_PUBLIC_HEADERS}
- ${TIME_INTERNAL_HEADERS}
+ "internal/get_current_time_chrono.inc"
+ "internal/get_current_time_posix.inc"
+ "time.cc"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::base
+ absl::core_headers
+ absl::int128
+ absl::strings
+ absl::civil_time
+ absl::time_zone
+ PUBLIC
)
-set(TIME_PUBLIC_LIBRARIES absl::base absl::stacktrace absl::int128 absl::strings)
-absl_library(
- TARGET
- absl_time
- SOURCES
- ${TIME_SRC}
- PUBLIC_LIBRARIES
- ${TIME_PUBLIC_LIBRARIES}
- EXPORT_NAME
- time
+absl_cc_library(
+ NAME
+ civil_time
+ HDRS
+ "internal/cctz/include/cctz/civil_time.h"
+ "internal/cctz/include/cctz/civil_time_detail.h"
+ SRCS
+ "internal/cctz/src/civil_time_detail.cc"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
)
+absl_cc_library(
+ NAME
+ time_zone
+ HDRS
+ "internal/cctz/include/cctz/time_zone.h"
+ "internal/cctz/include/cctz/zone_info_source.h"
+ SRCS
+ "internal/cctz/src/time_zone_fixed.cc"
+ "internal/cctz/src/time_zone_fixed.h"
+ "internal/cctz/src/time_zone_format.cc"
+ "internal/cctz/src/time_zone_if.cc"
+ "internal/cctz/src/time_zone_if.h"
+ "internal/cctz/src/time_zone_impl.cc"
+ "internal/cctz/src/time_zone_impl.h"
+ "internal/cctz/src/time_zone_info.cc"
+ "internal/cctz/src/time_zone_info.h"
+ "internal/cctz/src/time_zone_libc.cc"
+ "internal/cctz/src/time_zone_libc.h"
+ "internal/cctz/src/time_zone_lookup.cc"
+ "internal/cctz/src/time_zone_posix.cc"
+ "internal/cctz/src/time_zone_posix.h"
+ "internal/cctz/src/tzfile.h"
+ "internal/cctz/src/zone_info_source.cc"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+)
-
-#
-## TESTS
-#
-
-# test time_test
-list(APPEND TIME_TEST_SRC
- "civil_time_test.cc"
- "time_test.cc"
- "clock_test.cc"
- "duration_test.cc"
- "format_test.cc"
- "time_test.cc"
- "time_zone_test.cc"
- "internal/test_util.cc"
+absl_cc_library(
+ NAME
+ test_util
+ HDRS
+ "internal/test_util.h"
+ SRCS
+ "internal/test_util.cc"
+ "internal/zoneinfo.inc"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::time
+ absl::base
+ absl::time_zone
+ gmock
+ TESTONLY
)
-set(TIME_TEST_PUBLIC_LIBRARIES absl::time)
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
time_test
- SOURCES
- ${TIME_TEST_SRC}
- PUBLIC_LIBRARIES
- ${TIME_TEST_PUBLIC_LIBRARIES}
+ SRCS
+ "civil_time_test.cc"
+ "clock_test.cc"
+ "duration_test.cc"
+ "format_test.cc"
+ "time_test.cc"
+ "time_zone_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::test_util
+ absl::time
+ absl::base
+ absl::config
+ absl::core_headers
+ absl::time_zone
+ gmock_main
)
-
diff --git a/absl/time/duration.cc b/absl/time/duration.cc
index 2950c7cd..b77d5ec9 100644
--- a/absl/time/duration.cc
+++ b/absl/time/duration.cc
@@ -78,10 +78,16 @@ constexpr int64_t kint64min = std::numeric_limits<int64_t>::min();
// Can't use std::isinfinite() because it doesn't exist on windows.
inline bool IsFinite(double d) {
+ if (std::isnan(d)) return false;
return d != std::numeric_limits<double>::infinity() &&
d != -std::numeric_limits<double>::infinity();
}
+inline bool IsValidDivisor(double d) {
+ if (std::isnan(d)) return false;
+ return d != 0.0;
+}
+
// Can't use std::round() because it is only available in C++11.
// Note that we ignore the possibility of floating-point over/underflow.
template <typename Double>
@@ -455,7 +461,7 @@ Duration& Duration::operator/=(int64_t r) {
}
Duration& Duration::operator/=(double r) {
- if (time_internal::IsInfiniteDuration(*this) || r == 0.0) {
+ if (time_internal::IsInfiniteDuration(*this) || !IsValidDivisor(r)) {
const bool is_neg = (std::signbit(r) != 0) != (rep_hi_ < 0);
return *this = is_neg ? -InfiniteDuration() : InfiniteDuration();
}
diff --git a/absl/time/duration_test.cc b/absl/time/duration_test.cc
index 775da91e..61f3c5c0 100644
--- a/absl/time/duration_test.cc
+++ b/absl/time/duration_test.cc
@@ -803,6 +803,40 @@ TEST(Duration, DivisionByZero) {
EXPECT_EQ(-dbl_inf, absl::FDivDuration(-any_dur, zero));
}
+TEST(Duration, NaN) {
+ // Note that IEEE 754 does not define the behavior of a nan's sign when it is
+ // copied, so the code below allows for either + or - InfiniteDuration.
+#define TEST_NAN_HANDLING(NAME, NAN) \
+ do { \
+ const auto inf = absl::InfiniteDuration(); \
+ auto x = NAME(NAN); \
+ EXPECT_TRUE(x == inf || x == -inf); \
+ auto y = NAME(42); \
+ y *= NAN; \
+ EXPECT_TRUE(y == inf || y == -inf); \
+ auto z = NAME(42); \
+ z /= NAN; \
+ EXPECT_TRUE(z == inf || z == -inf); \
+ } while (0)
+
+ const double nan = std::numeric_limits<double>::quiet_NaN();
+ TEST_NAN_HANDLING(absl::Nanoseconds, nan);
+ TEST_NAN_HANDLING(absl::Microseconds, nan);
+ TEST_NAN_HANDLING(absl::Milliseconds, nan);
+ TEST_NAN_HANDLING(absl::Seconds, nan);
+ TEST_NAN_HANDLING(absl::Minutes, nan);
+ TEST_NAN_HANDLING(absl::Hours, nan);
+
+ TEST_NAN_HANDLING(absl::Nanoseconds, -nan);
+ TEST_NAN_HANDLING(absl::Microseconds, -nan);
+ TEST_NAN_HANDLING(absl::Milliseconds, -nan);
+ TEST_NAN_HANDLING(absl::Seconds, -nan);
+ TEST_NAN_HANDLING(absl::Minutes, -nan);
+ TEST_NAN_HANDLING(absl::Hours, -nan);
+
+#undef TEST_NAN_HANDLING
+}
+
TEST(Duration, Range) {
const absl::Duration range = ApproxYears(100 * 1e9);
const absl::Duration range_future = range;
diff --git a/absl/time/internal/cctz/include/cctz/civil_time_detail.h b/absl/time/internal/cctz/include/cctz/civil_time_detail.h
index 0cf27ddb..1c5d0970 100644
--- a/absl/time/internal/cctz/include/cctz/civil_time_detail.h
+++ b/absl/time/internal/cctz/include/cctz/civil_time_detail.h
@@ -386,12 +386,12 @@ class civil_time {
: civil_time(ct.f_) {}
// Factories for the maximum/minimum representable civil_time.
- static CONSTEXPR_F civil_time max() {
- const auto max_year = std::numeric_limits<std::int_least64_t>::max();
+ static CONSTEXPR_F civil_time (max)() {
+ const auto max_year = (std::numeric_limits<std::int_least64_t>::max)();
return civil_time(max_year, 12, 31, 23, 59, 59);
}
- static CONSTEXPR_F civil_time min() {
- const auto min_year = std::numeric_limits<std::int_least64_t>::min();
+ static CONSTEXPR_F civil_time (min)() {
+ const auto min_year = (std::numeric_limits<std::int_least64_t>::min)();
return civil_time(min_year, 1, 1, 0, 0, 0);
}
@@ -409,7 +409,7 @@ class civil_time {
return *this;
}
CONSTEXPR_M civil_time& operator-=(diff_t n) noexcept {
- if (n != std::numeric_limits<diff_t>::min()) {
+ if (n != (std::numeric_limits<diff_t>::min)()) {
f_ = step(T{}, f_, -n);
} else {
f_ = step(T{}, step(T{}, f_, -(n + 1)), 1);
diff --git a/absl/time/time.h b/absl/time/time.h
index 3fa9378f..ae3b3fad 100644
--- a/absl/time/time.h
+++ b/absl/time/time.h
@@ -69,6 +69,7 @@
#include <winsock2.h>
#endif
#include <chrono> // NOLINT(build/c++11)
+#include <cmath>
#include <cstdint>
#include <ctime>
#include <ostream>
@@ -411,10 +412,12 @@ Duration Milliseconds(T n) {
}
template <typename T, time_internal::EnableIfFloat<T> = 0>
Duration Seconds(T n) {
- if (n >= 0) {
+ if (n >= 0) { // Note: `NaN >= 0` is false.
if (n >= (std::numeric_limits<int64_t>::max)()) return InfiniteDuration();
return time_internal::MakePosDoubleDuration(n);
} else {
+ if (std::isnan(n))
+ return std::signbit(n) ? -InfiniteDuration() : InfiniteDuration();
if (n <= (std::numeric_limits<int64_t>::min)()) return -InfiniteDuration();
return -time_internal::MakePosDoubleDuration(-n);
}
@@ -1438,10 +1441,10 @@ T ToChronoDuration(Duration d) {
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();
+ 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();
+ if (v > (std::numeric_limits<Rep>::max)()) return (T::max)();
+ if (v < (std::numeric_limits<Rep>::min)()) return (T::min)();
return T{v};
}
diff --git a/absl/types/BUILD.bazel b/absl/types/BUILD.bazel
index d56fea6e..2e490009 100644
--- a/absl/types/BUILD.bazel
+++ b/absl/types/BUILD.bazel
@@ -15,7 +15,7 @@
#
load(
- "//absl:copts.bzl",
+ "//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
"ABSL_TEST_COPTS",
"ABSL_EXCEPTIONS_FLAG",
diff --git a/absl/types/CMakeLists.txt b/absl/types/CMakeLists.txt
index e8620766..05097d9e 100644
--- a/absl/types/CMakeLists.txt
+++ b/absl/types/CMakeLists.txt
@@ -13,216 +13,306 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-
-list(APPEND TYPES_PUBLIC_HEADERS
- "any.h"
- "bad_any_cast.h"
- "bad_optional_access.h"
- "optional.h"
- "span.h"
- "variant.h"
-)
-
-
-# any library
-absl_header_library(
- TARGET
- absl_any
- PUBLIC_LIBRARIES
- absl::bad_any_cast
- absl::base
- absl::meta
- absl::utility
- PRIVATE_COMPILE_FLAGS
- ${ABSL_EXCEPTIONS_FLAG}
- EXPORT_NAME
+absl_cc_library(
+ NAME
any
-)
-
-# span library
-absl_header_library(
- TARGET
- absl_span
- PUBLIC_LIBRARIES
+ HDRS
+ "any.h"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::bad_any_cast
+ absl::config
+ absl::core_headers
+ absl::type_traits
absl::utility
- EXPORT_NAME
- span
-)
-
-
-# bad_any_cast library
-list(APPEND BAD_ANY_CAST_SRC
- "bad_any_cast.cc"
- ${TYPES_PUBLIC_HEADERS}
+ PUBLIC
)
-absl_library(
- TARGET
- absl_bad_any_cast
- SOURCES
- ${BAD_ANY_CAST_SRC}
- PUBLIC_LIBRARIES
- EXPORT_NAME
+absl_cc_library(
+ NAME
bad_any_cast
+ HDRS
+ "bad_any_cast.h"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::bad_any_cast_impl
+ absl::config
+ PUBLIC
)
-
-# optional library
-list(APPEND OPTIONAL_SRC
- "optional.cc"
-)
-
-absl_library(
- TARGET
- absl_optional
- SOURCES
- ${OPTIONAL_SRC}
- PUBLIC_LIBRARIES
- absl::bad_optional_access
- absl::base
- absl::memory
- absl::meta
- absl::utility
- EXPORT_NAME
- optional
-)
-
-
-set(BAD_OPTIONAL_ACCESS_SRC "bad_optional_access.cc")
-set(BAD_OPTIONAL_ACCESS_LIBRARIES absl::base)
-
-absl_library(
- TARGET
- absl_bad_optional_access
- SOURCES
- ${BAD_OPTIONAL_ACCESS_SRC}
- PUBLIC_LIBRARIES
- ${BAD_OPTIONAL_ACCESS_PUBLIC_LIBRARIES}
- EXPORT_NAME
- bad_optional_access
-)
-
-# variant library
-absl_library(
- TARGET
- absl_variant
- SOURCES
- "bad_variant_access.h" "bad_variant_access.cc" "variant.h" "internal/variant.h"
- PUBLIC_LIBRARIES
- absl::base absl::meta absl::utility
- PRIVATE_COMPILE_FLAGS
+absl_cc_library(
+ NAME
+ bad_any_cast_impl
+ SRCS
+ "bad_any_cast.h"
+ "bad_any_cast.cc"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
${ABSL_EXCEPTIONS_FLAG}
- EXPORT_NAME
- variant
+ LINKOPTS
+ ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+ DEPS
+ absl::base
+ absl::config
)
-#
-## TESTS
-#
-
-
-# test any_test
-set(ANY_TEST_SRC "any_test.cc")
-set(ANY_TEST_PUBLIC_LIBRARIES absl::base absl_internal_throw_delegate absl::any absl::bad_any_cast absl::test_instance_tracker)
-
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
any_test
- SOURCES
- ${ANY_TEST_SRC}
- PUBLIC_LIBRARIES
- ${ANY_TEST_PUBLIC_LIBRARIES}
- PRIVATE_COMPILE_FLAGS
+ SRCS
+ "any_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
${ABSL_EXCEPTIONS_FLAG}
+ LINKOPTS
+ ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+ DEPS
+ absl::any
+ absl::base
+ absl::config
+ absl::exception_testing
+ absl::test_instance_tracker
+ gmock_main
)
-
-# test any_test_noexceptions
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
any_test_noexceptions
- SOURCES
- ${ANY_TEST_SRC}
- PUBLIC_LIBRARIES
- ${ANY_TEST_PUBLIC_LIBRARIES}
-)
-
-# test any_exception_safety_test
-set(ANY_EXCEPTION_SAFETY_TEST_SRC "any_exception_safety_test.cc")
-set(ANY_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES
- absl::any
- absl::base
- absl_internal_exception_safety_testing
+ SRCS
+ "any_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::any
+ absl::base
+ absl::config
+ absl::exception_testing
+ absl::test_instance_tracker
+ gmock_main
)
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
any_exception_safety_test
- SOURCES
- ${ANY_EXCEPTION_SAFETY_TEST_SRC}
- PUBLIC_LIBRARIES
- ${ANY_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES}
- PRIVATE_COMPILE_FLAGS
+ SRCS
+ "any_exception_safety_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
${ABSL_EXCEPTIONS_FLAG}
+ LINKOPTS
+ ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+ DEPS
+ absl::any
+ absl::exception_safety_testing
+ gmock_main
)
+absl_cc_library(
+ NAME
+ span
+ HDRS
+ "span.h"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::algorithm
+ absl::core_headers
+ absl::throw_delegate
+ absl::type_traits
+ PUBLIC
+)
-# test span_test
-set(SPAN_TEST_SRC "span_test.cc")
-set(SPAN_TEST_PUBLIC_LIBRARIES absl::base absl::strings absl_internal_throw_delegate absl::span absl::test_instance_tracker)
-
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
span_test
- SOURCES
- ${SPAN_TEST_SRC}
- PUBLIC_LIBRARIES
- ${SPAN_TEST_PUBLIC_LIBRARIES}
- PRIVATE_COMPILE_FLAGS
+ SRCS
+ "span_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
${ABSL_EXCEPTIONS_FLAG}
+ LINKOPTS
+ ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+ DEPS
+ absl::span
+ absl::base
+ absl::config
+ absl::core_headers
+ absl::exception_testing
+ absl::fixed_array
+ absl::inlined_vector
+ absl::hash_testing
+ absl::strings
+ gmock_main
)
-
-# test span_test_noexceptions
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
span_test_noexceptions
- SOURCES
- ${SPAN_TEST_SRC}
- PUBLIC_LIBRARIES
- ${SPAN_TEST_PUBLIC_LIBRARIES}
+ SRCS
+ "span_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::span
+ absl::base
+ absl::config
+ absl::core_headers
+ absl::exception_testing
+ absl::fixed_array
+ absl::inlined_vector
+ absl::hash_testing
+ absl::strings
+ gmock_main
)
+absl_cc_library(
+ NAME
+ optional
+ HDRS
+ "optional.h"
+ SRCS
+ "optional.cc"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::bad_optional_access
+ absl::config
+ absl::core_headers
+ absl::memory
+ absl::type_traits
+ absl::utility
+ PUBLIC
+)
+absl_cc_library(
+ NAME
+ bad_optional_access
+ HDRS
+ "bad_optional_access.h"
+ SRCS
+ "bad_optional_access.cc"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ ${ABSL_EXCEPTIONS_FLAG}
+ LINKOPTS
+ ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+ DEPS
+ absl::base
+ absl::config
+ PUBLIC
+)
-# test optional_test
-set(OPTIONAL_TEST_SRC "optional_test.cc")
-set(OPTIONAL_TEST_PUBLIC_LIBRARIES absl::base absl_internal_throw_delegate absl::optional absl_bad_optional_access)
+absl_cc_library(
+ NAME
+ bad_variant_access
+ HDRS
+ "bad_variant_access.h"
+ SRCS
+ "bad_variant_access.cc"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ ${ABSL_EXCEPTIONS_FLAG}
+ LINKOPTS
+ ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+ DEPS
+ absl::base
+ absl::config
+ PUBLIC
+)
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
optional_test
- SOURCES
- ${OPTIONAL_TEST_SRC}
- PUBLIC_LIBRARIES
- ${OPTIONAL_TEST_PUBLIC_LIBRARIES}
+ SRCS
+ "optional_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ ${ABSL_EXCEPTIONS_FLAG}
+ LINKOPTS
+ ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+ DEPS
+ absl::optional
+ absl::base
+ absl::config
+ absl::type_traits
+ absl::strings
+ gmock_main
+)
+
+absl_cc_test(
+ NAME
+ optional_exception_safety_test
+ SRCS
+ "optional_exception_safety_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ ${ABSL_EXCEPTIONS_FLAG}
+ LINKOPTS
+ ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+ DEPS
+ absl::optional
+ absl::exception_safety_testing
+ gmock_main
)
+absl_cc_library(
+ NAME
+ variant
+ HDRS
+ "variant.h"
+ SRCS
+ "internal/variant.h"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::bad_variant_access
+ absl::base_internal
+ absl::config
+ absl::core_headers
+ absl::type_traits
+ absl::utility
+ PUBLIC
+)
-# test optional_exception_safety_test
-set(OPTIONAL_EXCEPTION_SAFETY_TEST_SRC "optional_exception_safety_test.cc")
-set(OPTIONAL_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES
- absl::optional
- absl_internal_exception_safety_testing
+absl_cc_test(
+ NAME
+ variant_test
+ SRCS
+ "variant_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ ${ABSL_EXCEPTIONS_FLAG}
+ LINKOPTS
+ ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+ DEPS
+ absl::variant
+ absl::config
+ absl::core_headers
+ absl::memory
+ absl::type_traits
+ absl::strings
+ gmock_main
)
-absl_test(
- TARGET
- optional_exception_safety_test
- SOURCES
- ${OPTIONAL_EXCEPTION_SAFETY_TEST_SRC}
- PUBLIC_LIBRARIES
- ${OPTIONAL_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES}
- PRIVATE_COMPILE_FLAGS
+# TODO(cohenjon,zhangxy) Figure out why this test is failing on gcc 4.8
+if(CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.9)
+absl_cc_test(
+ NAME
+ variant_exception_safety_test
+ SRCS
+ "variant_exception_safety_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
${ABSL_EXCEPTIONS_FLAG}
+ LINKOPTS
+ ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+ DEPS
+ absl::variant
+ absl::config
+ absl::exception_safety_testing
+ absl::memory
+ gmock_main
)
+endif()
diff --git a/absl/types/internal/variant.h b/absl/types/internal/variant.h
index eff4fefe..477e5895 100644
--- a/absl/types/internal/variant.h
+++ b/absl/types/internal/variant.h
@@ -15,6 +15,7 @@
// Implementation details of absl/types/variant.h, pulled into a
// separate file to avoid cluttering the top of the API header with
// implementation details.
+//
#ifndef ABSL_TYPES_variant_internal_H_
#define ABSL_TYPES_variant_internal_H_
@@ -1234,23 +1235,29 @@ using VariantCopyBase = absl::conditional_t<
// Base that is dependent on whether or not the move-assign can be trivial.
template <class... T>
using VariantMoveAssignBase = absl::conditional_t<
- absl::disjunction<absl::conjunction<absl::is_move_assignable<Union<T...>>,
- std::is_move_constructible<Union<T...>>,
- std::is_destructible<Union<T...>>>,
- absl::negation<absl::conjunction<
- std::is_move_constructible<T>...,
- absl::is_move_assignable<T>...>>>::value,
+ absl::disjunction<
+ absl::conjunction<absl::is_move_assignable<Union<T...>>,
+ std::is_move_constructible<Union<T...>>,
+ std::is_destructible<Union<T...>>>,
+ absl::negation<absl::conjunction<std::is_move_constructible<T>...,
+ // Note: We're not qualifying this with
+ // absl:: because it doesn't compile
+ // under MSVC.
+ is_move_assignable<T>...>>>::value,
VariantCopyBase<T...>, VariantMoveAssignBaseNontrivial<T...>>;
// Base that is dependent on whether or not the copy-assign can be trivial.
template <class... T>
using VariantCopyAssignBase = absl::conditional_t<
- absl::disjunction<absl::conjunction<absl::is_copy_assignable<Union<T...>>,
- std::is_copy_constructible<Union<T...>>,
- std::is_destructible<Union<T...>>>,
- absl::negation<absl::conjunction<
- std::is_copy_constructible<T>...,
- absl::is_copy_assignable<T>...>>>::value,
+ absl::disjunction<
+ absl::conjunction<absl::is_copy_assignable<Union<T...>>,
+ std::is_copy_constructible<Union<T...>>,
+ std::is_destructible<Union<T...>>>,
+ absl::negation<absl::conjunction<std::is_copy_constructible<T>...,
+ // Note: We're not qualifying this with
+ // absl:: because it doesn't compile
+ // under MSVC.
+ is_copy_assignable<T>...>>>::value,
VariantMoveAssignBase<T...>, VariantCopyAssignBaseNontrivial<T...>>;
template <class... T>
diff --git a/absl/types/variant.h b/absl/types/variant.h
index 28aaef4f..48c5d7bf 100644
--- a/absl/types/variant.h
+++ b/absl/types/variant.h
@@ -82,7 +82,7 @@ namespace absl {
// absl::variant
// -----------------------------------------------------------------------------
//
-// An 'absl::variant` type is a form of type-safe union. An `absl::variant` --
+// An `absl::variant` type is a form of type-safe union. An `absl::variant` --
// except in exceptional cases -- always holds a value of one of its alternative
// types.
//
@@ -136,7 +136,7 @@ void swap(variant<Ts...>& v, variant<Ts...>& w) noexcept(noexcept(v.swap(w))) {
// variant_size
//
-// Returns the number of alterative types available for a given `absl::variant`
+// Returns the number of alternative types available for a given `absl::variant`
// type as a compile-time constant expression. As this is a class template, it
// is not generally useful for accessing the number of alternative types of
// any given `absl::variant` instance.
@@ -454,7 +454,7 @@ class variant<T0, Tn...> : private variant_internal::VariantBase<T0, Tn...> {
std::is_object<Tn>...>::value,
"Attempted to instantiate a variant containing a non-object "
"type.");
- // Intentionally not qualifing `negation` with `absl::` to work around a bug
+ // Intentionally not qualifying `negation` with `absl::` to work around a bug
// in MSVC 2015 with inline namespace and variadic template.
static_assert(absl::conjunction<negation<std::is_array<T0> >,
negation<std::is_array<Tn> >...>::value,
@@ -562,7 +562,7 @@ class variant<T0, Tn...> : private variant_internal::VariantBase<T0, Tn...> {
// Assignment Operators
- // Copy assignement operator
+ // Copy assignment operator
variant& operator=(const variant& other) = default;
// Move assignment operator
diff --git a/absl/utility/BUILD.bazel b/absl/utility/BUILD.bazel
index c01b49bc..5185ccd8 100644
--- a/absl/utility/BUILD.bazel
+++ b/absl/utility/BUILD.bazel
@@ -1,5 +1,5 @@
load(
- "//absl:copts.bzl",
+ "//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
"ABSL_TEST_COPTS",
)
diff --git a/absl/utility/CMakeLists.txt b/absl/utility/CMakeLists.txt
index dc3a6319..7fe34a5b 100644
--- a/absl/utility/CMakeLists.txt
+++ b/absl/utility/CMakeLists.txt
@@ -14,39 +14,31 @@
# limitations under the License.
#
-
-list(APPEND UTILITY_PUBLIC_HEADERS
- "utility.h"
-)
-
-absl_header_library(
- TARGET
- absl_utility
- PUBLIC_LIBRARIES
- absl::base
- EXPORT_NAME
+absl_cc_library(
+ NAME
utility
+ HDRS
+ "utility.h"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::base_internal
+ absl::config
+ absl::type_traits
+ PUBLIC
)
-
-#
-## TESTS
-#
-
-# test utility_test
-set(UTILITY_TEST_SRC "utility_test.cc")
-set(UTILITY_TEST_PUBLIC_LIBRARIES
- absl::base
- absl::memory
- absl::strings
- absl::utility
-)
-
-absl_test(
- TARGET
+absl_cc_test(
+ NAME
utility_test
- SOURCES
- ${UTILITY_TEST_SRC}
- PUBLIC_LIBRARIES
- ${UTILITY_TEST_PUBLIC_LIBRARIES}
+ SRCS
+ "utility_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::utility
+ absl::core_headers
+ absl::memory
+ absl::strings
+ gmock_main
)