about summary refs log tree commit diff
diff options
context:
space:
mode:
-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 8fdd510ff2..6d26169dbb 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 0000000000..bf8c4f6a0e
--- /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 571e48c5fa..e3bb8d052d 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 7348d63262..752e47b239 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 1b2b8c2b8b..17858a7778 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 cdeb18c2a3..ac33df9e57 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 7874db718d..794564e12f 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 f83c7bc80d..b35673de50 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 d2d3182003..34a080cb15 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 2a5a384736..0fcc8d3bed 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 4cbbbe5942..6a4c093603 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 9b1641240c..3ac3f68ddf 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 4bd68c48b9..5cbad246c6 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 dde3e010af..b34674a62d 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 d5e186a942..58950cc2ff 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 4b9833eb55..b19a7ffab8 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 b32cea2960..e62b2eaeba 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 a8162d41c4..0b2c306ccc 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 e03f94eca1..66962294d0 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 b6592ca560..cd914baf88 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 76542be191..292fea2a83 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 0161d0a99c..2a8240ae7c 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 bae5c15d48..ebcb560fc0 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 80929e3666..6830875022 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 aff8d15f49..a308e78819 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 0000000000..3085060933
--- /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 9e79cb38c3..87511148d0 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 80c9819307..d02ea193c1 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 a001347d49..d23f40698e 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 4da8442de0..5a2d91a3aa 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 64c3f1eaa7..ca8003e629 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 d410a2322f..883b92db77 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 248966b072..25aa8bdf8c 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 a1cae96953..ffe3d1bda9 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 9935adfa70..9de8782f4c 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 94cb67475f..c0ede35ad5 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 a2430e7a65..af9593850a 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 1b3b4ef955..b43d3407dc 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 8a788dea7b..b1b149146b 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 29a6db69c2..912336e991 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 c0ec03d4e8..2f5b8ad7a8 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 8afe81770a..9640ff4627 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 03ab0ae76d..fd9be786a6 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 c54cd1ab51..4d48af066a 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 5d77856d94..99cc0afe4e 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 30235e08da..eb81f8a17c 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 334a1484b6..4e23fefbd5 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 ca93d1e3cb..6e04abef4d 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 445d4c3580..0423630473 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 69d6eaadff..cba8ceb024 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 486fe0ebd9..539d951621 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 8eb55089b5..7333078938 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 bd894e1daa..f8b20015df 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 a45ff03982..507bc4ff29 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 b2525b72f3..ebb16c56a7 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 543c4a031c..61c72e75d1 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 d22539dc49..b7014fb2b0 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 d373f63b25..e7da070ba7 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 bab6d1a169..74b0965018 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 f4ed0d0011..6b2eb33147 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 cf0f86dcac..c38e35616f 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 53c1f744a0..10211229be 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 19f51de7f0..82d111a549 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 f231e4f889..2dfcbd27fe 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 8ce4acbb50..67791feedf 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 4a68c7d588..fd04e2df39 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 799bf859f3..977a95173d 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 59e1dc6484..594396c751 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 00d0fb726d..5d7d8a5cfd 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 4926b3214a..5ca66e2902 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 c0488797ad..58906aa467 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 68842abb20..0665488ed5 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 8d8b5dbd00..ebd52d28b7 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 086fcff03d..76beb59592 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 9df702dff6..ab40ed2a72 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 62ce6f3ae1..853c1fb82e 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 0000000000..741e48c477
--- /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 0000000000..d703a7761c
--- /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 0000000000..4f964e2b0a
--- /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 0000000000..e14a019cd0
--- /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