diff options
author | Abseil Team <absl-team@google.com> | 2019-03-19T18·14-0700 |
---|---|---|
committer | Derek Mauro <dmauro@google.com> | 2019-03-19T18·19-0400 |
commit | bf29470384a101b307873b26d358433138c857fc (patch) | |
tree | 1a8374bafdbfc606b4e70c0f581c3d6b34a08d7d /absl | |
parent | 6fd827124facd8336981e73218997f9e73029b4f (diff) |
Export of internal Abseil changes.
-- bdce7e57e9e886eff1114d0266781b443f7ec639 by Derek Mauro <dmauro@google.com>: Change {Get|Set}EnvironmentVariable to {Get|Set}EnvironmentVariableA for compatibility with /DUNICODE. PiperOrigin-RevId: 239229514 -- 2276ed502326a044a84060d34eb19d499e3a3be2 by Derek Mauro <dmauro@google.com>: Import of CCTZ from GitHub. PiperOrigin-RevId: 239228622 -- a462efb970ff43b08a362ef2343fb75ac1295a50 by Derek Mauro <dmauro@google.com>: Adding linking of CoreFoundation to CMakeLists in absl/time. Import https://github.com/abseil/abseil-cpp/pull/280. Fix #283 PiperOrigin-RevId: 239220785 -- fc23327b97f940c682aae1956cf7a1bf87f88c06 by Derek Mauro <dmauro@google.com>: Add hermetic test script that uses Docker to build with a very recent version of gcc (8.3.0 today) with libstdc++ and bazel. PiperOrigin-RevId: 239220448 -- 418c08a8f6a53e63b84e39473035774417ca3aa7 by Derek Mauro <dmauro@google.com>: Disable part of the variant exeception safety test on move assignment when using versions of libstd++ that contain a bug. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87431#c7 PiperOrigin-RevId: 239062455 -- 799722217aeda79679577843c91d5be62cbcbb42 by Matt Calabrese <calabrese@google.com>: Add internal-only IsSwappable traits corresponding to std::is_swappable and std::is_nothrow_swappable, which are used with the swap implementations of optional and variant. PiperOrigin-RevId: 239049448 -- aa46a036038a3de5c68ac5e5d3b4bf76f818d2ea by CJ Johnson <johnsoncj@google.com>: Make InlinedVectorStorage constructor explicit PiperOrigin-RevId: 239044361 -- 17949715b3aa21c794701f69f2154e91b6acabc3 by CJ Johnson <johnsoncj@google.com>: Add absl namesapce to internal/inlined_vector.h PiperOrigin-RevId: 239030789 -- 834628325953078cc08ed10d23bb8890e5bec897 by Derek Mauro <dmauro@google.com>: Add test script that uses Docker to build Abseil with gcc-4.8, libstdc++, and cmake. PiperOrigin-RevId: 239028433 -- 80fe24149ed73ed2ced995ad1e372fb060c60427 by CJ Johnson <johnsoncj@google.com>: Factors data members of InlinedVector into an impl type called InlinedVectorStorage so that (in future changes) the contents of a vector can be grouped together with a single pointer. PiperOrigin-RevId: 239021086 -- 585331436d5d4d79f845e45dcf79d918a0dc6169 by Derek Mauro <dmauro@google.com>: Add -Wno-missing-field-initializers to gcc compiler flags. gcc-4.x has spurious missing field initializer warnings. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36750 PiperOrigin-RevId: 239017217 -- 94602fe4e33ee3a552a7f2939c0f57a992f55075 by Abseil Team <absl-team@google.com>: Formatting fixes. PiperOrigin-RevId: 238983038 -- a1c1b63c08505574e0a8c491561840cecb2bb93e by Derek Mauro <dmauro@google.com>: Add hermetic test script that uses Docker to build with a very recent version of clang with libc++ and bazel. PiperOrigin-RevId: 238669118 -- e525f8d20bc2f79a0d69336b902f63858f3bff9d by Derek Mauro <dmauro@google.com>: Disable the test optionalTest.InPlaceTSFINAEBug until libc++ is updated. PiperOrigin-RevId: 238661703 -- f99a2a0b5ec424a059678f7f226600f137b4c74e by Derek Mauro <dmauro@google.com>: Correct the check for the FlatHashMap-Any test bug (list conditions instead of platforms when possible) PiperOrigin-RevId: 238653344 -- 777928035dbcbf39f361eb7d10dc3696822f692f by Jon Cohen <cohenjon@google.com>: Add install rules for Abseil CMake. These are attempted to be limited to in-project installation. This serves two purposes -- first it's morally the same as using Abseil in-source, except you don't have to rebuild us every time. Second, the presence of an install rule makes life massively simpler for package manager maintainers. Currently this doesn't install absl tests or testonly libraries. This can be added in a follow-up patch. Fixes #38, Fixes #80, Closes #182 PiperOrigin-RevId: 238645836 -- ded1c6ce697c191b7a6ff14572b3e6d183117b2c by Derek Mauro <dmauro@google.com>: Add hermetic test script that uses Docker to build with a very recent version of clang with libstdc++ and bazel. PiperOrigin-RevId: 238517815 GitOrigin-RevId: bdce7e57e9e886eff1114d0266781b443f7ec639 Change-Id: I6f745869cb8ef63851891ccac05ae9a7dd241c4f
Diffstat (limited to 'absl')
73 files changed, 444 insertions, 185 deletions
diff --git a/absl/algorithm/container.h b/absl/algorithm/container.h index 7348d63262e4..752e47b23939 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 1b2b8c2b8bc3..17858a7778a4 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 cdeb18c2a39d..ac33df9e575a 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 7874db718d09..794564e12f17 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 f83c7bc80df7..b35673de504a 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 d2d3182003e0..34a080cb15a6 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 2a5a38473621..0fcc8d3bed97 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 4cbbbe594221..6a4c093603f0 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 9b1641240cf8..3ac3f68ddf90 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 4bd68c48b944..5cbad246c647 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 dde3e010af65..b34674a62d4b 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 d5e186a9420b..58950cc2ff32 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 4b9833eb55a7..b19a7ffab820 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 b32cea2960bd..e62b2eaeba7b 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 a8162d41c47a..0b2c306ccc57 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 e03f94eca1d0..66962294d091 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 b6592ca560da..cd914baf88b7 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 76542be191cb..292fea2a8383 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 0161d0a99c91..2a8240ae7c17 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 bae5c15d482b..ebcb560fc04e 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 80929e3666e4..683087502295 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 aff8d15f4940..a308e7881962 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 000000000000..308506093300 --- /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 9e79cb38c363..87511148d04a 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 80c981930767..d02ea193c1c1 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 a001347d4909..d23f40698e93 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 4da8442de028..5a2d91a3aa6e 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 64c3f1eaa7d7..ca8003e6292a 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 d410a2322ff2..883b92db7757 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 248966b07204..25aa8bdf8c8c 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 a1cae9695359..ffe3d1bda9d6 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 9935adfa703b..9de8782f4cae 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 94cb67475f77..c0ede35ad523 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 a2430e7a653d..af9593850a4b 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 1b3b4ef9558b..b43d3407dcb4 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 8a788dea7b2e..b1b149146b44 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 29a6db69c2cc..912336e99165 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 c0ec03d4e836..2f5b8ad7a874 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 8afe81770a8c..9640ff4627cb 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 03ab0ae76d53..fd9be786a60e 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 c54cd1ab5177..4d48af066aee 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 5d77856d9458..99cc0afe4eb3 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 30235e08da09..eb81f8a17ca4 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 334a1484b6fd..4e23fefbd5b0 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 ca93d1e3cb0c..6e04abef4d91 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 445d4c3580c5..0423630473b1 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 69d6eaadffdc..cba8ceb024ae 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 486fe0ebd956..539d95162159 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 8eb55089b5c5..7333078938b9 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 bd894e1daa4d..f8b20015df6a 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 a45ff03982f0..507bc4ff295f 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 b2525b72f3de..ebb16c56a7ca 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 543c4a031cbc..61c72e75d13b 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 d22539dc49eb..b7014fb2b02d 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 d373f63b2547..e7da070ba72c 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 bab6d1a1699a..74b0965018c5 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 f4ed0d001156..6b2eb3314796 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 cf0f86dcac5d..c38e35616f76 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 53c1f744a0e1..10211229be00 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 19f51de7f04f..82d111a5492f 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 f231e4f889f0..2dfcbd27fef6 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 8ce4acbb5053..67791feedfb5 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 4a68c7d5884d..fd04e2df3985 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 799bf859f32f..977a95173db1 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 59e1dc64842b..594396c751df 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 00d0fb726d5b..5d7d8a5cfd21 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 4926b3214a02..5ca66e2902c6 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 c0488797adaa..58906aa467ff 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 68842abb20e5..0665488ed5f3 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 8d8b5dbd0093..ebd52d28b711 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 086fcff03d4c..76beb595925d 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 9df702dff6c1..ab40ed2a7217 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 62ce6f3ae1a4..853c1fb82e33 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_ |