summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2019-03-19 11:14:01 -0700
committerGravatar Derek Mauro <dmauro@google.com>2019-03-19 14:19:10 -0400
commitbf29470384a101b307873b26d358433138c857fc (patch)
tree1a8374bafdbfc606b4e70c0f581c3d6b34a08d7d
parent6fd827124facd8336981e73218997f9e73029b4f (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
-rw-r--r--CMake/AbseilHelpers.cmake39
-rw-r--r--CMake/abslConfig.cmake.in6
-rw-r--r--CMakeLists.txt47
-rw-r--r--absl/algorithm/container.h2
-rw-r--r--absl/base/const_init.h1
-rw-r--r--absl/base/dynamic_annotations.h1
-rw-r--r--absl/base/internal/cycleclock.h1
-rw-r--r--absl/base/internal/low_level_alloc.h1
-rw-r--r--absl/base/internal/low_level_alloc_test.cc1
-rw-r--r--absl/base/internal/low_level_scheduling.h3
-rw-r--r--absl/base/internal/raw_logging.h1
-rw-r--r--absl/base/internal/scoped_set_env.cc6
-rw-r--r--absl/base/internal/scoped_set_env_test.cc4
-rw-r--r--absl/base/internal/thread_identity.h1
-rw-r--r--absl/base/internal/unscaledcycleclock.h2
-rw-r--r--absl/base/log_severity.h1
-rw-r--r--absl/base/spinlock_test_common.cc2
-rw-r--r--absl/base/thread_annotations.h2
-rw-r--r--absl/compiler_config_setting.bzl1
-rw-r--r--absl/container/BUILD.bazel10
-rw-r--r--absl/container/CMakeLists.txt12
-rw-r--r--absl/container/fixed_array.h1
-rw-r--r--absl/container/flat_hash_map_test.cc7
-rw-r--r--absl/container/inlined_vector.h180
-rw-r--r--absl/container/internal/hashtablez_sampler.h1
-rw-r--r--absl/container/internal/inlined_vector.h130
-rw-r--r--absl/container/internal/raw_hash_set_test.cc2
-rw-r--r--absl/copts/GENERATED_AbseilCopts.cmake1
-rw-r--r--absl/copts/GENERATED_copts.bzl1
-rw-r--r--absl/copts/copts.py5
-rw-r--r--absl/debugging/internal/address_is_readable.h1
-rw-r--r--absl/debugging/internal/demangle_test.cc1
-rw-r--r--absl/debugging/internal/stacktrace_x86-inl.inc1
-rw-r--r--absl/debugging/leak_check.cc1
-rw-r--r--absl/debugging/stacktrace.cc1
-rw-r--r--absl/hash/hash.h1
-rw-r--r--absl/hash/hash_test.cc1
-rw-r--r--absl/hash/internal/city.h1
-rw-r--r--absl/meta/type_traits.h61
-rw-r--r--absl/meta/type_traits_test.cc81
-rw-r--r--absl/numeric/int128.h1
-rw-r--r--absl/strings/BUILD.bazel1
-rw-r--r--absl/strings/escaping.h2
-rw-r--r--absl/strings/internal/str_format/arg.h2
-rw-r--r--absl/strings/internal/str_format/convert_test.cc1
-rw-r--r--absl/strings/internal/str_format/extension.h1
-rw-r--r--absl/strings/internal/str_format/extension_test.cc1
-rw-r--r--absl/strings/internal/str_format/output_test.cc1
-rw-r--r--absl/strings/internal/utf8.h1
-rw-r--r--absl/strings/str_cat.h1
-rw-r--r--absl/strings/str_format.h1
-rw-r--r--absl/strings/str_split.h1
-rw-r--r--absl/strings/string_view.h2
-rw-r--r--absl/strings/substitute.h1
-rw-r--r--absl/synchronization/internal/create_thread_identity.h1
-rw-r--r--absl/synchronization/internal/kernel_timeout.h2
-rw-r--r--absl/synchronization/internal/per_thread_sem.cc1
-rw-r--r--absl/synchronization/internal/per_thread_sem.h1
-rw-r--r--absl/synchronization/internal/waiter.cc2
-rw-r--r--absl/synchronization/mutex.cc1
-rw-r--r--absl/synchronization/mutex.h4
-rw-r--r--absl/synchronization/mutex_test.cc6
-rw-r--r--absl/synchronization/notification.h1
-rw-r--r--absl/time/civil_time.h1
-rw-r--r--absl/time/duration.cc1
-rw-r--r--absl/time/internal/cctz/src/time_zone_lookup.cc2
-rw-r--r--absl/time/time.cc1
-rw-r--r--absl/time/time.h3
-rw-r--r--absl/types/any_exception_safety_test.cc1
-rw-r--r--absl/types/internal/variant.h5
-rw-r--r--absl/types/optional.h19
-rw-r--r--absl/types/optional_test.cc2
-rw-r--r--absl/types/variant.h17
-rw-r--r--absl/types/variant_exception_safety_test.cc9
-rw-r--r--absl/types/variant_test.cc1
-rw-r--r--absl/utility/utility.h1
-rwxr-xr-xci/linux_clang-latest_libcxx_bazel.sh62
-rwxr-xr-xci/linux_clang-latest_libstdcxx_bazel.sh61
-rwxr-xr-xci/linux_gcc-4.8_libstdcxx_cmake.sh61
-rwxr-xr-xci/linux_gcc-latest_libstdcxx_bazel.sh59
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