summaryrefslogtreecommitdiff
path: root/absl
diff options
context:
space:
mode:
Diffstat (limited to 'absl')
-rw-r--r--absl/algorithm/container.h2
-rw-r--r--absl/base/const_init.h1
-rw-r--r--absl/base/dynamic_annotations.h1
-rw-r--r--absl/base/internal/cycleclock.h1
-rw-r--r--absl/base/internal/low_level_alloc.h1
-rw-r--r--absl/base/internal/low_level_alloc_test.cc1
-rw-r--r--absl/base/internal/low_level_scheduling.h3
-rw-r--r--absl/base/internal/raw_logging.h1
-rw-r--r--absl/base/internal/scoped_set_env.cc6
-rw-r--r--absl/base/internal/scoped_set_env_test.cc4
-rw-r--r--absl/base/internal/thread_identity.h1
-rw-r--r--absl/base/internal/unscaledcycleclock.h2
-rw-r--r--absl/base/log_severity.h1
-rw-r--r--absl/base/spinlock_test_common.cc2
-rw-r--r--absl/base/thread_annotations.h2
-rw-r--r--absl/compiler_config_setting.bzl1
-rw-r--r--absl/container/BUILD.bazel10
-rw-r--r--absl/container/CMakeLists.txt12
-rw-r--r--absl/container/fixed_array.h1
-rw-r--r--absl/container/flat_hash_map_test.cc7
-rw-r--r--absl/container/inlined_vector.h180
-rw-r--r--absl/container/internal/hashtablez_sampler.h1
-rw-r--r--absl/container/internal/inlined_vector.h130
-rw-r--r--absl/container/internal/raw_hash_set_test.cc2
-rw-r--r--absl/copts/GENERATED_AbseilCopts.cmake1
-rw-r--r--absl/copts/GENERATED_copts.bzl1
-rw-r--r--absl/copts/copts.py5
-rw-r--r--absl/debugging/internal/address_is_readable.h1
-rw-r--r--absl/debugging/internal/demangle_test.cc1
-rw-r--r--absl/debugging/internal/stacktrace_x86-inl.inc1
-rw-r--r--absl/debugging/leak_check.cc1
-rw-r--r--absl/debugging/stacktrace.cc1
-rw-r--r--absl/hash/hash.h1
-rw-r--r--absl/hash/hash_test.cc1
-rw-r--r--absl/hash/internal/city.h1
-rw-r--r--absl/meta/type_traits.h61
-rw-r--r--absl/meta/type_traits_test.cc81
-rw-r--r--absl/numeric/int128.h1
-rw-r--r--absl/strings/BUILD.bazel1
-rw-r--r--absl/strings/escaping.h2
-rw-r--r--absl/strings/internal/str_format/arg.h2
-rw-r--r--absl/strings/internal/str_format/convert_test.cc1
-rw-r--r--absl/strings/internal/str_format/extension.h1
-rw-r--r--absl/strings/internal/str_format/extension_test.cc1
-rw-r--r--absl/strings/internal/str_format/output_test.cc1
-rw-r--r--absl/strings/internal/utf8.h1
-rw-r--r--absl/strings/str_cat.h1
-rw-r--r--absl/strings/str_format.h1
-rw-r--r--absl/strings/str_split.h1
-rw-r--r--absl/strings/string_view.h2
-rw-r--r--absl/strings/substitute.h1
-rw-r--r--absl/synchronization/internal/create_thread_identity.h1
-rw-r--r--absl/synchronization/internal/kernel_timeout.h2
-rw-r--r--absl/synchronization/internal/per_thread_sem.cc1
-rw-r--r--absl/synchronization/internal/per_thread_sem.h1
-rw-r--r--absl/synchronization/internal/waiter.cc2
-rw-r--r--absl/synchronization/mutex.cc1
-rw-r--r--absl/synchronization/mutex.h4
-rw-r--r--absl/synchronization/mutex_test.cc6
-rw-r--r--absl/synchronization/notification.h1
-rw-r--r--absl/time/civil_time.h1
-rw-r--r--absl/time/duration.cc1
-rw-r--r--absl/time/internal/cctz/src/time_zone_lookup.cc2
-rw-r--r--absl/time/time.cc1
-rw-r--r--absl/time/time.h3
-rw-r--r--absl/types/any_exception_safety_test.cc1
-rw-r--r--absl/types/internal/variant.h5
-rw-r--r--absl/types/optional.h19
-rw-r--r--absl/types/optional_test.cc2
-rw-r--r--absl/types/variant.h17
-rw-r--r--absl/types/variant_exception_safety_test.cc9
-rw-r--r--absl/types/variant_test.cc1
-rw-r--r--absl/utility/utility.h1
73 files changed, 444 insertions, 185 deletions
diff --git a/absl/algorithm/container.h b/absl/algorithm/container.h
index 7348d632..752e47b2 100644
--- a/absl/algorithm/container.h
+++ b/absl/algorithm/container.h
@@ -36,7 +36,6 @@
// For template parameter and variable naming, `C` indicates the container type
// to which the function is applied, `Pred` indicates the predicate object type
// to be used by the function and `T` indicates the applicable element type.
-//
#ifndef ABSL_ALGORITHM_CONTAINER_H_
#define ABSL_ALGORITHM_CONTAINER_H_
@@ -648,7 +647,6 @@ container_algorithm_internal::ContainerIter<C> c_generate_n(C& c, Size n,
// and `unique()` are omitted, because it's not clear whether or not such
// functions should call erase on their supplied sequences afterwards. Either
// behavior would be surprising for a different set of users.
-//
// c_remove_copy()
//
diff --git a/absl/base/const_init.h b/absl/base/const_init.h
index 1b2b8c2b..17858a77 100644
--- a/absl/base/const_init.h
+++ b/absl/base/const_init.h
@@ -60,7 +60,6 @@
//
// The absl::kConstInit tag should only be used to define objects with static
// or thread_local storage duration.
-//
namespace absl {
diff --git a/absl/base/dynamic_annotations.h b/absl/base/dynamic_annotations.h
index cdeb18c2..ac33df9e 100644
--- a/absl/base/dynamic_annotations.h
+++ b/absl/base/dynamic_annotations.h
@@ -139,6 +139,7 @@
#define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) /* empty */
#define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) /* empty */
#endif /* DYNAMIC_ANNOTATIONS_ENABLED || MEMORY_SANITIZER */
+
/* TODO(delesley) -- Replace __CLANG_SUPPORT_DYN_ANNOTATION__ with the
appropriate feature ID. */
#if defined(__clang__) && (!defined(SWIG)) \
diff --git a/absl/base/internal/cycleclock.h b/absl/base/internal/cycleclock.h
index 7874db71..794564e1 100644
--- a/absl/base/internal/cycleclock.h
+++ b/absl/base/internal/cycleclock.h
@@ -28,7 +28,6 @@
// not necessarily "CPU cycles" and code should not rely on that behavior, even
// if experimentally observed.
//
-//
// An arbitrary offset may have been added to the counter at power on.
//
// On some platforms, the rate and offset of the counter may differ
diff --git a/absl/base/internal/low_level_alloc.h b/absl/base/internal/low_level_alloc.h
index f83c7bc8..b35673de 100644
--- a/absl/base/internal/low_level_alloc.h
+++ b/absl/base/internal/low_level_alloc.h
@@ -119,4 +119,5 @@ class LowLevelAlloc {
} // namespace base_internal
} // namespace absl
+
#endif // ABSL_BASE_INTERNAL_LOW_LEVEL_ALLOC_H_
diff --git a/absl/base/internal/low_level_alloc_test.cc b/absl/base/internal/low_level_alloc_test.cc
index d2d31820..34a080cb 100644
--- a/absl/base/internal/low_level_alloc_test.cc
+++ b/absl/base/internal/low_level_alloc_test.cc
@@ -137,6 +137,7 @@ static void Test(bool use_new_arena, bool call_malloc_hook, int n) {
TEST_ASSERT(LowLevelAlloc::DeleteArena(arena));
}
}
+
// LowLevelAlloc is designed to be safe to call before main().
static struct BeforeMain {
BeforeMain() {
diff --git a/absl/base/internal/low_level_scheduling.h b/absl/base/internal/low_level_scheduling.h
index 2a5a3847..0fcc8d3b 100644
--- a/absl/base/internal/low_level_scheduling.h
+++ b/absl/base/internal/low_level_scheduling.h
@@ -86,6 +86,7 @@ class SchedulingGuard {
//------------------------------------------------------------------------------
// End of public interfaces.
//------------------------------------------------------------------------------
+
inline bool SchedulingGuard::ReschedulingIsAllowed() {
return false;
}
@@ -98,7 +99,7 @@ inline void SchedulingGuard::EnableRescheduling(bool /* disable_result */) {
return;
}
-
} // namespace base_internal
} // namespace absl
+
#endif // ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_
diff --git a/absl/base/internal/raw_logging.h b/absl/base/internal/raw_logging.h
index 4cbbbe59..6a4c0936 100644
--- a/absl/base/internal/raw_logging.h
+++ b/absl/base/internal/raw_logging.h
@@ -38,6 +38,7 @@
// ABSL_RAW_LOG(ERROR, "Failed foo with %i: %s", status, error);
// This will print an almost standard log line like this to stderr only:
// E0821 211317 file.cc:123] RAW: Failed foo with 22: bad_file
+
#define ABSL_RAW_LOG(severity, ...) \
do { \
constexpr const char* absl_raw_logging_internal_basename = \
diff --git a/absl/base/internal/scoped_set_env.cc b/absl/base/internal/scoped_set_env.cc
index 9b164124..3ac3f68d 100644
--- a/absl/base/internal/scoped_set_env.cc
+++ b/absl/base/internal/scoped_set_env.cc
@@ -33,7 +33,7 @@ const int kMaxEnvVarValueSize = 1024;
void SetEnvVar(const char* name, const char* value) {
#ifdef _WIN32
- SetEnvironmentVariable(name, value);
+ SetEnvironmentVariableA(name, value);
#else
if (value == nullptr) {
::unsetenv(name);
@@ -49,7 +49,7 @@ ScopedSetEnv::ScopedSetEnv(const char* var_name, const char* new_value)
: var_name_(var_name), was_unset_(false) {
#ifdef _WIN32
char buf[kMaxEnvVarValueSize];
- auto get_res = GetEnvironmentVariable(var_name_.c_str(), buf, sizeof(buf));
+ auto get_res = GetEnvironmentVariableA(var_name_.c_str(), buf, sizeof(buf));
ABSL_INTERNAL_CHECK(get_res < sizeof(buf), "value exceeds buffer size");
if (get_res == 0) {
@@ -58,7 +58,7 @@ ScopedSetEnv::ScopedSetEnv(const char* var_name, const char* new_value)
old_value_.assign(buf, get_res);
}
- SetEnvironmentVariable(var_name_.c_str(), new_value);
+ SetEnvironmentVariableA(var_name_.c_str(), new_value);
#else
const char* val = ::getenv(var_name_.c_str());
if (val == nullptr) {
diff --git a/absl/base/internal/scoped_set_env_test.cc b/absl/base/internal/scoped_set_env_test.cc
index 4bd68c48..5cbad246 100644
--- a/absl/base/internal/scoped_set_env_test.cc
+++ b/absl/base/internal/scoped_set_env_test.cc
@@ -26,8 +26,8 @@ using absl::base_internal::ScopedSetEnv;
std::string GetEnvVar(const char* name) {
#ifdef _WIN32
char buf[1024];
- auto get_res = GetEnvironmentVariable(name, buf, sizeof(buf));
- if (get_res == sizeof(buf)) {
+ auto get_res = GetEnvironmentVariableA(name, buf, sizeof(buf));
+ if (get_res >= sizeof(buf)) {
return "TOO_BIG";
}
diff --git a/absl/base/internal/thread_identity.h b/absl/base/internal/thread_identity.h
index dde3e010..b34674a6 100644
--- a/absl/base/internal/thread_identity.h
+++ b/absl/base/internal/thread_identity.h
@@ -237,4 +237,5 @@ inline ThreadIdentity* CurrentThreadIdentityIfPresent() {
} // namespace base_internal
} // namespace absl
+
#endif // ABSL_BASE_INTERNAL_THREAD_IDENTITY_H_
diff --git a/absl/base/internal/unscaledcycleclock.h b/absl/base/internal/unscaledcycleclock.h
index d5e186a9..58950cc2 100644
--- a/absl/base/internal/unscaledcycleclock.h
+++ b/absl/base/internal/unscaledcycleclock.h
@@ -83,6 +83,7 @@
defined(_M_IX86) || defined(_M_X64))
#define ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY
#endif
+
namespace absl {
namespace time_internal {
class UnscaledCycleClockWrapperForGetCurrentTime;
@@ -114,6 +115,7 @@ class UnscaledCycleClock {
} // namespace base_internal
} // namespace absl
+
#endif // ABSL_USE_UNSCALED_CYCLECLOCK
#endif // ABSL_BASE_INTERNAL_UNSCALEDCYCLECLOCK_H_
diff --git a/absl/base/log_severity.h b/absl/base/log_severity.h
index 4b9833eb..b19a7ffa 100644
--- a/absl/base/log_severity.h
+++ b/absl/base/log_severity.h
@@ -11,7 +11,6 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-//
#ifndef ABSL_BASE_INTERNAL_LOG_SEVERITY_H_
#define ABSL_BASE_INTERNAL_LOG_SEVERITY_H_
diff --git a/absl/base/spinlock_test_common.cc b/absl/base/spinlock_test_common.cc
index b32cea29..e62b2eae 100644
--- a/absl/base/spinlock_test_common.cc
+++ b/absl/base/spinlock_test_common.cc
@@ -54,6 +54,7 @@ namespace {
static constexpr int kArrayLength = 10;
static uint32_t values[kArrayLength];
+
static SpinLock static_spinlock(base_internal::kLinkerInitialized);
static SpinLock static_cooperative_spinlock(
base_internal::kLinkerInitialized,
@@ -189,6 +190,7 @@ TEST(SpinLock, WaitCyclesEncoding) {
SpinLockTest::DecodeWaitCycles(before_max_value);
EXPECT_GT(expected_max_value_decoded, before_max_value_decoded);
}
+
TEST(SpinLockWithThreads, StaticSpinLock) {
ThreadedTest(&static_spinlock);
}
diff --git a/absl/base/thread_annotations.h b/absl/base/thread_annotations.h
index a8162d41..0b2c306c 100644
--- a/absl/base/thread_annotations.h
+++ b/absl/base/thread_annotations.h
@@ -21,7 +21,6 @@
// code. The annotations can also help program analysis tools to identify
// potential thread safety issues.
//
-//
// These annotations are implemented using compiler attributes. Using the macros
// defined here instead of raw attributes allow for portability and future
// compatibility.
@@ -34,6 +33,7 @@
#ifndef ABSL_BASE_THREAD_ANNOTATIONS_H_
#define ABSL_BASE_THREAD_ANNOTATIONS_H_
+
#if defined(__clang__)
#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
#else
diff --git a/absl/compiler_config_setting.bzl b/absl/compiler_config_setting.bzl
index e03f94ec..66962294 100644
--- a/absl/compiler_config_setting.bzl
+++ b/absl/compiler_config_setting.bzl
@@ -12,7 +12,6 @@
# 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.
-#
"""Creates config_setting that allows selecting based on 'compiler' value."""
diff --git a/absl/container/BUILD.bazel b/absl/container/BUILD.bazel
index b6592ca5..cd914baf 100644
--- a/absl/container/BUILD.bazel
+++ b/absl/container/BUILD.bazel
@@ -112,10 +112,20 @@ cc_test(
)
cc_library(
+ name = "inlined_vector_internal",
+ hdrs = ["internal/inlined_vector.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ deps = [
+ "//absl/meta:type_traits",
+ ],
+)
+
+cc_library(
name = "inlined_vector",
hdrs = ["inlined_vector.h"],
copts = ABSL_DEFAULT_COPTS,
deps = [
+ ":inlined_vector_internal",
"//absl/algorithm",
"//absl/base:core_headers",
"//absl/base:throw_delegate",
diff --git a/absl/container/CMakeLists.txt b/absl/container/CMakeLists.txt
index 76542be1..292fea2a 100644
--- a/absl/container/CMakeLists.txt
+++ b/absl/container/CMakeLists.txt
@@ -109,6 +109,18 @@ absl_cc_test(
absl_cc_library(
NAME
+ inlined_vector_internal
+ HDRS
+ "internal/inlined_vector.h"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::type_traits
+ PUBLIC
+)
+
+absl_cc_library(
+ NAME
inlined_vector
HDRS
"inlined_vector.h"
diff --git a/absl/container/fixed_array.h b/absl/container/fixed_array.h
index 0161d0a9..2a8240ae 100644
--- a/absl/container/fixed_array.h
+++ b/absl/container/fixed_array.h
@@ -515,4 +515,5 @@ void FixedArray<T, N, A>::NonEmptyInlinedStorage::AnnotateDestruct(
static_cast<void>(n); // Mark used when not in asan mode
}
} // namespace absl
+
#endif // ABSL_CONTAINER_FIXED_ARRAY_H_
diff --git a/absl/container/flat_hash_map_test.cc b/absl/container/flat_hash_map_test.cc
index bae5c15d..ebcb560f 100644
--- a/absl/container/flat_hash_map_test.cc
+++ b/absl/container/flat_hash_map_test.cc
@@ -206,7 +206,9 @@ TEST(FlatHashMap, MergeExtractInsert) {
m.insert(std::move(node));
EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 17), Pair(2, 9)));
}
-#if !defined(__ANDROID__) && !defined(__APPLE__) && !defined(__EMSCRIPTEN__)
+
+#if (defined(ABSL_HAVE_STD_ANY) || !defined(_LIBCPP_VERSION)) && \
+ !defined(__EMSCRIPTEN__)
TEST(FlatHashMap, Any) {
absl::flat_hash_map<int, absl::any> m;
m.emplace(1, 7);
@@ -237,7 +239,8 @@ TEST(FlatHashMap, Any) {
ASSERT_NE(it2, m2.end());
EXPECT_EQ(7, it2->second);
}
-#endif // __ANDROID__
+#endif // (defined(ABSL_HAVE_STD_ANY) || !defined(_LIBCPP_VERSION)) &&
+ // !defined(__EMSCRIPTEN__)
} // namespace
} // namespace container_internal
diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h
index 80929e36..68308750 100644
--- a/absl/container/inlined_vector.h
+++ b/absl/container/inlined_vector.h
@@ -1,4 +1,4 @@
-// Copyright 2018 The Abseil Authors.
+// Copyright 2019 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.
@@ -50,6 +50,7 @@
#include "absl/base/internal/throw_delegate.h"
#include "absl/base/optimization.h"
#include "absl/base/port.h"
+#include "absl/container/internal/inlined_vector.h"
#include "absl/memory/memory.h"
namespace absl {
@@ -65,10 +66,10 @@ 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 GetInlinedCapacity() {
- return static_cast<typename A::size_type>(N);
- }
+ using Storage = inlined_vector_internal::InlinedVectorStorage<T, N, A>;
+ using Tag = typename Storage::Tag;
+ using AllocatorAndTag = typename Storage::AllocatorAndTag;
+ using Allocation = typename Storage::Allocation;
template <typename Iterator>
using IsAtLeastForwardIterator = std::is_convertible<
@@ -83,21 +84,21 @@ class InlinedVector {
using DisableIfAtLeastForwardIterator =
absl::enable_if_t<!IsAtLeastForwardIterator<Iterator>::value>;
- using rvalue_reference = typename A::value_type&&;
+ using rvalue_reference = typename Storage::rvalue_reference;
public:
- using allocator_type = A;
- using value_type = typename allocator_type::value_type;
- using pointer = typename allocator_type::pointer;
- using const_pointer = typename allocator_type::const_pointer;
- using reference = typename allocator_type::reference;
- using const_reference = typename allocator_type::const_reference;
- using size_type = typename allocator_type::size_type;
- using difference_type = typename allocator_type::difference_type;
- using iterator = pointer;
- using const_iterator = const_pointer;
- using reverse_iterator = std::reverse_iterator<iterator>;
- using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+ using allocator_type = typename Storage::allocator_type;
+ using value_type = typename Storage::value_type;
+ using pointer = typename Storage::pointer;
+ using const_pointer = typename Storage::const_pointer;
+ using reference = typename Storage::reference;
+ using const_reference = typename Storage::const_reference;
+ using size_type = typename Storage::size_type;
+ using difference_type = typename Storage::difference_type;
+ using iterator = typename Storage::iterator;
+ using const_iterator = typename Storage::const_iterator;
+ using reverse_iterator = typename Storage::reverse_iterator;
+ using const_reverse_iterator = typename Storage::const_reverse_iterator;
// ---------------------------------------------------------------------------
// InlinedVector Constructors and Destructor
@@ -105,30 +106,30 @@ class InlinedVector {
// Creates an empty inlined vector with a default initialized allocator.
InlinedVector() noexcept(noexcept(allocator_type()))
- : allocator_and_tag_(allocator_type()) {}
+ : storage_(allocator_type()) {}
// Creates an empty inlined vector with a specified allocator.
explicit InlinedVector(const allocator_type& alloc) noexcept
- : allocator_and_tag_(alloc) {}
+ : storage_(alloc) {}
// Creates an inlined vector with `n` copies of `value_type()`.
explicit InlinedVector(size_type n,
const allocator_type& alloc = allocator_type())
- : allocator_and_tag_(alloc) {
+ : storage_(alloc) {
InitAssign(n);
}
// Creates an inlined vector with `n` copies of `v`.
InlinedVector(size_type n, const_reference v,
const allocator_type& alloc = allocator_type())
- : allocator_and_tag_(alloc) {
+ : storage_(alloc) {
InitAssign(n, v);
}
// Creates an inlined vector of copies of the values in `list`.
InlinedVector(std::initializer_list<value_type> list,
const allocator_type& alloc = allocator_type())
- : allocator_and_tag_(alloc) {
+ : storage_(alloc) {
AppendForwardRange(list.begin(), list.end());
}
@@ -142,7 +143,7 @@ class InlinedVector {
EnableIfAtLeastForwardIterator<ForwardIterator>* = nullptr>
InlinedVector(ForwardIterator first, ForwardIterator last,
const allocator_type& alloc = allocator_type())
- : allocator_and_tag_(alloc) {
+ : storage_(alloc) {
AppendForwardRange(first, last);
}
@@ -152,7 +153,7 @@ class InlinedVector {
DisableIfAtLeastForwardIterator<InputIterator>* = nullptr>
InlinedVector(InputIterator first, InputIterator last,
const allocator_type& alloc = allocator_type())
- : allocator_and_tag_(alloc) {
+ : storage_(alloc) {
std::copy(first, last, std::back_inserter(*this));
}
@@ -162,7 +163,7 @@ class InlinedVector {
// Creates a copy of an `other` inlined vector using a specified allocator.
InlinedVector(const InlinedVector& other, const allocator_type& alloc)
- : allocator_and_tag_(alloc) {
+ : storage_(alloc) {
reserve(other.size());
if (allocated()) {
UninitializedCopy(other.begin(), other.end(), allocated_space());
@@ -191,7 +192,7 @@ class InlinedVector {
InlinedVector(InlinedVector&& other) noexcept(
absl::allocator_is_nothrow<allocator_type>::value ||
std::is_nothrow_move_constructible<value_type>::value)
- : allocator_and_tag_(other.allocator()) {
+ : storage_(other.allocator()) {
if (other.allocated()) {
// We can just steal the underlying buffer from the source.
// That leaves the source empty, so we clear its size.
@@ -222,7 +223,7 @@ class InlinedVector {
// ownership of `other`'s allocated memory.
InlinedVector(InlinedVector&& other, const allocator_type& alloc) noexcept(
absl::allocator_is_nothrow<allocator_type>::value)
- : allocator_and_tag_(alloc) {
+ : storage_(alloc) {
if (other.allocated()) {
if (alloc == other.allocator()) {
// We can just steal the allocation from the source.
@@ -282,7 +283,8 @@ class InlinedVector {
// will no longer be inlined and `capacity()` will equal its capacity on the
// allocated heap.
size_type capacity() const noexcept {
- return allocated() ? allocation().capacity() : GetInlinedCapacity();
+ return allocated() ? allocation().capacity()
+ : Storage::GetInlinedCapacity();
}
// `InlinedVector::data()`
@@ -800,19 +802,19 @@ class InlinedVector {
// `InlinedVector::shrink_to_fit()`
//
// Reduces memory usage by freeing unused memory. After this call, calls to
- // `capacity()` will be equal to `(std::max)(GetInlinedCapacity(), size())`.
+ // `capacity()` will be equal to `max(Storage::GetInlinedCapacity(), size())`.
//
- // If `size() <= GetInlinedCapacity()` and the elements are currently stored
- // on the heap, they will be moved to the inlined storage and the heap memory
- // will be deallocated.
+ // If `size() <= Storage::GetInlinedCapacity()` and the elements are currently
+ // stored on the heap, they will be moved to the inlined storage and the heap
+ // memory will be deallocated.
//
- // If `size() > GetInlinedCapacity()` and `size() < capacity()` the elements
- // will be moved to a smaller heap allocation.
+ // If `size() > Storage::GetInlinedCapacity()` and `size() < capacity()` the
+ // elements will be moved to a smaller heap allocation.
void shrink_to_fit() {
const auto s = size();
if (ABSL_PREDICT_FALSE(!allocated() || s == capacity())) return;
- if (s <= GetInlinedCapacity()) {
+ if (s <= Storage::GetInlinedCapacity()) {
// Move the elements to the inlined storage.
// We have to do this using a temporary, because `inlined_storage` and
// `allocation_storage` are in a union field.
@@ -845,88 +847,33 @@ class InlinedVector {
template <typename H, typename TheT, size_t TheN, typename TheA>
friend auto AbslHashValue(H h, const InlinedVector<TheT, TheN, TheA>& v) -> H;
- // Holds whether the vector is allocated or not in the lowest bit and the size
- // in the high bits:
- // `size_ = (size << 1) | is_allocated;`
- class Tag {
- public:
- Tag() : size_(0) {}
- size_type size() const { return size_ / 2; }
- void add_size(size_type n) { size_ += n * 2; }
- void set_inline_size(size_type n) { size_ = n * 2; }
- void set_allocated_size(size_type n) { size_ = (n * 2) + 1; }
- bool allocated() const { return size_ % 2; }
-
- private:
- size_type size_;
- };
-
- // Derives from `allocator_type` to use the empty base class optimization.
- // If the `allocator_type` is stateless, we can store our instance for free.
- class AllocatorAndTag : private allocator_type {
- public:
- explicit AllocatorAndTag(const allocator_type& a) : allocator_type(a) {}
-
- Tag& tag() { return tag_; }
- const Tag& tag() const { return tag_; }
-
- allocator_type& allocator() { return *this; }
- const allocator_type& allocator() const { return *this; }
-
- private:
- Tag tag_;
- };
-
- class Allocation {
- public:
- Allocation(allocator_type& a, size_type capacity)
- : capacity_(capacity), buffer_(Create(a, capacity)) {}
-
- void Dealloc(allocator_type& a) {
- std::allocator_traits<allocator_type>::deallocate(a, buffer_, capacity_);
- }
-
- size_type capacity() const { return capacity_; }
-
- const_pointer buffer() const { return buffer_; }
-
- pointer buffer() { return buffer_; }
+ const Tag& tag() const { return storage_.allocator_and_tag_.tag(); }
- private:
- static pointer Create(allocator_type& a, size_type n) {
- return std::allocator_traits<allocator_type>::allocate(a, n);
- }
-
- size_type capacity_;
- pointer buffer_;
- };
-
- const Tag& tag() const { return allocator_and_tag_.tag(); }
-
- Tag& tag() { return allocator_and_tag_.tag(); }
+ Tag& tag() { return storage_.allocator_and_tag_.tag(); }
Allocation& allocation() {
- return reinterpret_cast<Allocation&>(rep_.allocation_storage.allocation);
+ return reinterpret_cast<Allocation&>(
+ storage_.rep_.allocation_storage.allocation);
}
const Allocation& allocation() const {
return reinterpret_cast<const Allocation&>(
- rep_.allocation_storage.allocation);
+ storage_.rep_.allocation_storage.allocation);
}
void init_allocation(const Allocation& allocation) {
- new (&rep_.allocation_storage.allocation) Allocation(allocation);
+ new (&storage_.rep_.allocation_storage.allocation) Allocation(allocation);
}
// TODO(absl-team): investigate whether the reinterpret_cast is appropriate.
pointer inlined_space() {
return reinterpret_cast<pointer>(
- std::addressof(rep_.inlined_storage.inlined[0]));
+ std::addressof(storage_.rep_.inlined_storage.inlined[0]));
}
const_pointer inlined_space() const {
return reinterpret_cast<const_pointer>(
- std::addressof(rep_.inlined_storage.inlined[0]));
+ std::addressof(storage_.rep_.inlined_storage.inlined[0]));
}
pointer allocated_space() { return allocation().buffer(); }
@@ -934,10 +881,12 @@ class InlinedVector {
const_pointer allocated_space() const { return allocation().buffer(); }
const allocator_type& allocator() const {
- return allocator_and_tag_.allocator();
+ return storage_.allocator_and_tag_.allocator();
}
- allocator_type& allocator() { return allocator_and_tag_.allocator(); }
+ allocator_type& allocator() {
+ return storage_.allocator_and_tag_.allocator();
+ }
bool allocated() const { return tag().allocated(); }
@@ -994,7 +943,7 @@ class InlinedVector {
const size_type s = size();
assert(s <= capacity());
- size_type target = (std::max)(GetInlinedCapacity(), s + delta);
+ size_type target = (std::max)(Storage::GetInlinedCapacity(), s + delta);
// Compute new capacity by repeatedly doubling current capacity
// TODO(psrc): Check and avoid overflow?
@@ -1097,7 +1046,7 @@ class InlinedVector {
}
void InitAssign(size_type n) {
- if (n > GetInlinedCapacity()) {
+ if (n > Storage::GetInlinedCapacity()) {
Allocation new_allocation(allocator(), n);
init_allocation(new_allocation);
UninitializedFill(allocated_space(), allocated_space() + n);
@@ -1109,7 +1058,7 @@ class InlinedVector {
}
void InitAssign(size_type n, const_reference v) {
- if (n > GetInlinedCapacity()) {
+ if (n > Storage::GetInlinedCapacity()) {
Allocation new_allocation(allocator(), n);
init_allocation(new_allocation);
UninitializedFill(allocated_space(), allocated_space() + n, v);
@@ -1267,28 +1216,7 @@ class InlinedVector {
assert(a->size() == b_size);
}
- // Stores either the inlined or allocated representation
- union Rep {
- using ValueTypeBuffer =
- absl::aligned_storage_t<sizeof(value_type), alignof(value_type)>;
- using AllocationBuffer =
- absl::aligned_storage_t<sizeof(Allocation), alignof(Allocation)>;
-
- // Structs wrap the buffers to perform indirection that solves a bizarre
- // compilation error on Visual Studio (all known versions).
- struct InlinedRep {
- ValueTypeBuffer inlined[N];
- };
- struct AllocatedRep {
- AllocationBuffer allocation;
- };
-
- InlinedRep inlined_storage;
- AllocatedRep allocation_storage;
- };
-
- AllocatorAndTag allocator_and_tag_;
- Rep rep_;
+ Storage storage_;
};
// -----------------------------------------------------------------------------
diff --git a/absl/container/internal/hashtablez_sampler.h b/absl/container/internal/hashtablez_sampler.h
index aff8d15f..a308e788 100644
--- a/absl/container/internal/hashtablez_sampler.h
+++ b/absl/container/internal/hashtablez_sampler.h
@@ -34,7 +34,6 @@
// are using a table in an unusual circumstance where allocation or calling a
// linux syscall is unacceptable, this could interfere.
//
-//
// This utility is internal-only. Use at your own risk.
#ifndef ABSL_CONTAINER_INTERNAL_HASHTABLEZ_SAMPLER_H_
diff --git a/absl/container/internal/inlined_vector.h b/absl/container/internal/inlined_vector.h
new file mode 100644
index 00000000..30850609
--- /dev/null
+++ b/absl/container/internal/inlined_vector.h
@@ -0,0 +1,130 @@
+// Copyright 2019 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
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_INTERNAL_H_
+#define ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_INTERNAL_H_
+
+#include <cstddef>
+#include <iterator>
+#include <memory>
+
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+namespace inlined_vector_internal {
+
+template <typename T, size_t N, typename A>
+class InlinedVectorStorage {
+ static_assert(
+ N > 0, "InlinedVector cannot be instantiated with `0` inline elements.");
+
+ public:
+ using allocator_type = A;
+ using value_type = typename allocator_type::value_type;
+ using pointer = typename allocator_type::pointer;
+ using const_pointer = typename allocator_type::const_pointer;
+ using reference = typename allocator_type::reference;
+ using const_reference = typename allocator_type::const_reference;
+ using rvalue_reference = typename allocator_type::value_type&&;
+ using size_type = typename allocator_type::size_type;
+ using difference_type = typename allocator_type::difference_type;
+ using iterator = pointer;
+ using const_iterator = const_pointer;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+ constexpr static size_type GetInlinedCapacity() {
+ return static_cast<size_type>(N);
+ }
+
+ explicit InlinedVectorStorage(const allocator_type& a)
+ : allocator_and_tag_(a) {}
+
+ // TODO(johnsoncj): Make the below types and members private after migration
+
+ // Holds whether the vector is allocated or not in the lowest bit and the size
+ // in the high bits:
+ // `size_ = (size << 1) | is_allocated;`
+ class Tag {
+ size_type size_;
+
+ public:
+ Tag() : size_(0) {}
+ size_type size() const { return size_ / 2; }
+ void add_size(size_type n) { size_ += n * 2; }
+ void set_inline_size(size_type n) { size_ = n * 2; }
+ void set_allocated_size(size_type n) { size_ = (n * 2) + 1; }
+ bool allocated() const { return size_ % 2; }
+ };
+
+ // Derives from `allocator_type` to use the empty base class optimization.
+ // If the `allocator_type` is stateless, we can store our instance for free.
+ class AllocatorAndTag : private allocator_type {
+ Tag tag_;
+
+ public:
+ explicit AllocatorAndTag(const allocator_type& a) : allocator_type(a) {}
+ Tag& tag() { return tag_; }
+ const Tag& tag() const { return tag_; }
+ allocator_type& allocator() { return *this; }
+ const allocator_type& allocator() const { return *this; }
+ };
+
+ class Allocation {
+ size_type capacity_;
+ pointer buffer_;
+
+ public:
+ Allocation(allocator_type& a, size_type capacity)
+ : capacity_(capacity), buffer_(Create(a, capacity)) {}
+ void Dealloc(allocator_type& a) {
+ std::allocator_traits<allocator_type>::deallocate(a, buffer_, capacity_);
+ }
+ size_type capacity() const { return capacity_; }
+ const_pointer buffer() const { return buffer_; }
+ pointer buffer() { return buffer_; }
+ static pointer Create(allocator_type& a, size_type n) {
+ return std::allocator_traits<allocator_type>::allocate(a, n);
+ }
+ };
+
+ // Stores either the inlined or allocated representation
+ union Rep {
+ using ValueTypeBuffer =
+ absl::aligned_storage_t<sizeof(value_type), alignof(value_type)>;
+ using AllocationBuffer =
+ absl::aligned_storage_t<sizeof(Allocation), alignof(Allocation)>;
+
+ // Structs wrap the buffers to perform indirection that solves a bizarre
+ // compilation error on Visual Studio (all known versions).
+ struct InlinedRep {
+ ValueTypeBuffer inlined[N];
+ };
+
+ struct AllocatedRep {
+ AllocationBuffer allocation;
+ };
+
+ InlinedRep inlined_storage;
+ AllocatedRep allocation_storage;
+ };
+
+ AllocatorAndTag allocator_and_tag_;
+ Rep rep_;
+};
+
+} // namespace inlined_vector_internal
+} // namespace absl
+
+#endif // ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_INTERNAL_H_
diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc
index 9e79cb38..87511148 100644
--- a/absl/container/internal/raw_hash_set_test.cc
+++ b/absl/container/internal/raw_hash_set_test.cc
@@ -1080,6 +1080,7 @@ ExpectedStats XorSeedExpectedStats() {
ABSL_RAW_LOG(FATAL, "%s", "Unknown Group width");
return {};
}
+
TEST(Table, DISABLED_EnsureNonQuadraticTopNXorSeedByProbeSeqLength) {
ProbeStatsPerSize stats;
std::vector<size_t> sizes = {Group::kWidth << 5, Group::kWidth << 10};
@@ -1173,6 +1174,7 @@ ExpectedStats LinearTransformExpectedStats() {
ABSL_RAW_LOG(FATAL, "%s", "Unknown Group width");
return {};
}
+
TEST(Table, DISABLED_EnsureNonQuadraticTopNLinearTransformByProbeSeqLength) {
ProbeStatsPerSize stats;
std::vector<size_t> sizes = {Group::kWidth << 5, Group::kWidth << 10};
diff --git a/absl/copts/GENERATED_AbseilCopts.cmake b/absl/copts/GENERATED_AbseilCopts.cmake
index 80c98193..d02ea193 100644
--- a/absl/copts/GENERATED_AbseilCopts.cmake
+++ b/absl/copts/GENERATED_AbseilCopts.cmake
@@ -20,6 +20,7 @@ list(APPEND GCC_FLAGS
"-Wvarargs"
"-Wvla"
"-Wwrite-strings"
+ "-Wno-missing-field-initializers"
"-Wno-sign-compare"
)
diff --git a/absl/copts/GENERATED_copts.bzl b/absl/copts/GENERATED_copts.bzl
index a001347d..d23f4069 100644
--- a/absl/copts/GENERATED_copts.bzl
+++ b/absl/copts/GENERATED_copts.bzl
@@ -21,6 +21,7 @@ GCC_FLAGS = [
"-Wvarargs",
"-Wvla",
"-Wwrite-strings",
+ "-Wno-missing-field-initializers",
"-Wno-sign-compare",
]
diff --git a/absl/copts/copts.py b/absl/copts/copts.py
index 4da8442d..5a2d91a3 100644
--- a/absl/copts/copts.py
+++ b/absl/copts/copts.py
@@ -10,6 +10,7 @@ compilation options:
The generated copts are consumed by configure_copts.bzl and
AbseilConfigureCopts.cmake.
"""
+
COPT_VARS = {
"GCC_FLAGS": [
"-Wall",
@@ -24,6 +25,10 @@ COPT_VARS = {
"-Wvarargs",
"-Wvla", # variable-length array
"-Wwrite-strings",
+ # gcc-4.x has spurious missing field initializer warnings.
+ # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36750
+ # Remove when gcc-4.x is no longer supported.
+ "-Wno-missing-field-initializers",
# Google style does not use unsigned integers, though STL containers
# have unsigned types.
"-Wno-sign-compare",
diff --git a/absl/debugging/internal/address_is_readable.h b/absl/debugging/internal/address_is_readable.h
index 64c3f1ea..ca8003e6 100644
--- a/absl/debugging/internal/address_is_readable.h
+++ b/absl/debugging/internal/address_is_readable.h
@@ -11,7 +11,6 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-//
#ifndef ABSL_DEBUGGING_INTERNAL_ADDRESS_IS_READABLE_H_
#define ABSL_DEBUGGING_INTERNAL_ADDRESS_IS_READABLE_H_
diff --git a/absl/debugging/internal/demangle_test.cc b/absl/debugging/internal/demangle_test.cc
index d410a232..883b92db 100644
--- a/absl/debugging/internal/demangle_test.cc
+++ b/absl/debugging/internal/demangle_test.cc
@@ -176,6 +176,7 @@ static void TestOnInput(const char* input) {
TEST(DemangleRegression, NegativeLength) {
TestOnInput("_ZZn4");
}
+
TEST(DemangleRegression, DeeplyNestedArrayType) {
const int depth = 100000;
std::string data = "_ZStI";
diff --git a/absl/debugging/internal/stacktrace_x86-inl.inc b/absl/debugging/internal/stacktrace_x86-inl.inc
index 248966b0..25aa8bdf 100644
--- a/absl/debugging/internal/stacktrace_x86-inl.inc
+++ b/absl/debugging/internal/stacktrace_x86-inl.inc
@@ -33,6 +33,7 @@
#include "absl/debugging/internal/address_is_readable.h"
#include "absl/debugging/internal/vdso_support.h" // a no-op on non-elf or non-glibc systems
#include "absl/debugging/stacktrace.h"
+
#include "absl/base/internal/raw_logging.h"
#if defined(__linux__) && defined(__i386__)
diff --git a/absl/debugging/leak_check.cc b/absl/debugging/leak_check.cc
index a1cae969..ffe3d1bd 100644
--- a/absl/debugging/leak_check.cc
+++ b/absl/debugging/leak_check.cc
@@ -11,6 +11,7 @@
// 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.
+
// Wrappers around lsan_interface functions.
// When lsan is not linked in, these functions are not available,
// therefore Abseil code which depends on these functions is conditioned on the
diff --git a/absl/debugging/stacktrace.cc b/absl/debugging/stacktrace.cc
index 9935adfa..9de8782f 100644
--- a/absl/debugging/stacktrace.cc
+++ b/absl/debugging/stacktrace.cc
@@ -46,6 +46,7 @@
#include ABSL_STACKTRACE_INL_HEADER
#else
# error Cannot calculate stack trace: will need to write for your environment
+
# include "absl/debugging/internal/stacktrace_aarch64-inl.inc"
# include "absl/debugging/internal/stacktrace_arm-inl.inc"
# include "absl/debugging/internal/stacktrace_generic-inl.inc"
diff --git a/absl/hash/hash.h b/absl/hash/hash.h
index 94cb6747..c0ede35a 100644
--- a/absl/hash/hash.h
+++ b/absl/hash/hash.h
@@ -309,4 +309,5 @@ class HashState : public hash_internal::HashStateBase<HashState> {
};
} // namespace absl
+
#endif // ABSL_HASH_HASH_H_
diff --git a/absl/hash/hash_test.cc b/absl/hash/hash_test.cc
index a2430e7a..af959385 100644
--- a/absl/hash/hash_test.cc
+++ b/absl/hash/hash_test.cc
@@ -276,6 +276,7 @@ TEST(HashValueTest, Strings) {
const std::string dup = "foofoo";
const std::string large = "large";
const std::string huge = std::string(5000, 'a');
+
EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
std::string(), absl::string_view(),
std::string(""), absl::string_view(""),
diff --git a/absl/hash/internal/city.h b/absl/hash/internal/city.h
index 1b3b4ef9..b43d3407 100644
--- a/absl/hash/internal/city.h
+++ b/absl/hash/internal/city.h
@@ -49,7 +49,6 @@
#include <stdlib.h> // for size_t.
#include <utility>
-
namespace absl {
namespace hash_internal {
diff --git a/absl/meta/type_traits.h b/absl/meta/type_traits.h
index 8a788dea..b1b14914 100644
--- a/absl/meta/type_traits.h
+++ b/absl/meta/type_traits.h
@@ -485,4 +485,65 @@ inline void AssertHashEnabled() {
} // namespace absl
+// An internal namespace that is required to implement the C++17 swap traits.
+//
+// NOTE: This is its own top-level namespace to avoid subtleties due to
+// functions named "swap" that may appear in the absl namespace.
+namespace absl_internal_swap {
+
+using std::swap;
+
+template <class T>
+using IsSwappableImpl = decltype(swap(std::declval<T&>(), std::declval<T&>()));
+
+// NOTE: This dance with the default template parameter is for MSVC.
+template <class T,
+ class IsNoexcept = std::integral_constant<
+ bool, noexcept(swap(std::declval<T&>(), std::declval<T&>()))>>
+using IsNothrowSwappableImpl = typename std::enable_if<IsNoexcept::value>::type;
+
+// IsSwappable
+//
+// Determines whether the standard swap idiom is a valid expression for
+// arguments of type `T`.
+template <class T>
+struct IsSwappable
+ : absl::type_traits_internal::is_detected<IsSwappableImpl, T> {};
+
+// IsNothrowSwappable
+//
+// Determines whether the standard swap idiom is a valid expression for
+// arguments of type `T` and is noexcept.
+template <class T>
+struct IsNothrowSwappable
+ : absl::type_traits_internal::is_detected<IsNothrowSwappableImpl, T> {};
+
+// Swap()
+//
+// Performs the swap idiom from a namespace with no additional `swap` overloads.
+template <class T, absl::enable_if_t<IsSwappable<T>::value, int> = 0>
+void Swap(T& lhs, T& rhs) noexcept(IsNothrowSwappable<T>::value) {
+ swap(lhs, rhs);
+}
+
+} // namespace absl_internal_swap
+
+namespace absl {
+namespace type_traits_internal {
+
+// Make the swap-related traits/function accessible from this namespace.
+using absl_internal_swap::IsNothrowSwappable;
+using absl_internal_swap::IsSwappable;
+using absl_internal_swap::Swap;
+
+// StdSwapIsUnconstrained
+//
+// Some standard library implementations are broken in that they do not
+// constrain `std::swap`. This will effectively tell us if we are dealing with
+// one of those implementations.
+using StdSwapIsUnconstrained = IsSwappable<void()>;
+
+} // namespace type_traits_internal
+} // namespace absl
+
#endif // ABSL_META_TYPE_TRAITS_H_
diff --git a/absl/meta/type_traits_test.cc b/absl/meta/type_traits_test.cc
index 29a6db69..912336e9 100644
--- a/absl/meta/type_traits_test.cc
+++ b/absl/meta/type_traits_test.cc
@@ -953,4 +953,85 @@ TEST(TypeTraitsTest, IsMoveAssignable) {
#endif // _LIBCPP_VERSION
}
+namespace adl_namespace {
+
+struct DeletedSwap {
+};
+
+void swap(DeletedSwap&, DeletedSwap&) = delete;
+
+struct SpecialNoexceptSwap {
+ SpecialNoexceptSwap(SpecialNoexceptSwap&&) {}
+ SpecialNoexceptSwap& operator=(SpecialNoexceptSwap&&) { return *this; }
+ ~SpecialNoexceptSwap() = default;
+};
+
+void swap(SpecialNoexceptSwap&, SpecialNoexceptSwap&) noexcept {}
+
+} // namespace adl_namespace
+
+TEST(TypeTraitsTest, IsSwappable) {
+ using absl::type_traits_internal::IsSwappable;
+ using absl::type_traits_internal::StdSwapIsUnconstrained;
+
+ EXPECT_TRUE(IsSwappable<int>::value);
+
+ struct S {};
+ EXPECT_TRUE(IsSwappable<S>::value);
+
+ struct NoConstruct {
+ NoConstruct(NoConstruct&&) = delete;
+ NoConstruct& operator=(NoConstruct&&) { return *this; }
+ ~NoConstruct() = default;
+ };
+
+ EXPECT_EQ(IsSwappable<NoConstruct>::value, StdSwapIsUnconstrained::value);
+ struct NoAssign {
+ NoAssign(NoAssign&&) {}
+ NoAssign& operator=(NoAssign&&) = delete;
+ ~NoAssign() = default;
+ };
+
+ EXPECT_EQ(IsSwappable<NoAssign>::value, StdSwapIsUnconstrained::value);
+
+ EXPECT_FALSE(IsSwappable<adl_namespace::DeletedSwap>::value);
+
+ EXPECT_TRUE(IsSwappable<adl_namespace::SpecialNoexceptSwap>::value);
+}
+
+TEST(TypeTraitsTest, IsNothrowSwappable) {
+ using absl::type_traits_internal::IsNothrowSwappable;
+ using absl::type_traits_internal::StdSwapIsUnconstrained;
+
+ EXPECT_TRUE(IsNothrowSwappable<int>::value);
+
+ struct NonNoexceptMoves {
+ NonNoexceptMoves(NonNoexceptMoves&&) {}
+ NonNoexceptMoves& operator=(NonNoexceptMoves&&) { return *this; }
+ ~NonNoexceptMoves() = default;
+ };
+
+ EXPECT_FALSE(IsNothrowSwappable<NonNoexceptMoves>::value);
+
+ struct NoConstruct {
+ NoConstruct(NoConstruct&&) = delete;
+ NoConstruct& operator=(NoConstruct&&) { return *this; }
+ ~NoConstruct() = default;
+ };
+
+ EXPECT_FALSE(IsNothrowSwappable<NoConstruct>::value);
+
+ struct NoAssign {
+ NoAssign(NoAssign&&) {}
+ NoAssign& operator=(NoAssign&&) = delete;
+ ~NoAssign() = default;
+ };
+
+ EXPECT_FALSE(IsNothrowSwappable<NoAssign>::value);
+
+ EXPECT_FALSE(IsNothrowSwappable<adl_namespace::DeletedSwap>::value);
+
+ EXPECT_TRUE(IsNothrowSwappable<adl_namespace::SpecialNoexceptSwap>::value);
+}
+
} // namespace
diff --git a/absl/numeric/int128.h b/absl/numeric/int128.h
index c0ec03d4..2f5b8ad7 100644
--- a/absl/numeric/int128.h
+++ b/absl/numeric/int128.h
@@ -53,7 +53,6 @@
namespace absl {
-
// uint128
//
// An unsigned 128-bit integer type. The API is meant to mimic an intrinsic type
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel
index 8afe8177..9640ff46 100644
--- a/absl/strings/BUILD.bazel
+++ b/absl/strings/BUILD.bazel
@@ -12,7 +12,6 @@
# 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.
-#
load(
"//absl:copts/configure_copts.bzl",
diff --git a/absl/strings/escaping.h b/absl/strings/escaping.h
index 03ab0ae7..fd9be786 100644
--- a/absl/strings/escaping.h
+++ b/absl/strings/escaping.h
@@ -19,7 +19,6 @@
//
// This header file contains string utilities involved in escaping and
// unescaping strings in various ways.
-//
#ifndef ABSL_STRINGS_ESCAPING_H_
#define ABSL_STRINGS_ESCAPING_H_
@@ -56,7 +55,6 @@ namespace absl {
// UTF-8. (E.g., `\u2019` unescapes to the three bytes 0xE2, 0x80, and
// 0x99).
//
-//
// If any errors are encountered, this function returns `false`, leaving the
// `dest` output parameter in an unspecified state, and stores the first
// encountered error in `error`. To disable error reporting, set `error` to
diff --git a/absl/strings/internal/str_format/arg.h b/absl/strings/internal/str_format/arg.h
index c54cd1ab..4d48af06 100644
--- a/absl/strings/internal/str_format/arg.h
+++ b/absl/strings/internal/str_format/arg.h
@@ -35,12 +35,14 @@ struct HasUserDefinedConvert<
T, void_t<decltype(AbslFormatConvert(
std::declval<const T&>(), std::declval<ConversionSpec>(),
std::declval<FormatSink*>()))>> : std::true_type {};
+
template <typename T>
class StreamedWrapper;
// If 'v' can be converted (in the printf sense) according to 'conv',
// then convert it, appending to `sink` and return `true`.
// Otherwise fail and return `false`.
+
// Raw pointers.
struct VoidPtr {
VoidPtr() = default;
diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc
index 5d77856d..99cc0afe 100644
--- a/absl/strings/internal/str_format/convert_test.cc
+++ b/absl/strings/internal/str_format/convert_test.cc
@@ -363,6 +363,7 @@ typedef ::testing::Types<
AllIntTypes;
INSTANTIATE_TYPED_TEST_CASE_P(TypedFormatConvertTestWithAllIntTypes,
TypedFormatConvertTest, AllIntTypes);
+
TEST_F(FormatConvertTest, Uint128) {
absl::uint128 v = static_cast<absl::uint128>(0x1234567890abcdef) * 1979;
absl::uint128 max = absl::Uint128Max();
diff --git a/absl/strings/internal/str_format/extension.h b/absl/strings/internal/str_format/extension.h
index 30235e08..eb81f8a1 100644
--- a/absl/strings/internal/str_format/extension.h
+++ b/absl/strings/internal/str_format/extension.h
@@ -13,7 +13,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
-//
#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
#define ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
diff --git a/absl/strings/internal/str_format/extension_test.cc b/absl/strings/internal/str_format/extension_test.cc
index 334a1484..4e23fefb 100644
--- a/absl/strings/internal/str_format/extension_test.cc
+++ b/absl/strings/internal/str_format/extension_test.cc
@@ -18,6 +18,7 @@
#include <random>
#include <string>
+
#include "absl/strings/str_format.h"
#include "gtest/gtest.h"
diff --git a/absl/strings/internal/str_format/output_test.cc b/absl/strings/internal/str_format/output_test.cc
index ca93d1e3..6e04abef 100644
--- a/absl/strings/internal/str_format/output_test.cc
+++ b/absl/strings/internal/str_format/output_test.cc
@@ -17,7 +17,6 @@
#include <sstream>
#include <string>
-
#include "gmock/gmock.h"
#include "gtest/gtest.h"
diff --git a/absl/strings/internal/utf8.h b/absl/strings/internal/utf8.h
index 445d4c35..04236304 100644
--- a/absl/strings/internal/utf8.h
+++ b/absl/strings/internal/utf8.h
@@ -13,7 +13,6 @@
// limitations under the License.
//
// UTF8 utilities, implemented to reduce dependencies.
-//
#ifndef ABSL_STRINGS_INTERNAL_UTF8_H_
#define ABSL_STRINGS_INTERNAL_UTF8_H_
diff --git a/absl/strings/str_cat.h b/absl/strings/str_cat.h
index 69d6eaad..cba8ceb0 100644
--- a/absl/strings/str_cat.h
+++ b/absl/strings/str_cat.h
@@ -42,7 +42,6 @@
// Floating point numbers are formatted with six-digit precision, which is
// the default for "std::cout <<" or printf "%g" (the same as "%.6g").
//
-//
// You can convert to hexadecimal output rather than decimal output using the
// `Hex` type contained here. To do so, pass `Hex(my_int)` as a parameter to
// `StrCat()` or `StrAppend()`. You may specify a minimum hex field width using
diff --git a/absl/strings/str_format.h b/absl/strings/str_format.h
index 486fe0eb..539d9516 100644
--- a/absl/strings/str_format.h
+++ b/absl/strings/str_format.h
@@ -513,4 +513,5 @@ ABSL_MUST_USE_RESULT inline bool FormatUntyped(
}
} // namespace absl
+
#endif // ABSL_STRINGS_STR_FORMAT_H_
diff --git a/absl/strings/str_split.h b/absl/strings/str_split.h
index 8eb55089..73330789 100644
--- a/absl/strings/str_split.h
+++ b/absl/strings/str_split.h
@@ -71,7 +71,6 @@ namespace absl {
// - `ByLength`
// - `MaxSplits`
//
-//
// A Delimiter's `Find()` member function will be passed an input `text` that is
// to be split and a position (`pos`) to begin searching for the next delimiter
// in `text`. The returned absl::string_view should refer to the next occurrence
diff --git a/absl/strings/string_view.h b/absl/strings/string_view.h
index bd894e1d..f8b20015 100644
--- a/absl/strings/string_view.h
+++ b/absl/strings/string_view.h
@@ -101,7 +101,6 @@ namespace absl {
// example, when splitting a string, `std::vector<absl::string_view>` is a
// natural data type for the output.
//
-//
// When constructed from a source which is nul-terminated, the `string_view`
// itself will not include the nul-terminator unless a specific size (including
// the nul) is passed to the constructor. As a result, common idioms that work
@@ -508,6 +507,7 @@ inline bool operator==(string_view x, string_view y) noexcept {
if (len != y.size()) {
return false;
}
+
return x.data() == y.data() || len <= 0 ||
memcmp(x.data(), y.data(), len) == 0;
}
diff --git a/absl/strings/substitute.h b/absl/strings/substitute.h
index a45ff039..507bc4ff 100644
--- a/absl/strings/substitute.h
+++ b/absl/strings/substitute.h
@@ -45,7 +45,6 @@
// SubstituteAndAppend(&s, "My name is $0 and I am $1 years old.", "Bob", 5);
// EXPECT_EQ("Hi. My name is Bob and I am 5 years old.", s);
//
-//
// Supported types:
// * absl::string_view, std::string, const char* (null is equivalent to "")
// * int32_t, int64_t, uint32_t, uint64
diff --git a/absl/synchronization/internal/create_thread_identity.h b/absl/synchronization/internal/create_thread_identity.h
index b2525b72..ebb16c56 100644
--- a/absl/synchronization/internal/create_thread_identity.h
+++ b/absl/synchronization/internal/create_thread_identity.h
@@ -50,4 +50,5 @@ inline base_internal::ThreadIdentity* GetOrCreateCurrentThreadIdentity() {
} // namespace synchronization_internal
} // namespace absl
+
#endif // ABSL_SYNCHRONIZATION_INTERNAL_CREATE_THREAD_IDENTITY_H_
diff --git a/absl/synchronization/internal/kernel_timeout.h b/absl/synchronization/internal/kernel_timeout.h
index 543c4a03..61c72e75 100644
--- a/absl/synchronization/internal/kernel_timeout.h
+++ b/absl/synchronization/internal/kernel_timeout.h
@@ -53,6 +53,7 @@ class KernelTimeout {
// We explicitly do not support other custom formats: timespec, int64_t nanos.
// Unify on this and absl::Time, please.
+
bool has_timeout() const { return ns_ != 0; }
private:
@@ -148,4 +149,5 @@ class KernelTimeout {
} // namespace synchronization_internal
} // namespace absl
+
#endif // ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_
diff --git a/absl/synchronization/internal/per_thread_sem.cc b/absl/synchronization/internal/per_thread_sem.cc
index d22539dc..b7014fb2 100644
--- a/absl/synchronization/internal/per_thread_sem.cc
+++ b/absl/synchronization/internal/per_thread_sem.cc
@@ -89,6 +89,7 @@ ABSL_ATTRIBUTE_WEAK bool AbslInternalPerThreadSemWait(
if (identity->blocked_count_ptr != nullptr) {
identity->blocked_count_ptr->fetch_sub(1, std::memory_order_relaxed);
}
+
identity->is_idle.store(false, std::memory_order_relaxed);
identity->wait_start.store(0, std::memory_order_relaxed);
return !timeout;
diff --git a/absl/synchronization/internal/per_thread_sem.h b/absl/synchronization/internal/per_thread_sem.h
index d373f63b..e7da070b 100644
--- a/absl/synchronization/internal/per_thread_sem.h
+++ b/absl/synchronization/internal/per_thread_sem.h
@@ -104,4 +104,5 @@ bool absl::synchronization_internal::PerThreadSem::Wait(
absl::synchronization_internal::KernelTimeout t) {
return AbslInternalPerThreadSemWait(t);
}
+
#endif // ABSL_SYNCHRONIZATION_INTERNAL_PER_THREAD_SEM_H_
diff --git a/absl/synchronization/internal/waiter.cc b/absl/synchronization/internal/waiter.cc
index bab6d1a1..74b09650 100644
--- a/absl/synchronization/internal/waiter.cc
+++ b/absl/synchronization/internal/waiter.cc
@@ -40,6 +40,7 @@
#include <atomic>
#include <cassert>
#include <cstdint>
+
#include "absl/base/internal/raw_logging.h"
#include "absl/base/internal/thread_identity.h"
#include "absl/base/optimization.h"
@@ -81,6 +82,7 @@ static void MaybeBecomeIdle() {
#define FUTEX_BITSET_MATCH_ANY 0xFFFFFFFF
#endif
#endif
+
class Futex {
public:
static int WaitUntil(std::atomic<int32_t> *v, int32_t val,
diff --git a/absl/synchronization/mutex.cc b/absl/synchronization/mutex.cc
index f4ed0d00..6b2eb331 100644
--- a/absl/synchronization/mutex.cc
+++ b/absl/synchronization/mutex.cc
@@ -265,6 +265,7 @@ static const struct {
{ 0, "Signal on " },
{ 0, "SignalAll on " },
};
+
static absl::base_internal::SpinLock synch_event_mu(
absl::base_internal::kLinkerInitialized);
// protects synch_event
diff --git a/absl/synchronization/mutex.h b/absl/synchronization/mutex.h
index cf0f86dc..c38e3561 100644
--- a/absl/synchronization/mutex.h
+++ b/absl/synchronization/mutex.h
@@ -157,6 +157,7 @@ class LOCKABLE Mutex {
// ABSL_CONST_INIT Mutex mu(absl::kConstInit);
// }
explicit constexpr Mutex(absl::ConstInitType);
+
~Mutex();
// Mutex::Lock()
@@ -900,10 +901,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) {}
@@ -1047,4 +1050,5 @@ void SetMutexDeadlockDetectionMode(OnDeadlockCycle mode);
extern "C" {
void AbslInternalMutexYield();
} // extern "C"
+
#endif // ABSL_SYNCHRONIZATION_MUTEX_H_
diff --git a/absl/synchronization/mutex_test.cc b/absl/synchronization/mutex_test.cc
index 53c1f744..10211229 100644
--- a/absl/synchronization/mutex_test.cc
+++ b/absl/synchronization/mutex_test.cc
@@ -1032,9 +1032,9 @@ class ScopedDisableBazelTestWarnings {
ScopedDisableBazelTestWarnings() {
#ifdef WIN32
char file[MAX_PATH];
- if (GetEnvironmentVariable(kVarName, file, sizeof(file)) < sizeof(file)) {
+ if (GetEnvironmentVariableA(kVarName, file, sizeof(file)) < sizeof(file)) {
warnings_output_file_ = file;
- SetEnvironmentVariable(kVarName, nullptr);
+ SetEnvironmentVariableA(kVarName, nullptr);
}
#else
const char *file = getenv(kVarName);
@@ -1048,7 +1048,7 @@ class ScopedDisableBazelTestWarnings {
~ScopedDisableBazelTestWarnings() {
if (!warnings_output_file_.empty()) {
#ifdef WIN32
- SetEnvironmentVariable(kVarName, warnings_output_file_.c_str());
+ SetEnvironmentVariableA(kVarName, warnings_output_file_.c_str());
#else
setenv(kVarName, warnings_output_file_.c_str(), 0);
#endif
diff --git a/absl/synchronization/notification.h b/absl/synchronization/notification.h
index 19f51de7..82d111a5 100644
--- a/absl/synchronization/notification.h
+++ b/absl/synchronization/notification.h
@@ -110,4 +110,5 @@ class Notification {
};
} // namespace absl
+
#endif // ABSL_SYNCHRONIZATION_NOTIFICATION_H_
diff --git a/absl/time/civil_time.h b/absl/time/civil_time.h
index f231e4f8..2dfcbd27 100644
--- a/absl/time/civil_time.h
+++ b/absl/time/civil_time.h
@@ -66,7 +66,6 @@
//
// // Valid in C++14
// constexpr absl::CivilDay cd(1969, 07, 20);
-//
#ifndef ABSL_TIME_CIVIL_TIME_H_
#define ABSL_TIME_CIVIL_TIME_H_
diff --git a/absl/time/duration.cc b/absl/time/duration.cc
index 8ce4acbb..67791fee 100644
--- a/absl/time/duration.cc
+++ b/absl/time/duration.cc
@@ -901,6 +901,7 @@ bool ParseDuration(const std::string& dur_string, Duration* d) {
*d = dur;
return true;
}
+
bool ParseFlag(const std::string& text, Duration* dst, std::string* ) {
return ParseDuration(text, dst);
}
diff --git a/absl/time/internal/cctz/src/time_zone_lookup.cc b/absl/time/internal/cctz/src/time_zone_lookup.cc
index 4a68c7d5..fd04e2df 100644
--- a/absl/time/internal/cctz/src/time_zone_lookup.cc
+++ b/absl/time/internal/cctz/src/time_zone_lookup.cc
@@ -127,7 +127,7 @@ time_zone local_time_zone() {
#if defined(_MSC_VER)
_dupenv_s(&tz_env, nullptr, "TZ");
#elif defined(__APPLE__)
- CFTimeZoneRef system_time_zone = CFTimeZoneCopySystem();
+ CFTimeZoneRef system_time_zone = CFTimeZoneCopyDefault();
CFStringRef tz_name = CFTimeZoneGetName(system_time_zone);
tz_env = strdup(CFStringGetCStringPtr(tz_name, CFStringGetSystemEncoding()));
CFRelease(system_time_zone);
diff --git a/absl/time/time.cc b/absl/time/time.cc
index 799bf859..977a9517 100644
--- a/absl/time/time.cc
+++ b/absl/time/time.cc
@@ -41,6 +41,7 @@
#include "absl/time/internal/cctz/include/cctz/time_zone.h"
namespace cctz = absl::time_internal::cctz;
+
namespace absl {
namespace {
diff --git a/absl/time/time.h b/absl/time/time.h
index 59e1dc64..594396c7 100644
--- a/absl/time/time.h
+++ b/absl/time/time.h
@@ -58,7 +58,6 @@
// std::string s = absl::FormatTime(
// "My flight will land in Sydney on %Y-%m-%d at %H:%M:%S",
// landing, syd);
-//
#ifndef ABSL_TIME_TIME_H_
#define ABSL_TIME_TIME_H_
@@ -569,7 +568,6 @@ std::string UnparseFlag(Duration d);
// The `absl::Time` class represents an instant in time as a count of clock
// ticks of some granularity (resolution) from some starting point (epoch).
//
-//
// `absl::Time` uses a resolution that is high enough to avoid loss in
// precision, and a range that is wide enough to avoid overflow, when
// converting between tick counts in most Google time scales (i.e., resolution
@@ -1450,6 +1448,7 @@ T ToChronoDuration(Duration d) {
}
} // namespace time_internal
+
constexpr Duration Nanoseconds(int64_t n) {
return time_internal::FromInt64(n, std::nano{});
}
diff --git a/absl/types/any_exception_safety_test.cc b/absl/types/any_exception_safety_test.cc
index 00d0fb72..5d7d8a5c 100644
--- a/absl/types/any_exception_safety_test.cc
+++ b/absl/types/any_exception_safety_test.cc
@@ -135,6 +135,7 @@ TEST(AnyExceptionSafety, Assignment) {
EXPECT_TRUE(strong_empty_any_tester.Test(assign_val));
EXPECT_TRUE(strong_empty_any_tester.Test(move));
}
+
// libstdc++ std::any fails this test
#if !defined(ABSL_HAVE_STD_ANY)
TEST(AnyExceptionSafety, Emplace) {
diff --git a/absl/types/internal/variant.h b/absl/types/internal/variant.h
index 4926b321..5ca66e29 100644
--- a/absl/types/internal/variant.h
+++ b/absl/types/internal/variant.h
@@ -15,7 +15,6 @@
// 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_
@@ -1549,8 +1548,8 @@ struct SwapSameIndex {
variant<Types...>* w;
template <std::size_t I>
void operator()(SizeT<I>) const {
- using std::swap;
- swap(VariantCoreAccess::Access<I>(*v), VariantCoreAccess::Access<I>(*w));
+ type_traits_internal::Swap(VariantCoreAccess::Access<I>(*v),
+ VariantCoreAccess::Access<I>(*w));
}
void operator()(SizeT<variant_npos>) const {}
diff --git a/absl/types/optional.h b/absl/types/optional.h
index c0488797..58906aa4 100644
--- a/absl/types/optional.h
+++ b/absl/types/optional.h
@@ -114,10 +114,6 @@ namespace absl {
// need the inline variable support in C++17 for external linkage.
// * Throws `absl::bad_optional_access` instead of
// `std::bad_optional_access`.
-// * `optional::swap()` and `absl::swap()` relies on
-// `std::is_(nothrow_)swappable()`, which has been introduced in C++17.
-// As a workaround, we assume `is_swappable()` is always `true`
-// and `is_nothrow_swappable()` is the same as `std::is_trivial()`.
// * `make_optional()` cannot be declared `constexpr` due to the absence of
// guaranteed copy elision.
// * The move constructor's `noexcept` specification is stronger, i.e. if the
@@ -753,11 +749,10 @@ class optional : private optional_internal::optional_data<T>,
// Swap, standard semantics
void swap(optional& rhs) noexcept(
std::is_nothrow_move_constructible<T>::value&&
- std::is_trivial<T>::value) {
+ type_traits_internal::IsNothrowSwappable<T>::value) {
if (*this) {
if (rhs) {
- using std::swap;
- swap(**this, *rhs);
+ type_traits_internal::Swap(**this, *rhs);
} else {
rhs.construct(std::move(**this));
this->destruct();
@@ -909,12 +904,10 @@ class optional : private optional_internal::optional_data<T>,
//
// Performs a swap between two `absl::optional` objects, using standard
// semantics.
-//
-// NOTE: we assume `is_swappable()` is always `true`. A compile error will
-// result if this is not the case.
-template <typename T,
- typename std::enable_if<std::is_move_constructible<T>::value,
- bool>::type = false>
+template <typename T, typename std::enable_if<
+ std::is_move_constructible<T>::value &&
+ type_traits_internal::IsSwappable<T>::value,
+ bool>::type = false>
void swap(optional<T>& a, optional<T>& b) noexcept(noexcept(a.swap(b))) {
a.swap(b);
}
diff --git a/absl/types/optional_test.cc b/absl/types/optional_test.cc
index 68842abb..0665488e 100644
--- a/absl/types/optional_test.cc
+++ b/absl/types/optional_test.cc
@@ -1636,6 +1636,7 @@ TEST(optionalTest, AssignmentConstraints) {
EXPECT_TRUE(absl::is_copy_assignable<absl::optional<AnyLike>>::value);
}
+#if !defined(ABSL_HAVE_STD_OPTIONAL) && !defined(_LIBCPP_VERSION)
struct NestedClassBug {
struct Inner {
bool dummy = false;
@@ -1658,5 +1659,6 @@ TEST(optionalTest, InPlaceTSFINAEBug) {
o.emplace();
EXPECT_TRUE(o.has_value());
}
+#endif // !defined(ABSL_HAVE_STD_OPTIONAL) && !defined(_LIBCPP_VERSION)
} // namespace
diff --git a/absl/types/variant.h b/absl/types/variant.h
index 8d8b5dbd..ebd52d28 100644
--- a/absl/types/variant.h
+++ b/absl/types/variant.h
@@ -129,7 +129,12 @@ class variant;
// type (in which case, they will be swapped) or to two different types (in
// which case the values will need to be moved).
//
-template <typename... Ts>
+template <
+ typename... Ts,
+ absl::enable_if_t<
+ absl::conjunction<std::is_move_constructible<Ts>...,
+ type_traits_internal::IsSwappable<Ts>...>::value,
+ int> = 0>
void swap(variant<Ts...>& v, variant<Ts...>& w) noexcept(noexcept(v.swap(w))) {
v.swap(w);
}
@@ -688,12 +693,12 @@ class variant<T0, Tn...> : private variant_internal::VariantBase<T0, Tn...> {
//
// Swaps the values of two variant objects.
//
- // TODO(calabrese)
- // `variant::swap()` and `swap()` rely on `std::is_(nothrow)_swappable()`
- // which is introduced in C++17. So we assume `is_swappable()` is always
- // true and `is_nothrow_swappable()` is same as `std::is_trivial()`.
void swap(variant& rhs) noexcept(
- absl::conjunction<std::is_trivial<T0>, std::is_trivial<Tn>...>::value) {
+ absl::conjunction<
+ std::is_nothrow_move_constructible<T0>,
+ std::is_nothrow_move_constructible<Tn>...,
+ type_traits_internal::IsNothrowSwappable<T0>,
+ type_traits_internal::IsNothrowSwappable<Tn>...>::value) {
return variant_internal::VisitIndices<sizeof...(Tn) + 1>::Run(
variant_internal::Swap<T0, Tn...>{this, &rhs}, rhs.index());
}
diff --git a/absl/types/variant_exception_safety_test.cc b/absl/types/variant_exception_safety_test.cc
index 086fcff0..76beb595 100644
--- a/absl/types/variant_exception_safety_test.cc
+++ b/absl/types/variant_exception_safety_test.cc
@@ -24,6 +24,7 @@
#include "absl/base/config.h"
#include "absl/base/internal/exception_safety_testing.h"
#include "absl/memory/memory.h"
+
// See comment in absl/base/config.h
#if !defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE)
@@ -315,6 +316,12 @@ TEST(VariantExceptionSafetyTest, MoveAssign) {
EXPECT_FALSE(tester.WithContracts(strong_guarantee).Test());
}
{
+ // libstdc++ introduced a regression between 2018-09-25 and 2019-01-06.
+ // The fix is targeted for gcc-9.
+ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87431#c7
+ // https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=267614
+#if !(defined(ABSL_HAVE_STD_VARIANT) && \
+ defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE == 8)
// - otherwise (index() != j), equivalent to
// emplace<j>(get<j>(std::move(rhs)))
// - If an exception is thrown during the call to Tj's move construction
@@ -330,6 +337,8 @@ TEST(VariantExceptionSafetyTest, MoveAssign) {
auto copy = rhs;
*lhs = std::move(copy);
}));
+#endif // !(defined(ABSL_HAVE_STD_VARIANT) &&
+ // defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE == 8)
}
}
diff --git a/absl/types/variant_test.cc b/absl/types/variant_test.cc
index 9df702df..ab40ed2a 100644
--- a/absl/types/variant_test.cc
+++ b/absl/types/variant_test.cc
@@ -561,6 +561,7 @@ TEST(VariantTest, TestDtor) {
}
#ifdef ABSL_HAVE_EXCEPTIONS
+
// See comment in absl/base/config.h
#if defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE)
TEST(VariantTest, DISABLED_TestDtorValuelessByException)
diff --git a/absl/utility/utility.h b/absl/utility/utility.h
index 62ce6f3a..853c1fb8 100644
--- a/absl/utility/utility.h
+++ b/absl/utility/utility.h
@@ -35,7 +35,6 @@
// https://en.cppreference.com/w/cpp/utility/integer_sequence
// https://en.cppreference.com/w/cpp/utility/apply
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3658.html
-//
#ifndef ABSL_UTILITY_UTILITY_H_
#define ABSL_UTILITY_UTILITY_H_