diff options
80 files changed, 770 insertions, 194 deletions
diff --git a/CMake/AbseilHelpers.cmake b/CMake/AbseilHelpers.cmake index 8fdd510f..6d26169d 100644 --- a/CMake/AbseilHelpers.cmake +++ b/CMake/AbseilHelpers.cmake @@ -16,6 +16,7 @@ include(CMakeParseArguments) include(AbseilConfigureCopts) +include(GNUInstallDirs) # The IDE folder for Abseil that will be used if Abseil is included in a CMake # project that sets @@ -59,20 +60,17 @@ set(ABSL_IDE_FOLDER Abseil) # "b.cc" # DEPS # absl_internal_awesome # not "awesome"! +# PUBLIC # ) # -# If PUBLIC is set, absl_cc_library will instead create a target named -# absl_${NAME} and still an alias absl::${NAME}. -# # absl_cc_library( # NAME # main_lib # ... -# PUBLIC +# DEPS +# absl::fantastic_lib # since fantastic_lib is public # ) # -# User can then use the library as absl::main_lib (although absl_main_lib is defined too). -# # TODO: Implement "ALWAYSLINK" function(absl_cc_library) cmake_parse_arguments(ABSL_CC_LIB @@ -83,7 +81,7 @@ function(absl_cc_library) ) if (NOT ABSL_CC_LIB_TESTONLY OR ABSL_RUN_TESTS) - set(_NAME "absl_${ABSL_CC_LIB_NAME}") + set(_NAME "${ABSL_CC_LIB_NAME}") # Check if this is a header-only library # Note that as of February 2019, many popular OS's (for example, Ubuntu @@ -105,7 +103,10 @@ function(absl_cc_library) add_library(${_NAME} STATIC "") target_sources(${_NAME} PRIVATE ${ABSL_CC_LIB_SRCS} ${ABSL_CC_LIB_HDRS}) target_include_directories(${_NAME} - PUBLIC ${ABSL_COMMON_INCLUDE_DIRS}) + PUBLIC + $<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}> + $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> + ) target_compile_options(${_NAME} PRIVATE ${ABSL_CC_LIB_COPTS}) target_link_libraries(${_NAME} @@ -126,17 +127,37 @@ function(absl_cc_library) # INTERFACE libraries can't have the CXX_STANDARD property set set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD}) set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON) + + # When being installed, we lose the absl_ prefix. We want to put it back + # to have properly named lib files. This is a no-op when we are not being + # installed. + set_target_properties(${_NAME} PROPERTIES + OUTPUT_NAME "absl_${_NAME}" + ) else() # Generating header-only library add_library(${_NAME} INTERFACE) target_include_directories(${_NAME} - INTERFACE ${ABSL_COMMON_INCLUDE_DIRS}) + INTERFACE + $<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}> + $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> + ) target_link_libraries(${_NAME} INTERFACE ${ABSL_CC_LIB_DEPS} ${ABSL_CC_LIB_LINKOPTS} ) target_compile_definitions(${_NAME} INTERFACE ${ABSL_CC_LIB_DEFINES}) endif() + # TODO currently we don't install googletest alongside abseil sources, so + # installed abseil can't be tested. + if (NOT ABSL_CC_LIB_TESTONLY) + install(TARGETS ${_NAME} EXPORT ${PROJECT_NAME}Targets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) + endif() + add_library(absl::${ABSL_CC_LIB_NAME} ALIAS ${_NAME}) endif() endfunction() diff --git a/CMake/abslConfig.cmake.in b/CMake/abslConfig.cmake.in new file mode 100644 index 00000000..bf8c4f6a --- /dev/null +++ b/CMake/abslConfig.cmake.in @@ -0,0 +1,6 @@ +## absl CMake configuration file. Note that there is no corresponding +# abslConfigVersion.cmake since non-LTS Abseil isn't versioned. + +@PACKAGE_INIT@ + +include ("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
\ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 571e48c5..e3bb8d05 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,14 +26,26 @@ if (POLICY CMP0025) cmake_policy(SET CMP0025 NEW) endif() +# if command can use IN_LIST +cmake_policy(SET CMP0057 NEW) + project(absl) +# when absl is included as subproject (i.e. using add_subdirectory(abseil-cpp)) +# in the source tree of a project that uses it, install rules are disabled. +if(NOT "^${CMAKE_SOURCE_DIR}$" STREQUAL "^${PROJECT_SOURCE_DIR}$") + set(ABSL_ENABLE_INSTALL FALSE) +else() + set(ABSL_ENABLE_INSTALL TRUE) +endif() + list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/CMake ${CMAKE_CURRENT_LIST_DIR}/absl/copts ) include(GNUInstallDirs) +include(CMakePackageConfigHelpers) include(AbseilHelpers) @@ -73,11 +85,23 @@ if(${ABSL_RUN_TESTS}) enable_testing() endif() +# We don't support system-wide installation +list(APPEND SYSTEM_INSTALL_DIRS "/usr/local" "/usr" "/opt/" "/opt/local" "c:/Program Files/${PROJECT_NAME}") +if(NOT DEFINED CMAKE_INSTALL_PREFIX OR CMAKE_INSTALL_PREFIX IN_LIST SYSTEM_INSTALL_DIRS) + message(WARNING "\ +The default and system-level install directories are unsupported except in LTS \ +releases of Abseil. Please set CMAKE_INSTALL_PREFIX to install Abseil in your \ +source or build tree directly.\ + ") +endif() + ## check targets if(BUILD_TESTING) if(${ABSL_USE_GOOGLETEST_HEAD}) include(CMake/DownloadGTest.cmake) + set(absl_gtest_src_dir ${CMAKE_BINARY_DIR}/googletest-src) + set(absl_gtest_build_dir ${CMAKE_BINARY_DIR}/googletest-build) endif() check_target(gtest) @@ -93,3 +117,26 @@ if(BUILD_TESTING) endif() add_subdirectory(absl) + +# install as a subdirectory only +install(EXPORT ${PROJECT_NAME}Targets + NAMESPACE absl:: + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake" +) + +configure_package_config_file( + CMake/abslConfig.cmake.in + "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake" +) + +install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake +) + +install(DIRECTORY absl + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + FILES_MATCHING + PATTERN "*.inc" + PATTERN "*.h" +) 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_ diff --git a/ci/linux_clang-latest_libcxx_bazel.sh b/ci/linux_clang-latest_libcxx_bazel.sh new file mode 100755 index 00000000..741e48c4 --- /dev/null +++ b/ci/linux_clang-latest_libcxx_bazel.sh @@ -0,0 +1,62 @@ +#!/bin/bash +# +# 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. + +# This script that can be invoked to test abseil-cpp in a hermetic environment +# using a Docker image on Linux. You must have Docker installed to use this +# script. + +set -euox pipefail + +if [ -z ${ABSEIL_ROOT:-} ]; then + ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" +fi + +if [ -z ${STD:-} ]; then + STD="c++11 c++14 c++17" +fi + +if [ -z ${COMPILATION_MODE:-} ]; then + COMPILATION_MODE="fastbuild opt" +fi + +for std in ${STD}; do + for compilation_mode in ${COMPILATION_MODE}; do + echo "--------------------------------------------------------------------" + echo "Testing with --compilation_mode=${compilation_mode} and --std=${std}" + + time docker run \ + --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \ + --workdir=/abseil-cpp \ + --cap-add=SYS_PTRACE \ + --rm \ + -e CC="/opt/llvm/clang/bin/clang" \ + -e BAZEL_COMPILER="llvm" \ + -e BAZEL_CXXOPTS="-std=${std}:-nostdinc++" \ + -e BAZEL_LINKOPTS="-L/opt/llvm/libcxx/lib:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/libcxx/lib" \ + -e CPLUS_INCLUDE_PATH="/opt/llvm/libcxx/include/c++/v1" \ + gcr.io/google.com/absl-177019/linux_clang-latest:20190313 \ + /usr/local/bin/bazel test ... \ + --compilation_mode=${compilation_mode} \ + --copt=-Werror \ + --define="absl=1" \ + --keep_going \ + --show_timestamps \ + --test_env="GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1" \ + --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \ + --test_output=errors \ + --test_tag_filters=-benchmark + done +done diff --git a/ci/linux_clang-latest_libstdcxx_bazel.sh b/ci/linux_clang-latest_libstdcxx_bazel.sh new file mode 100755 index 00000000..d703a776 --- /dev/null +++ b/ci/linux_clang-latest_libstdcxx_bazel.sh @@ -0,0 +1,61 @@ +#!/bin/bash +# +# 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. + +# This script that can be invoked to test abseil-cpp in a hermetic environment +# using a Docker image on Linux. You must have Docker installed to use this +# script. + +set -euox pipefail + +if [ -z ${ABSEIL_ROOT:-} ]; then + ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" +fi + +if [ -z ${STD:-} ]; then + STD="c++11 c++14 c++17" +fi + +if [ -z ${COMPILATION_MODE:-} ]; then + COMPILATION_MODE="fastbuild opt" +fi + +for std in ${STD}; do + for compilation_mode in ${COMPILATION_MODE}; do + echo "--------------------------------------------------------------------" + echo "Testing with --compilation_mode=${compilation_mode} and --std=${std}" + + time docker run \ + --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \ + --workdir=/abseil-cpp \ + --cap-add=SYS_PTRACE \ + --rm \ + -e CC="/opt/llvm/clang/bin/clang" \ + -e BAZEL_COMPILER="llvm" \ + -e BAZEL_CXXOPTS="-std=${std}" \ + -e CPLUS_INCLUDE_PATH="/usr/include/c++/6" \ + gcr.io/google.com/absl-177019/linux_clang-latest:20190313 \ + /usr/local/bin/bazel test ... \ + --compilation_mode=${compilation_mode} \ + --copt=-Werror \ + --define="absl=1" \ + --keep_going \ + --show_timestamps \ + --test_env="GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1" \ + --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \ + --test_output=errors \ + --test_tag_filters=-benchmark + done +done diff --git a/ci/linux_gcc-4.8_libstdcxx_cmake.sh b/ci/linux_gcc-4.8_libstdcxx_cmake.sh new file mode 100755 index 00000000..4f964e2b --- /dev/null +++ b/ci/linux_gcc-4.8_libstdcxx_cmake.sh @@ -0,0 +1,61 @@ +#!/bin/bash +# +# 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. + +# TODO(absl-team): This script isn't fully hermetic because +# -DABSL_USE_GOOGLETEST_HEAD=ON means that this script isn't pinned to a fixed +# version of GoogleTest. This means that an upstream change to GoogleTest could +# break this test. Fix this by allowing this script to pin to a known-good +# version of GoogleTest. + +set -euox pipefail + +if [ -z ${ABSEIL_ROOT:-} ]; then + ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" +fi + +if [ -z ${ABSL_CMAKE_CXX_STANDARDS:-} ]; then + ABSL_CMAKE_CXX_STANDARDS="11 14" +fi + +if [ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]; then + ABSL_CMAKE_BUILD_TYPES="Debug Release" +fi + +for std in ${ABSL_CMAKE_CXX_STANDARDS}; do + for compilation_mode in ${ABSL_CMAKE_BUILD_TYPES}; do + echo "--------------------------------------------------------------------" + echo "Testing with CMAKE_BUILD_TYPE=${compilation_mode} and -std=c++${std}" + + time docker run \ + --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \ + --workdir=/abseil-cpp \ + --tmpfs=/buildfs:exec \ + --cap-add=SYS_PTRACE \ + --rm \ + -e CFLAGS="-Werror" \ + -e CXXFLAGS="-Werror" \ + gcr.io/google.com/absl-177019/linux_gcc-4.8:20190316 \ + /bin/bash -c " + cd /buildfs && \ + cmake /abseil-cpp \ + -DABSL_USE_GOOGLETEST_HEAD=ON \ + -DABSL_RUN_TESTS=ON \ + -DCMAKE_BUILD_TYPE=${compilation_mode} \ + -DCMAKE_CXX_STANDARD=${std} && \ + make -j$(nproc) VERBOSE=1 && \ + ctest -j$(nproc) --output-on-failure" + done +done diff --git a/ci/linux_gcc-latest_libstdcxx_bazel.sh b/ci/linux_gcc-latest_libstdcxx_bazel.sh new file mode 100755 index 00000000..e14a019c --- /dev/null +++ b/ci/linux_gcc-latest_libstdcxx_bazel.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# +# 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. + +# This script that can be invoked to test abseil-cpp in a hermetic environment +# using a Docker image on Linux. You must have Docker installed to use this +# script. + +set -euox pipefail + +if [ -z ${ABSEIL_ROOT:-} ]; then + ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" +fi + +if [ -z ${STD:-} ]; then + STD="c++11 c++14 c++17" +fi + +if [ -z ${COMPILATION_MODE:-} ]; then + COMPILATION_MODE="fastbuild opt" +fi + +for std in ${STD}; do + for compilation_mode in ${COMPILATION_MODE}; do + echo "--------------------------------------------------------------------" + echo "Testing with --compilation_mode=${compilation_mode} and --std=${std}" + + time docker run \ + --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \ + --workdir=/abseil-cpp \ + --cap-add=SYS_PTRACE \ + --rm \ + -e CC="/usr/local/bin/gcc" \ + -e BAZEL_CXXOPTS="-std=${std}" \ + gcr.io/google.com/absl-177019/linux_gcc-latest:20190318 \ + /usr/local/bin/bazel test ... \ + --compilation_mode=${compilation_mode} \ + --copt=-Werror \ + --define="absl=1" \ + --keep_going \ + --show_timestamps \ + --test_env="GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1" \ + --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \ + --test_output=errors \ + --test_tag_filters=-benchmark + done +done |