From 0cbdc774b97f7e80ab60dbe2ed4eaca3b2e33fc8 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Fri, 10 May 2019 12:38:49 -0700 Subject: Export of internal Abseil changes. -- ab1a58c85a462884413ec0022dc1fff19ccb8602 by Abseil Team : Clarified the documentation in str_format.h to say that use of absl::FormatSpec is ok for wrapper functions. Added tests that express this. PiperOrigin-RevId: 247657991 -- fef9481e58d579f1514babcb960ca60a51883fd8 by CJ Johnson : Adds exception safety tests for InlinedVector::InlinedVector() and InlinedVector::InlinedVector(const allocator_type&). PiperOrigin-RevId: 247617048 -- ef3217e1cd1e9a6ff5f2025e061b8ce3735af78f by Abseil Team : Internal change. PiperOrigin-RevId: 247614063 -- ed4c3345c4a04d8ec5c9e627058f17fce55925b1 by CJ Johnson : Update InlinedVector::clear() Introduces inlined_vector_exception_safety_test with the first test (clear), adds new benchmarks (for clear), and updates the implementation of clear. PiperOrigin-RevId: 247496049 -- 144a3a77c93bc8b2226da6f4b56166ee3d9868de by Derek Mauro : Internal change PiperOrigin-RevId: 247482532 -- 286bbb89e154d5424955b644edad5fe04be487f8 by Derek Mauro : Add scripts to run ASAN and TSAN on CI. PiperOrigin-RevId: 247479658 GitOrigin-RevId: ab1a58c85a462884413ec0022dc1fff19ccb8602 Change-Id: Ief4c5a62587d0c59d405735df469d498aa6bf101 --- ci/linux_clang-latest_libcxx_tsan_bazel.sh | 83 ++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100755 ci/linux_clang-latest_libcxx_tsan_bazel.sh (limited to 'ci/linux_clang-latest_libcxx_tsan_bazel.sh') diff --git a/ci/linux_clang-latest_libcxx_tsan_bazel.sh b/ci/linux_clang-latest_libcxx_tsan_bazel.sh new file mode 100755 index 00000000..c4edd198 --- /dev/null +++ b/ci/linux_clang-latest_libcxx_tsan_bazel.sh @@ -0,0 +1,83 @@ +#!/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 + +readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190508" + +# USE_BAZEL_CACHE=1 only works on Kokoro. +# Without access to the credentials this won't work. +if [ ${USE_BAZEL_CACHE:-0} -ne 0 ]; then + DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}" + # Bazel doesn't track changes to tools outside of the workspace + # (e.g. /usr/bin/gcc), so by appending the docker container to the + # remote_http_cache url, we make changes to the container part of + # the cache key. Hashing the key is to make it shorter and url-safe. + container_key=$(echo ${DOCKER_CONTAINER} | sha256sum | head -c 16) + BAZEL_EXTRA_ARGS="--remote_http_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}" +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-tsan/lib:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/libcxx-tsan/lib" \ + -e CPLUS_INCLUDE_PATH="/opt/llvm/libcxx-tsan/include/c++/v1" \ + ${DOCKER_EXTRA_ARGS:-} \ + ${DOCKER_CONTAINER} \ + /usr/local/bin/bazel test ... \ + --build_tag_filters="-notsan" \ + --compilation_mode=${compilation_mode} \ + --copt="-DDYNAMIC_ANNOTATIONS_ENABLED=1" \ + --copt="-DTHREAD_SANITIZER" \ + --copt="-fsanitize=thread" \ + --copt=-Werror \ + --keep_going \ + --linkopt="-fsanitize=thread" \ + --show_timestamps \ + --test_env="TSAN_OPTIONS=report_atomic_races=0" \ + --test_env="TSAN_SYMBOLIZER_PATH=/opt/llvm/clang/bin/llvm-symbolizer" \ + --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \ + --test_output=errors \ + --test_tag_filters="-benchmark,-notsan" \ + ${BAZEL_EXTRA_ARGS:-} + done +done -- cgit v1.2.3 From b1dd425423380126f6441ce4fbb6f8f6c75b793a Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Mon, 10 Jun 2019 12:49:13 -0700 Subject: Export of internal Abseil changes. -- 3febef1a42d092676134bd0b0d54d13a878198a2 by Derek Mauro : Update to LLVM r361107 and Bazel 0.26.1 PiperOrigin-RevId: 252463968 -- 0408a7f5c1f990414b2ee6efb615238fc44bcd3a by Gennadiy Civil : Import of CCTZ from GitHub. PiperOrigin-RevId: 252432385 GitOrigin-RevId: 3febef1a42d092676134bd0b0d54d13a878198a2 Change-Id: I9edade19982dfe490c7c4b894e094c4e7d80adb1 --- absl/copts/GENERATED_AbseilCopts.cmake | 2 -- absl/copts/GENERATED_copts.bzl | 2 -- absl/copts/copts.py | 2 -- absl/time/internal/cctz/src/time_zone_fixed.cc | 16 ++++++++-------- ci/linux_clang-latest_libcxx_asan_bazel.sh | 2 +- ci/linux_clang-latest_libcxx_bazel.sh | 2 +- ci/linux_clang-latest_libcxx_tsan_bazel.sh | 2 +- ci/linux_clang-latest_libstdcxx_bazel.sh | 2 +- 8 files changed, 12 insertions(+), 18 deletions(-) (limited to 'ci/linux_clang-latest_libcxx_tsan_bazel.sh') diff --git a/absl/copts/GENERATED_AbseilCopts.cmake b/absl/copts/GENERATED_AbseilCopts.cmake index c4948d42..927ef290 100644 --- a/absl/copts/GENERATED_AbseilCopts.cmake +++ b/absl/copts/GENERATED_AbseilCopts.cmake @@ -77,7 +77,6 @@ list(APPEND ABSL_CLANG_CL_TEST_FLAGS "-Wno-unused-template" "-Wno-used-but-marked-unused" "-Wno-zero-as-null-pointer-constant" - "-Wno-gnu-include-next" "-Wno-gnu-zero-variadic-macro-arguments" ) @@ -181,7 +180,6 @@ list(APPEND ABSL_LLVM_TEST_FLAGS "-Wno-unused-template" "-Wno-used-but-marked-unused" "-Wno-zero-as-null-pointer-constant" - "-Wno-gnu-include-next" "-Wno-gnu-zero-variadic-macro-arguments" ) diff --git a/absl/copts/GENERATED_copts.bzl b/absl/copts/GENERATED_copts.bzl index 422b3a9b..58bdfef9 100644 --- a/absl/copts/GENERATED_copts.bzl +++ b/absl/copts/GENERATED_copts.bzl @@ -78,7 +78,6 @@ ABSL_CLANG_CL_TEST_FLAGS = [ "-Wno-unused-template", "-Wno-used-but-marked-unused", "-Wno-zero-as-null-pointer-constant", - "-Wno-gnu-include-next", "-Wno-gnu-zero-variadic-macro-arguments", ] @@ -182,7 +181,6 @@ ABSL_LLVM_TEST_FLAGS = [ "-Wno-unused-template", "-Wno-used-but-marked-unused", "-Wno-zero-as-null-pointer-constant", - "-Wno-gnu-include-next", "-Wno-gnu-zero-variadic-macro-arguments", ] diff --git a/absl/copts/copts.py b/absl/copts/copts.py index 5bede34c..4594fda2 100644 --- a/absl/copts/copts.py +++ b/absl/copts/copts.py @@ -105,8 +105,6 @@ LLVM_TEST_DISABLE_WARNINGS_FLAGS = [ "-Wno-unused-template", "-Wno-used-but-marked-unused", "-Wno-zero-as-null-pointer-constant", - # For a libc++ bug fixed in r357267 - "-Wno-gnu-include-next", # gtest depends on this GNU extension being offered. "-Wno-gnu-zero-variadic-macro-arguments", ] diff --git a/absl/time/internal/cctz/src/time_zone_fixed.cc b/absl/time/internal/cctz/src/time_zone_fixed.cc index 81ece72b..b0d159a2 100644 --- a/absl/time/internal/cctz/src/time_zone_fixed.cc +++ b/absl/time/internal/cctz/src/time_zone_fixed.cc @@ -27,7 +27,7 @@ namespace cctz { namespace { // The prefix used for the internal names of fixed-offset zones. -const char kFixedOffsetPrefix[] = "Fixed/UTC"; +const char kFixedZonePrefix[] = "Fixed/UTC"; const char kDigits[] = "0123456789"; @@ -55,11 +55,11 @@ bool FixedOffsetFromName(const std::string& name, seconds* offset) { return true; } - const std::size_t prefix_len = sizeof(kFixedOffsetPrefix) - 1; - const char* const ep = kFixedOffsetPrefix + prefix_len; + const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1; + const char* const ep = kFixedZonePrefix + prefix_len; if (name.size() != prefix_len + 9) // +99:99:99 return false; - if (!std::equal(kFixedOffsetPrefix, ep, name.begin())) + if (!std::equal(kFixedZonePrefix, ep, name.begin())) return false; const char* np = name.data() + prefix_len; if (np[0] != '+' && np[0] != '-') @@ -102,9 +102,9 @@ std::string FixedOffsetToName(const seconds& offset) { } int hours = minutes / 60; minutes %= 60; - char buf[sizeof(kFixedOffsetPrefix) - 1 + sizeof("-24:00:00")]; - std::strcpy(buf, kFixedOffsetPrefix); - char* ep = buf + sizeof(kFixedOffsetPrefix) - 1; + const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1; + char buf[prefix_len + sizeof("-24:00:00")]; + char* ep = std::copy(kFixedZonePrefix, kFixedZonePrefix + prefix_len, buf); *ep++ = sign; ep = Format02d(ep, hours); *ep++ = ':'; @@ -118,7 +118,7 @@ std::string FixedOffsetToName(const seconds& offset) { std::string FixedOffsetToAbbr(const seconds& offset) { std::string abbr = FixedOffsetToName(offset); - const std::size_t prefix_len = sizeof(kFixedOffsetPrefix) - 1; + const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1; if (abbr.size() == prefix_len + 9) { // +99:99:99 abbr.erase(0, prefix_len); // +99:99:99 abbr.erase(6, 1); // +99:9999 diff --git a/ci/linux_clang-latest_libcxx_asan_bazel.sh b/ci/linux_clang-latest_libcxx_asan_bazel.sh index 113acdbe..a175810a 100755 --- a/ci/linux_clang-latest_libcxx_asan_bazel.sh +++ b/ci/linux_clang-latest_libcxx_asan_bazel.sh @@ -32,7 +32,7 @@ if [ -z ${COMPILATION_MODE:-} ]; then COMPILATION_MODE="fastbuild opt" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190508" +readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190610" # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. diff --git a/ci/linux_clang-latest_libcxx_bazel.sh b/ci/linux_clang-latest_libcxx_bazel.sh index f32cbef7..844fff5d 100755 --- a/ci/linux_clang-latest_libcxx_bazel.sh +++ b/ci/linux_clang-latest_libcxx_bazel.sh @@ -32,7 +32,7 @@ if [ -z ${COMPILATION_MODE:-} ]; then COMPILATION_MODE="fastbuild opt" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190508" +readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190610" # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. diff --git a/ci/linux_clang-latest_libcxx_tsan_bazel.sh b/ci/linux_clang-latest_libcxx_tsan_bazel.sh index c4edd198..b856b4e6 100755 --- a/ci/linux_clang-latest_libcxx_tsan_bazel.sh +++ b/ci/linux_clang-latest_libcxx_tsan_bazel.sh @@ -32,7 +32,7 @@ if [ -z ${COMPILATION_MODE:-} ]; then COMPILATION_MODE="fastbuild opt" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190508" +readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190610" # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. diff --git a/ci/linux_clang-latest_libstdcxx_bazel.sh b/ci/linux_clang-latest_libstdcxx_bazel.sh index 7bbecd6f..320b7cdf 100755 --- a/ci/linux_clang-latest_libstdcxx_bazel.sh +++ b/ci/linux_clang-latest_libstdcxx_bazel.sh @@ -32,7 +32,7 @@ if [ -z ${COMPILATION_MODE:-} ]; then COMPILATION_MODE="fastbuild opt" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190508" +readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190610" # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. -- cgit v1.2.3 From 8f11724067248acc330b4d1f12f0c76d03f2cfb1 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Thu, 13 Jun 2019 09:14:42 -0700 Subject: Export of internal Abseil changes. -- fc61fc3822d414a1abda906a81208d2667195de3 by Abseil Team : Clarify documentation relating to the output of the various printing functions. PiperOrigin-RevId: 253041344 -- 06cb414d1006cd89e38b381d52763b048909d69a by Jorg Brown : Change absl::container_internal::CompressedTuple to instantiate its internal Storage class with the name of the type it's holding, rather than the name of the Tuple. This is not an externally-visible change, other than less compiler memory is used and less debug information is generated. PiperOrigin-RevId: 252940185 -- 33b3f3ed6037eac7d1b7989a3641370e92beaeb9 by Jorg Brown : Change absl::container_internal::CompressedTuple to instantiate its internal Storage class with the name of the type it's holding, rather than the name of the Tuple. This is not an externally-visible change, other than less compiler memory is used and less debug information is generated. PiperOrigin-RevId: 252902091 -- 88595f4e7d6ac57bebdc9811045867f5d7477b5b by Abseil Team : Unset thread_local/__thread support for Emscripten. PiperOrigin-RevId: 252706297 -- cabd1715d873dc457271940335c764e62defb952 by Derek Mauro : Rollback LLVM and Bazel version due to intermittent network failures downloading from GitHub PiperOrigin-RevId: 252661245 GitOrigin-RevId: fc61fc3822d414a1abda906a81208d2667195de3 Change-Id: I4c30995a2db7acef19415ad519259131584db261 --- absl/base/config.h | 7 +++++++ absl/copts/GENERATED_AbseilCopts.cmake | 2 ++ absl/copts/GENERATED_copts.bzl | 2 ++ absl/copts/copts.py | 2 ++ absl/strings/str_cat.h | 3 ++- absl/strings/str_format.h | 11 +++++++++-- absl/strings/substitute.h | 7 +++++-- ci/linux_clang-latest_libcxx_asan_bazel.sh | 2 +- ci/linux_clang-latest_libcxx_bazel.sh | 2 +- ci/linux_clang-latest_libcxx_tsan_bazel.sh | 2 +- ci/linux_clang-latest_libstdcxx_bazel.sh | 2 +- 11 files changed, 33 insertions(+), 9 deletions(-) (limited to 'ci/linux_clang-latest_libcxx_tsan_bazel.sh') diff --git a/absl/base/config.h b/absl/base/config.h index 2a14fe74..f12f84fd 100644 --- a/absl/base/config.h +++ b/absl/base/config.h @@ -181,6 +181,13 @@ #endif #endif // defined(__ANDROID__) && defined(__clang__) +// Emscripten doesn't yet support `thread_local` or `__thread`. +// https://github.com/emscripten-core/emscripten/issues/3502 +#if defined(__EMSCRIPTEN__) +#undef ABSL_HAVE_TLS +#undef ABSL_HAVE_THREAD_LOCAL +#endif // defined(__EMSCRIPTEN__) + // ABSL_HAVE_INTRINSIC_INT128 // // Checks whether the __int128 compiler extension for a 128-bit integral type is diff --git a/absl/copts/GENERATED_AbseilCopts.cmake b/absl/copts/GENERATED_AbseilCopts.cmake index 927ef290..c4948d42 100644 --- a/absl/copts/GENERATED_AbseilCopts.cmake +++ b/absl/copts/GENERATED_AbseilCopts.cmake @@ -77,6 +77,7 @@ list(APPEND ABSL_CLANG_CL_TEST_FLAGS "-Wno-unused-template" "-Wno-used-but-marked-unused" "-Wno-zero-as-null-pointer-constant" + "-Wno-gnu-include-next" "-Wno-gnu-zero-variadic-macro-arguments" ) @@ -180,6 +181,7 @@ list(APPEND ABSL_LLVM_TEST_FLAGS "-Wno-unused-template" "-Wno-used-but-marked-unused" "-Wno-zero-as-null-pointer-constant" + "-Wno-gnu-include-next" "-Wno-gnu-zero-variadic-macro-arguments" ) diff --git a/absl/copts/GENERATED_copts.bzl b/absl/copts/GENERATED_copts.bzl index 58bdfef9..422b3a9b 100644 --- a/absl/copts/GENERATED_copts.bzl +++ b/absl/copts/GENERATED_copts.bzl @@ -78,6 +78,7 @@ ABSL_CLANG_CL_TEST_FLAGS = [ "-Wno-unused-template", "-Wno-used-but-marked-unused", "-Wno-zero-as-null-pointer-constant", + "-Wno-gnu-include-next", "-Wno-gnu-zero-variadic-macro-arguments", ] @@ -181,6 +182,7 @@ ABSL_LLVM_TEST_FLAGS = [ "-Wno-unused-template", "-Wno-used-but-marked-unused", "-Wno-zero-as-null-pointer-constant", + "-Wno-gnu-include-next", "-Wno-gnu-zero-variadic-macro-arguments", ] diff --git a/absl/copts/copts.py b/absl/copts/copts.py index 4594fda2..5bede34c 100644 --- a/absl/copts/copts.py +++ b/absl/copts/copts.py @@ -105,6 +105,8 @@ LLVM_TEST_DISABLE_WARNINGS_FLAGS = [ "-Wno-unused-template", "-Wno-used-but-marked-unused", "-Wno-zero-as-null-pointer-constant", + # For a libc++ bug fixed in r357267 + "-Wno-gnu-include-next", # gtest depends on this GNU extension being offered. "-Wno-gnu-zero-variadic-macro-arguments", ] diff --git a/absl/strings/str_cat.h b/absl/strings/str_cat.h index 559ee0aa..a99aac01 100644 --- a/absl/strings/str_cat.h +++ b/absl/strings/str_cat.h @@ -37,7 +37,8 @@ // attempt to pass ':' instead of ":" might result in a 58 ending up in your // result. // -// Bools convert to "0" or "1". +// Bools convert to "0" or "1". Pointers to types other than `char *` are not +// valid inputs. No output is generated for null `char *` pointers. // // Floating point numbers are formatted with six-digit precision, which is // the default for "std::cout <<" or printf "%g" (the same as "%.6g"). diff --git a/absl/strings/str_format.h b/absl/strings/str_format.h index da3208e1..0b93c288 100644 --- a/absl/strings/str_format.h +++ b/absl/strings/str_format.h @@ -20,7 +20,8 @@ // The `str_format` library is a typesafe replacement for the family of // `printf()` string formatting routines within the `` standard library // header. Like the `printf` family, the `str_format` uses a "format string" to -// perform argument substitutions based on types. +// perform argument substitutions based on types. See the `FormatSpec` section +// below for format string documentation. // // Example: // @@ -67,6 +68,7 @@ // In addition, the `str_format` library provides extension points for // augmenting formatting to new types. These extensions are fully documented // within the `str_format_extension.h` header file. + #ifndef ABSL_STRINGS_STR_FORMAT_H_ #define ABSL_STRINGS_STR_FORMAT_H_ @@ -211,6 +213,11 @@ class FormatCountCapture { // written to this point. The resulting value must be captured within an // `absl::FormatCountCapture` type. // +// Implementation-defined behavior: +// * A null pointer provided to "%s" or "%p" is output as "(nil)". +// * A non-null pointer provided to "%p" is output in hex as if by %#x or +// %#lx. +// // NOTE: `o`, `x\X` and `u` will convert signed values to their unsigned // counterpart before formatting. // @@ -226,7 +233,7 @@ class FormatCountCapture { // "%e", .01 -> "1.00000e-2" // "%a", -3.0 -> "-0x1.8p+1" // "%g", .01 -> "1e-2" -// "%p", *int -> "0x7ffdeb6ad2a4" +// "%p", (void*)&value -> "0x7ffdeb6ad2a4" // // int n = 0; // std::string s = absl::StrFormat( diff --git a/absl/strings/substitute.h b/absl/strings/substitute.h index 32dec30b..233e9dcf 100644 --- a/absl/strings/substitute.h +++ b/absl/strings/substitute.h @@ -35,10 +35,13 @@ // and single digit positional ids to indicate which substitution arguments to // use at that location within the format string. // +// A '$$' sequence in the format string causes a literal '$' character to be +// output. +// // Example 1: -// std::string s = Substitute("$1 purchased $0 $2. Thanks $1!", +// std::string s = Substitute("$1 purchased $0 $2 for $$10. Thanks $1!", // 5, "Bob", "Apples"); -// EXPECT_EQ("Bob purchased 5 Apples. Thanks Bob!", s); +// EXPECT_EQ("Bob purchased 5 Apples for $10. Thanks Bob!", s); // // Example 2: // std::string s = "Hi. "; diff --git a/ci/linux_clang-latest_libcxx_asan_bazel.sh b/ci/linux_clang-latest_libcxx_asan_bazel.sh index a175810a..113acdbe 100755 --- a/ci/linux_clang-latest_libcxx_asan_bazel.sh +++ b/ci/linux_clang-latest_libcxx_asan_bazel.sh @@ -32,7 +32,7 @@ if [ -z ${COMPILATION_MODE:-} ]; then COMPILATION_MODE="fastbuild opt" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190610" +readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190508" # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. diff --git a/ci/linux_clang-latest_libcxx_bazel.sh b/ci/linux_clang-latest_libcxx_bazel.sh index 844fff5d..f32cbef7 100755 --- a/ci/linux_clang-latest_libcxx_bazel.sh +++ b/ci/linux_clang-latest_libcxx_bazel.sh @@ -32,7 +32,7 @@ if [ -z ${COMPILATION_MODE:-} ]; then COMPILATION_MODE="fastbuild opt" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190610" +readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190508" # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. diff --git a/ci/linux_clang-latest_libcxx_tsan_bazel.sh b/ci/linux_clang-latest_libcxx_tsan_bazel.sh index b856b4e6..c4edd198 100755 --- a/ci/linux_clang-latest_libcxx_tsan_bazel.sh +++ b/ci/linux_clang-latest_libcxx_tsan_bazel.sh @@ -32,7 +32,7 @@ if [ -z ${COMPILATION_MODE:-} ]; then COMPILATION_MODE="fastbuild opt" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190610" +readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190508" # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. diff --git a/ci/linux_clang-latest_libstdcxx_bazel.sh b/ci/linux_clang-latest_libstdcxx_bazel.sh index 320b7cdf..7bbecd6f 100755 --- a/ci/linux_clang-latest_libstdcxx_bazel.sh +++ b/ci/linux_clang-latest_libstdcxx_bazel.sh @@ -32,7 +32,7 @@ if [ -z ${COMPILATION_MODE:-} ]; then COMPILATION_MODE="fastbuild opt" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190610" +readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190508" # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. -- cgit v1.2.3 From e6b050212c859fbaf67abac76105da10ec348274 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Tue, 2 Jul 2019 12:50:48 -0700 Subject: Export of internal Abseil changes. -- c2e2e2b21c3fe59b63279e7418c93c7289ee3e27 by Mark Barolak : Import of CCTZ from GitHub. PiperOrigin-RevId: 256220326 -- 3996b01f0c3eb60f72825b154dce8019b6215f1d by Derek Mauro : Add GCC 4.9 test script. This will become our new minumum version and GCC 4.8 will be removed soon. PiperOrigin-RevId: 256160891 -- 2c13aa44bc8e497ebae9abe8b8adf73c2152622d by Abseil Team : [Trivial] tweak flat_hash_map.h doc comment The comment is probably right both ways, but the lack of an "if" here seemed jarring to me. PiperOrigin-RevId: 256089069 -- 16bc03b9b30fbf08d7dc61025fa8ec4b57077be8 by Abseil Team : Fix symbolization for elf files whose SYMTAB section is stripped, but have a DYNSYM section. Previously, if we did not find a SYMTAB section, we would bail out of symbolization early, rather than checking the DYNSYM section. PiperOrigin-RevId: 256061954 -- 4c60ee329b1eeb0b0d10c4f76f282e5fbae2c5b2 by Derek Mauro : Update to LLVM r363242 and Bazel 0.27.0 PiperOrigin-RevId: 256024405 -- 18e1ba970d33f122026803d8ca90035b9088949d by Eric Fiselier : Disable variant tests that break with P0608R3 PiperOrigin-RevId: 255975764 -- 0a89858464977e86096b62476faa3b64eb94aa1d by Abseil Team : Internal change PiperOrigin-RevId: 255891019 -- 9b7424cac66f5407f0ed74ed288bf3099a4fa330 by CJ Johnson : Updates the implementation of InlinedVector::insert(...) to be exception safe and adds an exception safety tests for insert(...) PiperOrigin-RevId: 255881809 -- 1288f4ba3883c510d92b09437fb8b051c19aa241 by CJ Johnson : Updates the implementation of InlinedVector::insert(...) to be exception safe and adds an exception safety tests for insert(...) PiperOrigin-RevId: 255875277 -- 39c04f3621491eaff9e2eda619718d5b5f20fbd9 by Abseil Team : Use a typedef to allow building with NVCC Without this change NVCC fails to compile compressed_tuple.h. NVCC is relevant because TensorFlow uses NVCC on Ubuntu and inclues abseil. PiperOrigin-RevId: 255850176 -- e23f0309ccad69eb508ca02c9034cd4cdd740da0 by Abseil Team : Internal change PiperOrigin-RevId: 255787167 -- 054aafcebf595077054164f1da3703124ab209b4 by Abseil Team : Updates the ScopedAllocatorWorks test for InlinedVector to not rely on the byte count allocated by the standard library In doing so, removes LegacyNextCapacityFrom(...) impl function from InlinedVector Also applies clang-format to the test file PiperOrigin-RevId: 255760356 -- eb05fc9f78e3a163c93f1866e9fe9a8ad0d01622 by Abseil Team : Internal change PiperOrigin-RevId: 255706834 -- 97abb824417604c45d9fcbb3e4ff1aa3000836f2 by Jorg Brown : Enhance compatibility of abseil's strings package with nvcc. PiperOrigin-RevId: 255688500 -- efc5b9c221ee31e15d10b35d31c8f3ae6eddaa8c by Abseil Team : Follow CCTZ's lead and allow GetWeekday() and GetYearDay() to be called with any civil-time type. A CivilSecond, for example, has a weekday just as much as a CivilDay does. PiperOrigin-RevId: 255659840 -- a75acbe954457919d8c6c8f4c2339b543760b375 by Derek Mauro : Increase the timeout of randen_engine_test. It seems to timeout under TSAN often enough to justify the increase. PiperOrigin-RevId: 255628086 -- 160976ba47c7c6eb57af08e21f8eb640aa51e91b by Derek Mauro : Update CMake documentation Fixes https://github.com/abseil/abseil-cpp/issues/332 PiperOrigin-RevId: 255607313 GitOrigin-RevId: c2e2e2b21c3fe59b63279e7418c93c7289ee3e27 Change-Id: Iba4ac7ed23cbcdb22965b4958601f689be92cda4 --- CMake/README.md | 16 +-- absl/container/flat_hash_map.h | 2 +- absl/container/inlined_vector_test.cc | 135 ++++++++++++--------- absl/container/internal/compressed_tuple.h | 11 +- absl/container/internal/inlined_vector.h | 16 ++- absl/copts/GENERATED_AbseilCopts.cmake | 2 - absl/copts/GENERATED_copts.bzl | 2 - absl/copts/copts.py | 2 - absl/debugging/symbolize_elf.inc | 48 +++----- absl/random/internal/BUILD.bazel | 10 +- absl/strings/BUILD.bazel | 1 - absl/strings/CMakeLists.txt | 1 - absl/strings/internal/str_format/bind.h | 20 ++- absl/strings/str_format_test.cc | 17 +-- absl/time/civil_time.h | 12 +- absl/time/civil_time_test.cc | 12 ++ .../internal/cctz/include/cctz/civil_time_detail.h | 14 +-- absl/time/internal/cctz/src/time_zone_info.cc | 4 +- absl/time/time.cc | 5 +- absl/time/time_test.cc | 16 +-- absl/types/variant_test.cc | 12 +- ci/linux_clang-latest_libcxx_asan_bazel.sh | 2 +- ci/linux_clang-latest_libcxx_bazel.sh | 2 +- ci/linux_clang-latest_libcxx_tsan_bazel.sh | 2 +- ci/linux_clang-latest_libstdcxx_bazel.sh | 2 +- ci/linux_gcc-4.9_libstdcxx_bazel.sh | 75 ++++++++++++ ci/linux_gcc-latest_libstdcxx_bazel.sh | 2 +- 27 files changed, 284 insertions(+), 159 deletions(-) create mode 100755 ci/linux_gcc-4.9_libstdcxx_bazel.sh (limited to 'ci/linux_clang-latest_libcxx_tsan_bazel.sh') diff --git a/CMake/README.md b/CMake/README.md index 02359d36..469dfef5 100644 --- a/CMake/README.md +++ b/CMake/README.md @@ -37,20 +37,12 @@ section of your executable or of your library.
Here is a short CMakeLists.txt example of a project file using Abseil. ```cmake -cmake_minimum_required(VERSION 2.8.12) +cmake_minimum_required(VERSION 3.5) project(my_project) -set(CMAKE_CXX_FLAGS "-std=c++11 -stdlib=libc++ ${CMAKE_CXX_FLAGS}") - -if(MSVC) - # /wd4005 macro-redefinition - # /wd4068 unknown pragma - # /wd4244 conversion from 'type1' to 'type2' - # /wd4267 conversion from 'size_t' to 'type2' - # /wd4800 force value to bool 'true' or 'false' (performance warning) - add_compile_options(/wd4005 /wd4068 /wd4244 /wd4267 /wd4800) - add_definitions(/DNOMINMAX /DWIN32_LEAN_AND_MEAN=1 /D_CRT_SECURE_NO_WARNINGS) -endif() +# Pick the C++ standard to compile with. +# Abseil currently supports C++11, C++14, and C++17. +set(CMAKE_CXX_STANDARD 11) add_subdirectory(abseil-cpp) diff --git a/absl/container/flat_hash_map.h b/absl/container/flat_hash_map.h index 00cc4dcf..0bc501b1 100644 --- a/absl/container/flat_hash_map.h +++ b/absl/container/flat_hash_map.h @@ -77,7 +77,7 @@ struct FlatHashMapPolicy; // NOTE: A `flat_hash_map` stores its value types directly inside its // implementation array to avoid memory indirection. Because a `flat_hash_map` // is designed to move data when rehashed, map values will not retain pointer -// stability. If you require pointer stability, or your values are large, +// stability. If you require pointer stability, or if your values are large, // consider using `absl::flat_hash_map>` instead. // If your types are not moveable or you require pointer stability for keys, // consider `absl::node_hash_map`. diff --git a/absl/container/inlined_vector_test.cc b/absl/container/inlined_vector_test.cc index 50315b83..60fe89b2 100644 --- a/absl/container/inlined_vector_test.cc +++ b/absl/container/inlined_vector_test.cc @@ -76,9 +76,12 @@ TYPED_TEST_SUITE_P(InstanceTest); // destroyed in the erase(begin, end) test. class RefCounted { public: - RefCounted(int value, int* count) : value_(value), count_(count) { Ref(); } + RefCounted(int value, int* count) : value_(value), count_(count) { + Ref(); + } - RefCounted(const RefCounted& v) : value_(v.value_), count_(v.count_) { + RefCounted(const RefCounted& v) + : value_(v.value_), count_(v.count_) { Ref(); } @@ -287,7 +290,7 @@ TEST(RefCountedVec, EraseBeginEnd) { } // Check that the elements at the end are preserved. - for (int i = erase_end; i < len; ++i) { + for (int i = erase_end; i< len; ++i) { EXPECT_EQ(1, counts[i]); } } @@ -549,10 +552,10 @@ TEST(IntVec, Resize) { static const int kResizeElem = 1000000; for (int k = 0; k < 10; k++) { // Enlarging resize - v.resize(len + k, kResizeElem); - EXPECT_EQ(len + k, v.size()); - EXPECT_LE(len + k, v.capacity()); - for (int i = 0; i < len + k; i++) { + v.resize(len+k, kResizeElem); + EXPECT_EQ(len+k, v.size()); + EXPECT_LE(len+k, v.capacity()); + for (int i = 0; i < len+k; i++) { if (i < len) { EXPECT_EQ(i, v[i]); } else { @@ -863,7 +866,7 @@ TYPED_TEST_P(InstanceTest, Swap) { auto min_len = std::min(l1, l2); auto max_len = std::max(l1, l2); for (int i = 0; i < l1; i++) a.push_back(Instance(i)); - for (int i = 0; i < l2; i++) b.push_back(Instance(100 + i)); + for (int i = 0; i < l2; i++) b.push_back(Instance(100+i)); EXPECT_EQ(tracker.instances(), l1 + l2); tracker.ResetCopiesMovesSwaps(); { @@ -931,7 +934,7 @@ TEST(IntVec, EqualAndNotEqual) { EXPECT_FALSE(a == b); EXPECT_TRUE(a != b); - b[i] = b[i] - 1; // Back to before + b[i] = b[i] - 1; // Back to before EXPECT_TRUE(a == b); EXPECT_FALSE(a != b); } @@ -998,7 +1001,7 @@ TYPED_TEST_P(InstanceTest, CountConstructorsDestructors) { // reserve() must not increase the number of initialized objects SCOPED_TRACE("reserve"); - v.reserve(len + 1000); + v.reserve(len+1000); EXPECT_EQ(tracker.instances(), len); EXPECT_EQ(tracker.copies() + tracker.moves(), len); @@ -1244,8 +1247,9 @@ void InstanceCountElemAssignWithAllocationTest() { absl::InlinedVector v(original_contents.begin(), original_contents.end()); v.assign(3, Instance(123)); - EXPECT_THAT(v, AllOf(SizeIs(3), ElementsAre(ValueIs(123), ValueIs(123), - ValueIs(123)))); + EXPECT_THAT(v, + AllOf(SizeIs(3), + ElementsAre(ValueIs(123), ValueIs(123), ValueIs(123)))); EXPECT_LE(v.size(), v.capacity()); } } @@ -1524,8 +1528,8 @@ TYPED_TEST_P(InstanceTest, InitializerListAssign) { SCOPED_TRACE(original_size); absl::InlinedVector v(original_size, Instance(12345)); v.assign({Instance(3), Instance(4), Instance(5)}); - EXPECT_THAT( - v, AllOf(SizeIs(3), ElementsAre(ValueIs(3), ValueIs(4), ValueIs(5)))); + EXPECT_THAT(v, AllOf(SizeIs(3), + ElementsAre(ValueIs(3), ValueIs(4), ValueIs(5)))); EXPECT_LE(3, v.capacity()); } } @@ -1550,7 +1554,7 @@ TEST(DynamicVec, DynamicVecCompiles) { TEST(AllocatorSupportTest, Constructors) { using MyAlloc = CountingAllocator; using AllocVec = absl::InlinedVector; - const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7}; + const int ia[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; int64_t allocated = 0; MyAlloc alloc(&allocated); { AllocVec ABSL_ATTRIBUTE_UNUSED v; } @@ -1566,7 +1570,7 @@ TEST(AllocatorSupportTest, Constructors) { TEST(AllocatorSupportTest, CountAllocations) { using MyAlloc = CountingAllocator; using AllocVec = absl::InlinedVector; - const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7}; + const int ia[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; int64_t allocated = 0; MyAlloc alloc(&allocated); { @@ -1630,8 +1634,8 @@ TEST(AllocatorSupportTest, SwapBothAllocated) { int64_t allocated1 = 0; int64_t allocated2 = 0; { - const int ia1[] = {0, 1, 2, 3, 4, 5, 6, 7}; - const int ia2[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; + const int ia1[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + const int ia2[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; MyAlloc a1(&allocated1); MyAlloc a2(&allocated2); AllocVec v1(ia1, ia1 + ABSL_ARRAYSIZE(ia1), a1); @@ -1655,8 +1659,8 @@ TEST(AllocatorSupportTest, SwapOneAllocated) { int64_t allocated1 = 0; int64_t allocated2 = 0; { - const int ia1[] = {0, 1, 2, 3, 4, 5, 6, 7}; - const int ia2[] = {0, 1, 2, 3}; + const int ia1[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + const int ia2[] = { 0, 1, 2, 3 }; MyAlloc a1(&allocated1); MyAlloc a2(&allocated2); AllocVec v1(ia1, ia1 + ABSL_ARRAYSIZE(ia1), a1); @@ -1677,42 +1681,65 @@ TEST(AllocatorSupportTest, SwapOneAllocated) { TEST(AllocatorSupportTest, ScopedAllocatorWorks) { using StdVector = std::vector>; - using Alloc = CountingAllocator; - using ScopedAlloc = std::scoped_allocator_adaptor; - using AllocVec = absl::InlinedVector; - - { - int64_t total_allocated_byte_count = 0; - - AllocVec inlined_case(ScopedAlloc(Alloc(+&total_allocated_byte_count))); - inlined_case.emplace_back(); - - int64_t absl_responsible_for_count = total_allocated_byte_count; - EXPECT_EQ(absl_responsible_for_count, 0); - - inlined_case[0].emplace_back(); - EXPECT_GT(total_allocated_byte_count, absl_responsible_for_count); - - inlined_case.clear(); - EXPECT_EQ(total_allocated_byte_count, 0); - } - - { - int64_t total_allocated_byte_count = 0; - - AllocVec allocated_case(ScopedAlloc(Alloc(+&total_allocated_byte_count))); - allocated_case.emplace_back(); - allocated_case.emplace_back(); - - int64_t absl_responsible_for_count = total_allocated_byte_count; - EXPECT_GT(absl_responsible_for_count, 0); + using MyAlloc = + std::scoped_allocator_adaptor>; + using AllocVec = absl::InlinedVector; + + // MSVC 2017's std::vector allocates different amounts of memory in debug + // versus opt mode. + int64_t test_allocated = 0; + StdVector v(CountingAllocator{&test_allocated}); + // The amount of memory allocated by a default constructed vector + auto default_std_vec_allocated = test_allocated; + v.push_back(1); + // The amound of memory allocated by a copy-constructed vector with one + // element. + int64_t one_element_std_vec_copy_allocated = test_allocated; - allocated_case[1].emplace_back(); - EXPECT_GT(total_allocated_byte_count, absl_responsible_for_count); + int64_t allocated = 0; + AllocVec vec(MyAlloc{CountingAllocator{&allocated}}); + EXPECT_EQ(allocated, 0); - allocated_case.clear(); - EXPECT_EQ(total_allocated_byte_count, 0); - } + // This default constructs a vector, but the allocator should pass itself + // into the vector, so check allocation compared to that. + // The absl::InlinedVector does not allocate any memory. + // The vector may allocate any memory. + auto expected = default_std_vec_allocated; + vec.resize(1); + EXPECT_EQ(allocated, expected); + + // We make vector allocate memory. + // It must go through the allocator even though we didn't construct the + // vector directly. This assumes that vec[0] doesn't need to grow its + // allocation. + expected += sizeof(int); + vec[0].push_back(1); + EXPECT_EQ(allocated, expected); + + // Another allocating vector. + expected += one_element_std_vec_copy_allocated; + vec.push_back(vec[0]); + EXPECT_EQ(allocated, expected); + + // Overflow the inlined memory. + // The absl::InlinedVector will now allocate. + expected += sizeof(StdVector) * 8 + default_std_vec_allocated * 3; + vec.resize(5); + EXPECT_EQ(allocated, expected); + + // Adding one more in external mode should also work. + expected += one_element_std_vec_copy_allocated; + vec.push_back(vec[0]); + EXPECT_EQ(allocated, expected); + + // And extending these should still work. This assumes that vec[0] does not + // need to grow its allocation. + expected += sizeof(int); + vec[0].push_back(1); + EXPECT_EQ(allocated, expected); + + vec.clear(); + EXPECT_EQ(allocated, 0); } TEST(AllocatorSupportTest, SizeAllocConstructor) { diff --git a/absl/container/internal/compressed_tuple.h b/absl/container/internal/compressed_tuple.h index 1713ad68..c29ab41e 100644 --- a/absl/container/internal/compressed_tuple.h +++ b/absl/container/internal/compressed_tuple.h @@ -188,6 +188,9 @@ class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple template using ElemT = internal_compressed_tuple::ElemT; + template + using StorageT = internal_compressed_tuple::Storage, I>; + public: constexpr CompressedTuple() = default; explicit constexpr CompressedTuple(Ts... base) @@ -200,19 +203,17 @@ class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple template constexpr const ElemT& get() const& { - return internal_compressed_tuple::Storage, I>::get(); + return StorageT::get(); } template ElemT&& get() && { - return std::move(*this) - .internal_compressed_tuple::template Storage, I>::get(); + return std::move(*this).StorageT::get(); } template constexpr const ElemT&& get() const&& { - return absl::move(*this) - .internal_compressed_tuple::template Storage, I>::get(); + return absl::move(*this).StorageT::get(); } }; diff --git a/absl/container/internal/inlined_vector.h b/absl/container/internal/inlined_vector.h index 84b97791..0ab2d7da 100644 --- a/absl/container/internal/inlined_vector.h +++ b/absl/container/internal/inlined_vector.h @@ -402,6 +402,16 @@ class Storage { return current_capacity * 2; } + static size_type LegacyNextCapacityFrom(size_type current_capacity, + size_type requested_capacity) { + // TODO(johnsoncj): Get rid of this old behavior. + size_type new_capacity = current_capacity; + while (new_capacity < requested_capacity) { + new_capacity *= 2; + } + return new_capacity; + } + using Metadata = container_internal::CompressedTuple; @@ -512,7 +522,8 @@ auto Storage::Resize(ValueAdapter values, size_type new_size) -> void { absl::Span destroy_loop; if (new_size > storage_view.capacity) { - pointer new_data = allocation_tx.Allocate(new_size); + pointer new_data = allocation_tx.Allocate( + LegacyNextCapacityFrom(storage_view.capacity, new_size)); // Construct new objects in `new_data` construct_loop = {new_data + storage_view.size, @@ -632,7 +643,8 @@ auto Storage::Reserve(size_type requested_capacity) -> void { IteratorValueAdapter move_values( MoveIterator(storage_view.data)); - pointer new_data = allocation_tx.Allocate(requested_capacity); + pointer new_data = allocation_tx.Allocate( + LegacyNextCapacityFrom(storage_view.capacity, requested_capacity)); inlined_vector_internal::ConstructElements(GetAllocPtr(), new_data, &move_values, storage_view.size); diff --git a/absl/copts/GENERATED_AbseilCopts.cmake b/absl/copts/GENERATED_AbseilCopts.cmake index 88400e98..01bd40b2 100644 --- a/absl/copts/GENERATED_AbseilCopts.cmake +++ b/absl/copts/GENERATED_AbseilCopts.cmake @@ -77,7 +77,6 @@ list(APPEND ABSL_CLANG_CL_TEST_FLAGS "-Wno-unused-template" "-Wno-used-but-marked-unused" "-Wno-zero-as-null-pointer-constant" - "-Wno-gnu-include-next" "-Wno-gnu-zero-variadic-macro-arguments" ) @@ -181,7 +180,6 @@ list(APPEND ABSL_LLVM_TEST_FLAGS "-Wno-unused-template" "-Wno-used-but-marked-unused" "-Wno-zero-as-null-pointer-constant" - "-Wno-gnu-include-next" "-Wno-gnu-zero-variadic-macro-arguments" ) diff --git a/absl/copts/GENERATED_copts.bzl b/absl/copts/GENERATED_copts.bzl index d7edc936..82f332f4 100644 --- a/absl/copts/GENERATED_copts.bzl +++ b/absl/copts/GENERATED_copts.bzl @@ -78,7 +78,6 @@ ABSL_CLANG_CL_TEST_FLAGS = [ "-Wno-unused-template", "-Wno-used-but-marked-unused", "-Wno-zero-as-null-pointer-constant", - "-Wno-gnu-include-next", "-Wno-gnu-zero-variadic-macro-arguments", ] @@ -182,7 +181,6 @@ ABSL_LLVM_TEST_FLAGS = [ "-Wno-unused-template", "-Wno-used-but-marked-unused", "-Wno-zero-as-null-pointer-constant", - "-Wno-gnu-include-next", "-Wno-gnu-zero-variadic-macro-arguments", ] diff --git a/absl/copts/copts.py b/absl/copts/copts.py index d850bb4f..068abceb 100644 --- a/absl/copts/copts.py +++ b/absl/copts/copts.py @@ -105,8 +105,6 @@ LLVM_TEST_DISABLE_WARNINGS_FLAGS = [ "-Wno-unused-template", "-Wno-used-but-marked-unused", "-Wno-zero-as-null-pointer-constant", - # For a libc++ bug fixed in r357267 - "-Wno-gnu-include-next", # gtest depends on this GNU extension being offered. "-Wno-gnu-zero-variadic-macro-arguments", ] diff --git a/absl/debugging/symbolize_elf.inc b/absl/debugging/symbolize_elf.inc index 5ac7ff5d..e7305213 100644 --- a/absl/debugging/symbolize_elf.inc +++ b/absl/debugging/symbolize_elf.inc @@ -762,37 +762,27 @@ FindSymbolResult Symbolizer::GetSymbolFromObjectFile( } } - // Consult a regular symbol table first. - if (!GetSectionHeaderByType(obj.fd, obj.elf_header.e_shnum, - obj.elf_header.e_shoff, SHT_SYMTAB, &symtab, - tmp_buf, tmp_buf_size)) { - return SYMBOL_NOT_FOUND; - } - if (!ReadFromOffsetExact( - obj.fd, &strtab, sizeof(strtab), - obj.elf_header.e_shoff + symtab.sh_link * sizeof(symtab))) { - return SYMBOL_NOT_FOUND; - } - const FindSymbolResult rc = - FindSymbol(pc, obj.fd, out, out_size, relocation, &strtab, &symtab, - opd_ptr, tmp_buf, tmp_buf_size); - if (rc != SYMBOL_NOT_FOUND) { - return rc; // Found the symbol in a regular symbol table. + // Consult a regular symbol table, then fall back to the dynamic symbol table. + for (const auto symbol_table_type : {SHT_SYMTAB, SHT_DYNSYM}) { + if (!GetSectionHeaderByType(obj.fd, obj.elf_header.e_shnum, + obj.elf_header.e_shoff, symbol_table_type, + &symtab, tmp_buf, tmp_buf_size)) { + continue; + } + if (!ReadFromOffsetExact( + obj.fd, &strtab, sizeof(strtab), + obj.elf_header.e_shoff + symtab.sh_link * sizeof(symtab))) { + continue; + } + const FindSymbolResult rc = + FindSymbol(pc, obj.fd, out, out_size, relocation, &strtab, &symtab, + opd_ptr, tmp_buf, tmp_buf_size); + if (rc != SYMBOL_NOT_FOUND) { + return rc; + } } - // If the symbol is not found, then consult a dynamic symbol table. - if (!GetSectionHeaderByType(obj.fd, obj.elf_header.e_shnum, - obj.elf_header.e_shoff, SHT_DYNSYM, &symtab, - tmp_buf, tmp_buf_size)) { - return SYMBOL_NOT_FOUND; - } - if (!ReadFromOffsetExact( - obj.fd, &strtab, sizeof(strtab), - obj.elf_header.e_shoff + symtab.sh_link * sizeof(symtab))) { - return SYMBOL_NOT_FOUND; - } - return FindSymbol(pc, obj.fd, out, out_size, relocation, &strtab, &symtab, - opd_ptr, tmp_buf, tmp_buf_size); + return SYMBOL_NOT_FOUND; } namespace { diff --git a/absl/random/internal/BUILD.bazel b/absl/random/internal/BUILD.bazel index c9e4e880..fd5471a6 100644 --- a/absl/random/internal/BUILD.bazel +++ b/absl/random/internal/BUILD.bazel @@ -522,7 +522,7 @@ cc_test( cc_test( name = "randen_engine_test", - size = "small", + size = "medium", srcs = [ "randen_engine_test.cc", ], @@ -598,12 +598,12 @@ cc_library( copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ + ":distribution_impl", + ":fast_uniform_bits", + ":iostream_state_saver", + ":traits", "//absl/base:core_headers", "//absl/meta:type_traits", - "//absl/random/internal:distribution_impl", - "//absl/random/internal:fast_uniform_bits", - "//absl/random/internal:iostream_state_saver", - "//absl/random/internal:traits", ], ) diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel index f18b1600..20511a35 100644 --- a/absl/strings/BUILD.bazel +++ b/absl/strings/BUILD.bazel @@ -559,7 +559,6 @@ cc_library( ":strings", "//absl/base:config", "//absl/base:core_headers", - "//absl/container:inlined_vector", "//absl/meta:type_traits", "//absl/numeric:int128", "//absl/types:span", diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt index f7821290..e63eec19 100644 --- a/absl/strings/CMakeLists.txt +++ b/absl/strings/CMakeLists.txt @@ -387,7 +387,6 @@ absl_cc_library( absl::strings absl::config absl::core_headers - absl::inlined_vector absl::type_traits absl::int128 absl::span diff --git a/absl/strings/internal/str_format/bind.h b/absl/strings/internal/str_format/bind.h index 4f782952..7df140a4 100644 --- a/absl/strings/internal/str_format/bind.h +++ b/absl/strings/internal/str_format/bind.h @@ -7,7 +7,6 @@ #include #include "absl/base/port.h" -#include "absl/container/inlined_vector.h" #include "absl/strings/internal/str_format/arg.h" #include "absl/strings/internal/str_format/checker.h" #include "absl/strings/internal/str_format/parser.h" @@ -138,7 +137,17 @@ class Streamable { public: Streamable(const UntypedFormatSpecImpl& format, absl::Span args) - : format_(format), args_(args.begin(), args.end()) {} + : format_(format) { + if (args.size() <= ABSL_ARRAYSIZE(few_args_)) { + for (size_t i = 0; i < args.size(); ++i) { + few_args_[i] = args[i]; + } + args_ = absl::MakeSpan(few_args_, args.size()); + } else { + many_args_.assign(args.begin(), args.end()); + args_ = many_args_; + } + } std::ostream& Print(std::ostream& os) const; @@ -148,7 +157,12 @@ class Streamable { private: const UntypedFormatSpecImpl& format_; - absl::InlinedVector args_; + absl::Span args_; + // if args_.size() is 4 or less: + FormatArgImpl few_args_[4] = {FormatArgImpl(0), FormatArgImpl(0), + FormatArgImpl(0), FormatArgImpl(0)}; + // if args_.size() is more than 4: + std::vector many_args_; }; // for testing diff --git a/absl/strings/str_format_test.cc b/absl/strings/str_format_test.cc index 96c62349..cfd81bb3 100644 --- a/absl/strings/str_format_test.cc +++ b/absl/strings/str_format_test.cc @@ -30,8 +30,8 @@ TEST_F(FormatEntryPointTest, UntypedFormat) { "", "a", "%80d", -#if !defined(_MSC_VER) && !defined(__ANDROID__) - // MSVC and Android don't support positional syntax. +#if !defined(_MSC_VER) && !defined(__ANDROID__) && !defined(__native_client__) + // MSVC, NaCL and Android don't support positional syntax. "complicated multipart %% %1$d format %1$0999d", #endif // _MSC_VER }; @@ -153,17 +153,20 @@ TEST_F(FormatEntryPointTest, Stream) { "", "a", "%80d", -#if !defined(_MSC_VER) && !defined(__ANDROID__) - // MSVC doesn't support positional syntax. + "%d %u %c %s %f %g", +#if !defined(_MSC_VER) && !defined(__ANDROID__) && !defined(__native_client__) + // MSVC, NaCL and Android don't support positional syntax. "complicated multipart %% %1$d format %1$080d", #endif // _MSC_VER }; std::string buf(4096, '\0'); for (const auto& fmt : formats) { - const auto parsed = ParsedFormat<'d'>::NewAllowIgnored(fmt); + const auto parsed = + ParsedFormat<'d', 'u', 'c', 's', 'f', 'g'>::NewAllowIgnored(fmt); std::ostringstream oss; - oss << StreamFormat(*parsed, 123); - int fmt_result = snprintf(&*buf.begin(), buf.size(), fmt.c_str(), 123); + oss << StreamFormat(*parsed, 123, 3, 49, "multistreaming!!!", 1.01, 1.01); + int fmt_result = snprintf(&*buf.begin(), buf.size(), fmt.c_str(), // + 123, 3, 49, "multistreaming!!!", 1.01, 1.01); ASSERT_TRUE(oss) << fmt; ASSERT_TRUE(fmt_result >= 0 && static_cast(fmt_result) < buf.size()) << fmt_result; diff --git a/absl/time/civil_time.h b/absl/time/civil_time.h index 6bb7eec7..beaf7d89 100644 --- a/absl/time/civil_time.h +++ b/absl/time/civil_time.h @@ -370,15 +370,15 @@ using Weekday = time_internal::cctz::weekday; // GetWeekday() // -// Returns the absl::Weekday for the given absl::CivilDay. +// Returns the absl::Weekday for the given (realigned) civil-time value. // // Example: // // absl::CivilDay a(2015, 8, 13); // absl::Weekday wd = absl::GetWeekday(a); // wd == absl::Weekday::thursday // -inline Weekday GetWeekday(CivilDay cd) { - return time_internal::cctz::get_weekday(cd); +inline Weekday GetWeekday(CivilSecond cs) { + return time_internal::cctz::get_weekday(cs); } // NextWeekday() @@ -420,7 +420,7 @@ inline CivilDay PrevWeekday(CivilDay cd, Weekday wd) { // GetYearDay() // -// Returns the day-of-year for the given absl::CivilDay. +// Returns the day-of-year for the given (realigned) civil-time value. // // Example: // @@ -429,8 +429,8 @@ inline CivilDay PrevWeekday(CivilDay cd, Weekday wd) { // absl::CivilDay b(2015, 12, 31); // int yd_dec_31 = absl::GetYearDay(b); // yd_dec_31 = 365 // -inline int GetYearDay(CivilDay cd) { - return time_internal::cctz::get_yearday(cd); +inline int GetYearDay(CivilSecond cs) { + return time_internal::cctz::get_yearday(cs); } // FormatCivilTime() diff --git a/absl/time/civil_time_test.cc b/absl/time/civil_time_test.cc index 070f0d57..03cd1f12 100644 --- a/absl/time/civil_time_test.cc +++ b/absl/time/civil_time_test.cc @@ -616,6 +616,8 @@ TEST(CivilTime, Properties) { EXPECT_EQ(4, ss.hour()); EXPECT_EQ(5, ss.minute()); EXPECT_EQ(6, ss.second()); + EXPECT_EQ(absl::Weekday::tuesday, absl::GetWeekday(ss)); + EXPECT_EQ(34, absl::GetYearDay(ss)); absl::CivilMinute mm(2015, 2, 3, 4, 5, 6); EXPECT_EQ(2015, mm.year()); @@ -624,6 +626,8 @@ TEST(CivilTime, Properties) { EXPECT_EQ(4, mm.hour()); EXPECT_EQ(5, mm.minute()); EXPECT_EQ(0, mm.second()); + EXPECT_EQ(absl::Weekday::tuesday, absl::GetWeekday(mm)); + EXPECT_EQ(34, absl::GetYearDay(mm)); absl::CivilHour hh(2015, 2, 3, 4, 5, 6); EXPECT_EQ(2015, hh.year()); @@ -632,6 +636,8 @@ TEST(CivilTime, Properties) { EXPECT_EQ(4, hh.hour()); EXPECT_EQ(0, hh.minute()); EXPECT_EQ(0, hh.second()); + EXPECT_EQ(absl::Weekday::tuesday, absl::GetWeekday(hh)); + EXPECT_EQ(34, absl::GetYearDay(hh)); absl::CivilDay d(2015, 2, 3, 4, 5, 6); EXPECT_EQ(2015, d.year()); @@ -640,6 +646,8 @@ TEST(CivilTime, Properties) { EXPECT_EQ(0, d.hour()); EXPECT_EQ(0, d.minute()); EXPECT_EQ(0, d.second()); + EXPECT_EQ(absl::Weekday::tuesday, absl::GetWeekday(d)); + EXPECT_EQ(34, absl::GetYearDay(d)); absl::CivilMonth m(2015, 2, 3, 4, 5, 6); EXPECT_EQ(2015, m.year()); @@ -648,6 +656,8 @@ TEST(CivilTime, Properties) { EXPECT_EQ(0, m.hour()); EXPECT_EQ(0, m.minute()); EXPECT_EQ(0, m.second()); + EXPECT_EQ(absl::Weekday::sunday, absl::GetWeekday(m)); + EXPECT_EQ(32, absl::GetYearDay(m)); absl::CivilYear y(2015, 2, 3, 4, 5, 6); EXPECT_EQ(2015, y.year()); @@ -656,6 +666,8 @@ TEST(CivilTime, Properties) { EXPECT_EQ(0, y.hour()); EXPECT_EQ(0, y.minute()); EXPECT_EQ(0, y.second()); + EXPECT_EQ(absl::Weekday::thursday, absl::GetWeekday(y)); + EXPECT_EQ(1, absl::GetYearDay(y)); } TEST(CivilTime, Format) { diff --git a/absl/time/internal/cctz/include/cctz/civil_time_detail.h b/absl/time/internal/cctz/include/cctz/civil_time_detail.h index 0dcb1ad4..433078a7 100644 --- a/absl/time/internal/cctz/include/cctz/civil_time_detail.h +++ b/absl/time/internal/cctz/include/cctz/civil_time_detail.h @@ -535,8 +535,7 @@ enum class weekday { sunday, }; -template -CONSTEXPR_F weekday get_weekday(const civil_time& ct) noexcept { +CONSTEXPR_F weekday get_weekday(const civil_second& cs) noexcept { CONSTEXPR_D weekday k_weekday_by_mon_off[13] = { weekday::monday, weekday::tuesday, weekday::wednesday, weekday::thursday, weekday::friday, weekday::saturday, @@ -547,9 +546,9 @@ CONSTEXPR_F weekday get_weekday(const civil_time& ct) noexcept { CONSTEXPR_D int k_weekday_offsets[1 + 12] = { -1, 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4, }; - year_t wd = 2400 + (ct.year() % 400) - (ct.month() < 3); + year_t wd = 2400 + (cs.year() % 400) - (cs.month() < 3); wd += wd / 4 - wd / 100 + wd / 400; - wd += k_weekday_offsets[ct.month()] + ct.day(); + wd += k_weekday_offsets[cs.month()] + cs.day(); return k_weekday_by_mon_off[wd % 7 + 6]; } @@ -595,13 +594,12 @@ CONSTEXPR_F civil_day prev_weekday(civil_day cd, weekday wd) noexcept { } } -template -CONSTEXPR_F int get_yearday(const civil_time& ct) noexcept { +CONSTEXPR_F int get_yearday(const civil_second& cs) noexcept { CONSTEXPR_D int k_month_offsets[1 + 12] = { -1, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, }; - const int feb29 = (ct.month() > 2 && impl::is_leap_year(ct.year())); - return k_month_offsets[ct.month()] + feb29 + ct.day(); + const int feb29 = (cs.month() > 2 && impl::is_leap_year(cs.year())); + return k_month_offsets[cs.month()] + feb29 + cs.day(); } //////////////////////////////////////////////////////////////////////// diff --git a/absl/time/internal/cctz/src/time_zone_info.cc b/absl/time/internal/cctz/src/time_zone_info.cc index 184bd434..72bb3bde 100644 --- a/absl/time/internal/cctz/src/time_zone_info.cc +++ b/absl/time/internal/cctz/src/time_zone_info.cc @@ -505,9 +505,9 @@ bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) { if (tzh.tzh_version[0] != '\0') { // Snarf up the NL-enclosed future POSIX spec. Note // that version '3' files utilize an extended format. - auto get_char = [](ZoneInfoSource* zip) -> int { + auto get_char = [](ZoneInfoSource* azip) -> int { unsigned char ch; // all non-EOF results are positive - return (zip->Read(&ch, 1) == 1) ? ch : EOF; + return (azip->Read(&ch, 1) == 1) ? ch : EOF; }; if (get_char(zip) != '\n') return false; diff --git a/absl/time/time.cc b/absl/time/time.cc index 338c4523..6a387bce 100644 --- a/absl/time/time.cc +++ b/absl/time/time.cc @@ -457,8 +457,7 @@ struct tm ToTM(absl::Time t, absl::TimeZone tz) { tm.tm_year = static_cast(cs.year() - 1900); } - const CivilDay cd(cs); - switch (GetWeekday(cd)) { + switch (GetWeekday(cs)) { case Weekday::sunday: tm.tm_wday = 0; break; @@ -481,7 +480,7 @@ struct tm ToTM(absl::Time t, absl::TimeZone tz) { tm.tm_wday = 6; break; } - tm.tm_yday = GetYearDay(cd) - 1; + tm.tm_yday = GetYearDay(cs) - 1; tm.tm_isdst = ci.is_dst ? 1 : 0; return tm; diff --git a/absl/time/time_test.cc b/absl/time/time_test.cc index e2b2f809..37af39d9 100644 --- a/absl/time/time_test.cc +++ b/absl/time/time_test.cc @@ -112,7 +112,7 @@ TEST(Time, UnixEpoch) { const auto ci = absl::UTCTimeZone().At(absl::UnixEpoch()); EXPECT_EQ(absl::CivilSecond(1970, 1, 1, 0, 0, 0), ci.cs); EXPECT_EQ(absl::ZeroDuration(), ci.subsecond); - EXPECT_EQ(absl::Weekday::thursday, absl::GetWeekday(absl::CivilDay(ci.cs))); + EXPECT_EQ(absl::Weekday::thursday, absl::GetWeekday(ci.cs)); } TEST(Time, Breakdown) { @@ -123,14 +123,14 @@ TEST(Time, Breakdown) { auto ci = tz.At(t); EXPECT_CIVIL_INFO(ci, 1969, 12, 31, 19, 0, 0, -18000, false); EXPECT_EQ(absl::ZeroDuration(), ci.subsecond); - EXPECT_EQ(absl::Weekday::wednesday, absl::GetWeekday(absl::CivilDay(ci.cs))); + EXPECT_EQ(absl::Weekday::wednesday, absl::GetWeekday(ci.cs)); // Just before the epoch. t -= absl::Nanoseconds(1); ci = tz.At(t); EXPECT_CIVIL_INFO(ci, 1969, 12, 31, 18, 59, 59, -18000, false); EXPECT_EQ(absl::Nanoseconds(999999999), ci.subsecond); - EXPECT_EQ(absl::Weekday::wednesday, absl::GetWeekday(absl::CivilDay(ci.cs))); + EXPECT_EQ(absl::Weekday::wednesday, absl::GetWeekday(ci.cs)); // Some time later. t += absl::Hours(24) * 2735; @@ -139,7 +139,7 @@ TEST(Time, Breakdown) { ci = tz.At(t); EXPECT_CIVIL_INFO(ci, 1977, 6, 28, 14, 30, 15, -14400, true); EXPECT_EQ(8, ci.subsecond / absl::Nanoseconds(1)); - EXPECT_EQ(absl::Weekday::tuesday, absl::GetWeekday(absl::CivilDay(ci.cs))); + EXPECT_EQ(absl::Weekday::tuesday, absl::GetWeekday(ci.cs)); } TEST(Time, AdditiveOperators) { @@ -979,15 +979,15 @@ TEST(Time, ConversionSaturation) { EXPECT_CIVIL_INFO(ci, std::numeric_limits::max(), 12, 31, 23, 59, 59, 0, false); EXPECT_EQ(absl::InfiniteDuration(), ci.subsecond); - EXPECT_EQ(absl::Weekday::thursday, absl::GetWeekday(absl::CivilDay(ci.cs))); - EXPECT_EQ(365, absl::GetYearDay(absl::CivilDay(ci.cs))); + EXPECT_EQ(absl::Weekday::thursday, absl::GetWeekday(ci.cs)); + EXPECT_EQ(365, absl::GetYearDay(ci.cs)); EXPECT_STREQ("-00", ci.zone_abbr); // artifact of TimeZone::At() ci = utc.At(absl::InfinitePast()); EXPECT_CIVIL_INFO(ci, std::numeric_limits::min(), 1, 1, 0, 0, 0, 0, false); EXPECT_EQ(-absl::InfiniteDuration(), ci.subsecond); - EXPECT_EQ(absl::Weekday::sunday, absl::GetWeekday(absl::CivilDay(ci.cs))); - EXPECT_EQ(1, absl::GetYearDay(absl::CivilDay(ci.cs))); + EXPECT_EQ(absl::Weekday::sunday, absl::GetWeekday(ci.cs)); + EXPECT_EQ(1, absl::GetYearDay(ci.cs)); EXPECT_STREQ("-00", ci.zone_abbr); // artifact of TimeZone::At() // Approach the maximal Time value from below. diff --git a/absl/types/variant_test.cc b/absl/types/variant_test.cc index 2efaf21e..85201b3e 100644 --- a/absl/types/variant_test.cc +++ b/absl/types/variant_test.cc @@ -2112,7 +2112,8 @@ TEST(VariantTest, Hash) { // Miscellaneous and deprecated tests // //////////////////////////////////////// -// Test that a set requiring a basic type conversion works correctly. +// Test that a set requiring a basic type conversion works correctly +#if !defined(ABSL_HAVE_STD_VARIANT) TEST(VariantTest, TestConvertingSet) { typedef variant Variant; Variant v(1.0); @@ -2122,6 +2123,7 @@ TEST(VariantTest, TestConvertingSet) { ASSERT_TRUE(nullptr != absl::get_if(&v)); EXPECT_DOUBLE_EQ(2, absl::get(v)); } +#endif // ABSL_HAVE_STD_VARIANT // Test that a vector of variants behaves reasonably. TEST(VariantTest, Container) { @@ -2273,6 +2275,7 @@ struct Convertible2 { }; TEST(VariantTest, TestRvalueConversion) { +#if !defined(ABSL_HAVE_STD_VARIANT) variant var( ConvertVariantTo>( variant(0))); @@ -2305,6 +2308,7 @@ TEST(VariantTest, TestRvalueConversion) { variant2 = ConvertVariantTo>(variant(42)); ASSERT_TRUE(absl::holds_alternative(variant2)); EXPECT_EQ(42, absl::get(variant2)); +#endif // !ABSL_HAVE_STD_VARIANT variant variant3( ConvertVariantTo>( @@ -2317,6 +2321,7 @@ TEST(VariantTest, TestRvalueConversion) { } TEST(VariantTest, TestLvalueConversion) { +#if !defined(ABSL_HAVE_STD_VARIANT) variant source1 = 0; variant destination( ConvertVariantTo>(source1)); @@ -2353,6 +2358,7 @@ TEST(VariantTest, TestLvalueConversion) { variant2 = ConvertVariantTo>(source6); ASSERT_TRUE(absl::holds_alternative(variant2)); EXPECT_EQ(42, absl::get(variant2)); +#endif variant source7((Convertible1())); variant variant3( @@ -2417,6 +2423,7 @@ TEST(VariantTest, DoesNotMoveFromLvalues) { } TEST(VariantTest, TestRvalueConversionViaConvertVariantTo) { +#if !defined(ABSL_HAVE_STD_VARIANT) variant var( ConvertVariantTo>( variant(3))); @@ -2442,6 +2449,7 @@ TEST(VariantTest, TestRvalueConversionViaConvertVariantTo) { variant2 = ConvertVariantTo>(variant(42)); EXPECT_THAT(absl::get_if(&variant2), Pointee(42)); +#endif variant variant3( ConvertVariantTo>( @@ -2454,6 +2462,7 @@ TEST(VariantTest, TestRvalueConversionViaConvertVariantTo) { } TEST(VariantTest, TestLvalueConversionViaConvertVariantTo) { +#if !defined(ABSL_HAVE_STD_VARIANT) variant source1 = 3; variant destination( ConvertVariantTo>(source1)); @@ -2485,6 +2494,7 @@ TEST(VariantTest, TestLvalueConversionViaConvertVariantTo) { variant source6(42); variant2 = ConvertVariantTo>(source6); EXPECT_THAT(absl::get_if(&variant2), Pointee(42)); +#endif // !ABSL_HAVE_STD_VARIANT variant source7((Convertible1())); variant variant3( diff --git a/ci/linux_clang-latest_libcxx_asan_bazel.sh b/ci/linux_clang-latest_libcxx_asan_bazel.sh index 113acdbe..4d1d28a9 100755 --- a/ci/linux_clang-latest_libcxx_asan_bazel.sh +++ b/ci/linux_clang-latest_libcxx_asan_bazel.sh @@ -32,7 +32,7 @@ if [ -z ${COMPILATION_MODE:-} ]; then COMPILATION_MODE="fastbuild opt" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190508" +readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190701" # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. diff --git a/ci/linux_clang-latest_libcxx_bazel.sh b/ci/linux_clang-latest_libcxx_bazel.sh index f32cbef7..1197369a 100755 --- a/ci/linux_clang-latest_libcxx_bazel.sh +++ b/ci/linux_clang-latest_libcxx_bazel.sh @@ -32,7 +32,7 @@ if [ -z ${COMPILATION_MODE:-} ]; then COMPILATION_MODE="fastbuild opt" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190508" +readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190701" # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. diff --git a/ci/linux_clang-latest_libcxx_tsan_bazel.sh b/ci/linux_clang-latest_libcxx_tsan_bazel.sh index c4edd198..04171df8 100755 --- a/ci/linux_clang-latest_libcxx_tsan_bazel.sh +++ b/ci/linux_clang-latest_libcxx_tsan_bazel.sh @@ -32,7 +32,7 @@ if [ -z ${COMPILATION_MODE:-} ]; then COMPILATION_MODE="fastbuild opt" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190508" +readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190701" # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. diff --git a/ci/linux_clang-latest_libstdcxx_bazel.sh b/ci/linux_clang-latest_libstdcxx_bazel.sh index 7bbecd6f..c2217a07 100755 --- a/ci/linux_clang-latest_libstdcxx_bazel.sh +++ b/ci/linux_clang-latest_libstdcxx_bazel.sh @@ -32,7 +32,7 @@ if [ -z ${COMPILATION_MODE:-} ]; then COMPILATION_MODE="fastbuild opt" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190508" +readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190701" # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. diff --git a/ci/linux_gcc-4.9_libstdcxx_bazel.sh b/ci/linux_gcc-4.9_libstdcxx_bazel.sh new file mode 100755 index 00000000..bdd3e468 --- /dev/null +++ b/ci/linux_gcc-4.9_libstdcxx_bazel.sh @@ -0,0 +1,75 @@ +#!/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" +fi + +if [ -z ${COMPILATION_MODE:-} ]; then + COMPILATION_MODE="fastbuild opt" +fi + +readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-4.9:20190702" + +# USE_BAZEL_CACHE=1 only works on Kokoro. +# Without access to the credentials this won't work. +if [ ${USE_BAZEL_CACHE:-0} -ne 0 ]; then + DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}" + # Bazel doesn't track changes to tools outside of the workspace + # (e.g. /usr/bin/gcc), so by appending the docker container to the + # remote_http_cache url, we make changes to the container part of + # the cache key. Hashing the key is to make it shorter and url-safe. + container_key=$(echo ${DOCKER_CONTAINER} | sha256sum | head -c 16) + BAZEL_EXTRA_ARGS="--remote_http_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}" +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/bin/gcc-4.9" \ + -e BAZEL_CXXOPTS="-std=${std}" \ + ${DOCKER_EXTRA_ARGS:-} \ + ${DOCKER_CONTAINER} \ + /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 \ + ${BAZEL_EXTRA_ARGS:-} + done +done diff --git a/ci/linux_gcc-latest_libstdcxx_bazel.sh b/ci/linux_gcc-latest_libstdcxx_bazel.sh index 24469628..2ef81114 100755 --- a/ci/linux_gcc-latest_libstdcxx_bazel.sh +++ b/ci/linux_gcc-latest_libstdcxx_bazel.sh @@ -32,7 +32,7 @@ if [ -z ${COMPILATION_MODE:-} ]; then COMPILATION_MODE="fastbuild opt" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-latest:20190318" +readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-latest:20190701" # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. -- cgit v1.2.3 From d9aa92d7fb324314f9df487ac23d32a25650b742 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Tue, 13 Aug 2019 10:20:16 -0700 Subject: Export of internal Abseil changes -- 2dd3b23ea940804de727e396b300cfae4b1b71a1 by Derek Mauro : Upgrade to LLVM r366207 and Bazel 0.28.1 for Linux-Clang testing. PiperOrigin-RevId: 263162761 -- f03ae9e4e9f42c075745d28b4ced78071e73724a by Derek Mauro : Remove unneeded dependencies on //absl/base from targets that no longer depend on it. PiperOrigin-RevId: 263129193 -- 8ec2aab1eea50e7f71a6a687a07e5ae0e0945f5e by Derek Mauro : Move raw_logging to a separate target (raw_logging_internal) PiperOrigin-RevId: 262972007 GitOrigin-RevId: 2dd3b23ea940804de727e396b300cfae4b1b71a1 Change-Id: I3f4580e87797386b0b5e90c8ced74cbf078f61c1 --- absl/base/BUILD.bazel | 20 ++++++++++++++------ absl/base/CMakeLists.txt | 21 +++++++++++++++------ absl/container/BUILD.bazel | 11 ++++++----- absl/container/CMakeLists.txt | 9 +++++---- absl/debugging/BUILD.bazel | 16 +++++++++------- absl/debugging/CMakeLists.txt | 17 ++++++++++------- absl/flags/BUILD.bazel | 6 +++--- absl/flags/CMakeLists.txt | 8 ++++---- absl/memory/BUILD.bazel | 1 - absl/memory/CMakeLists.txt | 1 - absl/random/BUILD.bazel | 18 +++++++++--------- absl/random/CMakeLists.txt | 29 +++++++++++++++-------------- absl/random/internal/BUILD.bazel | 17 +++++++++-------- absl/strings/BUILD.bazel | 18 ++++++++---------- absl/strings/CMakeLists.txt | 11 +++++------ absl/synchronization/BUILD.bazel | 10 ++++++---- absl/synchronization/CMakeLists.txt | 8 +++++--- absl/time/BUILD.bazel | 4 ++-- absl/time/CMakeLists.txt | 24 ++++++++++++------------ absl/types/BUILD.bazel | 12 ++++++------ absl/types/CMakeLists.txt | 14 +++++++------- ci/linux_clang-latest_libcxx_asan_bazel.sh | 2 +- ci/linux_clang-latest_libcxx_bazel.sh | 2 +- ci/linux_clang-latest_libcxx_tsan_bazel.sh | 2 +- ci/linux_clang-latest_libstdcxx_bazel.sh | 2 +- 25 files changed, 154 insertions(+), 129 deletions(-) (limited to 'ci/linux_clang-latest_libcxx_tsan_bazel.sh') diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel index a512272a..bfdc7ab5 100644 --- a/absl/base/BUILD.bazel +++ b/absl/base/BUILD.bazel @@ -48,11 +48,19 @@ cc_library( cc_library( name = "raw_logging_internal", + srcs = ["internal/raw_logging.cc"], + hdrs = ["internal/raw_logging.h"], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, visibility = [ "//absl:__subpackages__", ], + deps = [ + ":atomic_hook", + ":config", + ":core_headers", + ":log_severity", + ], ) cc_library( @@ -137,6 +145,7 @@ cc_library( ":config", ":core_headers", ":dynamic_annotations", + ":raw_logging_internal", ":spinlock_wait", ], ) @@ -164,7 +173,6 @@ cc_library( name = "base", srcs = [ "internal/cycleclock.cc", - "internal/raw_logging.cc", "internal/spinlock.cc", "internal/sysinfo.cc", "internal/thread_identity.cc", @@ -176,7 +184,6 @@ cc_library( "internal/cycleclock.h", "internal/low_level_scheduling.h", "internal/per_thread_tls.h", - "internal/raw_logging.h", "internal/spinlock.h", "internal/sysinfo.h", "internal/thread_identity.h", @@ -195,6 +202,7 @@ cc_library( ":core_headers", ":dynamic_annotations", ":log_severity", + ":raw_logging_internal", ":spinlock_wait", "//absl/meta:type_traits", ], @@ -238,8 +246,8 @@ cc_library( "//absl:__subpackages__", ], deps = [ - ":base", ":config", + ":raw_logging_internal", ], ) @@ -382,6 +390,7 @@ cc_library( deps = [ ":base", ":base_internal", + ":raw_logging_internal", "//absl/synchronization", "@com_github_google_benchmark//:benchmark_main", ], @@ -455,7 +464,7 @@ cc_test( copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ - ":base", + ":raw_logging_internal", "//absl/strings", "@com_google_googletest//:gtest_main", ], @@ -543,7 +552,7 @@ cc_library( visibility = [ "//absl:__subpackages__", ], - deps = [":base"], + deps = [":raw_logging_internal"], ) cc_test( @@ -565,7 +574,6 @@ cc_test( copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ - ":base", ":log_severity", "@com_google_googletest//:gtest_main", ], diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt index cc7960e3..bd56b5c3 100644 --- a/absl/base/CMakeLists.txt +++ b/absl/base/CMakeLists.txt @@ -39,6 +39,15 @@ absl_cc_library( absl_cc_library( NAME raw_logging_internal + HDRS + "internal/raw_logging.h" + SRCS + "internal/raw_logging.cc" + DEPS + absl::atomic_hook + absl::config + absl::core_headers + absl::log_severity COPTS ${ABSL_DEFAULT_COPTS} ) @@ -119,6 +128,7 @@ absl_cc_library( absl::config absl::core_headers absl::dynamic_annotations + absl::raw_logging_internal absl::spinlock_wait Threads::Threads ) @@ -146,7 +156,6 @@ absl_cc_library( "internal/cycleclock.h" "internal/low_level_scheduling.h" "internal/per_thread_tls.h" - "internal/raw_logging.h" "internal/spinlock.h" "internal/sysinfo.h" "internal/thread_identity.h" @@ -155,7 +164,6 @@ absl_cc_library( "log_severity.h" SRCS "internal/cycleclock.cc" - "internal/raw_logging.cc" "internal/spinlock.cc" "internal/sysinfo.cc" "internal/thread_identity.cc" @@ -170,6 +178,7 @@ absl_cc_library( absl::core_headers absl::dynamic_annotations absl::log_severity + absl::raw_logging_internal absl::spinlock_wait absl::type_traits Threads::Threads @@ -187,7 +196,8 @@ absl_cc_library( ${ABSL_DEFAULT_COPTS} ${ABSL_EXCEPTIONS_FLAG} DEPS - absl::base + absl::config + absl::raw_logging_internal ) absl_cc_library( @@ -415,7 +425,7 @@ absl_cc_test( COPTS ${ABSL_TEST_COPTS} DEPS - absl::base + absl::raw_logging_internal absl::strings gtest_main ) @@ -493,7 +503,7 @@ absl_cc_library( COPTS ${ABSL_DEFAULT_COPTS} DEPS - absl::base + absl::raw_logging_internal ) absl_cc_test( @@ -525,7 +535,6 @@ absl_cc_test( SRCS "log_severity_test.cc" DEPS - absl::base absl::log_severity gmock gtest_main diff --git a/absl/container/BUILD.bazel b/absl/container/BUILD.bazel index 1859d9e9..90f4d0b7 100644 --- a/absl/container/BUILD.bazel +++ b/absl/container/BUILD.bazel @@ -166,9 +166,9 @@ cc_test( ":counting_allocator", ":inlined_vector", ":test_instance_tracker", - "//absl/base", "//absl/base:core_headers", "//absl/base:exception_testing", + "//absl/base:raw_logging_internal", "//absl/hash:hash_testing", "//absl/memory", "//absl/strings", @@ -185,9 +185,9 @@ cc_test( ":counting_allocator", ":inlined_vector", ":test_instance_tracker", - "//absl/base", "//absl/base:core_headers", "//absl/base:exception_testing", + "//absl/base:raw_logging_internal", "//absl/hash:hash_testing", "//absl/memory", "//absl/strings", @@ -203,8 +203,8 @@ cc_test( tags = ["benchmark"], deps = [ ":inlined_vector", - "//absl/base", "//absl/base:core_headers", + "//absl/base:raw_logging_internal", "//absl/strings", "@com_github_google_benchmark//:benchmark_main", ], @@ -635,6 +635,7 @@ cc_test( ":raw_hash_set", "//absl/base", "//absl/base:core_headers", + "//absl/base:raw_logging_internal", "//absl/strings", "@com_google_googletest//:gtest_main", ], @@ -678,8 +679,8 @@ cc_test( visibility = ["//visibility:private"], deps = [ ":layout", - "//absl/base", "//absl/base:core_headers", + "//absl/base:raw_logging_internal", "//absl/types:span", "@com_google_googletest//:gtest_main", ], @@ -884,7 +885,7 @@ cc_test( ":btree_test_common", ":counting_allocator", ":test_instance_tracker", - "//absl/base", + "//absl/base:raw_logging_internal", "//absl/flags:flag", "//absl/hash:hash_testing", "//absl/memory", diff --git a/absl/container/CMakeLists.txt b/absl/container/CMakeLists.txt index 6cabe0c9..fb966ec7 100644 --- a/absl/container/CMakeLists.txt +++ b/absl/container/CMakeLists.txt @@ -72,13 +72,13 @@ absl_cc_test( SRCS "btree_test.cc" DEPS - absl::base absl::btree absl::btree_test_common absl::compare absl::counting_allocator absl::flags absl::hash_testing + absl::raw_logging_internal absl::strings absl::test_instance_tracker absl::type_traits @@ -235,11 +235,11 @@ absl_cc_test( absl::counting_allocator absl::inlined_vector absl::test_instance_tracker - absl::base absl::core_headers absl::exception_testing absl::hash_testing absl::memory + absl::raw_logging_internal absl::strings gmock_main ) @@ -254,11 +254,11 @@ absl_cc_test( DEPS absl::inlined_vector absl::test_instance_tracker - absl::base absl::core_headers absl::exception_testing absl::hash_testing absl::memory + absl::raw_logging_internal absl::strings gmock_main ) @@ -715,6 +715,7 @@ absl_cc_test( absl::raw_hash_set absl::base absl::core_headers + absl::raw_logging_internal absl::strings gmock_main ) @@ -758,8 +759,8 @@ absl_cc_test( ${ABSL_TEST_COPTS} DEPS absl::layout - absl::base absl::core_headers + absl::raw_logging_internal absl::span gmock_main ) diff --git a/absl/debugging/BUILD.bazel b/absl/debugging/BUILD.bazel index 913cfafb..760c481f 100644 --- a/absl/debugging/BUILD.bazel +++ b/absl/debugging/BUILD.bazel @@ -37,7 +37,6 @@ cc_library( linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":debugging_internal", - "//absl/base", "//absl/base:core_headers", ], ) @@ -63,6 +62,7 @@ cc_library( "//absl/base:core_headers", "//absl/base:dynamic_annotations", "//absl/base:malloc_internal", + "//absl/base:raw_logging_internal", ], ) @@ -76,6 +76,7 @@ cc_test( ":symbolize", "//absl/base", "//absl/base:core_headers", + "//absl/base:raw_logging_internal", "//absl/memory", "@com_google_googletest//:gtest", ], @@ -95,8 +96,8 @@ cc_library( deps = [ ":stacktrace", ":symbolize", - "//absl/base", "//absl/base:core_headers", + "//absl/base:raw_logging_internal", ], ) @@ -112,6 +113,7 @@ cc_library( "//absl/base", "//absl/base:config", "//absl/base:core_headers", + "//absl/base:raw_logging_internal", ], ) @@ -127,7 +129,7 @@ cc_test( ":failure_signal_handler", ":stacktrace", ":symbolize", - "//absl/base", + "//absl/base:raw_logging_internal", "//absl/strings", "@com_google_googletest//:gtest", ], @@ -156,9 +158,9 @@ cc_library( copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ - "//absl/base", "//absl/base:core_headers", "//absl/base:dynamic_annotations", + "//absl/base:raw_logging_internal", ], ) @@ -181,8 +183,8 @@ cc_test( deps = [ ":demangle_internal", ":stack_consumption", - "//absl/base", "//absl/base:core_headers", + "//absl/base:raw_logging_internal", "//absl/memory", "@com_google_googletest//:gtest_main", ], @@ -292,8 +294,8 @@ cc_library( linkopts = ABSL_DEFAULT_LINKOPTS, visibility = ["//visibility:private"], deps = [ - "//absl/base", "//absl/base:core_headers", + "//absl/base:raw_logging_internal", ], ) @@ -304,8 +306,8 @@ cc_test( linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":stack_consumption", - "//absl/base", "//absl/base:core_headers", + "//absl/base:raw_logging_internal", "@com_google_googletest//:gtest_main", ], ) diff --git a/absl/debugging/CMakeLists.txt b/absl/debugging/CMakeLists.txt index 001e2727..c409e33e 100644 --- a/absl/debugging/CMakeLists.txt +++ b/absl/debugging/CMakeLists.txt @@ -25,7 +25,6 @@ absl_cc_library( ${ABSL_DEFAULT_COPTS} DEPS absl::debugging_internal - absl::base absl::core_headers PUBLIC ) @@ -52,6 +51,7 @@ absl_cc_library( absl::core_headers absl::dynamic_annotations absl::malloc_internal + absl::raw_logging_internal PUBLIC ) @@ -68,6 +68,7 @@ absl_cc_test( absl::base absl::core_headers absl::memory + absl::raw_logging_internal gmock ) @@ -83,8 +84,8 @@ absl_cc_library( DEPS absl::stacktrace absl::symbolize - absl::base absl::core_headers + absl::raw_logging_internal ) absl_cc_library( @@ -102,6 +103,7 @@ absl_cc_library( absl::base absl::config absl::core_headers + absl::raw_logging_internal PUBLIC ) @@ -116,8 +118,8 @@ absl_cc_test( absl::failure_signal_handler absl::stacktrace absl::symbolize - absl::base absl::strings + absl::raw_logging_internal Threads::Threads gmock ) @@ -144,9 +146,9 @@ absl_cc_library( COPTS ${ABSL_DEFAULT_COPTS} DEPS - absl::base absl::core_headers absl::dynamic_annotations + absl::raw_logging_internal ) absl_cc_library( @@ -174,9 +176,9 @@ absl_cc_test( DEPS absl::demangle_internal absl::stack_consumption - absl::base absl::core_headers absl::memory + absl::raw_logging_internal gmock_main ) @@ -273,6 +275,7 @@ absl_cc_test( absl::leak_check_api_enabled_for_testing absl::leak_check_disable absl::base + absl::raw_logging_internal gmock_main ) @@ -286,8 +289,8 @@ absl_cc_library( COPTS ${ABSL_DEFAULT_COPTS} DEPS - absl::base absl::core_headers + absl::raw_logging_internal TESTONLY ) @@ -300,8 +303,8 @@ absl_cc_test( ${ABSL_TEST_COPTS} DEPS absl::stack_consumption - absl::base absl::core_headers + absl::raw_logging_internal gmock_main ) diff --git a/absl/flags/BUILD.bazel b/absl/flags/BUILD.bazel index 2fe61eaa..4720791a 100644 --- a/absl/flags/BUILD.bazel +++ b/absl/flags/BUILD.bazel @@ -97,8 +97,8 @@ cc_library( deps = [ ":config", ":marshalling", - "//absl/base", "//absl/base:core_headers", + "//absl/base:raw_logging_internal", "//absl/strings", "//absl/synchronization", "//absl/types:optional", @@ -123,9 +123,9 @@ cc_library( deps = [ ":config", ":handle", - "//absl/base", "//absl/base:core_headers", "//absl/base:dynamic_annotations", + "//absl/base:raw_logging_internal", "//absl/strings", "//absl/synchronization", ], @@ -306,7 +306,7 @@ cc_test( deps = [ ":flag", ":parse", - "//absl/base", + "//absl/base:raw_logging_internal", "//absl/base:scoped_set_env", "//absl/strings", "//absl/types:span", diff --git a/absl/flags/CMakeLists.txt b/absl/flags/CMakeLists.txt index fa1d4e17..9860979c 100644 --- a/absl/flags/CMakeLists.txt +++ b/absl/flags/CMakeLists.txt @@ -84,11 +84,11 @@ absl_cc_library( DEPS absl::flags_config absl::flags_marshalling - absl::base absl::core_headers + absl::optional + absl::raw_logging_internal absl::strings absl::synchronization - absl::optional ) # Internal-only target, do not depend on directly. @@ -108,9 +108,9 @@ absl_cc_library( DEPS absl::flags_config absl::flags_handle - absl::base absl::core_headers absl::dynamic_annotations + absl::raw_logging_internal absl::strings absl::synchronization ) @@ -265,8 +265,8 @@ absl_cc_test( ${ABSL_TEST_COPTS} DEPS absl::flags - absl::base absl::flags_parse + absl::raw_logging_internal absl::scoped_set_env absl::span absl::strings diff --git a/absl/memory/BUILD.bazel b/absl/memory/BUILD.bazel index f815ef94..4dba6366 100644 --- a/absl/memory/BUILD.bazel +++ b/absl/memory/BUILD.bazel @@ -45,7 +45,6 @@ cc_test( linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":memory", - "//absl/base", "//absl/base:core_headers", "@com_google_googletest//:gtest_main", ], diff --git a/absl/memory/CMakeLists.txt b/absl/memory/CMakeLists.txt index 0a812203..1b3697ec 100644 --- a/absl/memory/CMakeLists.txt +++ b/absl/memory/CMakeLists.txt @@ -36,7 +36,6 @@ absl_cc_test( ${ABSL_TEST_COPTS} DEPS absl::memory - absl::base absl::core_headers gmock_main ) diff --git a/absl/random/BUILD.bazel b/absl/random/BUILD.bazel index f7587bf9..d09f0cb3 100644 --- a/absl/random/BUILD.bazel +++ b/absl/random/BUILD.bazel @@ -119,7 +119,7 @@ cc_test( deps = [ ":distributions", ":random", - "//absl/base", + "//absl/base:raw_logging_internal", "//absl/random/internal:distribution_test_util", "//absl/random/internal:sequence_urbg", "//absl/strings", @@ -168,8 +168,8 @@ cc_test( deps = [ ":distributions", ":random", - "//absl/base", "//absl/base:core_headers", + "//absl/base:raw_logging_internal", "//absl/random/internal:distribution_test_util", "//absl/random/internal:sequence_urbg", "//absl/strings", @@ -189,7 +189,7 @@ cc_test( deps = [ ":distributions", ":random", - "//absl/base", + "//absl/base:raw_logging_internal", "//absl/random/internal:distribution_test_util", "//absl/random/internal:sequence_urbg", "//absl/strings", @@ -214,8 +214,8 @@ cc_test( deps = [ ":distributions", ":random", - "//absl/base", "//absl/base:core_headers", + "//absl/base:raw_logging_internal", "//absl/container:flat_hash_map", "//absl/random/internal:distribution_test_util", "//absl/random/internal:sequence_urbg", @@ -234,8 +234,8 @@ cc_test( deps = [ ":distributions", ":random", - "//absl/base", "//absl/base:core_headers", + "//absl/base:raw_logging_internal", "//absl/random/internal:distribution_test_util", "//absl/random/internal:sequence_urbg", "//absl/strings", @@ -256,8 +256,8 @@ cc_test( deps = [ ":distributions", ":random", - "//absl/base", "//absl/base:core_headers", + "//absl/base:raw_logging_internal", "//absl/random/internal:distribution_test_util", "//absl/random/internal:sequence_urbg", "//absl/strings", @@ -278,7 +278,7 @@ cc_test( deps = [ ":distributions", ":random", - "//absl/base", + "//absl/base:raw_logging_internal", "//absl/random/internal:distribution_test_util", "//absl/random/internal:sequence_urbg", "//absl/strings", @@ -302,7 +302,7 @@ cc_test( deps = [ ":distributions", ":random", - "//absl/base", + "//absl/base:raw_logging_internal", "//absl/random/internal:distribution_test_util", "//absl/random/internal:sequence_urbg", "//absl/strings", @@ -321,7 +321,7 @@ cc_test( deps = [ ":distributions", ":random", - "//absl/base", + "//absl/base:raw_logging_internal", "//absl/random/internal:distribution_test_util", "//absl/random/internal:sequence_urbg", "//absl/strings", diff --git a/absl/random/CMakeLists.txt b/absl/random/CMakeLists.txt index 2d5c0658..7603690d 100644 --- a/absl/random/CMakeLists.txt +++ b/absl/random/CMakeLists.txt @@ -137,9 +137,9 @@ absl_cc_test( DEPS absl::random_distributions absl::random_random - absl::base absl::random_internal_distribution_test_util absl::random_internal_sequence_urbg + absl::raw_logging_internal absl::strings absl::str_format gmock @@ -174,6 +174,7 @@ absl_cc_test( ${ABSL_DEFAULT_LINKOPTS} absl::random_distributions absl::random_random + absl::raw_logging_internal gmock gtest_main ) @@ -187,12 +188,12 @@ absl_cc_test( ${ABSL_TEST_COPTS} LINKOPTS ${ABSL_DEFAULT_LINKOPTS} - absl::base absl::core_headers absl::random_distributions absl::random_internal_distribution_test_util absl::random_internal_sequence_urbg absl::random_random + absl::raw_logging_internal absl::strings absl::str_format gmock @@ -209,11 +210,11 @@ absl_cc_test( LINKOPTS ${ABSL_DEFAULT_LINKOPTS} DEPS - absl::base absl::random_distributions absl::random_internal_distribution_test_util absl::random_internal_sequence_urbg absl::random_random + absl::raw_logging_internal absl::strings gmock gtest_main @@ -231,11 +232,11 @@ absl_cc_test( DEPS absl::random_distributions absl::random_random - absl::base absl::core_headers absl::flat_hash_map absl::random_internal_distribution_test_util absl::random_internal_sequence_urbg + absl::raw_logging_internal absl::strings absl::str_format gmock @@ -252,12 +253,12 @@ absl_cc_test( LINKOPTS ${ABSL_DEFAULT_LINKOPTS} DEPS - absl::base absl::core_headers absl::random_distributions absl::random_internal_distribution_test_util absl::random_internal_sequence_urbg absl::random_random + absl::raw_logging_internal absl::strings absl::str_format gmock @@ -274,12 +275,12 @@ absl_cc_test( LINKOPTS ${ABSL_DEFAULT_LINKOPTS} DEPS - absl::base absl::core_headers absl::random_distributions absl::random_internal_distribution_test_util absl::random_internal_sequence_urbg absl::random_random + absl::raw_logging_internal absl::strings absl::str_format gmock @@ -296,11 +297,11 @@ absl_cc_test( LINKOPTS ${ABSL_DEFAULT_LINKOPTS} DEPS - absl::base absl::random_distributions absl::random_internal_distribution_test_util absl::random_internal_sequence_urbg absl::random_random + absl::raw_logging_internal absl::strings gmock gtest_main @@ -316,7 +317,6 @@ absl_cc_test( LINKOPTS ${ABSL_DEFAULT_LINKOPTS} DEPS - absl::base absl::random_distributions absl::random_internal_distribution_test_util absl::random_internal_sequence_urbg @@ -336,11 +336,11 @@ absl_cc_test( LINKOPTS ${ABSL_DEFAULT_LINKOPTS} DEPS - absl::base absl::random_distributions absl::random_internal_distribution_test_util absl::random_internal_sequence_urbg absl::random_random + absl::raw_logging_internal absl::strings gmock gtest_main @@ -449,10 +449,10 @@ absl_cc_library( LINKOPTS ${ABSL_DEFAULT_LINKOPTS} DEPS - absl::base absl::core_headers absl::optional absl::random_internal_fast_uniform_bits + absl::raw_logging_internal absl::span absl::strings ) @@ -478,6 +478,7 @@ absl_cc_library( absl::random_internal_seed_material absl::random_internal_traits absl::random_seed_gen_exception + absl::raw_logging_internal absl::span ) @@ -624,6 +625,7 @@ absl_cc_library( DEPS absl::random_internal_iostream_state_saver absl::random_internal_randen + absl::raw_logging_internal absl::type_traits ) @@ -654,7 +656,6 @@ absl_cc_library( LINKOPTS ${ABSL_DEFAULT_LINKOPTS} DEPS - absl::base absl::random_internal_platform absl::random_internal_randen_hwaes absl::random_internal_randen_slow @@ -726,8 +727,8 @@ absl_cc_library( LINKOPTS ${ABSL_DEFAULT_LINKOPTS} DEPS - absl::base absl::core_headers + absl::raw_logging_internal absl::strings absl::str_format absl::span @@ -941,9 +942,9 @@ absl_cc_test( LINKOPTS ${ABSL_DEFAULT_LINKOPTS} DEPS - absl::base absl::random_internal_explicit_seed_seq absl::random_internal_randen_engine + absl::raw_logging_internal absl::strings absl::time gmock @@ -995,7 +996,7 @@ absl_cc_test( absl::random_internal_platform absl::random_internal_randen_hwaes absl::random_internal_randen_hwaes_impl - absl::base + absl::raw_logging_internal absl::str_format gmock gtest diff --git a/absl/random/internal/BUILD.bazel b/absl/random/internal/BUILD.bazel index fd5471a6..7416e936 100644 --- a/absl/random/internal/BUILD.bazel +++ b/absl/random/internal/BUILD.bazel @@ -78,8 +78,8 @@ cc_library( linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":fast_uniform_bits", - "//absl/base", "//absl/base:core_headers", + "//absl/base:raw_logging_internal", "//absl/strings", "//absl/types:optional", "//absl/types:span", @@ -107,6 +107,7 @@ cc_library( "//absl/base:config", "//absl/base:core_headers", "//absl/base:endian", + "//absl/base:raw_logging_internal", "//absl/random:seed_gen_exception", "//absl/types:span", ], @@ -255,7 +256,7 @@ cc_library( ":platform", ":randen_hwaes", ":randen_slow", - "//absl/base", + "//absl/base:raw_logging_internal", ], ) @@ -334,8 +335,8 @@ cc_library( copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ - "//absl/base", "//absl/base:core_headers", + "//absl/base:raw_logging_internal", "//absl/strings", "//absl/strings:str_format", "//absl/types:span", @@ -531,7 +532,7 @@ cc_test( deps = [ ":explicit_seed_seq", ":randen_engine", - "//absl/base", + "//absl/base:raw_logging_internal", "//absl/strings", "//absl/time", "@com_google_googletest//:gtest_main", @@ -574,7 +575,7 @@ cc_test( ":platform", ":randen_hwaes", ":randen_hwaes_impl", # build_cleaner: keep - "//absl/base", + "//absl/base:raw_logging_internal", "//absl/strings:str_format", "@com_google_googletest//:gtest", ], @@ -588,7 +589,7 @@ cc_library( deps = [ ":platform", ":randen_engine", - "//absl/base", + "//absl/base:raw_logging_internal", ], ) @@ -620,7 +621,7 @@ cc_test( ], deps = [ ":nanobenchmark", - "//absl/base", + "//absl/base:raw_logging_internal", "//absl/strings", ], ) @@ -641,7 +642,7 @@ cc_test( ":randen_hwaes", ":randen_hwaes_impl", ":randen_slow", - "//absl/base", + "//absl/base:raw_logging_internal", "//absl/strings", ], ) diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel index 20511a35..9679dc30 100644 --- a/absl/strings/BUILD.bazel +++ b/absl/strings/BUILD.bazel @@ -73,6 +73,7 @@ cc_library( "//absl/base:config", "//absl/base:core_headers", "//absl/base:endian", + "//absl/base:raw_logging_internal", "//absl/base:throw_delegate", "//absl/memory", "//absl/meta:type_traits", @@ -140,7 +141,7 @@ cc_test( visibility = ["//visibility:private"], deps = [ ":strings", - "//absl/base", + "//absl/base:raw_logging_internal", "@com_github_google_benchmark//:benchmark_main", ], ) @@ -225,8 +226,8 @@ cc_test( visibility = ["//visibility:private"], deps = [ ":strings", - "//absl/base", "//absl/base:core_headers", + "//absl/base:raw_logging_internal", "@com_github_google_benchmark//:benchmark_main", ], ) @@ -268,7 +269,7 @@ cc_test( visibility = ["//visibility:private"], deps = [ ":strings", - "//absl/base", + "//absl/base:raw_logging_internal", "@com_github_google_benchmark//:benchmark_main", ], ) @@ -306,7 +307,7 @@ cc_test( visibility = ["//visibility:private"], deps = [ ":strings", - "//absl/base", + "//absl/base:raw_logging_internal", "@com_github_google_benchmark//:benchmark_main", ], ) @@ -414,8 +415,8 @@ cc_test( deps = [ ":pow10_helper", ":strings", - "//absl/base", "//absl/base:core_headers", + "//absl/base:raw_logging_internal", "@com_google_googletest//:gtest_main", ], ) @@ -428,7 +429,7 @@ cc_test( visibility = ["//visibility:private"], deps = [ ":strings", - "//absl/base", + "//absl/base:raw_logging_internal", "@com_github_google_benchmark//:benchmark_main", ], ) @@ -474,7 +475,6 @@ cc_test( ":pow10_helper", ":str_format", ":strings", - "//absl/base", "@com_google_googletest//:gtest_main", ], ) @@ -488,7 +488,7 @@ cc_test( copts = ABSL_TEST_COPTS, deps = [ ":strings", - "//absl/base", + "//absl/base:raw_logging_internal", "@com_google_googletest//:gtest_main", ], ) @@ -503,7 +503,6 @@ cc_test( copts = ABSL_TEST_COPTS, deps = [ ":strings", - "//absl/base", "@com_google_googletest//:gtest_main", ], ) @@ -518,7 +517,6 @@ cc_test( ], deps = [ ":strings", - "//absl/base", "@com_github_google_benchmark//:benchmark_main", ], ) diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt index e63eec19..82a906b7 100644 --- a/absl/strings/CMakeLists.txt +++ b/absl/strings/CMakeLists.txt @@ -59,10 +59,11 @@ absl_cc_library( absl::config absl::core_headers absl::endian - absl::throw_delegate + absl::int128 absl::memory + absl::raw_logging_internal + absl::throw_delegate absl::type_traits - absl::int128 PUBLIC ) @@ -276,9 +277,9 @@ absl_cc_test( ${ABSL_TEST_COPTS} DEPS absl::strings - absl::base absl::core_headers absl::pow10_helper + absl::raw_logging_internal gmock_main ) @@ -317,7 +318,6 @@ absl_cc_test( DEPS absl::strings absl::str_format - absl::base absl::pow10_helper gmock_main ) @@ -332,7 +332,7 @@ absl_cc_test( ${ABSL_TEST_COPTS} DEPS absl::strings - absl::base + absl::raw_logging_internal gmock_main ) @@ -347,7 +347,6 @@ absl_cc_test( ${ABSL_TEST_COPTS} DEPS absl::strings - absl::base gmock_main ) diff --git a/absl/synchronization/BUILD.bazel b/absl/synchronization/BUILD.bazel index fca8cb69..d40d861f 100644 --- a/absl/synchronization/BUILD.bazel +++ b/absl/synchronization/BUILD.bazel @@ -44,6 +44,7 @@ cc_library( "//absl/base:base_internal", "//absl/base:core_headers", "//absl/base:malloc_internal", + "//absl/base:raw_logging_internal", ], ) @@ -84,6 +85,7 @@ cc_library( "//absl/base:core_headers", "//absl/base:dynamic_annotations", "//absl/base:malloc_internal", + "//absl/base:raw_logging_internal", "//absl/debugging:stacktrace", "//absl/debugging:symbolize", "//absl/time", @@ -124,8 +126,8 @@ cc_test( linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":graphcycles_internal", - "//absl/base", "//absl/base:core_headers", + "//absl/base:raw_logging_internal", "@com_google_googletest//:gtest_main", ], ) @@ -140,7 +142,7 @@ cc_test( ], deps = [ ":graphcycles_internal", - "//absl/base", + "//absl/base:raw_logging_internal", "@com_github_google_benchmark//:benchmark_main", ], ) @@ -171,6 +173,7 @@ cc_test( ":thread_pool", "//absl/base", "//absl/base:core_headers", + "//absl/base:raw_logging_internal", "//absl/memory", "//absl/time", "@com_google_googletest//:gtest_main", @@ -243,7 +246,6 @@ cc_test( deps = [ ":per_thread_sem_test_common", ":synchronization", - "//absl/base", "//absl/strings", "//absl/time", "@com_google_googletest//:gtest_main", @@ -260,7 +262,7 @@ cc_test( tags = ["no_test_ios_x86_64"], deps = [ ":synchronization", - "//absl/base", "//absl/base:core_headers", + "//absl/base:raw_logging_internal", ], ) diff --git a/absl/synchronization/CMakeLists.txt b/absl/synchronization/CMakeLists.txt index 4b708823..ce669c52 100644 --- a/absl/synchronization/CMakeLists.txt +++ b/absl/synchronization/CMakeLists.txt @@ -28,6 +28,7 @@ absl_cc_library( absl::base_internal absl::core_headers absl::malloc_internal + absl::raw_logging_internal ) absl_cc_library( @@ -62,6 +63,7 @@ absl_cc_library( absl::core_headers absl::dynamic_annotations absl::malloc_internal + absl::raw_logging_internal absl::stacktrace absl::symbolize absl::time @@ -104,8 +106,8 @@ absl_cc_test( ${ABSL_TEST_COPTS} DEPS absl::graphcycles_internal - absl::base absl::core_headers + absl::raw_logging_internal gmock_main ) @@ -135,6 +137,7 @@ absl_cc_test( absl::base absl::core_headers absl::memory + absl::raw_logging_internal absl::time gmock_main ) @@ -178,7 +181,6 @@ absl_cc_test( DEPS absl::per_thread_sem_test_common absl::synchronization - absl::base absl::strings absl::time gmock_main @@ -193,6 +195,6 @@ absl_cc_test( ${ABSL_TEST_COPTS} DEPS absl::synchronization - absl::base absl::core_headers + absl::raw_logging_internal ) diff --git a/absl/time/BUILD.bazel b/absl/time/BUILD.bazel index 55e83a8c..1c387e46 100644 --- a/absl/time/BUILD.bazel +++ b/absl/time/BUILD.bazel @@ -46,6 +46,7 @@ cc_library( deps = [ "//absl/base", "//absl/base:core_headers", + "//absl/base:raw_logging_internal", "//absl/numeric:int128", "//absl/strings", "//absl/time/internal/cctz:civil_time", @@ -68,7 +69,7 @@ cc_library( ], deps = [ ":time", - "//absl/base", + "//absl/base:raw_logging_internal", "//absl/time/internal/cctz:time_zone", "@com_google_googletest//:gtest", ], @@ -89,7 +90,6 @@ cc_test( deps = [ ":test_util", ":time", - "//absl/base", "//absl/base:config", "//absl/base:core_headers", "//absl/time/internal/cctz:time_zone", diff --git a/absl/time/CMakeLists.txt b/absl/time/CMakeLists.txt index 59098321..853563e8 100644 --- a/absl/time/CMakeLists.txt +++ b/absl/time/CMakeLists.txt @@ -22,21 +22,22 @@ absl_cc_library( "clock.h" "time.h" SRCS - "civil_time.cc" - "clock.cc" - "duration.cc" - "format.cc" - "internal/get_current_time_chrono.inc" - "internal/get_current_time_posix.inc" - "time.cc" + "civil_time.cc" + "clock.cc" + "duration.cc" + "format.cc" + "internal/get_current_time_chrono.inc" + "internal/get_current_time_posix.inc" + "time.cc" COPTS ${ABSL_DEFAULT_COPTS} DEPS absl::base + absl::civil_time absl::core_headers absl::int128 + absl::raw_logging_internal absl::strings - absl::civil_time absl::time_zone PUBLIC ) @@ -88,7 +89,7 @@ absl_cc_library( absl_cc_library( NAME - test_util + time_internal_test_util HDRS "internal/test_util.h" SRCS @@ -98,7 +99,7 @@ absl_cc_library( ${ABSL_DEFAULT_COPTS} DEPS absl::time - absl::base + absl::raw_logging_internal absl::time_zone gmock TESTONLY @@ -117,9 +118,8 @@ absl_cc_test( COPTS ${ABSL_TEST_COPTS} DEPS - absl::test_util + absl::time_internal_test_util absl::time - absl::base absl::config absl::core_headers absl::time_zone diff --git a/absl/types/BUILD.bazel b/absl/types/BUILD.bazel index 66ecb044..6e287ce0 100644 --- a/absl/types/BUILD.bazel +++ b/absl/types/BUILD.bazel @@ -62,8 +62,8 @@ cc_library( linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS + ABSL_DEFAULT_LINKOPTS, visibility = ["//visibility:private"], deps = [ - "//absl/base", "//absl/base:config", + "//absl/base:raw_logging_internal", ], ) @@ -77,9 +77,9 @@ cc_test( linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS + ABSL_DEFAULT_LINKOPTS, deps = [ ":any", - "//absl/base", "//absl/base:config", "//absl/base:exception_testing", + "//absl/base:raw_logging_internal", "//absl/container:test_instance_tracker", "@com_google_googletest//:gtest_main", ], @@ -95,9 +95,9 @@ cc_test( linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":any", - "//absl/base", "//absl/base:config", "//absl/base:exception_testing", + "//absl/base:raw_logging_internal", "//absl/container:test_instance_tracker", "@com_google_googletest//:gtest_main", ], @@ -195,8 +195,8 @@ cc_library( copts = ABSL_DEFAULT_COPTS + ABSL_EXCEPTIONS_FLAG, linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS + ABSL_DEFAULT_LINKOPTS, deps = [ - "//absl/base", "//absl/base:config", + "//absl/base:raw_logging_internal", ], ) @@ -207,8 +207,8 @@ cc_library( copts = ABSL_EXCEPTIONS_FLAG + ABSL_DEFAULT_COPTS, linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS + ABSL_DEFAULT_LINKOPTS, deps = [ - "//absl/base", "//absl/base:config", + "//absl/base:raw_logging_internal", ], ) @@ -222,8 +222,8 @@ cc_test( linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS + ABSL_DEFAULT_LINKOPTS, deps = [ ":optional", - "//absl/base", "//absl/base:config", + "//absl/base:raw_logging_internal", "//absl/meta:type_traits", "//absl/strings", "@com_google_googletest//:gtest_main", diff --git a/absl/types/CMakeLists.txt b/absl/types/CMakeLists.txt index 4ce685da..ddae7f2a 100644 --- a/absl/types/CMakeLists.txt +++ b/absl/types/CMakeLists.txt @@ -54,8 +54,8 @@ absl_cc_library( LINKOPTS ${ABSL_EXCEPTIONS_FLAG_LINKOPTS} DEPS - absl::base absl::config + absl::raw_logging_internal ) absl_cc_test( @@ -70,9 +70,9 @@ absl_cc_test( ${ABSL_EXCEPTIONS_FLAG_LINKOPTS} DEPS absl::any - absl::base absl::config absl::exception_testing + absl::raw_logging_internal absl::test_instance_tracker gmock_main ) @@ -86,9 +86,9 @@ absl_cc_test( ${ABSL_TEST_COPTS} DEPS absl::any - absl::base absl::config absl::exception_testing + absl::raw_logging_internal absl::test_instance_tracker gmock_main ) @@ -202,8 +202,8 @@ absl_cc_library( LINKOPTS ${ABSL_EXCEPTIONS_FLAG_LINKOPTS} DEPS - absl::base absl::config + absl::raw_logging_internal PUBLIC ) @@ -220,8 +220,8 @@ absl_cc_library( LINKOPTS ${ABSL_EXCEPTIONS_FLAG_LINKOPTS} DEPS - absl::base absl::config + absl::raw_logging_internal PUBLIC ) @@ -237,10 +237,10 @@ absl_cc_test( ${ABSL_EXCEPTIONS_FLAG_LINKOPTS} DEPS absl::optional - absl::base absl::config - absl::type_traits + absl::raw_logging_internal absl::strings + absl::type_traits gmock_main ) diff --git a/ci/linux_clang-latest_libcxx_asan_bazel.sh b/ci/linux_clang-latest_libcxx_asan_bazel.sh index 07af64d0..e18cf882 100755 --- a/ci/linux_clang-latest_libcxx_asan_bazel.sh +++ b/ci/linux_clang-latest_libcxx_asan_bazel.sh @@ -32,7 +32,7 @@ if [ -z ${COMPILATION_MODE:-} ]; then COMPILATION_MODE="fastbuild opt" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190701" +readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190813" # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. diff --git a/ci/linux_clang-latest_libcxx_bazel.sh b/ci/linux_clang-latest_libcxx_bazel.sh index 1197369a..42bde353 100755 --- a/ci/linux_clang-latest_libcxx_bazel.sh +++ b/ci/linux_clang-latest_libcxx_bazel.sh @@ -32,7 +32,7 @@ if [ -z ${COMPILATION_MODE:-} ]; then COMPILATION_MODE="fastbuild opt" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190701" +readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190813" # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. diff --git a/ci/linux_clang-latest_libcxx_tsan_bazel.sh b/ci/linux_clang-latest_libcxx_tsan_bazel.sh index 04171df8..452c515c 100755 --- a/ci/linux_clang-latest_libcxx_tsan_bazel.sh +++ b/ci/linux_clang-latest_libcxx_tsan_bazel.sh @@ -32,7 +32,7 @@ if [ -z ${COMPILATION_MODE:-} ]; then COMPILATION_MODE="fastbuild opt" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190701" +readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190813" # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. diff --git a/ci/linux_clang-latest_libstdcxx_bazel.sh b/ci/linux_clang-latest_libstdcxx_bazel.sh index c2217a07..4b063ad8 100755 --- a/ci/linux_clang-latest_libstdcxx_bazel.sh +++ b/ci/linux_clang-latest_libstdcxx_bazel.sh @@ -32,7 +32,7 @@ if [ -z ${COMPILATION_MODE:-} ]; then COMPILATION_MODE="fastbuild opt" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190701" +readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190813" # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. -- cgit v1.2.3 From 2d2d7fbc283315b676159716376e739d3d23ed94 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Fri, 23 Aug 2019 11:38:04 -0700 Subject: Export of internal Abseil changes -- d6748c733a70cd74ad9b76a0c9cd6b3fe2cecacf by Xiaoyi Zhang : Remove empty block, to address alerts reported in https://github.com/abseil/abseil-cpp/issues/368. PiperOrigin-RevId: 265099887 -- 232e2036b5668d6d1296b881f9347756d84541ee by Derek Mauro : Make the Linux Bazel CI scripts test with the exception mode explicitly set. PiperOrigin-RevId: 265092105 -- 942a40696c2c9b833be03e92d22a6ede7bccb6d4 by Xiaoyi Zhang : Import https://github.com/abseil/abseil-cpp/pull/372. Suppress the unused variable warning on GCC, i.e. "-Wunused-variable". PiperOrigin-RevId: 265063925 -- 7ef90796b52cbdc260afc77cf47206f9356471d0 by Xiaoyi Zhang : Add quotes to `ABSL_COMMON_INCLUDE_DIRS` since it's a list and may contain a `;`. This addresses https://github.com/abseil/abseil-cpp/issues/373. PiperOrigin-RevId: 265059077 -- 43f3ae742e00b83672ad6c5bc5b17fdb8f9fe6fe by Gennadiy Rozental : Internal re-organization PiperOrigin-RevId: 264913945 -- 6a2adf9c08ee1d98cc6b2855a676345c6495294a by Andy Soffer : Publicly expose type names for uniform interval tags as in, for example, absl::IntervalClosedClosedTag, and add equality comparison operators. PiperOrigin-RevId: 264861162 -- 3c90c6e05fd61d56b419cd2d39dab8f17b8711b8 by Abseil Team : Add validity check on returned frame pointer. PiperOrigin-RevId: 264858823 -- 2db87e0cfa0c6bea7ba81684b834cb8a73b7d748 by Gennadiy Rozental : Add MUST_USE_RESULT attribute to absl::GetFlag to prevent accidental misuse. PiperOrigin-RevId: 264782762 GitOrigin-RevId: d6748c733a70cd74ad9b76a0c9cd6b3fe2cecacf Change-Id: I169e9c5358e4f63000c1255e806d26b8afecf5ff --- CMake/AbseilHelpers.cmake | 4 +- absl/base/internal/spinlock.h | 3 +- absl/debugging/internal/stacktrace_x86-inl.inc | 8 +- absl/flags/BUILD.bazel | 2 + absl/flags/CMakeLists.txt | 2 + absl/flags/declare.h | 5 ++ absl/flags/flag.cc | 16 ++++ absl/flags/flag.h | 106 ++++++++++++++++++++++++- absl/flags/internal/commandlineflag.cc | 93 +--------------------- absl/flags/internal/commandlineflag.h | 64 +++++++-------- absl/flags/internal/flag.cc | 51 ++++++++++++ absl/flags/internal/flag.h | 49 ++++++++++-- absl/flags/internal/registry.cc | 62 +++++++++------ absl/flags/internal/registry.h | 21 +---- absl/flags/internal/usage_test.cc | 2 +- absl/random/distributions.h | 19 ++--- absl/random/distributions_test.cc | 19 ++--- absl/random/internal/uniform_helper.h | 57 ++++++++----- ci/linux_clang-latest_libcxx_asan_bazel.sh | 77 +++++++++--------- ci/linux_clang-latest_libcxx_bazel.sh | 57 +++++++------ ci/linux_clang-latest_libcxx_tsan_bazel.sh | 67 ++++++++-------- ci/linux_clang-latest_libstdcxx_bazel.sh | 55 +++++++------ ci/linux_gcc-4.9_libstdcxx_bazel.sh | 51 ++++++------ ci/linux_gcc-latest_libstdcxx_bazel.sh | 51 ++++++------ 24 files changed, 549 insertions(+), 392 deletions(-) create mode 100644 absl/flags/internal/flag.cc (limited to 'ci/linux_clang-latest_libcxx_tsan_bazel.sh') diff --git a/CMake/AbseilHelpers.cmake b/CMake/AbseilHelpers.cmake index 58f98c8c..67b97fe1 100644 --- a/CMake/AbseilHelpers.cmake +++ b/CMake/AbseilHelpers.cmake @@ -108,7 +108,7 @@ function(absl_cc_library) target_sources(${_NAME} PRIVATE ${ABSL_CC_LIB_SRCS} ${ABSL_CC_LIB_HDRS}) target_include_directories(${_NAME} PUBLIC - $ + "$" $ ) target_compile_options(${_NAME} @@ -145,7 +145,7 @@ function(absl_cc_library) add_library(${_NAME} INTERFACE) target_include_directories(${_NAME} INTERFACE - $ + "$" $ ) target_link_libraries(${_NAME} diff --git a/absl/base/internal/spinlock.h b/absl/base/internal/spinlock.h index a55aa20b..6ee60ac8 100644 --- a/absl/base/internal/spinlock.h +++ b/absl/base/internal/spinlock.h @@ -225,11 +225,10 @@ inline uint32_t SpinLock::TryLockInternal(uint32_t lock_value, } } - if (lockword_.compare_exchange_strong( + if (!lockword_.compare_exchange_strong( lock_value, kSpinLockHeld | lock_value | wait_cycles | sched_disabled_bit, std::memory_order_acquire, std::memory_order_relaxed)) { - } else { base_internal::SchedulingGuard::EnableRescheduling(sched_disabled_bit != 0); } diff --git a/absl/debugging/internal/stacktrace_x86-inl.inc b/absl/debugging/internal/stacktrace_x86-inl.inc index 25aa8bdf..9494441e 100644 --- a/absl/debugging/internal/stacktrace_x86-inl.inc +++ b/absl/debugging/internal/stacktrace_x86-inl.inc @@ -36,6 +36,8 @@ #include "absl/base/internal/raw_logging.h" +using absl::debugging_internal::AddressIsReadable; + #if defined(__linux__) && defined(__i386__) // Count "push %reg" instructions in VDSO __kernel_vsyscall(), // preceeding "syscall" or "sysenter". @@ -81,7 +83,7 @@ static int CountPushInstructions(const unsigned char *const addr) { // "mov reg,reg" if (addr[i + 1] == 0xE5) { // Found "mov %esp,%ebp". - return 0; + return 0; } ++i; // Skip register encoding byte. } else if (addr[i] == 0x0F && @@ -222,7 +224,7 @@ static void **NextStackFrame(void **old_fp, const void *uc) { // "double fault" in case we hit the first fault due to e.g. stack // corruption. void *const reg_esp2 = reg_esp[num_push_instructions - 1]; - if (absl::debugging_internal::AddressIsReadable(reg_esp2)) { + if (AddressIsReadable(reg_esp2)) { // Alleged %esp is readable, use it for further unwinding. new_fp = reinterpret_cast(reg_esp2); } @@ -274,7 +276,7 @@ static void **NextStackFrame(void **old_fp, const void *uc) { // Note: NextStackFrame() is only called while the program // is already on its last leg, so it's ok to be slow here. - if (!absl::debugging_internal::AddressIsReadable(new_fp)) { + if (!AddressIsReadable(new_fp)) { return nullptr; } } diff --git a/absl/flags/BUILD.bazel b/absl/flags/BUILD.bazel index c338dbee..e7742de6 100644 --- a/absl/flags/BUILD.bazel +++ b/absl/flags/BUILD.bazel @@ -136,6 +136,7 @@ cc_library( name = "flag", srcs = [ "flag.cc", + "internal/flag.cc", ], hdrs = [ "declare.h", @@ -152,6 +153,7 @@ cc_library( "//absl/base", "//absl/base:core_headers", "//absl/strings", + "//absl/synchronization", ], ) diff --git a/absl/flags/CMakeLists.txt b/absl/flags/CMakeLists.txt index 9860979c..d9084a9c 100644 --- a/absl/flags/CMakeLists.txt +++ b/absl/flags/CMakeLists.txt @@ -120,6 +120,7 @@ absl_cc_library( flags SRCS "flag.cc" + "internal/flag.cc" HDRS "declare.h" "flag.h" @@ -136,6 +137,7 @@ absl_cc_library( absl::base absl::core_headers absl::strings + absl::synchronization ) # Internal-only target, do not depend on directly. diff --git a/absl/flags/declare.h b/absl/flags/declare.h index 556ec5e9..0a113a2b 100644 --- a/absl/flags/declare.h +++ b/absl/flags/declare.h @@ -39,8 +39,13 @@ class Flag; // Flag // // Forward declaration of the `absl::Flag` type for use in defining the macro. +#if defined(_MSC_VER) +template +class Flag; +#else template using Flag = flags_internal::Flag; +#endif } // namespace absl diff --git a/absl/flags/flag.cc b/absl/flags/flag.cc index f16cc75e..a02d069e 100644 --- a/absl/flags/flag.cc +++ b/absl/flags/flag.cc @@ -41,4 +41,20 @@ ABSL_FLAGS_INTERNAL_FOR_EACH_LOCK_FREE(ABSL_FLAGS_ATOMIC_GET) #undef ABSL_FLAGS_ATOMIC_GET +// This global nutex protects on-demand construction of flag objects in MSVC +// builds. +#if defined(_MSC_VER) + +namespace flags_internal { + +ABSL_CONST_INIT static absl::Mutex construction_guard(absl::kConstInit); + +void LockGlobalConstructionGuard() { construction_guard.Lock(); } + +void UnlockGlobalConstructionGuard() { construction_guard.Unlock(); } + +} // namespace flags_internal + +#endif + } // namespace absl diff --git a/absl/flags/flag.h b/absl/flags/flag.h index 36c771cf..881f8502 100644 --- a/absl/flags/flag.h +++ b/absl/flags/flag.h @@ -63,8 +63,100 @@ namespace absl { // ABSL_FLAG(int, count, 0, "Count of items to process"); // // No public methods of `absl::Flag` are part of the Abseil Flags API. +#if !defined(_MSC_VER) template using Flag = flags_internal::Flag; +#else +// MSVC debug builds do not implement constexpr correctly for classes with +// virtual methods. To work around this we adding level of indirection, so that +// the class `absl::Flag` contains an `internal::Flag*` (instead of being an +// alias to that class) and dynamically allocates an instance when necessary. +// We also forward all calls to internal::Flag methods via trampoline methods. +// In this setup the `absl::Flag` class does not have virtual methods and thus +// MSVC is able to initialize it at link time. To deal with multiple threads +// accessing the flag for the first time concurrently we use an atomic boolean +// indicating if flag object is constructed. We also employ the double-checked +// locking pattern where the second level of protection is a global Mutex, so +// if two threads attempt to construct the flag concurrently only one wins. + +namespace flags_internal { +void LockGlobalConstructionGuard(); +void UnlockGlobalConstructionGuard(); +} // namespace flags_internal + +template +class Flag { + public: + constexpr Flag(const char* name, const flags_internal::HelpGenFunc help_gen, + const char* filename, + const flags_internal::FlagMarshallingOpFn marshalling_op, + const flags_internal::InitialValGenFunc initial_value_gen) + : name_(name), + help_gen_(help_gen), + filename_(filename), + marshalling_op_(marshalling_op), + initial_value_gen_(initial_value_gen), + inited_(false) {} + + flags_internal::Flag* GetImpl() const { + if (!inited_.load(std::memory_order_acquire)) { + flags_internal::LockGlobalConstructionGuard(); + + if (inited_.load(std::memory_order_acquire)) { + return impl_; + } + + impl_ = new flags_internal::Flag(name_, help_gen_, filename_, + marshalling_op_, initial_value_gen_); + inited_.store(true, std::memory_order_release); + + flags_internal::UnlockGlobalConstructionGuard(); + } + + return impl_; + } + + // absl::Flag API + bool IsRetired() const { return GetImpl()->IsRetired(); } + bool IsAbseilFlag() const { return GetImpl()->IsAbseilFlag(); } + absl::string_view Name() const { return GetImpl()->Name(); } + std::string Help() const { return GetImpl()->Help(); } + bool IsModified() const { return GetImpl()->IsModified(); } + void SetModified(bool is_modified) { GetImpl()->SetModified(is_modified); } + bool IsSpecifiedOnCommandLine() const { + GetImpl()->IsSpecifiedOnCommandLine(); + } + absl::string_view Typename() const { return GetImpl()->Typename(); } + std::string Filename() const { return GetImpl()->Filename(); } + std::string DefaultValue() const { return GetImpl()->DefaultValue(); } + std::string CurrentValue() const { return GetImpl()->CurrentValue(); } + bool HasValidatorFn() const { return GetImpl()->HasValidatorFn(); } + bool InvokeValidator(const void* value) const { + return GetImpl()->InvokeValidator(value); + } + template + inline bool IsOfType() const { + return GetImpl()->IsOftype(); + } + T Get() const { return GetImpl()->Get(); } + bool AtomicGet(T* v) const { return GetImpl()->AtomicGet(v); } + void Set(const T& v) { GetImpl()->Set(v); } + void SetCallback(const flags_internal::FlagCallback mutation_callback) { + GetImpl()->SetCallback(mutation_callback); + } + void InvokeCallback() { GetImpl()->InvokeCallback(); } + + private: + const char* name_; + const flags_internal::HelpGenFunc help_gen_; + const char* filename_; + const flags_internal::FlagMarshallingOpFn marshalling_op_; + const flags_internal::InitialValGenFunc initial_value_gen_; + + mutable std::atomic inited_; + mutable flags_internal::Flag* impl_ = nullptr; +}; +#endif // GetFlag() // @@ -83,7 +175,7 @@ using Flag = flags_internal::Flag; // // FLAGS_firstname is a Flag of type `std::string` // std::string first_name = absl::GetFlag(FLAGS_firstname); template -T GetFlag(const absl::Flag& flag) { +ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag& flag) { #define ABSL_FLAGS_INTERNAL_LOCK_FREE_VALIDATE(BIT) \ static_assert( \ !std::is_same::value, \ @@ -96,7 +188,7 @@ T GetFlag(const absl::Flag& flag) { // Overload for `GetFlag()` for types that support lock-free reads. #define ABSL_FLAGS_INTERNAL_LOCK_FREE_EXPORT(T) \ - extern T GetFlag(const absl::Flag& flag); + ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag& flag); ABSL_FLAGS_INTERNAL_FOR_EACH_LOCK_FREE(ABSL_FLAGS_INTERNAL_LOCK_FREE_EXPORT) #undef ABSL_FLAGS_INTERNAL_LOCK_FREE_EXPORT @@ -184,13 +276,23 @@ void SetFlag(absl::Flag* flag, const V& v) { #if ABSL_FLAGS_STRIP_NAMES #define ABSL_FLAG_IMPL_FLAGNAME(txt) "" #define ABSL_FLAG_IMPL_FILENAME() "" +#if !defined(_MSC_VER) #define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \ absl::flags_internal::FlagRegistrar(&flag) #else +#define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \ + absl::flags_internal::FlagRegistrar(flag.GetImpl()) +#endif +#else #define ABSL_FLAG_IMPL_FLAGNAME(txt) txt #define ABSL_FLAG_IMPL_FILENAME() __FILE__ +#if !defined(_MSC_VER) #define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \ absl::flags_internal::FlagRegistrar(&flag) +#else +#define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \ + absl::flags_internal::FlagRegistrar(flag.GetImpl()) +#endif #endif // ABSL_FLAG_IMPL macro definition conditional on ABSL_FLAGS_STRIP_HELP diff --git a/absl/flags/internal/commandlineflag.cc b/absl/flags/internal/commandlineflag.cc index 98a46695..2063cda6 100644 --- a/absl/flags/internal/commandlineflag.cc +++ b/absl/flags/internal/commandlineflag.cc @@ -68,7 +68,7 @@ absl::Mutex* InitFlag(CommandLineFlag* flag) { { absl::MutexLock lock(mu); - if (!flag->retired && flag->def == nullptr) { + if (!flag->IsRetired() && flag->def == nullptr) { // Need to initialize def and cur fields. flag->def = (*flag->make_init_value)(); flag->cur = Clone(flag->op, flag->def); @@ -94,16 +94,6 @@ absl::Mutex* CommandLineFlag::InitFlagIfNecessary() const return &this->locks->primary_mu; } -void CommandLineFlag::Destroy() const { - // Values are heap allocated for retired and Abseil Flags. - if (IsRetired() || IsAbseilFlag()) { - if (this->cur) Delete(this->op, this->cur); - if (this->def) Delete(this->op, this->def); - } - - delete this->locks; -} - bool CommandLineFlag::IsModified() const { absl::MutexLock l(InitFlagIfNecessary()); return modified; @@ -159,87 +149,6 @@ std::string CommandLineFlag::CurrentValue() const { return Unparse(this->marshalling_op, this->cur); } -bool CommandLineFlag::HasValidatorFn() const { - absl::MutexLock l(InitFlagIfNecessary()); - - return this->validator != nullptr; -} - -bool CommandLineFlag::SetValidatorFn(FlagValidator fn) { - absl::MutexLock l(InitFlagIfNecessary()); - - // ok to register the same function over and over again - if (fn == this->validator) return true; - - // Can't set validator to a different function, unless reset first. - if (fn != nullptr && this->validator != nullptr) { - ABSL_INTERNAL_LOG( - WARNING, absl::StrCat("Ignoring SetValidatorFn() for flag '", Name(), - "': validate-fn already registered")); - - return false; - } - - this->validator = fn; - return true; -} - -bool CommandLineFlag::InvokeValidator(const void* value) const - EXCLUSIVE_LOCKS_REQUIRED(this->locks->primary_mu) { - if (!this->validator) { - return true; - } - - (void)value; - - ABSL_INTERNAL_LOG( - FATAL, - absl::StrCat("Flag '", Name(), - "' of encapsulated type should not have a validator")); - - return false; -} - -void CommandLineFlag::SetCallback( - const flags_internal::FlagCallback mutation_callback) { - absl::MutexLock l(InitFlagIfNecessary()); - - callback = mutation_callback; - - InvokeCallback(); -} - -// If the flag has a mutation callback this function invokes it. While the -// callback is being invoked the primary flag's mutex is unlocked and it is -// re-locked back after call to callback is completed. Callback invocation is -// guarded by flag's secondary mutex instead which prevents concurrent callback -// invocation. Note that it is possible for other thread to grab the primary -// lock and update flag's value at any time during the callback invocation. -// This is by design. Callback can get a value of the flag if necessary, but it -// might be different from the value initiated the callback and it also can be -// different by the time the callback invocation is completed. -// Requires that *primary_lock be held in exclusive mode; it may be released -// and reacquired by the implementation. -void CommandLineFlag::InvokeCallback() - EXCLUSIVE_LOCKS_REQUIRED(this->locks->primary_mu) { - if (!this->callback) return; - - // The callback lock is guaranteed initialized, because *locks->primary_mu - // exists. - absl::Mutex* callback_mu = &this->locks->callback_mu; - - // When executing the callback we need the primary flag's mutex to be unlocked - // so that callback can retrieve the flag's value. - this->locks->primary_mu.Unlock(); - - { - absl::MutexLock lock(callback_mu); - this->callback(); - } - - this->locks->primary_mu.Lock(); -} - // Attempts to parse supplied `value` string using parsing routine in the `flag` // argument. If parsing is successful, it will try to validate that the parsed // value is valid for the specified 'flag'. Finally this function stores the diff --git a/absl/flags/internal/commandlineflag.h b/absl/flags/internal/commandlineflag.h index d82443a7..23512576 100644 --- a/absl/flags/internal/commandlineflag.h +++ b/absl/flags/internal/commandlineflag.h @@ -71,13 +71,6 @@ using InitialValGenFunc = void* (*)(); struct CommandLineFlagInfo; -// Signature for the mutation callback used by watched Flags -// The callback is noexcept. -// TODO(rogeeff): add noexcept after C++17 support is added. -using FlagCallback = void (*)(); - -using FlagValidator = bool (*)(); - extern const char kStrippedFlagHelp[]; // The per-type function @@ -201,53 +194,55 @@ struct CommandLineFlag { const char* name_arg, HelpText help_text, const char* filename_arg, const flags_internal::FlagOpFn op_arg, const flags_internal::FlagMarshallingOpFn marshalling_op_arg, - const flags_internal::InitialValGenFunc initial_value_gen, - const bool retired_arg, void* def_arg, void* cur_arg) + const flags_internal::InitialValGenFunc initial_value_gen, void* def_arg, + void* cur_arg) : name(name_arg), help(help_text), filename(filename_arg), op(op_arg), marshalling_op(marshalling_op_arg), make_init_value(initial_value_gen), - retired(retired_arg), inited(false), modified(false), on_command_line(false), - validator(nullptr), - callback(nullptr), def(def_arg), cur(cur_arg), counter(0), atomic(kAtomicInit), locks(nullptr) {} - // Revert the init routine. - void Destroy() const; + // Virtual destructor + virtual void Destroy() const = 0; // Not copyable/assignable. CommandLineFlag(const CommandLineFlag&) = delete; CommandLineFlag& operator=(const CommandLineFlag&) = delete; + // Access methods. + + // Returns true iff this object corresponds to retired flag + virtual bool IsRetired() const { return false; } + // Returns true iff this is a handle to an Abseil Flag. + virtual bool IsAbseilFlag() const { return true; } + absl::string_view Name() const { return name; } std::string Help() const { return help.GetHelpText(); } - bool IsRetired() const { return this->retired; } bool IsModified() const; void SetModified(bool is_modified); bool IsSpecifiedOnCommandLine() const; - // Returns true iff this is a handle to an Abseil Flag. - bool IsAbseilFlag() const { - // Set to null for V1 flags - return this->make_init_value != nullptr; - } absl::string_view Typename() const; std::string Filename() const; std::string DefaultValue() const; std::string CurrentValue() const; - bool HasValidatorFn() const; - bool SetValidatorFn(FlagValidator fn); - bool InvokeValidator(const void* value) const; + // Interfaces to operate on validators. + virtual bool HasValidatorFn() const { return false; } + virtual bool InvokeValidator(const void* /*value*/) const { return true; } + // Invoke the flag validators for old flags. + // TODO(rogeeff): implement proper validators for Abseil Flags + bool ValidateDefaultValue() const; + bool ValidateInputValue(absl::string_view value) const; // Return true iff flag has type T. template @@ -268,8 +263,8 @@ struct CommandLineFlag { return res; } - void SetCallback(const flags_internal::FlagCallback mutation_callback); - void InvokeCallback(); + // Interfaces to overate on callbacks. + virtual void InvokeCallback() {} // Sets the value of the flag based on specified std::string `value`. If the flag // was successfully set to new value, it returns true. Otherwise, sets `error` @@ -286,29 +281,23 @@ struct CommandLineFlag { void StoreAtomic(size_t size); void CheckDefaultValueParsingRoundtrip() const; - // Invoke the flag validators for old flags. - // TODO(rogeeff): implement proper validators for Abseil Flags - bool ValidateDefaultValue() const; - bool ValidateInputValue(absl::string_view value) const; // Constant configuration for a particular flag. - private: + protected: + ~CommandLineFlag() = default; + const char* const name; const HelpText help; const char* const filename; - protected: const FlagOpFn op; // Type-specific handler const FlagMarshallingOpFn marshalling_op; // Marshalling ops handler const InitialValGenFunc make_init_value; // Makes initial value for the flag - const bool retired; // Is the flag retired? std::atomic inited; // fields have been lazily initialized // Mutable state (guarded by locks->primary_mu). bool modified; // Has flag value been modified? bool on_command_line; // Specified on command line. - FlagValidator validator; // Validator function, or nullptr - FlagCallback callback; // Mutation callback, or nullptr void* def; // Lazily initialized pointer to default value void* cur; // Lazily initialized pointer to current value int64_t counter; // Mutation counter @@ -326,7 +315,7 @@ struct CommandLineFlag { // Ensure that the lazily initialized fields of *flag have been initialized, // and return the lock which should be locked when flag's state is mutated. - absl::Mutex* InitFlagIfNecessary() const; + absl::Mutex* InitFlagIfNecessary() const LOCK_RETURNED(locks->primary_mu); // copy construct new value of flag's type in a memory referenced by dst // based on current flag's value @@ -342,6 +331,11 @@ struct CommandLineFlag { friend bool TryParseLocked(CommandLineFlag* flag, void* dst, absl::string_view value, std::string* err); friend absl::Mutex* InitFlag(CommandLineFlag* flag); + + // This is a short term, until we completely rework persistent state + // storage API. + virtual void* GetValidator() const { return nullptr; } + virtual void SetValidator(void*) {} }; // Update any copy of the flag value that is stored in an atomic word. diff --git a/absl/flags/internal/flag.cc b/absl/flags/internal/flag.cc new file mode 100644 index 00000000..34629b30 --- /dev/null +++ b/absl/flags/internal/flag.cc @@ -0,0 +1,51 @@ +// +// 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. + +#include "absl/flags/internal/flag.h" + +#include "absl/synchronization/mutex.h" + +namespace absl { +namespace flags_internal { + +// If the flag has a mutation callback this function invokes it. While the +// callback is being invoked the primary flag's mutex is unlocked and it is +// re-locked back after call to callback is completed. Callback invocation is +// guarded by flag's secondary mutex instead which prevents concurrent +// callback invocation. Note that it is possible for other thread to grab the +// primary lock and update flag's value at any time during the callback +// invocation. This is by design. Callback can get a value of the flag if +// necessary, but it might be different from the value initiated the callback +// and it also can be different by the time the callback invocation is +// completed. Requires that *primary_lock be held in exclusive mode; it may be +// released and reacquired by the implementation. +void InvokeCallback(absl::Mutex* primary_mu, absl::Mutex* callback_mu, + FlagCallback cb) EXCLUSIVE_LOCKS_REQUIRED(primary_mu) { + if (!cb) return; + + // When executing the callback we need the primary flag's mutex to be + // unlocked so that callback can retrieve the flag's value. + primary_mu->Unlock(); + + { + absl::MutexLock lock(callback_mu); + cb(); + } + + primary_mu->Lock(); +} + +} // namespace flags_internal +} // namespace absl diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h index bc50de54..fad36877 100644 --- a/absl/flags/internal/flag.h +++ b/absl/flags/internal/flag.h @@ -22,20 +22,30 @@ namespace absl { namespace flags_internal { +// Signature for the mutation callback used by watched Flags +// The callback is noexcept. +// TODO(rogeeff): add noexcept after C++17 support is added. +using FlagCallback = void (*)(); + +void InvokeCallback(absl::Mutex* primary_mu, absl::Mutex* callback_mu, + FlagCallback cb) EXCLUSIVE_LOCKS_REQUIRED(primary_mu); + // This is "unspecified" implementation of absl::Flag type. template -class Flag : public flags_internal::CommandLineFlag { +class Flag final : public flags_internal::CommandLineFlag { public: - constexpr Flag(const char* name, const flags_internal::HelpGenFunc help_gen, - const char* filename, + constexpr Flag(const char* name_arg, + const flags_internal::HelpGenFunc help_gen, + const char* filename_arg, const flags_internal::FlagMarshallingOpFn marshalling_op_arg, const flags_internal::InitialValGenFunc initial_value_gen) : flags_internal::CommandLineFlag( - name, flags_internal::HelpText::FromFunctionPointer(help_gen), - filename, &flags_internal::FlagOps, marshalling_op_arg, + name_arg, flags_internal::HelpText::FromFunctionPointer(help_gen), + filename_arg, &flags_internal::FlagOps, marshalling_op_arg, initial_value_gen, - /*retired_arg=*/false, /*def_arg=*/nullptr, - /*cur_arg=*/nullptr) {} + /*def_arg=*/nullptr, + /*cur_arg=*/nullptr), + callback_(nullptr) {} T Get() const { // Implementation notes: @@ -76,6 +86,31 @@ class Flag : public flags_internal::CommandLineFlag { } void Set(const T& v) { this->Write(&v, &flags_internal::FlagOps); } + + void SetCallback(const flags_internal::FlagCallback mutation_callback) { + absl::MutexLock l(InitFlagIfNecessary()); + + callback_ = mutation_callback; + + InvokeCallback(); + } + void InvokeCallback() override + EXCLUSIVE_LOCKS_REQUIRED(this->locks->primary_mu) { + flags_internal::InvokeCallback(&this->locks->primary_mu, + &this->locks->callback_mu, callback_); + } + + private: + void Destroy() const override { + // Values are heap allocated Abseil Flags. + if (this->cur) Delete(this->op, this->cur); + if (this->def) Delete(this->op, this->def); + + delete this->locks; + } + + // Flag's data + FlagCallback callback_; // Mutation callback }; // This class facilitates Flag object registration and tail expression-based diff --git a/absl/flags/internal/registry.cc b/absl/flags/internal/registry.cc index 4e5d1106..0d4eec98 100644 --- a/absl/flags/internal/registry.cc +++ b/absl/flags/internal/registry.cc @@ -31,18 +31,6 @@ namespace absl { namespace flags_internal { -namespace { - -void DestroyFlag(CommandLineFlag* flag) NO_THREAD_SAFETY_ANALYSIS { - flag->Destroy(); - - // CommandLineFlag handle object is heap allocated for non Abseil Flags. - if (!flag->IsAbseilFlag()) { - delete flag; - } -} - -} // namespace // -------------------------------------------------------------------- // FlagRegistry @@ -59,7 +47,7 @@ class FlagRegistry { FlagRegistry() = default; ~FlagRegistry() { for (auto& p : flags_) { - DestroyFlag(p.second); + p.second->Destroy(); } } @@ -141,7 +129,7 @@ void FlagRegistry::RegisterFlag(CommandLineFlag* flag) { true); } else if (old_flag->IsRetired()) { // Retired definitions are idempotent. Just keep the old one. - DestroyFlag(flag); + flag->Destroy(); return; } else if (old_flag->Filename() != flag->Filename()) { flags_internal::ReportUsageError( @@ -224,7 +212,7 @@ class FlagSaverImpl { saved.marshalling_op = flag->marshalling_op; { absl::MutexLock l(flag->InitFlagIfNecessary()); - saved.validator = flag->validator; + saved.validator = flag->GetValidator(); saved.modified = flag->modified; saved.on_command_line = flag->on_command_line; saved.current = Clone(saved.op, flag->cur); @@ -250,7 +238,7 @@ class FlagSaverImpl { bool restored = false; { absl::MutexLock l(flag->InitFlagIfNecessary()); - flag->validator = src.validator; + flag->SetValidator(src.validator); flag->modified = src.modified; flag->on_command_line = src.on_command_line; if (flag->counter != src.counter || @@ -290,9 +278,9 @@ class FlagSaverImpl { FlagOpFn op; FlagMarshallingOpFn marshalling_op; int64_t counter; + void* validator; bool modified; bool on_command_line; - bool (*validator)(); const void* current; // nullptr after restore const void* default_value; // nullptr after restore }; @@ -414,14 +402,38 @@ bool RegisterCommandLineFlag(CommandLineFlag* flag) { // -------------------------------------------------------------------- -bool Retire(FlagOpFn ops, FlagMarshallingOpFn marshalling_ops, - const char* name) { - auto* flag = new CommandLineFlag( - name, - /*help_text=*/absl::flags_internal::HelpText::FromStaticCString(nullptr), - /*filename_arg=*/"RETIRED", ops, marshalling_ops, - /*initial_value_gen=*/nullptr, - /*retired_arg=*/true, nullptr, nullptr); +namespace { + +class RetiredFlagObj final : public flags_internal::CommandLineFlag { + public: + constexpr RetiredFlagObj(const char* name_arg, FlagOpFn ops, + FlagMarshallingOpFn marshalling_ops) + : flags_internal::CommandLineFlag( + name_arg, flags_internal::HelpText::FromStaticCString(nullptr), + /*filename_arg=*/"RETIRED", ops, marshalling_ops, + /*initial_value_gen=*/nullptr, + /*def_arg=*/nullptr, + /*cur_arg=*/nullptr) {} + + private: + bool IsRetired() const override { return true; } + + void Destroy() const override { + // Values are heap allocated for Retired Flags. + if (this->cur) Delete(this->op, this->cur); + if (this->def) Delete(this->op, this->def); + + if (this->locks) delete this->locks; + + delete this; + } +}; + +} // namespace + +bool Retire(const char* name, FlagOpFn ops, + FlagMarshallingOpFn marshalling_ops) { + auto* flag = new flags_internal::RetiredFlagObj(name, ops, marshalling_ops); FlagRegistry::GlobalRegistry()->RegisterFlag(flag); return true; } diff --git a/absl/flags/internal/registry.h b/absl/flags/internal/registry.h index 27566fbf..884a8db5 100644 --- a/absl/flags/internal/registry.h +++ b/absl/flags/internal/registry.h @@ -106,29 +106,16 @@ bool RegisterCommandLineFlag(CommandLineFlag*); // 4: Remove the old_lib 'retired' registration. // 5: Eventually delete the graveyard registration entirely. // -// Returns bool to enable use in namespace-scope initializers. -// For example: -// -// static const bool dummy = base::RetiredFlag("myflag"); -// -// Or to declare several at once: -// -// static bool dummies[] = { -// base::RetiredFlag("some_string_flag"), -// base::RetiredFlag("some_double_flag"), -// base::RetiredFlag("some_int32_flag") -// }; // Retire flag with name "name" and type indicated by ops. -bool Retire(FlagOpFn ops, FlagMarshallingOpFn marshalling_ops, - const char* name); +bool Retire(const char* name, FlagOpFn ops, + FlagMarshallingOpFn marshalling_ops); // Registered a retired flag with name 'flag_name' and type 'T'. template inline bool RetiredFlag(const char* flag_name) { - return flags_internal::Retire(flags_internal::FlagOps, - flags_internal::FlagMarshallingOps, - flag_name); + return flags_internal::Retire(flag_name, flags_internal::FlagOps, + flags_internal::FlagMarshallingOps); } // If the flag is retired, returns true and indicates in |*type_is_bool| diff --git a/absl/flags/internal/usage_test.cc b/absl/flags/internal/usage_test.cc index 781e1d2b..8538b2b6 100644 --- a/absl/flags/internal/usage_test.cc +++ b/absl/flags/internal/usage_test.cc @@ -395,7 +395,7 @@ TEST_F(UsageReportingTest, TestUsageFlag_helpon) { } // namespace int main(int argc, char* argv[]) { - absl::GetFlag(FLAGS_undefok); // Force linking of parse.cc + (void)absl::GetFlag(FLAGS_undefok); // Force linking of parse.cc flags::SetProgramInvocationName("usage_test"); absl::SetProgramUsageMessage(kTestUsageMessage); ::testing::InitGoogleTest(&argc, argv); diff --git a/absl/random/distributions.h b/absl/random/distributions.h index d8ba3cdb..18ff2484 100644 --- a/absl/random/distributions.h +++ b/absl/random/distributions.h @@ -68,18 +68,13 @@ namespace absl { -ABSL_INTERNAL_INLINE_CONSTEXPR(random_internal::IntervalClosedClosedT, - IntervalClosedClosed, {}); -ABSL_INTERNAL_INLINE_CONSTEXPR(random_internal::IntervalClosedClosedT, - IntervalClosed, {}); -ABSL_INTERNAL_INLINE_CONSTEXPR(random_internal::IntervalClosedOpenT, - IntervalClosedOpen, {}); -ABSL_INTERNAL_INLINE_CONSTEXPR(random_internal::IntervalOpenOpenT, - IntervalOpenOpen, {}); -ABSL_INTERNAL_INLINE_CONSTEXPR(random_internal::IntervalOpenOpenT, - IntervalOpen, {}); -ABSL_INTERNAL_INLINE_CONSTEXPR(random_internal::IntervalOpenClosedT, - IntervalOpenClosed, {}); +ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalClosedClosedTag, IntervalClosedClosed, + {}); +ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalClosedClosedTag, IntervalClosed, {}); +ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalClosedOpenTag, IntervalClosedOpen, {}); +ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalOpenOpenTag, IntervalOpenOpen, {}); +ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalOpenOpenTag, IntervalOpen, {}); +ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalOpenClosedTag, IntervalOpenClosed, {}); // ----------------------------------------------------------------------------- // absl::Uniform(tag, bitgen, lo, hi) diff --git a/absl/random/distributions_test.cc b/absl/random/distributions_test.cc index eb82868d..2d92723a 100644 --- a/absl/random/distributions_test.cc +++ b/absl/random/distributions_test.cc @@ -171,14 +171,11 @@ void CheckArgsInferType() { ""); static_assert( absl::conjunction< + std::is_same(0))>, std::is_same( - 0))>, - std::is_same( - 0))>>::value, + absl::IntervalOpenOpenTag, B, A>(0))>>::value, ""); } @@ -218,12 +215,10 @@ void CheckArgsReturnExpectedType() { absl::conjunction< std::is_same(0))>, - std::is_same(0))>>::value, + absl::IntervalOpenOpenTag, A, B, Expect>(0))>, + std::is_same(0))>>::value, ""); } diff --git a/absl/random/internal/uniform_helper.h b/absl/random/internal/uniform_helper.h index ebcc3744..9e89e526 100644 --- a/absl/random/internal/uniform_helper.h +++ b/absl/random/internal/uniform_helper.h @@ -30,12 +30,33 @@ class uniform_real_distribution; // Interval tag types which specify whether the interval is open or closed // on either boundary. + namespace random_internal { -struct IntervalClosedClosedT {}; -struct IntervalClosedOpenT {}; -struct IntervalOpenClosedT {}; -struct IntervalOpenOpenT {}; +template +struct TagTypeCompare {}; + +template +constexpr bool operator==(TagTypeCompare, TagTypeCompare) { + // Tags are mono-states. They always compare equal. + return true; +} +template +constexpr bool operator!=(TagTypeCompare, TagTypeCompare) { + return false; +} +} // namespace random_internal + +struct IntervalClosedClosedTag + : public random_internal::TagTypeCompare {}; +struct IntervalClosedOpenTag + : public random_internal::TagTypeCompare {}; +struct IntervalOpenClosedTag + : public random_internal::TagTypeCompare {}; +struct IntervalOpenOpenTag + : public random_internal::TagTypeCompare {}; + +namespace random_internal { // The functions // uniform_lower_bound(tag, a, b) // and @@ -56,8 +77,8 @@ template typename absl::enable_if_t< absl::conjunction< std::is_integral, - absl::disjunction, - std::is_same>>::value, + absl::disjunction, + std::is_same>>::value, IntType> uniform_lower_bound(Tag, IntType a, IntType) { return a + 1; @@ -67,8 +88,8 @@ template typename absl::enable_if_t< absl::conjunction< std::is_floating_point, - absl::disjunction, - std::is_same>>::value, + absl::disjunction, + std::is_same>>::value, FloatType> uniform_lower_bound(Tag, FloatType a, FloatType b) { return std::nextafter(a, b); @@ -76,8 +97,8 @@ uniform_lower_bound(Tag, FloatType a, FloatType b) { template typename absl::enable_if_t< - absl::disjunction, - std::is_same>::value, + absl::disjunction, + std::is_same>::value, NumType> uniform_lower_bound(Tag, NumType a, NumType) { return a; @@ -87,8 +108,8 @@ template typename absl::enable_if_t< absl::conjunction< std::is_integral, - absl::disjunction, - std::is_same>>::value, + absl::disjunction, + std::is_same>>::value, IntType> uniform_upper_bound(Tag, IntType, IntType b) { return b - 1; @@ -98,8 +119,8 @@ template typename absl::enable_if_t< absl::conjunction< std::is_floating_point, - absl::disjunction, - std::is_same>>::value, + absl::disjunction, + std::is_same>>::value, FloatType> uniform_upper_bound(Tag, FloatType, FloatType b) { return b; @@ -109,8 +130,8 @@ template typename absl::enable_if_t< absl::conjunction< std::is_integral, - absl::disjunction, - std::is_same>>::value, + absl::disjunction, + std::is_same>>::value, IntType> uniform_upper_bound(Tag, IntType, IntType b) { return b; @@ -120,8 +141,8 @@ template typename absl::enable_if_t< absl::conjunction< std::is_floating_point, - absl::disjunction, - std::is_same>>::value, + absl::disjunction, + std::is_same>>::value, FloatType> uniform_upper_bound(Tag, FloatType, FloatType b) { return std::nextafter(b, (std::numeric_limits::max)()); diff --git a/ci/linux_clang-latest_libcxx_asan_bazel.sh b/ci/linux_clang-latest_libcxx_asan_bazel.sh index e26e9555..cc8c695a 100755 --- a/ci/linux_clang-latest_libcxx_asan_bazel.sh +++ b/ci/linux_clang-latest_libcxx_asan_bazel.sh @@ -32,6 +32,10 @@ if [ -z ${COMPILATION_MODE:-} ]; then COMPILATION_MODE="fastbuild opt" fi +if [ -z ${EXCEPTIONS_MODE:-} ]; then + EXCEPTIONS_MODE="-fno-exceptions -fexceptions" +fi + readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190813" # USE_BAZEL_CACHE=1 only works on Kokoro. @@ -48,41 +52,42 @@ 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" \ - ${DOCKER_EXTRA_ARGS:-} \ - ${DOCKER_CONTAINER} \ - /usr/local/bin/bazel test ... \ - --compilation_mode=${compilation_mode} \ - --copt="-DDYNAMIC_ANNOTATIONS_ENABLED=1" \ - --copt="-DADDRESS_SANITIZER" \ - --copt="-DUNDEFINED_BEHAVIOR_SANITIZER" \ - --copt="-fsanitize=address" \ - --copt="-fsanitize=float-divide-by-zero" \ - --copt="-fsanitize=nullability" \ - --copt="-fsanitize=undefined" \ - --copt=-Werror \ - --keep_going \ - --linkopt="-fsanitize=address" \ - --linkopt="-fsanitize-link-c++-runtime" \ - --show_timestamps \ - --test_env="ASAN_SYMBOLIZER_PATH=/opt/llvm/clang/bin/llvm-symbolizer" \ - --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \ - --test_env="UBSAN_OPTIONS=print_stacktrace=1" \ - --test_env="UBSAN_SYMBOLIZER_PATH=/opt/llvm/clang/bin/llvm-symbolizer" \ - --test_output=errors \ - --test_tag_filters="-benchmark,-noasan" \ - ${BAZEL_EXTRA_ARGS:-} + for exceptions_mode in ${EXCEPTIONS_MODE}; do + echo "--------------------------------------------------------------------" + 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" \ + ${DOCKER_EXTRA_ARGS:-} \ + ${DOCKER_CONTAINER} \ + /usr/local/bin/bazel test ... \ + --compilation_mode="${compilation_mode}" \ + --copt="${exceptions_mode}" \ + --copt="-DDYNAMIC_ANNOTATIONS_ENABLED=1" \ + --copt="-DADDRESS_SANITIZER" \ + --copt="-DUNDEFINED_BEHAVIOR_SANITIZER" \ + --copt="-fsanitize=address" \ + --copt="-fsanitize=float-divide-by-zero" \ + --copt="-fsanitize=nullability" \ + --copt="-fsanitize=undefined" \ + --copt=-Werror \ + --keep_going \ + --linkopt="-fsanitize=address" \ + --linkopt="-fsanitize-link-c++-runtime" \ + --show_timestamps \ + --test_env="ASAN_SYMBOLIZER_PATH=/opt/llvm/clang/bin/llvm-symbolizer" \ + --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \ + --test_env="UBSAN_OPTIONS=print_stacktrace=1" \ + --test_env="UBSAN_SYMBOLIZER_PATH=/opt/llvm/clang/bin/llvm-symbolizer" \ + --test_output=errors \ + --test_tag_filters="-benchmark,-noasan" \ + ${BAZEL_EXTRA_ARGS:-} + done done done diff --git a/ci/linux_clang-latest_libcxx_bazel.sh b/ci/linux_clang-latest_libcxx_bazel.sh index 42bde353..5849a84e 100755 --- a/ci/linux_clang-latest_libcxx_bazel.sh +++ b/ci/linux_clang-latest_libcxx_bazel.sh @@ -32,6 +32,10 @@ if [ -z ${COMPILATION_MODE:-} ]; then COMPILATION_MODE="fastbuild opt" fi +if [ -z ${EXCEPTIONS_MODE:-} ]; then + EXCEPTIONS_MODE="-fno-exceptions -fexceptions" +fi + readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190813" # USE_BAZEL_CACHE=1 only works on Kokoro. @@ -48,31 +52,32 @@ 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" \ - ${DOCKER_EXTRA_ARGS:-} \ - ${DOCKER_CONTAINER} \ - /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 \ - ${BAZEL_EXTRA_ARGS:-} + for exceptions_mode in ${EXCEPTIONS_MODE}; do + echo "--------------------------------------------------------------------" + 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" \ + ${DOCKER_EXTRA_ARGS:-} \ + ${DOCKER_CONTAINER} \ + /usr/local/bin/bazel test ... \ + --compilation_mode="${compilation_mode}" \ + --copt="${exceptions_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 \ + ${BAZEL_EXTRA_ARGS:-} + done done done diff --git a/ci/linux_clang-latest_libcxx_tsan_bazel.sh b/ci/linux_clang-latest_libcxx_tsan_bazel.sh index 452c515c..8721ada2 100755 --- a/ci/linux_clang-latest_libcxx_tsan_bazel.sh +++ b/ci/linux_clang-latest_libcxx_tsan_bazel.sh @@ -32,6 +32,10 @@ if [ -z ${COMPILATION_MODE:-} ]; then COMPILATION_MODE="fastbuild opt" fi +if [ -z ${EXCEPTIONS_MODE:-} ]; then + EXCEPTIONS_MODE="-fno-exceptions -fexceptions" +fi + readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190813" # USE_BAZEL_CACHE=1 only works on Kokoro. @@ -48,36 +52,37 @@ 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-tsan/lib:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/libcxx-tsan/lib" \ - -e CPLUS_INCLUDE_PATH="/opt/llvm/libcxx-tsan/include/c++/v1" \ - ${DOCKER_EXTRA_ARGS:-} \ - ${DOCKER_CONTAINER} \ - /usr/local/bin/bazel test ... \ - --build_tag_filters="-notsan" \ - --compilation_mode=${compilation_mode} \ - --copt="-DDYNAMIC_ANNOTATIONS_ENABLED=1" \ - --copt="-DTHREAD_SANITIZER" \ - --copt="-fsanitize=thread" \ - --copt=-Werror \ - --keep_going \ - --linkopt="-fsanitize=thread" \ - --show_timestamps \ - --test_env="TSAN_OPTIONS=report_atomic_races=0" \ - --test_env="TSAN_SYMBOLIZER_PATH=/opt/llvm/clang/bin/llvm-symbolizer" \ - --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \ - --test_output=errors \ - --test_tag_filters="-benchmark,-notsan" \ - ${BAZEL_EXTRA_ARGS:-} + for exceptions_mode in ${EXCEPTIONS_MODE}; do + echo "--------------------------------------------------------------------" + 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-tsan/lib:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/libcxx-tsan/lib" \ + -e CPLUS_INCLUDE_PATH="/opt/llvm/libcxx-tsan/include/c++/v1" \ + ${DOCKER_EXTRA_ARGS:-} \ + ${DOCKER_CONTAINER} \ + /usr/local/bin/bazel test ... \ + --build_tag_filters="-notsan" \ + --compilation_mode="${compilation_mode}" \ + --copt="${exceptions_mode}" \ + --copt="-DDYNAMIC_ANNOTATIONS_ENABLED=1" \ + --copt="-DTHREAD_SANITIZER" \ + --copt="-fsanitize=thread" \ + --copt=-Werror \ + --keep_going \ + --linkopt="-fsanitize=thread" \ + --show_timestamps \ + --test_env="TSAN_OPTIONS=report_atomic_races=0" \ + --test_env="TSAN_SYMBOLIZER_PATH=/opt/llvm/clang/bin/llvm-symbolizer" \ + --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \ + --test_output=errors \ + --test_tag_filters="-benchmark,-notsan" \ + ${BAZEL_EXTRA_ARGS:-} + done done done diff --git a/ci/linux_clang-latest_libstdcxx_bazel.sh b/ci/linux_clang-latest_libstdcxx_bazel.sh index 4b063ad8..78ce0b32 100755 --- a/ci/linux_clang-latest_libstdcxx_bazel.sh +++ b/ci/linux_clang-latest_libstdcxx_bazel.sh @@ -32,6 +32,10 @@ if [ -z ${COMPILATION_MODE:-} ]; then COMPILATION_MODE="fastbuild opt" fi +if [ -z ${EXCEPTIONS_MODE:-} ]; then + EXCEPTIONS_MODE="-fno-exceptions -fexceptions" +fi + readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190813" # USE_BAZEL_CACHE=1 only works on Kokoro. @@ -48,30 +52,31 @@ 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" \ - ${DOCKER_EXTRA_ARGS:-} \ - ${DOCKER_CONTAINER} \ - /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 \ - ${BAZEL_EXTRA_ARGS:-} + for exceptions_mode in ${EXCEPTIONS_MODE}; do + echo "--------------------------------------------------------------------" + 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" \ + ${DOCKER_EXTRA_ARGS:-} \ + ${DOCKER_CONTAINER} \ + /usr/local/bin/bazel test ... \ + --compilation_mode="${compilation_mode}" \ + --copt="${exceptions_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 \ + ${BAZEL_EXTRA_ARGS:-} + done done done diff --git a/ci/linux_gcc-4.9_libstdcxx_bazel.sh b/ci/linux_gcc-4.9_libstdcxx_bazel.sh index bdd3e468..c3b936bc 100755 --- a/ci/linux_gcc-4.9_libstdcxx_bazel.sh +++ b/ci/linux_gcc-4.9_libstdcxx_bazel.sh @@ -32,6 +32,10 @@ if [ -z ${COMPILATION_MODE:-} ]; then COMPILATION_MODE="fastbuild opt" fi +if [ -z ${EXCEPTIONS_MODE:-} ]; then + EXCEPTIONS_MODE="-fno-exceptions -fexceptions" +fi + readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-4.9:20190702" # USE_BAZEL_CACHE=1 only works on Kokoro. @@ -48,28 +52,29 @@ 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/bin/gcc-4.9" \ - -e BAZEL_CXXOPTS="-std=${std}" \ - ${DOCKER_EXTRA_ARGS:-} \ - ${DOCKER_CONTAINER} \ - /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 \ - ${BAZEL_EXTRA_ARGS:-} + for exceptions_mode in ${EXCEPTIONS_MODE}; do + echo "--------------------------------------------------------------------" + time docker run \ + --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \ + --workdir=/abseil-cpp \ + --cap-add=SYS_PTRACE \ + --rm \ + -e CC="/usr/bin/gcc-4.9" \ + -e BAZEL_CXXOPTS="-std=${std}" \ + ${DOCKER_EXTRA_ARGS:-} \ + ${DOCKER_CONTAINER} \ + /usr/local/bin/bazel test ... \ + --compilation_mode="${compilation_mode}" \ + --copt="${exceptions_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 \ + ${BAZEL_EXTRA_ARGS:-} + done done done diff --git a/ci/linux_gcc-latest_libstdcxx_bazel.sh b/ci/linux_gcc-latest_libstdcxx_bazel.sh index 92933e3a..10f6be21 100755 --- a/ci/linux_gcc-latest_libstdcxx_bazel.sh +++ b/ci/linux_gcc-latest_libstdcxx_bazel.sh @@ -32,6 +32,10 @@ if [ -z ${COMPILATION_MODE:-} ]; then COMPILATION_MODE="fastbuild opt" fi +if [ -z ${EXCEPTIONS_MODE:-} ]; then + EXCEPTIONS_MODE="-fno-exceptions -fexceptions" +fi + readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-latest:20190703" # USE_BAZEL_CACHE=1 only works on Kokoro. @@ -48,28 +52,29 @@ 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}" \ - ${DOCKER_EXTRA_ARGS:-} \ - ${DOCKER_CONTAINER} \ - /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 \ - ${BAZEL_EXTRA_ARGS:-} + for exceptions_mode in ${EXCEPTIONS_MODE}; do + echo "--------------------------------------------------------------------" + 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}" \ + ${DOCKER_EXTRA_ARGS:-} \ + ${DOCKER_CONTAINER} \ + /usr/local/bin/bazel test ... \ + --compilation_mode="${compilation_mode}" \ + --copt="${exceptions_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 \ + ${BAZEL_EXTRA_ARGS:-} + done done done -- cgit v1.2.3 From 2796d500aea5a31d26b8b24a33fab7a1c8fa2f32 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Mon, 21 Oct 2019 10:21:03 -0700 Subject: Export of internal Abseil changes -- b770d03c2f1042d399c3f9576e881691cbe962c4 by Abseil Team : Avoid applying the workaround for MSVC's static initialization problems when using clang-cl. PiperOrigin-RevId: 275870089 -- 2b8fc02ec49aeb5ad56cef20259cdd7f6ee0c917 by Abseil Team : Document return values. PiperOrigin-RevId: 275839042 -- baa99064f9a28b188661df7fba989fcd558818af by Abseil Team : Support "auto" and other uncommon builtin types in absl::debugging_internal::Demangle. PiperOrigin-RevId: 275556195 -- f9d5c6a3a0d374dbf105d6e2e9e0c8fa949ed187 by Gennadiy Rozental : Internal rework. PiperOrigin-RevId: 275550005 -- 2679a77db5b26349e8c8b2059621af55d2fca139 by Mark Barolak : Remove a comment reference to the no longer extant ::string implementation. PiperOrigin-RevId: 275531987 -- 7b427a7613c44a98c6f13da43b2bff2837ca6b19 by Derek Mauro : Upgrade to Bazel 1.0.0 and CMake 3.15.4 PiperOrigin-RevId: 275500823 -- 81f7d20905debf9d1e300bd2e9899f88d27f632a by Derek Mauro : Fix -Wimplicit-int-float-conversion warning in latest clang PiperOrigin-RevId: 275492439 GitOrigin-RevId: b770d03c2f1042d399c3f9576e881691cbe962c4 Change-Id: I9b39dad524489f0d62c912d02e8ac43761c81e55 --- absl/debugging/internal/demangle.cc | 34 ++- absl/debugging/stacktrace.h | 30 +- absl/flags/BUILD.bazel | 4 +- absl/flags/declare.h | 2 +- absl/flags/flag.cc | 2 +- absl/flags/flag.h | 10 +- absl/flags/flag_test.cc | 9 +- absl/flags/internal/commandlineflag.cc | 333 --------------------- absl/flags/internal/commandlineflag.h | 187 ++++-------- absl/flags/internal/flag.cc | 337 ++++++++++++++++++++-- absl/flags/internal/flag.h | 237 ++++++++++----- absl/flags/internal/registry.cc | 45 +-- absl/flags/internal/registry.h | 6 +- absl/random/internal/iostream_state_saver_test.cc | 8 +- absl/strings/internal/resize_uninitialized.h | 3 +- ci/cmake_install_test.sh | 3 +- ci/linux_clang-latest_libcxx_asan_bazel.sh | 2 +- ci/linux_clang-latest_libcxx_bazel.sh | 2 +- ci/linux_clang-latest_libcxx_tsan_bazel.sh | 2 +- ci/linux_clang-latest_libstdcxx_bazel.sh | 2 +- ci/linux_gcc-4.9_libstdcxx_bazel.sh | 2 +- ci/linux_gcc-latest_libstdcxx_bazel.sh | 2 +- ci/linux_gcc-latest_libstdcxx_cmake.sh | 2 +- 23 files changed, 634 insertions(+), 630 deletions(-) (limited to 'ci/linux_clang-latest_libcxx_tsan_bazel.sh') diff --git a/absl/debugging/internal/demangle.cc b/absl/debugging/internal/demangle.cc index 52a553fd..3809e496 100644 --- a/absl/debugging/internal/demangle.cc +++ b/absl/debugging/internal/demangle.cc @@ -93,6 +93,8 @@ static const AbbrevPair kOperatorList[] = { }; // List of builtin types from Itanium C++ ABI. +// +// Invariant: only one- or two-character type abbreviations here. static const AbbrevPair kBuiltinTypeList[] = { {"v", "void", 0}, {"w", "wchar_t", 0}, @@ -115,6 +117,16 @@ static const AbbrevPair kBuiltinTypeList[] = { {"e", "long double", 0}, {"g", "__float128", 0}, {"z", "ellipsis", 0}, + + {"De", "decimal128", 0}, // IEEE 754r decimal floating point (128 bits) + {"Dd", "decimal64", 0}, // IEEE 754r decimal floating point (64 bits) + {"Dc", "decltype(auto)", 0}, + {"Da", "auto", 0}, + {"Dn", "std::nullptr_t", 0}, // i.e., decltype(nullptr) + {"Df", "decimal32", 0}, // IEEE 754r decimal floating point (32 bits) + {"Di", "char32_t", 0}, + {"Ds", "char16_t", 0}, + {"Dh", "float16", 0}, // IEEE 754r half-precision float (16 bits) {nullptr, nullptr, 0}, }; @@ -1168,12 +1180,6 @@ static bool ParseType(State *state) { } state->parse_state = copy; - // nullptr_t, i.e. decltype(nullptr). - if (ParseTwoCharToken(state, "Dn")) { - return true; - } - state->parse_state = copy; - if (ParseOneCharToken(state, 'U') && ParseSourceName(state) && ParseType(state)) { return true; @@ -1214,16 +1220,26 @@ static bool ParseCVQualifiers(State *state) { return num_cv_qualifiers > 0; } -// ::= v, etc. +// ::= v, etc. # single-character builtin types // ::= u +// ::= Dd, etc. # two-character builtin types +// +// Not supported: +// ::= DF _ # _FloatN (N bits) +// static bool ParseBuiltinType(State *state) { ComplexityGuard guard(state); if (guard.IsTooComplex()) return false; const AbbrevPair *p; for (p = kBuiltinTypeList; p->abbrev != nullptr; ++p) { - if (RemainingInput(state)[0] == p->abbrev[0]) { + // Guaranteed only 1- or 2-character strings in kBuiltinTypeList. + if (p->abbrev[1] == '\0') { + if (ParseOneCharToken(state, p->abbrev[0])) { + MaybeAppend(state, p->real_name); + return true; + } + } else if (p->abbrev[2] == '\0' && ParseTwoCharToken(state, p->abbrev)) { MaybeAppend(state, p->real_name); - ++state->parse_state.mangled_idx; return true; } } diff --git a/absl/debugging/stacktrace.h b/absl/debugging/stacktrace.h index 3fc1c03f..cd8fae76 100644 --- a/absl/debugging/stacktrace.h +++ b/absl/debugging/stacktrace.h @@ -36,10 +36,10 @@ namespace absl { // GetStackFrames() // // Records program counter values for up to `max_depth` frames, skipping the -// most recent `skip_count` stack frames, and stores their corresponding values -// and sizes in `results` and `sizes` buffers. (Note that the frame generated -// for the `absl::GetStackFrames()` routine itself is also skipped.) -// routine itself. +// most recent `skip_count` stack frames, stores their corresponding values +// and sizes in `results` and `sizes` buffers, and returns the number of frames +// stored. (Note that the frame generated for the `absl::GetStackFrames()` +// routine itself is also skipped.) // // Example: // @@ -54,8 +54,8 @@ namespace absl { // The current stack frame would consist of three function calls: `bar()`, // `foo()`, and then `main()`; however, since the `GetStackFrames()` call sets // `skip_count` to `1`, it will skip the frame for `bar()`, the most recently -// invoked function call. It will therefore return two program counters and will -// produce values that map to the following function calls: +// invoked function call. It will therefore return 2 and fill `result` with +// program counters within the following functions: // // result[0] foo() // result[1] main() @@ -82,9 +82,10 @@ extern int GetStackFrames(void** result, int* sizes, int max_depth, // // Records program counter values obtained from a signal handler. Records // program counter values for up to `max_depth` frames, skipping the most recent -// `skip_count` stack frames, and stores their corresponding values and sizes in -// `results` and `sizes` buffers. (Note that the frame generated for the -// `absl::GetStackFramesWithContext()` routine itself is also skipped.) +// `skip_count` stack frames, stores their corresponding values and sizes in +// `results` and `sizes` buffers, and returns the number of frames stored. (Note +// that the frame generated for the `absl::GetStackFramesWithContext()` routine +// itself is also skipped.) // // The `uc` parameter, if non-null, should be a pointer to a `ucontext_t` value // passed to a signal handler registered via the `sa_sigaction` field of a @@ -105,8 +106,9 @@ extern int GetStackFramesWithContext(void** result, int* sizes, int max_depth, // GetStackTrace() // // Records program counter values for up to `max_depth` frames, skipping the -// most recent `skip_count` stack frames, and stores their corresponding values -// in `results`. Note that this function is similar to `absl::GetStackFrames()` +// most recent `skip_count` stack frames, stores their corresponding values +// in `results`, and returns the number of frames +// stored. Note that this function is similar to `absl::GetStackFrames()` // except that it returns the stack trace only, and not stack frame sizes. // // Example: @@ -131,9 +133,9 @@ extern int GetStackTrace(void** result, int max_depth, int skip_count); // // Records program counter values obtained from a signal handler. Records // program counter values for up to `max_depth` frames, skipping the most recent -// `skip_count` stack frames, and stores their corresponding values in -// `results`. (Note that the frame generated for the -// `absl::GetStackFramesWithContext()` routine itself is also skipped.) +// `skip_count` stack frames, stores their corresponding values in `results`, +// and returns the number of frames stored. (Note that the frame generated for +// the `absl::GetStackFramesWithContext()` routine itself is also skipped.) // // The `uc` parameter, if non-null, should be a pointer to a `ucontext_t` value // passed to a signal handler registered via the `sa_sigaction` field of a diff --git a/absl/flags/BUILD.bazel b/absl/flags/BUILD.bazel index 2e0dc389..cf449198 100644 --- a/absl/flags/BUILD.bazel +++ b/absl/flags/BUILD.bazel @@ -40,6 +40,7 @@ cc_library( deps = [ ":handle", ":registry", + "//absl/base:core_headers", "//absl/memory", "//absl/strings", "//absl/synchronization", @@ -135,9 +136,6 @@ cc_library( ":config", ":marshalling", "//absl/base:core_headers", - "//absl/base:raw_logging_internal", - "//absl/strings", - "//absl/synchronization", "//absl/types:optional", ], ) diff --git a/absl/flags/declare.h b/absl/flags/declare.h index 0a113a2b..4926a09e 100644 --- a/absl/flags/declare.h +++ b/absl/flags/declare.h @@ -39,7 +39,7 @@ class Flag; // Flag // // Forward declaration of the `absl::Flag` type for use in defining the macro. -#if defined(_MSC_VER) +#if defined(_MSC_VER) && !defined(__clang__) template class Flag; #else diff --git a/absl/flags/flag.cc b/absl/flags/flag.cc index 69038bbf..37bbce23 100644 --- a/absl/flags/flag.cc +++ b/absl/flags/flag.cc @@ -43,7 +43,7 @@ ABSL_FLAGS_INTERNAL_FOR_EACH_LOCK_FREE(ABSL_FLAGS_ATOMIC_GET) // This global nutex protects on-demand construction of flag objects in MSVC // builds. -#if defined(_MSC_VER) +#if defined(_MSC_VER) && !defined(__clang__) namespace flags_internal { diff --git a/absl/flags/flag.h b/absl/flags/flag.h index 85900ef8..c0060b44 100644 --- a/absl/flags/flag.h +++ b/absl/flags/flag.h @@ -63,7 +63,7 @@ namespace absl { // ABSL_FLAG(int, count, 0, "Count of items to process"); // // No public methods of `absl::Flag` are part of the Abseil Flags API. -#if !defined(_MSC_VER) +#if !defined(_MSC_VER) || defined(__clang__) template using Flag = flags_internal::Flag; #else @@ -119,7 +119,6 @@ class Flag { absl::string_view Name() const { return GetImpl()->Name(); } std::string Help() const { return GetImpl()->Help(); } bool IsModified() const { return GetImpl()->IsModified(); } - void SetModified(bool is_modified) { GetImpl()->SetModified(is_modified); } bool IsSpecifiedOnCommandLine() const { return GetImpl()->IsSpecifiedOnCommandLine(); } @@ -127,9 +126,6 @@ class Flag { std::string Filename() const { return GetImpl()->Filename(); } std::string DefaultValue() const { return GetImpl()->DefaultValue(); } std::string CurrentValue() const { return GetImpl()->CurrentValue(); } - bool InvokeValidator(const void* value) const { - return GetImpl()->InvokeValidator(value); - } template inline bool IsOfType() const { return GetImpl()->template IsOfType(); @@ -272,7 +268,7 @@ void SetFlag(absl::Flag* flag, const V& v) { #if ABSL_FLAGS_STRIP_NAMES #define ABSL_FLAG_IMPL_FLAGNAME(txt) "" #define ABSL_FLAG_IMPL_FILENAME() "" -#if !defined(_MSC_VER) +#if !defined(_MSC_VER) || defined(__clang__) #define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \ absl::flags_internal::FlagRegistrar(&flag) #else @@ -282,7 +278,7 @@ void SetFlag(absl::Flag* flag, const V& v) { #else #define ABSL_FLAG_IMPL_FLAGNAME(txt) txt #define ABSL_FLAG_IMPL_FILENAME() __FILE__ -#if !defined(_MSC_VER) +#if !defined(_MSC_VER) || defined(__clang__) #define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \ absl::flags_internal::FlagRegistrar(&flag) #else diff --git a/absl/flags/flag_test.cc b/absl/flags/flag_test.cc index a652042c..59dc579c 100644 --- a/absl/flags/flag_test.cc +++ b/absl/flags/flag_test.cc @@ -42,15 +42,14 @@ void TestCallback() {} template bool TestConstructionFor() { constexpr flags::Flag f1("f1", &TestHelpMsg, "file", - &absl::flags_internal::FlagMarshallingOps, - &TestMakeDflt); + &flags::FlagMarshallingOps, &TestMakeDflt); EXPECT_EQ(f1.Name(), "f1"); EXPECT_EQ(f1.Help(), "help"); EXPECT_EQ(f1.Filename(), "file"); - ABSL_CONST_INIT static flags::Flag f2( - "f2", &TestHelpMsg, "file", &absl::flags_internal::FlagMarshallingOps, - &TestMakeDflt); + ABSL_CONST_INIT static flags::Flag f2("f2", &TestHelpMsg, "file", + &flags::FlagMarshallingOps, + &TestMakeDflt); flags::FlagRegistrar(&f2).OnUpdate(TestCallback); EXPECT_EQ(f2.Name(), "f2"); diff --git a/absl/flags/internal/commandlineflag.cc b/absl/flags/internal/commandlineflag.cc index 99f73611..caf33bc4 100644 --- a/absl/flags/internal/commandlineflag.cc +++ b/absl/flags/internal/commandlineflag.cc @@ -15,14 +15,7 @@ #include "absl/flags/internal/commandlineflag.h" -#include - -#include "absl/base/internal/raw_logging.h" -#include "absl/base/optimization.h" -#include "absl/flags/config.h" #include "absl/flags/usage_config.h" -#include "absl/strings/str_cat.h" -#include "absl/synchronization/mutex.h" namespace absl { namespace flags_internal { @@ -35,80 +28,6 @@ namespace flags_internal { // This is used by this file, and also in commandlineflags_reporting.cc const char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001"; -namespace { - -// Currently we only validate flag values for user-defined flag types. -bool ShouldValidateFlagValue(const CommandLineFlag& flag) { -#define DONT_VALIDATE(T) \ - if (flag.IsOfType()) return false; - ABSL_FLAGS_INTERNAL_FOR_EACH_LOCK_FREE(DONT_VALIDATE) - DONT_VALIDATE(std::string) - DONT_VALIDATE(std::vector) -#undef DONT_VALIDATE - - return true; -} - -} // namespace - -absl::Mutex* InitFlag(CommandLineFlag* flag) { - ABSL_CONST_INIT static absl::Mutex init_lock(absl::kConstInit); - absl::Mutex* mu; - - { - absl::MutexLock lock(&init_lock); - - if (flag->locks_ == nullptr) { // Must initialize Mutexes for this flag. - flag->locks_ = new flags_internal::CommandLineFlagLocks; - } - - mu = &flag->locks_->primary_mu; - } - - { - absl::MutexLock lock(mu); - - if (!flag->IsRetired() && flag->def_ == nullptr) { - // Need to initialize def and cur fields. - flag->def_ = (*flag->make_init_value_)(); - flag->cur_ = Clone(flag->op_, flag->def_); - UpdateCopy(flag); - flag->inited_.store(true, std::memory_order_release); - flag->InvokeCallback(); - } - } - - flag->inited_.store(true, std::memory_order_release); - return mu; -} - -// Ensure that the lazily initialized fields of *flag have been initialized, -// and return &flag->locks_->primary_mu. -absl::Mutex* CommandLineFlag::InitFlagIfNecessary() const - ABSL_LOCK_RETURNED(locks_->primary_mu) { - if (!inited_.load(std::memory_order_acquire)) { - return InitFlag(const_cast(this)); - } - - // All fields initialized; locks_ is therefore safe to read. - return &locks_->primary_mu; -} - -bool CommandLineFlag::IsModified() const { - absl::MutexLock l(InitFlagIfNecessary()); - return modified_; -} - -void CommandLineFlag::SetModified(bool is_modified) { - absl::MutexLock l(InitFlagIfNecessary()); - modified_ = is_modified; -} - -bool CommandLineFlag::IsSpecifiedOnCommandLine() const { - absl::MutexLock l(InitFlagIfNecessary()); - return on_command_line_; -} - absl::string_view CommandLineFlag::Typename() const { // We do not store/report type in Abseil Flags, so that user do not rely on in // at runtime @@ -137,223 +56,6 @@ std::string CommandLineFlag::Filename() const { return flags_internal::GetUsageConfig().normalize_filename(filename_); } -std::string CommandLineFlag::DefaultValue() const { - absl::MutexLock l(InitFlagIfNecessary()); - - return Unparse(marshalling_op_, def_); -} - -std::string CommandLineFlag::CurrentValue() const { - absl::MutexLock l(InitFlagIfNecessary()); - - return Unparse(marshalling_op_, cur_); -} - -int64_t CommandLineFlag::MutationCounter() const { - absl::MutexLock l(InitFlagIfNecessary()); - - return counter_; -} - -// Attempts to parse supplied `value` string using parsing routine in the `flag` -// argument. If parsing is successful, it will try to validate that the parsed -// value is valid for the specified 'flag'. Finally this function stores the -// parsed value in 'dst' assuming it is a pointer to the flag's value type. In -// case if any error is encountered in either step, the error message is stored -// in 'err' -bool TryParseLocked(CommandLineFlag* flag, void* dst, absl::string_view value, - std::string* err) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(flag->locks_->primary_mu) { - void* tentative_value = Clone(flag->op_, flag->def_); - std::string parse_err; - if (!Parse(flag->marshalling_op_, value, tentative_value, &parse_err)) { - auto type_name = flag->Typename(); - absl::string_view err_sep = parse_err.empty() ? "" : "; "; - absl::string_view typename_sep = type_name.empty() ? "" : " "; - *err = absl::StrCat("Illegal value '", value, "' specified for", - typename_sep, type_name, " flag '", flag->Name(), "'", - err_sep, parse_err); - Delete(flag->op_, tentative_value); - return false; - } - - if (!flag->InvokeValidator(tentative_value)) { - *err = absl::StrCat("Failed validation of new value '", - Unparse(flag->marshalling_op_, tentative_value), - "' for flag '", flag->Name(), "'"); - Delete(flag->op_, tentative_value); - return false; - } - - flag->counter_++; - Copy(flag->op_, tentative_value, dst); - Delete(flag->op_, tentative_value); - return true; -} - -// Sets the value of the flag based on specified string `value`. If the flag -// was successfully set to new value, it returns true. Otherwise, sets `err` -// to indicate the error, leaves the flag unchanged, and returns false. There -// are three ways to set the flag's value: -// * Update the current flag value -// * Update the flag's default value -// * Update the current flag value if it was never set before -// The mode is selected based on 'set_mode' parameter. -bool CommandLineFlag::SetFromString(absl::string_view value, - FlagSettingMode set_mode, - ValueSource source, std::string* err) { - if (IsRetired()) return false; - - absl::MutexLock l(InitFlagIfNecessary()); - - // Direct-access flags can be modified without going through the - // flag API. Detect such changes and update the flag->modified_ bit. - if (!IsAbseilFlag()) { - if (!modified_ && ChangedDirectly(this, cur_, def_)) { - modified_ = true; - } - } - - switch (set_mode) { - case SET_FLAGS_VALUE: { - // set or modify the flag's value - if (!TryParseLocked(this, cur_, value, err)) return false; - modified_ = true; - UpdateCopy(this); - InvokeCallback(); - - if (source == kCommandLine) { - on_command_line_ = true; - } - break; - } - case SET_FLAG_IF_DEFAULT: { - // set the flag's value, but only if it hasn't been set by someone else - if (!modified_) { - if (!TryParseLocked(this, cur_, value, err)) return false; - modified_ = true; - UpdateCopy(this); - InvokeCallback(); - } else { - // TODO(rogeeff): review and fix this semantic. Currently we do not fail - // in this case if flag is modified. This is misleading since the flag's - // value is not updated even though we return true. - // *err = absl::StrCat(Name(), " is already set to ", - // CurrentValue(), "\n"); - // return false; - return true; - } - break; - } - case SET_FLAGS_DEFAULT: { - // modify the flag's default-value - if (!TryParseLocked(this, def_, value, err)) return false; - - if (!modified_) { - // Need to set both defvalue *and* current, in this case - Copy(op_, def_, cur_); - UpdateCopy(this); - InvokeCallback(); - } - break; - } - default: { - // unknown set_mode - assert(false); - return false; - } - } - - return true; -} - -void CommandLineFlag::CheckDefaultValueParsingRoundtrip() const { - std::string v = DefaultValue(); - - absl::MutexLock lock(InitFlagIfNecessary()); - - void* dst = Clone(op_, def_); - std::string error; - if (!flags_internal::Parse(marshalling_op_, v, dst, &error)) { - ABSL_INTERNAL_LOG( - FATAL, - absl::StrCat("Flag ", Name(), " (from ", Filename(), - "): std::string form of default value '", v, - "' could not be parsed; error=", error)); - } - - // We do not compare dst to def since parsing/unparsing may make - // small changes, e.g., precision loss for floating point types. - Delete(op_, dst); -} - -bool CommandLineFlag::ValidateDefaultValue() const { - absl::MutexLock lock(InitFlagIfNecessary()); - return InvokeValidator(def_); -} - -bool CommandLineFlag::ValidateInputValue(absl::string_view value) const { - absl::MutexLock l(InitFlagIfNecessary()); // protect default value access - - void* obj = Clone(op_, def_); - std::string ignored_error; - const bool result = - flags_internal::Parse(marshalling_op_, value, obj, &ignored_error) && - InvokeValidator(obj); - Delete(op_, obj); - return result; -} - -void CommandLineFlag::Read(void* dst, - const flags_internal::FlagOpFn dst_op) const { - absl::ReaderMutexLock l(InitFlagIfNecessary()); - - // `dst_op` is the unmarshaling operation corresponding to the declaration - // visibile at the call site. `op` is the Flag's defined unmarshalling - // operation. They must match for this operation to be well-defined. - if (ABSL_PREDICT_FALSE(dst_op != op_)) { - ABSL_INTERNAL_LOG( - ERROR, - absl::StrCat("Flag '", Name(), - "' is defined as one type and declared as another")); - } - CopyConstruct(op_, cur_, dst); -} - -void CommandLineFlag::Write(const void* src, - const flags_internal::FlagOpFn src_op) { - absl::MutexLock l(InitFlagIfNecessary()); - - // `src_op` is the marshalling operation corresponding to the declaration - // visible at the call site. `op` is the Flag's defined marshalling operation. - // They must match for this operation to be well-defined. - if (ABSL_PREDICT_FALSE(src_op != op_)) { - ABSL_INTERNAL_LOG( - ERROR, - absl::StrCat("Flag '", Name(), - "' is defined as one type and declared as another")); - } - - if (ShouldValidateFlagValue(*this)) { - void* obj = Clone(op_, src); - std::string ignored_error; - std::string src_as_str = Unparse(marshalling_op_, src); - if (!Parse(marshalling_op_, src_as_str, obj, &ignored_error) || - !InvokeValidator(obj)) { - ABSL_INTERNAL_LOG(ERROR, absl::StrCat("Attempt to set flag '", Name(), - "' to invalid value ", src_as_str)); - } - Delete(op_, obj); - } - - modified_ = true; - counter_++; - Copy(op_, src, cur_); - - UpdateCopy(this); - InvokeCallback(); -} - std::string HelpText::GetHelpText() const { if (help_function_) return help_function_(); if (help_message_) return help_message_; @@ -361,40 +63,5 @@ std::string HelpText::GetHelpText() const { return {}; } -// Update any copy of the flag value that is stored in an atomic word. -// In addition if flag has a mutation callback this function invokes it. -void UpdateCopy(CommandLineFlag* flag) { -#define STORE_ATOMIC(T) \ - else if (flag->IsOfType()) { \ - flag->StoreAtomic(); \ - } - - if (false) { - } - ABSL_FLAGS_INTERNAL_FOR_EACH_LOCK_FREE(STORE_ATOMIC) -#undef STORE_ATOMIC -} - -// Return true iff flag value was changed via direct-access. -bool ChangedDirectly(CommandLineFlag* flag, const void* a, const void* b) { - if (!flag->IsAbseilFlag()) { -// Need to compare values for direct-access flags. -#define CHANGED_FOR_TYPE(T) \ - if (flag->IsOfType()) { \ - return *reinterpret_cast(a) != *reinterpret_cast(b); \ - } - - CHANGED_FOR_TYPE(bool); - CHANGED_FOR_TYPE(int32_t); - CHANGED_FOR_TYPE(int64_t); - CHANGED_FOR_TYPE(uint64_t); - CHANGED_FOR_TYPE(double); - CHANGED_FOR_TYPE(std::string); -#undef CHANGED_FOR_TYPE - } - - return false; -} - } // namespace flags_internal } // namespace absl diff --git a/absl/flags/internal/commandlineflag.h b/absl/flags/internal/commandlineflag.h index 528d3106..13a3352e 100644 --- a/absl/flags/internal/commandlineflag.h +++ b/absl/flags/internal/commandlineflag.h @@ -16,12 +16,10 @@ #ifndef ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_ #define ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_ -#include #include #include "absl/base/macros.h" #include "absl/flags/marshalling.h" -#include "absl/synchronization/mutex.h" #include "absl/types/optional.h" namespace absl { @@ -151,14 +149,6 @@ inline size_t Sizeof(FlagOpFn op) { op(flags_internal::kSizeof, nullptr, nullptr))); } -// The following struct contains the locks in a CommandLineFlag struct. -// They are in a separate struct that is lazily allocated to avoid problems -// with static initialization and to avoid multiple allocations. -struct CommandLineFlagLocks { - absl::Mutex primary_mu; // protects several fields in CommandLineFlag - absl::Mutex callback_mu; // used to serialize callbacks -}; - // Holds either a pointer to help text or a function which produces it. This is // needed for supporting both static initialization of Flags while supporting // the legacy registration framework. We can't use absl::variant inline bool IsOfType() const { - return op_ == &flags_internal::FlagOps; + return TypeId() == &flags_internal::FlagOps; } // Attempts to retrieve the flag value. Returns value on success, // absl::nullopt otherwise. template absl::optional Get() const { - if (IsRetired() || flags_internal::FlagOps != op_) return absl::nullopt; - - T res; - Read(&res, flags_internal::FlagOps); + if (IsRetired() || !IsOfType()) { + return absl::nullopt; + } - return res; + // Implementation notes: + // + // We are wrapping a union around the value of `T` to serve three purposes: + // + // 1. `U.value` has correct size and alignment for a value of type `T` + // 2. The `U.value` constructor is not invoked since U's constructor does + // not + // do it explicitly. + // 3. The `U.value` destructor is invoked since U's destructor does it + // explicitly. This makes `U` a kind of RAII wrapper around non default + // constructible value of T, which is destructed when we leave the + // scope. We do need to destroy U.value, which is constructed by + // CommandLineFlag::Read even though we left it in a moved-from state + // after std::move. + // + // All of this serves to avoid requiring `T` being default constructible. + union U { + T value; + U() {} + ~U() { value.~T(); } + }; + U u; + + Read(&u.value); + return std::move(u.value); } + // Polymorphic access methods + + // Returns true iff this object corresponds to retired flag + virtual bool IsRetired() const { return false; } + // Returns true iff this is a handle to an Abseil Flag. + virtual bool IsAbseilFlag() const { return true; } + // Returns id of the flag's value type. + virtual flags_internal::FlagOpFn TypeId() const = 0; + virtual bool IsModified() const = 0; + virtual bool IsSpecifiedOnCommandLine() const = 0; + virtual std::string DefaultValue() const = 0; + virtual std::string CurrentValue() const = 0; + + // Interfaces to operate on validators. + virtual bool ValidateInputValue(absl::string_view value) const = 0; + // Interface to save flag to some persistent state. Returns current flag state // or nullptr if flag does not support saving and restoring a state. virtual std::unique_ptr SaveState() = 0; - // Interfaces to overate on callbacks. - virtual void InvokeCallback() {} - // Sets the value of the flag based on specified std::string `value`. If the flag // was successfully set to new value, it returns true. Otherwise, sets `error` // to indicate the error, leaves the flag unchanged, and returns false. There @@ -289,74 +276,28 @@ class CommandLineFlag { // * Update the flag's default value // * Update the current flag value if it was never set before // The mode is selected based on `set_mode` parameter. - bool SetFromString(absl::string_view value, - flags_internal::FlagSettingMode set_mode, - flags_internal::ValueSource source, std::string* error); + virtual bool SetFromString(absl::string_view value, + flags_internal::FlagSettingMode set_mode, + flags_internal::ValueSource source, + std::string* error) = 0; - void CheckDefaultValueParsingRoundtrip() const; + // Checks that flags default value can be converted to std::string and back to the + // flag's value type. + virtual void CheckDefaultValueParsingRoundtrip() const = 0; // Constant configuration for a particular flag. protected: ~CommandLineFlag() = default; - // Thread safe access to mutation counter. - int64_t MutationCounter() const; - - const char* const name_; - const HelpText help_; - const char* const filename_; - - const FlagOpFn op_; // Type-specific handler - const FlagMarshallingOpFn marshalling_op_; // Marshalling ops handler - const InitialValGenFunc make_init_value_; // Makes initial value for the flag - std::atomic inited_; // fields have been lazily initialized - - // Mutable state (guarded by locks_->primary_mu). - bool modified_; // Has flag value been modified? - bool on_command_line_; // Specified on command line. - void* def_; // Lazily initialized pointer to default value - void* cur_; // Lazily initialized pointer to current value - int64_t counter_; // Mutation counter - - // Lazily initialized mutexes for this flag value. We cannot inline a - // SpinLock or Mutex here because those have non-constexpr constructors and - // so would prevent constant initialization of this type. - // TODO(rogeeff): fix it once Mutex has constexpr constructor - struct CommandLineFlagLocks* locks_; // locks, laziliy allocated. - - // Ensure that the lazily initialized fields of *flag have been initialized, - // and return the lock which should be locked when flag's state is mutated. - absl::Mutex* InitFlagIfNecessary() const ABSL_LOCK_RETURNED(locks_->primary_mu); - - // copy construct new value of flag's type in a memory referenced by dst - // based on current flag's value - void Read(void* dst, const flags_internal::FlagOpFn dst_op) const; - // updates flag's value to *src (locked) - void Write(const void* src, const flags_internal::FlagOpFn src_op); - - friend class FlagRegistry; - friend class FlagPtrMap; - friend class FlagSaverImpl; - friend bool TryParseLocked(CommandLineFlag* flag, void* dst, - absl::string_view value, std::string* err); - friend absl::Mutex* InitFlag(CommandLineFlag* flag); -}; + const char* const name_; // Flags name passed to ABSL_FLAG as second arg. + const HelpText help_; // The function generating help message. + const char* const filename_; // The file name where ABSL_FLAG resides. -// Update any copy of the flag value that is stored in an atomic word. -// In addition if flag has a mutation callback this function invokes it. While -// callback is being invoked the primary flag's mutex is unlocked and it is -// re-locked back after call to callback is completed. Callback invocation is -// guarded by flag's secondary mutex instead which prevents concurrent callback -// invocation. Note that it is possible for other thread to grab the primary -// lock and update flag's value at any time during the callback invocation. -// This is by design. Callback can get a value of the flag if necessary, but it -// might be different from the value initiated the callback and it also can be -// different by the time the callback invocation is completed. -// Requires that *primary_lock be held in exclusive mode; it may be released -// and reacquired by the implementation. -void UpdateCopy(CommandLineFlag* flag); -// Return true iff flag value was changed via direct-access. -bool ChangedDirectly(CommandLineFlag* flag, const void* a, const void* b); + private: + // Copy-construct a new value of the flag's type in a memory referenced by + // the dst based on the current flag's value. + virtual void Read(void* dst) const = 0; +}; // This macro is the "source of truth" for the list of supported flag types we // expect to perform lock free operations on. Specifically it generates code, diff --git a/absl/flags/internal/flag.cc b/absl/flags/internal/flag.cc index 0f403581..061113d7 100644 --- a/absl/flags/internal/flag.cc +++ b/absl/flags/internal/flag.cc @@ -15,36 +15,331 @@ #include "absl/flags/internal/flag.h" +#include "absl/base/optimization.h" #include "absl/synchronization/mutex.h" namespace absl { namespace flags_internal { +namespace { -// If the flag has a mutation callback this function invokes it. While the -// callback is being invoked the primary flag's mutex is unlocked and it is -// re-locked back after call to callback is completed. Callback invocation is -// guarded by flag's secondary mutex instead which prevents concurrent -// callback invocation. Note that it is possible for other thread to grab the -// primary lock and update flag's value at any time during the callback -// invocation. This is by design. Callback can get a value of the flag if -// necessary, but it might be different from the value initiated the callback -// and it also can be different by the time the callback invocation is -// completed. Requires that *primary_lock be held in exclusive mode; it may be -// released and reacquired by the implementation. -void InvokeCallback(absl::Mutex* primary_mu, absl::Mutex* callback_mu, - FlagCallback cb) ABSL_EXCLUSIVE_LOCKS_REQUIRED(primary_mu) { - if (!cb) return; - - // When executing the callback we need the primary flag's mutex to be - // unlocked so that callback can retrieve the flag's value. - primary_mu->Unlock(); +// Currently we only validate flag values for user-defined flag types. +bool ShouldValidateFlagValue(const CommandLineFlag& flag) { +#define DONT_VALIDATE(T) \ + if (flag.IsOfType()) return false; + ABSL_FLAGS_INTERNAL_FOR_EACH_LOCK_FREE(DONT_VALIDATE) + DONT_VALIDATE(std::string) + DONT_VALIDATE(std::vector) +#undef DONT_VALIDATE + return true; +} + +} // namespace + +void FlagImpl::Init() { + ABSL_CONST_INIT static absl::Mutex init_lock(absl::kConstInit); + + { + absl::MutexLock lock(&init_lock); + + if (locks_ == nullptr) { // Must initialize Mutexes for this flag. + locks_ = new FlagImpl::CommandLineFlagLocks; + } + } + + absl::MutexLock lock(&locks_->primary_mu); + + if (def_ != nullptr) { + inited_.store(true, std::memory_order_release); + } else { + // Need to initialize def and cur fields. + def_ = (*initial_value_gen_)(); + cur_ = Clone(op_, def_); + StoreAtomic(); + inited_.store(true, std::memory_order_release); + InvokeCallback(); + } +} + +// Ensures that the lazily initialized data is initialized, +// and returns pointer to the mutex guarding flags data. +absl::Mutex* FlagImpl::DataGuard() const + ABSL_LOCK_RETURNED(locks_->primary_mu) { + if (ABSL_PREDICT_FALSE(!inited_.load(std::memory_order_acquire))) { + const_cast(this)->Init(); + } + + // All fields initialized; locks_ is therefore safe to read. + return &locks_->primary_mu; +} + +void FlagImpl::Destroy() const { { - absl::MutexLock lock(callback_mu); - cb(); + absl::MutexLock l(DataGuard()); + + // Values are heap allocated for Abseil Flags. + if (cur_) Delete(op_, cur_); + if (def_) Delete(op_, def_); } - primary_mu->Lock(); + delete locks_; +} + +bool FlagImpl::IsModified() const { + absl::MutexLock l(DataGuard()); + return modified_; +} + +bool FlagImpl::IsSpecifiedOnCommandLine() const { + absl::MutexLock l(DataGuard()); + return on_command_line_; +} + +std::string FlagImpl::DefaultValue() const { + absl::MutexLock l(DataGuard()); + + return Unparse(marshalling_op_, def_); +} + +std::string FlagImpl::CurrentValue() const { + absl::MutexLock l(DataGuard()); + + return Unparse(marshalling_op_, cur_); +} + +void FlagImpl::SetCallback( + const flags_internal::FlagCallback mutation_callback) { + absl::MutexLock l(DataGuard()); + + callback_ = mutation_callback; + + InvokeCallback(); +} + +void FlagImpl::InvokeCallback() const + ABSL_EXCLUSIVE_LOCKS_REQUIRED(locks_->primary_mu) { + if (!callback_) return; + + // If the flag has a mutation callback this function invokes it. While the + // callback is being invoked the primary flag's mutex is unlocked and it is + // re-locked back after call to callback is completed. Callback invocation is + // guarded by flag's secondary mutex instead which prevents concurrent + // callback invocation. Note that it is possible for other thread to grab the + // primary lock and update flag's value at any time during the callback + // invocation. This is by design. Callback can get a value of the flag if + // necessary, but it might be different from the value initiated the callback + // and it also can be different by the time the callback invocation is + // completed. Requires that *primary_lock be held in exclusive mode; it may be + // released and reacquired by the implementation. + DataGuard()->Unlock(); + + { + absl::MutexLock lock(&locks_->callback_mu); + callback_(); + } + + DataGuard()->Lock(); +} + +bool FlagImpl::RestoreState(const CommandLineFlag& flag, const void* value, + bool modified, bool on_command_line, + int64_t counter) { + { + absl::MutexLock l(DataGuard()); + + if (counter_ == counter) return false; + } + + Write(flag, value, op_); + + { + absl::MutexLock l(DataGuard()); + + modified_ = modified; + on_command_line_ = on_command_line; + } + + return true; +} + +// Attempts to parse supplied `value` string using parsing routine in the `flag` +// argument. If parsing successful, this function stores the parsed value in +// 'dst' assuming it is a pointer to the flag's value type. In case if any error +// is encountered in either step, the error message is stored in 'err' +bool FlagImpl::TryParse(const CommandLineFlag& flag, void* dst, + absl::string_view value, std::string* err) const + ABSL_EXCLUSIVE_LOCKS_REQUIRED(locks_->primary_mu) { + void* tentative_value = Clone(op_, def_); + std::string parse_err; + if (!Parse(marshalling_op_, value, tentative_value, &parse_err)) { + auto type_name = flag.Typename(); + absl::string_view err_sep = parse_err.empty() ? "" : "; "; + absl::string_view typename_sep = type_name.empty() ? "" : " "; + *err = absl::StrCat("Illegal value '", value, "' specified for", + typename_sep, type_name, " flag '", flag.Name(), "'", + err_sep, parse_err); + Delete(op_, tentative_value); + return false; + } + + Copy(op_, tentative_value, dst); + Delete(op_, tentative_value); + return true; +} + +void FlagImpl::Read(const CommandLineFlag& flag, void* dst, + const flags_internal::FlagOpFn dst_op) const { + absl::ReaderMutexLock l(DataGuard()); + + // `dst_op` is the unmarshaling operation corresponding to the declaration + // visibile at the call site. `op` is the Flag's defined unmarshalling + // operation. They must match for this operation to be well-defined. + if (ABSL_PREDICT_FALSE(dst_op != op_)) { + ABSL_INTERNAL_LOG( + ERROR, + absl::StrCat("Flag '", flag.Name(), + "' is defined as one type and declared as another")); + } + CopyConstruct(op_, cur_, dst); +} + +void FlagImpl::StoreAtomic() ABSL_EXCLUSIVE_LOCKS_REQUIRED(locks_->primary_mu) { + size_t data_size = Sizeof(op_); + + if (data_size <= sizeof(int64_t)) { + int64_t t = 0; + std::memcpy(&t, cur_, data_size); + atomic_.store(t, std::memory_order_release); + } +} + +void FlagImpl::Write(const CommandLineFlag& flag, const void* src, + const flags_internal::FlagOpFn src_op) { + absl::MutexLock l(DataGuard()); + + // `src_op` is the marshalling operation corresponding to the declaration + // visible at the call site. `op` is the Flag's defined marshalling operation. + // They must match for this operation to be well-defined. + if (ABSL_PREDICT_FALSE(src_op != op_)) { + ABSL_INTERNAL_LOG( + ERROR, + absl::StrCat("Flag '", flag.Name(), + "' is defined as one type and declared as another")); + } + + if (ShouldValidateFlagValue(flag)) { + void* obj = Clone(op_, src); + std::string ignored_error; + std::string src_as_str = Unparse(marshalling_op_, src); + if (!Parse(marshalling_op_, src_as_str, obj, &ignored_error)) { + ABSL_INTERNAL_LOG(ERROR, + absl::StrCat("Attempt to set flag '", flag.Name(), + "' to invalid value ", src_as_str)); + } + Delete(op_, obj); + } + + modified_ = true; + counter_++; + Copy(op_, src, cur_); + + StoreAtomic(); + InvokeCallback(); +} + +// Sets the value of the flag based on specified string `value`. If the flag +// was successfully set to new value, it returns true. Otherwise, sets `err` +// to indicate the error, leaves the flag unchanged, and returns false. There +// are three ways to set the flag's value: +// * Update the current flag value +// * Update the flag's default value +// * Update the current flag value if it was never set before +// The mode is selected based on 'set_mode' parameter. +bool FlagImpl::SetFromString(const CommandLineFlag& flag, + absl::string_view value, FlagSettingMode set_mode, + ValueSource source, std::string* err) { + absl::MutexLock l(DataGuard()); + + switch (set_mode) { + case SET_FLAGS_VALUE: { + // set or modify the flag's value + if (!TryParse(flag, cur_, value, err)) return false; + modified_ = true; + counter_++; + StoreAtomic(); + InvokeCallback(); + + if (source == kCommandLine) { + on_command_line_ = true; + } + break; + } + case SET_FLAG_IF_DEFAULT: { + // set the flag's value, but only if it hasn't been set by someone else + if (!modified_) { + if (!TryParse(flag, cur_, value, err)) return false; + modified_ = true; + counter_++; + StoreAtomic(); + InvokeCallback(); + } else { + // TODO(rogeeff): review and fix this semantic. Currently we do not fail + // in this case if flag is modified. This is misleading since the flag's + // value is not updated even though we return true. + // *err = absl::StrCat(Name(), " is already set to ", + // CurrentValue(), "\n"); + // return false; + return true; + } + break; + } + case SET_FLAGS_DEFAULT: { + // modify the flag's default-value + if (!TryParse(flag, def_, value, err)) return false; + + if (!modified_) { + // Need to set both default value *and* current, in this case + Copy(op_, def_, cur_); + StoreAtomic(); + InvokeCallback(); + } + break; + } + } + + return true; +} + +void FlagImpl::CheckDefaultValueParsingRoundtrip( + const CommandLineFlag& flag) const { + std::string v = DefaultValue(); + + absl::MutexLock lock(DataGuard()); + + void* dst = Clone(op_, def_); + std::string error; + if (!flags_internal::Parse(marshalling_op_, v, dst, &error)) { + ABSL_INTERNAL_LOG( + FATAL, + absl::StrCat("Flag ", flag.Name(), " (from ", flag.Filename(), + "): std::string form of default value '", v, + "' could not be parsed; error=", error)); + } + + // We do not compare dst to def since parsing/unparsing may make + // small changes, e.g., precision loss for floating point types. + Delete(op_, dst); +} + +bool FlagImpl::ValidateInputValue(absl::string_view value) const { + absl::MutexLock l(DataGuard()); + + void* obj = Clone(op_, def_); + std::string ignored_error; + const bool result = + flags_internal::Parse(marshalling_op_, value, obj, &ignored_error); + Delete(op_, obj); + return result; } } // namespace flags_internal diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h index 2b21c440..ce0ccf2d 100644 --- a/absl/flags/internal/flag.h +++ b/absl/flags/internal/flag.h @@ -16,12 +16,15 @@ #ifndef ABSL_FLAGS_INTERNAL_FLAG_H_ #define ABSL_FLAGS_INTERNAL_FLAG_H_ +#include #include +#include "absl/base/thread_annotations.h" #include "absl/flags/internal/commandlineflag.h" #include "absl/flags/internal/registry.h" #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" +#include "absl/synchronization/mutex.h" namespace absl { namespace flags_internal { @@ -66,6 +69,124 @@ using FlagCallback = void (*)(); void InvokeCallback(absl::Mutex* primary_mu, absl::Mutex* callback_mu, FlagCallback cb) ABSL_EXCLUSIVE_LOCKS_REQUIRED(primary_mu); +// The class encapsulates the Flag's data and safe access to it. +class FlagImpl { + public: + constexpr FlagImpl(const flags_internal::FlagOpFn op, + const flags_internal::FlagMarshallingOpFn marshalling_op, + const flags_internal::InitialValGenFunc initial_value_gen) + : op_(op), + marshalling_op_(marshalling_op), + initial_value_gen_(initial_value_gen) {} + + // Forces destruction of the Flag's data. + void Destroy() const; + + // Constant access methods + bool IsModified() const ABSL_LOCKS_EXCLUDED(locks_->primary_mu); + bool IsSpecifiedOnCommandLine() const ABSL_LOCKS_EXCLUDED(locks_->primary_mu); + std::string DefaultValue() const ABSL_LOCKS_EXCLUDED(locks_->primary_mu); + std::string CurrentValue() const ABSL_LOCKS_EXCLUDED(locks_->primary_mu); + void Read(const CommandLineFlag& flag, void* dst, + const flags_internal::FlagOpFn dst_op) const + ABSL_LOCKS_EXCLUDED(locks_->primary_mu); + // Attempts to parse supplied `value` std::string. + bool TryParse(const CommandLineFlag& flag, void* dst, absl::string_view value, + std::string* err) const + ABSL_EXCLUSIVE_LOCKS_REQUIRED(locks_->primary_mu); + template + bool AtomicGet(T* v) const { + const int64_t r = atomic_.load(std::memory_order_acquire); + if (r != flags_internal::AtomicInit()) { + std::memcpy(v, &r, sizeof(T)); + return true; + } + + return false; + } + + // Mutating access methods + void Write(const CommandLineFlag& flag, const void* src, + const flags_internal::FlagOpFn src_op) + ABSL_LOCKS_EXCLUDED(locks_->primary_mu); + bool SetFromString(const CommandLineFlag& flag, absl::string_view value, + FlagSettingMode set_mode, ValueSource source, + std::string* err) ABSL_LOCKS_EXCLUDED(locks_->primary_mu); + // If possible, updates copy of the Flag's value that is stored in an + // atomic word. + void StoreAtomic() ABSL_EXCLUSIVE_LOCKS_REQUIRED(locks_->primary_mu); + + // Interfaces to operate on callbacks. + void SetCallback(const flags_internal::FlagCallback mutation_callback) + ABSL_LOCKS_EXCLUDED(locks_->primary_mu); + void InvokeCallback() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(locks_->primary_mu); + + // Interfaces to save/restore mutable flag data + template + std::unique_ptr SaveState( + Flag* flag) const ABSL_LOCKS_EXCLUDED(locks_->primary_mu) { + T&& cur_value = flag->Get(); + absl::MutexLock l(DataGuard()); + + return absl::make_unique>( + flag, std::move(cur_value), modified_, on_command_line_, counter_); + } + bool RestoreState(const CommandLineFlag& flag, const void* value, + bool modified, bool on_command_line, int64_t counter) + ABSL_LOCKS_EXCLUDED(locks_->primary_mu); + + // Value validation interfaces. + void CheckDefaultValueParsingRoundtrip(const CommandLineFlag& flag) const + ABSL_LOCKS_EXCLUDED(locks_->primary_mu); + bool ValidateInputValue(absl::string_view value) const + ABSL_LOCKS_EXCLUDED(locks_->primary_mu); + + private: + // Lazy initialization of the Flag's data. + void Init(); + // Ensures that the lazily initialized data is initialized, + // and returns pointer to the mutex guarding flags data. + absl::Mutex* DataGuard() const ABSL_LOCK_RETURNED(locks_->primary_mu); + + // Immutable Flag's data. + const FlagOpFn op_; // Type-specific handler + const FlagMarshallingOpFn marshalling_op_; // Marshalling ops handler + const InitialValGenFunc initial_value_gen_; // Makes flag's initial value + + // Mutable Flag's data. (guarded by locks_->primary_mu). + // Indicates that locks_, cur_ and def_ fields have been lazily initialized. + std::atomic inited_{false}; + // Has flag value been modified? + bool modified_ ABSL_GUARDED_BY(locks_->primary_mu) = false; + // Specified on command line. + bool on_command_line_ ABSL_GUARDED_BY(locks_->primary_mu) = false; + // Lazily initialized pointer to default value + void* def_ ABSL_GUARDED_BY(locks_->primary_mu) = nullptr; + // Lazily initialized pointer to current value + void* cur_ ABSL_GUARDED_BY(locks_->primary_mu) = nullptr; + // Mutation counter + int64_t counter_ ABSL_GUARDED_BY(locks_->primary_mu) = 0; + // For some types, a copy of the current value is kept in an atomically + // accessible field. + std::atomic atomic_{flags_internal::AtomicInit()}; + // Mutation callback + FlagCallback callback_ = nullptr; + + // Lazily initialized mutexes for this flag value. We cannot inline a + // SpinLock or Mutex here because those have non-constexpr constructors and + // so would prevent constant initialization of this type. + // TODO(rogeeff): fix it once Mutex has constexpr constructor + // The following struct contains the locks in a CommandLineFlag struct. + // They are in a separate struct that is lazily allocated to avoid problems + // with static initialization and to avoid multiple allocations. + struct CommandLineFlagLocks { + absl::Mutex primary_mu; // protects several fields in CommandLineFlag + absl::Mutex callback_mu; // used to serialize callbacks + }; + + CommandLineFlagLocks* locks_ = nullptr; // locks, laziliy allocated. +}; + // This is "unspecified" implementation of absl::Flag type. template class Flag final : public flags_internal::CommandLineFlag { @@ -76,30 +197,11 @@ class Flag final : public flags_internal::CommandLineFlag { const flags_internal::InitialValGenFunc initial_value_gen) : flags_internal::CommandLineFlag( name, flags_internal::HelpText::FromFunctionPointer(help_gen), - filename, &flags_internal::FlagOps, marshalling_op, - initial_value_gen, - /*def=*/nullptr, - /*cur=*/nullptr), - atomic_(flags_internal::AtomicInit()), - callback_(nullptr) {} + filename), + impl_(&flags_internal::FlagOps, marshalling_op, initial_value_gen) {} T Get() const { - // Implementation notes: - // - // We are wrapping a union around the value of `T` to serve three purposes: - // - // 1. `U.value` has correct size and alignment for a value of type `T` - // 2. The `U.value` constructor is not invoked since U's constructor does - // not - // do it explicitly. - // 3. The `U.value` destructor is invoked since U's destructor does it - // explicitly. This makes `U` a kind of RAII wrapper around non default - // constructible value of T, which is destructed when we leave the - // scope. We do need to destroy U.value, which is constructed by - // CommandLineFlag::Read even though we left it in a moved-from state - // after std::move. - // - // All of this serves to avoid requiring `T` being default constructible. + // See implementation notes in CommandLineFlag::Get(). union U { T value; U() {} @@ -107,89 +209,70 @@ class Flag final : public flags_internal::CommandLineFlag { }; U u; - Read(&u.value, &flags_internal::FlagOps); + impl_.Read(*this, &u.value, &flags_internal::FlagOps); return std::move(u.value); } - bool AtomicGet(T* v) const { - const int64_t r = atomic_.load(std::memory_order_acquire); - if (r != flags_internal::AtomicInit()) { - std::memcpy(v, &r, sizeof(T)); - return true; - } - - return false; - } + bool AtomicGet(T* v) const { return impl_.AtomicGet(v); } - void Set(const T& v) { Write(&v, &flags_internal::FlagOps); } + void Set(const T& v) { impl_.Write(*this, &v, &flags_internal::FlagOps); } void SetCallback(const flags_internal::FlagCallback mutation_callback) { - absl::MutexLock l(InitFlagIfNecessary()); - - callback_ = mutation_callback; - - InvokeCallback(); + impl_.SetCallback(mutation_callback); } - private: - friend class FlagState; - - void Destroy() const override { - // Values are heap allocated for Abseil Flags. - if (cur_) Delete(op_, cur_); - if (def_) Delete(op_, def_); - - delete locks_; + // CommandLineFlag interface + bool IsModified() const override { return impl_.IsModified(); } + bool IsSpecifiedOnCommandLine() const override { + return impl_.IsSpecifiedOnCommandLine(); } + std::string DefaultValue() const override { return impl_.DefaultValue(); } + std::string CurrentValue() const override { return impl_.CurrentValue(); } - void StoreAtomic() override { - if (sizeof(T) <= sizeof(int64_t)) { - int64_t t = 0; - std::memcpy(&t, cur_, (std::min)(sizeof(T), sizeof(int64_t))); - atomic_.store(t, std::memory_order_release); - } + bool ValidateInputValue(absl::string_view value) const override { + return impl_.ValidateInputValue(value); } // Interfaces to save and restore flags to/from persistent state. // Returns current flag state or nullptr if flag does not support // saving and restoring a state. std::unique_ptr SaveState() override { - T curr_value = Get(); - - absl::MutexLock l(InitFlagIfNecessary()); - - return absl::make_unique>( - this, std::move(curr_value), modified_, on_command_line_, counter_); + return impl_.SaveState(this); } // Restores the flag state to the supplied state object. If there is // nothing to restore returns false. Otherwise returns true. bool RestoreState(const flags_internal::FlagState& flag_state) { - if (MutationCounter() == flag_state.counter_) return false; - - Set(flag_state.cur_value_); + return impl_.RestoreState(*this, &flag_state.cur_value_, + flag_state.modified_, flag_state.on_command_line_, + flag_state.counter_); + } - // Race condition here? This should disappear once we move the rest of the - // flag's data into Flag's internals. + bool SetFromString(absl::string_view value, + flags_internal::FlagSettingMode set_mode, + flags_internal::ValueSource source, + std::string* error) override { + return impl_.SetFromString(*this, value, set_mode, source, error); + } - absl::MutexLock l(InitFlagIfNecessary()); - modified_ = flag_state.modified_; - on_command_line_ = flag_state.on_command_line_; - return true; + void CheckDefaultValueParsingRoundtrip() const override { + impl_.CheckDefaultValueParsingRoundtrip(*this); } - // Interfaces to overate on callbacks. - void InvokeCallback() override - ABSL_EXCLUSIVE_LOCKS_REQUIRED(locks_->primary_mu) { - flags_internal::InvokeCallback(&locks_->primary_mu, &locks_->callback_mu, - callback_); + private: + friend class FlagState; + + void Destroy() const override { impl_.Destroy(); } + + void Read(void* dst) const override { + impl_.Read(*this, dst, &flags_internal::FlagOps); + } + flags_internal::FlagOpFn TypeId() const override { + return &flags_internal::FlagOps; } // Flag's data - // For some types, a copy of the current value is kept in an atomically - // accessible field. - std::atomic atomic_; - FlagCallback callback_; // Mutation callback + FlagImpl impl_; }; template diff --git a/absl/flags/internal/registry.cc b/absl/flags/internal/registry.cc index 6b2564d1..ae7671a9 100644 --- a/absl/flags/internal/registry.cc +++ b/absl/flags/internal/registry.cc @@ -118,7 +118,7 @@ void FlagRegistry::RegisterFlag(CommandLineFlag* flag) { (flag->IsRetired() ? old_flag->Filename() : flag->Filename()), "'."), true); - } else if (flag->op_ != old_flag->op_) { + } else if (flag->TypeId() != old_flag->TypeId()) { flags_internal::ReportUsageError( absl::StrCat("Flag '", flag->Name(), "' was defined more than once but with " @@ -275,38 +275,49 @@ namespace { class RetiredFlagObj final : public flags_internal::CommandLineFlag { public: - constexpr RetiredFlagObj(const char* name, FlagOpFn ops, - FlagMarshallingOpFn marshalling_ops) + constexpr RetiredFlagObj(const char* name, FlagOpFn ops) : flags_internal::CommandLineFlag( name, flags_internal::HelpText::FromStaticCString(nullptr), - /*filename=*/"RETIRED", ops, marshalling_ops, - /*initial_value_gen=*/nullptr, - /*def=*/nullptr, - /*cur=*/nullptr) {} + /*filename=*/"RETIRED"), + op_(ops) {} private: - bool IsRetired() const override { return true; } - void Destroy() const override { // Values are heap allocated for Retired Flags. - if (cur_) Delete(op_, cur_); - if (def_) Delete(op_, def_); - - if (locks_) delete locks_; - delete this; } + flags_internal::FlagOpFn TypeId() const override { return op_; } + bool IsRetired() const override { return true; } + bool IsModified() const override { return false; } + bool IsSpecifiedOnCommandLine() const override { return false; } + std::string DefaultValue() const override { return ""; } + std::string CurrentValue() const override { return ""; } + + // Any input is valid + bool ValidateInputValue(absl::string_view) const override { return true; } + std::unique_ptr SaveState() override { return nullptr; } + + bool SetFromString(absl::string_view, flags_internal::FlagSettingMode, + flags_internal::ValueSource, std::string*) override { + return false; + } + + void CheckDefaultValueParsingRoundtrip() const override {} + + void Read(void*) const override {} + + // Data members + const FlagOpFn op_; }; } // namespace -bool Retire(const char* name, FlagOpFn ops, - FlagMarshallingOpFn marshalling_ops) { - auto* flag = new flags_internal::RetiredFlagObj(name, ops, marshalling_ops); +bool Retire(const char* name, FlagOpFn ops) { + auto* flag = new flags_internal::RetiredFlagObj(name, ops); FlagRegistry::GlobalRegistry()->RegisterFlag(flag); return true; } diff --git a/absl/flags/internal/registry.h b/absl/flags/internal/registry.h index eb134a9f..1889f3a0 100644 --- a/absl/flags/internal/registry.h +++ b/absl/flags/internal/registry.h @@ -76,14 +76,12 @@ bool RegisterCommandLineFlag(CommandLineFlag*); // // Retire flag with name "name" and type indicated by ops. -bool Retire(const char* name, FlagOpFn ops, - FlagMarshallingOpFn marshalling_ops); +bool Retire(const char* name, FlagOpFn ops); // Registered a retired flag with name 'flag_name' and type 'T'. template inline bool RetiredFlag(const char* flag_name) { - return flags_internal::Retire(flag_name, flags_internal::FlagOps, - flags_internal::FlagMarshallingOps); + return flags_internal::Retire(flag_name, flags_internal::FlagOps); } // If the flag is retired, returns true and indicates in |*type_is_bool| diff --git a/absl/random/internal/iostream_state_saver_test.cc b/absl/random/internal/iostream_state_saver_test.cc index 722766d0..7bb8ad95 100644 --- a/absl/random/internal/iostream_state_saver_test.cc +++ b/absl/random/internal/iostream_state_saver_test.cc @@ -196,8 +196,8 @@ TEST(IOStreamStateSaver, RoundTripFloats) { EXPECT_EQ(-d, StreamRoundTrip(-d)); // Avoid undefined behavior (overflow/underflow). - if (d <= std::numeric_limits::max() && - d >= std::numeric_limits::lowest()) { + if (f <= static_cast(std::numeric_limits::max()) && + f >= static_cast(std::numeric_limits::lowest())) { int64_t x = static_cast(f); EXPECT_EQ(x, StreamRoundTrip(x)); } @@ -264,8 +264,8 @@ TEST(IOStreamStateSaver, RoundTripDoubles) { } // Avoid undefined behavior (overflow/underflow). - if (d <= std::numeric_limits::max() && - d >= std::numeric_limits::lowest()) { + if (d <= static_cast(std::numeric_limits::max()) && + d >= static_cast(std::numeric_limits::lowest())) { int64_t x = static_cast(d); EXPECT_EQ(x, StreamRoundTrip(x)); } diff --git a/absl/strings/internal/resize_uninitialized.h b/absl/strings/internal/resize_uninitialized.h index 469962b2..0f5e964d 100644 --- a/absl/strings/internal/resize_uninitialized.h +++ b/absl/strings/internal/resize_uninitialized.h @@ -35,8 +35,7 @@ struct ResizeUninitializedTraits { static void Resize(string_type* s, size_t new_size) { s->resize(new_size); } }; -// __resize_default_init is provided by libc++ >= 8.0 and by Google's internal -// ::string implementation. +// __resize_default_init is provided by libc++ >= 8.0 template struct ResizeUninitializedTraits< string_type, absl::void_t() diff --git a/ci/cmake_install_test.sh b/ci/cmake_install_test.sh index 03eb0432..6a3c19bd 100755 --- a/ci/cmake_install_test.sh +++ b/ci/cmake_install_test.sh @@ -28,6 +28,5 @@ time docker run \ --rm \ -e CFLAGS="-Werror" \ -e CXXFLAGS="-Werror" \ - gcr.io/google.com/absl-177019/linux_gcc-latest:20190703 \ + gcr.io/google.com/absl-177019/linux_gcc-latest:20191018 \ /bin/bash CMake/install_test_project/test.sh $@ - diff --git a/ci/linux_clang-latest_libcxx_asan_bazel.sh b/ci/linux_clang-latest_libcxx_asan_bazel.sh index cc8c695a..fa38ff20 100755 --- a/ci/linux_clang-latest_libcxx_asan_bazel.sh +++ b/ci/linux_clang-latest_libcxx_asan_bazel.sh @@ -36,7 +36,7 @@ if [ -z ${EXCEPTIONS_MODE:-} ]; then EXCEPTIONS_MODE="-fno-exceptions -fexceptions" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190813" +readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20191018" # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. diff --git a/ci/linux_clang-latest_libcxx_bazel.sh b/ci/linux_clang-latest_libcxx_bazel.sh index 5849a84e..c3319a1b 100755 --- a/ci/linux_clang-latest_libcxx_bazel.sh +++ b/ci/linux_clang-latest_libcxx_bazel.sh @@ -36,7 +36,7 @@ if [ -z ${EXCEPTIONS_MODE:-} ]; then EXCEPTIONS_MODE="-fno-exceptions -fexceptions" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190813" +readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20191018" # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. diff --git a/ci/linux_clang-latest_libcxx_tsan_bazel.sh b/ci/linux_clang-latest_libcxx_tsan_bazel.sh index 8721ada2..200541b9 100755 --- a/ci/linux_clang-latest_libcxx_tsan_bazel.sh +++ b/ci/linux_clang-latest_libcxx_tsan_bazel.sh @@ -36,7 +36,7 @@ if [ -z ${EXCEPTIONS_MODE:-} ]; then EXCEPTIONS_MODE="-fno-exceptions -fexceptions" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190813" +readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20191018" # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. diff --git a/ci/linux_clang-latest_libstdcxx_bazel.sh b/ci/linux_clang-latest_libstdcxx_bazel.sh index 78ce0b32..5ea18373 100755 --- a/ci/linux_clang-latest_libstdcxx_bazel.sh +++ b/ci/linux_clang-latest_libstdcxx_bazel.sh @@ -36,7 +36,7 @@ if [ -z ${EXCEPTIONS_MODE:-} ]; then EXCEPTIONS_MODE="-fno-exceptions -fexceptions" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190813" +readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20191018" # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. diff --git a/ci/linux_gcc-4.9_libstdcxx_bazel.sh b/ci/linux_gcc-4.9_libstdcxx_bazel.sh index c3b936bc..f8102cc0 100755 --- a/ci/linux_gcc-4.9_libstdcxx_bazel.sh +++ b/ci/linux_gcc-4.9_libstdcxx_bazel.sh @@ -36,7 +36,7 @@ if [ -z ${EXCEPTIONS_MODE:-} ]; then EXCEPTIONS_MODE="-fno-exceptions -fexceptions" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-4.9:20190702" +readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-4.9:20191018" # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. diff --git a/ci/linux_gcc-latest_libstdcxx_bazel.sh b/ci/linux_gcc-latest_libstdcxx_bazel.sh index 10f6be21..a6efa197 100755 --- a/ci/linux_gcc-latest_libstdcxx_bazel.sh +++ b/ci/linux_gcc-latest_libstdcxx_bazel.sh @@ -36,7 +36,7 @@ if [ -z ${EXCEPTIONS_MODE:-} ]; then EXCEPTIONS_MODE="-fno-exceptions -fexceptions" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-latest:20190703" +readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-latest:20191018" # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. diff --git a/ci/linux_gcc-latest_libstdcxx_cmake.sh b/ci/linux_gcc-latest_libstdcxx_cmake.sh index 3e831c14..ec328748 100755 --- a/ci/linux_gcc-latest_libstdcxx_cmake.sh +++ b/ci/linux_gcc-latest_libstdcxx_cmake.sh @@ -47,7 +47,7 @@ for std in ${ABSL_CMAKE_CXX_STANDARDS}; do --rm \ -e CFLAGS="-Werror" \ -e CXXFLAGS="-Werror" \ - gcr.io/google.com/absl-177019/linux_gcc-latest:20190703 \ + gcr.io/google.com/absl-177019/linux_gcc-latest:20191018 \ /bin/bash -c " cd /buildfs && \ cmake /abseil-cpp \ -- cgit v1.2.3 From 1de0166368e2ae67347f92099d6dca3ab3a4a496 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Fri, 3 Jan 2020 08:41:10 -0800 Subject: Export of internal Abseil changes -- 330051e00cd57ee516b4eaf656965656ffbcd0bc by Abseil Team : Fix indentation in comment. PiperOrigin-RevId: 287997504 -- 35fb1a893e708031ba4fc0db460875eb0d31820e by Abseil Team : Enable compile-time enforcement that absl::Substitute patterns to not contain unescaped $ symbols. absl::Substitute already considers unescaped $ symbols undefined behavior and crashes when it's passed them in debug builds. Some code isn't ever built in debug mode, though, and inadvertently used some unescaped $ symbols, which led to surprising results. This change will prevent that problem from happening in the future. PiperOrigin-RevId: 287906643 -- c5762833ebde6d7110bf68041a823b571c238e9e by Gennadiy Rozental : Move all the flag data into a single place instead of being split between handle and flag object. After this change CommandLineFlag will not hold any data anymore. And we also do not need to pass the CommandLineFlag around in Abseil Flag implementation to report flag name and location. PiperOrigin-RevId: 287899076 -- 8b5fb644f1e3d9267b7a75106fe9a72c886db786 by Derek Mauro : Upgrade CI testing to Bazel 2.0.0 and Clang 407ac2eb5f13 -fno-sanitize-blacklist is to workaround https://github.com/bazelbuild/bazel/issues/10510 PiperOrigin-RevId: 287875363 -- a20cc1d58895de2babc3748a6c79d1d6813734ef by Abseil Team : Make ABSL_RETIRED_FLAG behave consistently with ABSL_FLAG. Before the change: ABSL_RETIRED_FLAG does not compile when there are competing ctors in the type, even when ABSL_FLAG does. After the change: ABSL_RETIRED_FLAG compiles when ABSL_FLAG does. PiperOrigin-RevId: 286483183 -- 1cff7e67329d2be9e50bee1f2e76ef9ffd2edde5 by Abseil Team : Support C++20 erase_if API in unordered associative containers See [unord.set.erasure]: https://eel.is/c++draft/unord.set.erasure See [unord.map.erasure]: https://eel.is/c++draft/unord.map.erasure PiperOrigin-RevId: 286461140 GitOrigin-RevId: 330051e00cd57ee516b4eaf656965656ffbcd0bc Change-Id: I5513110b41c2af08a44da54612cff341ac5c6607 --- absl/container/flat_hash_map.h | 9 ++++ absl/container/flat_hash_map_test.cc | 38 +++++++++++++ absl/container/flat_hash_set.h | 8 +++ absl/container/flat_hash_set_test.cc | 36 +++++++++++++ absl/container/internal/raw_hash_set.h | 11 ++++ absl/container/node_hash_map.h | 9 ++++ absl/container/node_hash_map_test.cc | 38 +++++++++++++ absl/container/node_hash_set.h | 8 +++ absl/container/node_hash_set_test.cc | 36 +++++++++++++ absl/flags/BUILD.bazel | 4 +- absl/flags/CMakeLists.txt | 3 +- absl/flags/flag.h | 48 +++++++---------- absl/flags/flag_test.cc | 31 ++--------- absl/flags/internal/commandlineflag.cc | 62 ---------------------- absl/flags/internal/commandlineflag.h | 26 ++++----- absl/flags/internal/flag.cc | 69 +++++++++++++----------- absl/flags/internal/flag.h | 85 ++++++++++++++---------------- absl/flags/internal/registry.cc | 8 +-- absl/strings/substitute.h | 7 ++- absl/strings/substitute_test.cc | 4 +- ci/cmake_install_test.sh | 2 +- ci/linux_clang-latest_libcxx_asan_bazel.sh | 3 +- ci/linux_clang-latest_libcxx_bazel.sh | 2 +- ci/linux_clang-latest_libcxx_tsan_bazel.sh | 3 +- ci/linux_clang-latest_libstdcxx_bazel.sh | 2 +- ci/linux_gcc-latest_libstdcxx_bazel.sh | 2 +- ci/linux_gcc-latest_libstdcxx_cmake.sh | 2 +- 27 files changed, 327 insertions(+), 229 deletions(-) delete mode 100644 absl/flags/internal/commandlineflag.cc (limited to 'ci/linux_clang-latest_libcxx_tsan_bazel.sh') diff --git a/absl/container/flat_hash_map.h b/absl/container/flat_hash_map.h index fb570cd4..fcb70d86 100644 --- a/absl/container/flat_hash_map.h +++ b/absl/container/flat_hash_map.h @@ -532,6 +532,15 @@ class flat_hash_map : public absl::container_internal::raw_hash_map< using Base::key_eq; }; +// erase_if(flat_hash_map<>, Pred) +// +// Erases all elements that satisfy the predicate `pred` from the container `c`. +template +void erase_if(flat_hash_map& c, Predicate pred) { + container_internal::EraseIf(pred, &c); +} + namespace container_internal { template diff --git a/absl/container/flat_hash_map_test.cc b/absl/container/flat_hash_map_test.cc index dae8e003..fd9c5604 100644 --- a/absl/container/flat_hash_map_test.cc +++ b/absl/container/flat_hash_map_test.cc @@ -30,6 +30,7 @@ namespace { using ::absl::container_internal::hash_internal::Enum; using ::absl::container_internal::hash_internal::EnumClass; using ::testing::_; +using ::testing::IsEmpty; using ::testing::Pair; using ::testing::UnorderedElementsAre; @@ -215,6 +216,43 @@ TEST(FlatHashMap, MergeExtractInsert) { EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 17), Pair(2, 9))); } +bool FirstIsEven(std::pair p) { return p.first % 2 == 0; } + +TEST(FlatHashMap, EraseIf) { + // Erase all elements. + { + flat_hash_map s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; + erase_if(s, [](std::pair) { return true; }); + EXPECT_THAT(s, IsEmpty()); + } + // Erase no elements. + { + flat_hash_map s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; + erase_if(s, [](std::pair) { return false; }); + EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3), + Pair(4, 4), Pair(5, 5))); + } + // Erase specific elements. + { + flat_hash_map s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; + erase_if(s, + [](std::pair kvp) { return kvp.first % 2 == 1; }); + EXPECT_THAT(s, UnorderedElementsAre(Pair(2, 2), Pair(4, 4))); + } + // Predicate is function reference. + { + flat_hash_map s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; + erase_if(s, FirstIsEven); + EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(3, 3), Pair(5, 5))); + } + // Predicate is function pointer. + { + flat_hash_map s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; + erase_if(s, &FirstIsEven); + EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(3, 3), Pair(5, 5))); + } +} + #if (defined(ABSL_USES_STD_ANY) || !defined(_LIBCPP_VERSION)) && \ !defined(__EMSCRIPTEN__) TEST(FlatHashMap, Any) { diff --git a/absl/container/flat_hash_set.h b/absl/container/flat_hash_set.h index 930107ea..94be6e3d 100644 --- a/absl/container/flat_hash_set.h +++ b/absl/container/flat_hash_set.h @@ -439,6 +439,14 @@ class flat_hash_set using Base::key_eq; }; +// erase_if(flat_hash_set<>, Pred) +// +// Erases all elements that satisfy the predicate `pred` from the container `c`. +template +void erase_if(flat_hash_set& c, Predicate pred) { + container_internal::EraseIf(pred, &c); +} + namespace container_internal { template diff --git a/absl/container/flat_hash_set_test.cc b/absl/container/flat_hash_set_test.cc index 6eacb1bb..40d7f85c 100644 --- a/absl/container/flat_hash_set_test.cc +++ b/absl/container/flat_hash_set_test.cc @@ -31,6 +31,7 @@ namespace { using ::absl::container_internal::hash_internal::Enum; using ::absl::container_internal::hash_internal::EnumClass; +using ::testing::IsEmpty; using ::testing::Pointee; using ::testing::UnorderedElementsAre; using ::testing::UnorderedElementsAreArray; @@ -124,6 +125,41 @@ TEST(FlatHashSet, MergeExtractInsert) { EXPECT_THAT(set2, UnorderedElementsAre(Pointee(7), Pointee(23))); } +bool IsEven(int k) { return k % 2 == 0; } + +TEST(FlatHashSet, EraseIf) { + // Erase all elements. + { + flat_hash_set s = {1, 2, 3, 4, 5}; + erase_if(s, [](int) { return true; }); + EXPECT_THAT(s, IsEmpty()); + } + // Erase no elements. + { + flat_hash_set s = {1, 2, 3, 4, 5}; + erase_if(s, [](int) { return false; }); + EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5)); + } + // Erase specific elements. + { + flat_hash_set s = {1, 2, 3, 4, 5}; + erase_if(s, [](int k) { return k % 2 == 1; }); + EXPECT_THAT(s, UnorderedElementsAre(2, 4)); + } + // Predicate is function reference. + { + flat_hash_set s = {1, 2, 3, 4, 5}; + erase_if(s, IsEven); + EXPECT_THAT(s, UnorderedElementsAre(1, 3, 5)); + } + // Predicate is function pointer. + { + flat_hash_set s = {1, 2, 3, 4, 5}; + erase_if(s, &IsEven); + EXPECT_THAT(s, UnorderedElementsAre(1, 3, 5)); + } +} + } // namespace } // namespace container_internal ABSL_NAMESPACE_END diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h index 4103e02a..b1c686ed 100644 --- a/absl/container/internal/raw_hash_set.h +++ b/absl/container/internal/raw_hash_set.h @@ -1801,6 +1801,17 @@ class raw_hash_set { settings_{0, hasher{}, key_equal{}, allocator_type{}}; }; +// Erases all elements that satisfy the predicate `pred` from the container `c`. +template +void EraseIf(Predicate pred, raw_hash_set* c) { + for (auto it = c->begin(), last = c->end(); it != last;) { + auto copy_it = it++; + if (pred(*copy_it)) { + c->erase(copy_it); + } + } +} + namespace hashtable_debug_internal { template struct HashtableDebugAccess> { diff --git a/absl/container/node_hash_map.h b/absl/container/node_hash_map.h index e8065a98..fccea184 100644 --- a/absl/container/node_hash_map.h +++ b/absl/container/node_hash_map.h @@ -522,6 +522,15 @@ class node_hash_map void resize(typename Base::size_type hint) { this->rehash(hint); } }; +// erase_if(node_hash_map<>, Pred) +// +// Erases all elements that satisfy the predicate `pred` from the container `c`. +template +void erase_if(node_hash_map& c, Predicate pred) { + container_internal::EraseIf(pred, &c); +} + namespace container_internal { template diff --git a/absl/container/node_hash_map_test.cc b/absl/container/node_hash_map_test.cc index f923e915..5d74b814 100644 --- a/absl/container/node_hash_map_test.cc +++ b/absl/container/node_hash_map_test.cc @@ -26,6 +26,7 @@ namespace container_internal { namespace { using ::testing::Field; +using ::testing::IsEmpty; using ::testing::Pair; using ::testing::UnorderedElementsAre; @@ -216,6 +217,43 @@ TEST(NodeHashMap, MergeExtractInsert) { EXPECT_THAT(set2, UnorderedElementsAre(Elem(7, -70), Elem(17, 23))); } +bool FirstIsEven(std::pair p) { return p.first % 2 == 0; } + +TEST(NodeHashMap, EraseIf) { + // Erase all elements. + { + node_hash_map s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; + erase_if(s, [](std::pair) { return true; }); + EXPECT_THAT(s, IsEmpty()); + } + // Erase no elements. + { + node_hash_map s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; + erase_if(s, [](std::pair) { return false; }); + EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3), + Pair(4, 4), Pair(5, 5))); + } + // Erase specific elements. + { + node_hash_map s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; + erase_if(s, + [](std::pair kvp) { return kvp.first % 2 == 1; }); + EXPECT_THAT(s, UnorderedElementsAre(Pair(2, 2), Pair(4, 4))); + } + // Predicate is function reference. + { + node_hash_map s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; + erase_if(s, FirstIsEven); + EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(3, 3), Pair(5, 5))); + } + // Predicate is function pointer. + { + node_hash_map s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; + erase_if(s, &FirstIsEven); + EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(3, 3), Pair(5, 5))); + } +} + } // namespace } // namespace container_internal ABSL_NAMESPACE_END diff --git a/absl/container/node_hash_set.h b/absl/container/node_hash_set.h index 43ada3f9..0e2dee54 100644 --- a/absl/container/node_hash_set.h +++ b/absl/container/node_hash_set.h @@ -435,6 +435,14 @@ class node_hash_set void resize(typename Base::size_type hint) { this->rehash(hint); } }; +// erase_if(node_hash_set<>, Pred) +// +// Erases all elements that satisfy the predicate `pred` from the container `c`. +template +void erase_if(node_hash_set& c, Predicate pred) { + container_internal::EraseIf(pred, &c); +} + namespace container_internal { template diff --git a/absl/container/node_hash_set_test.cc b/absl/container/node_hash_set_test.cc index e1d544ff..7ddad202 100644 --- a/absl/container/node_hash_set_test.cc +++ b/absl/container/node_hash_set_test.cc @@ -25,6 +25,7 @@ namespace container_internal { namespace { using ::absl::container_internal::hash_internal::Enum; using ::absl::container_internal::hash_internal::EnumClass; +using ::testing::IsEmpty; using ::testing::Pointee; using ::testing::UnorderedElementsAre; @@ -101,6 +102,41 @@ TEST(NodeHashSet, MergeExtractInsert) { EXPECT_THAT(set2, UnorderedElementsAre(Pointee(7), Pointee(23))); } +bool IsEven(int k) { return k % 2 == 0; } + +TEST(NodeHashSet, EraseIf) { + // Erase all elements. + { + node_hash_set s = {1, 2, 3, 4, 5}; + erase_if(s, [](int) { return true; }); + EXPECT_THAT(s, IsEmpty()); + } + // Erase no elements. + { + node_hash_set s = {1, 2, 3, 4, 5}; + erase_if(s, [](int) { return false; }); + EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5)); + } + // Erase specific elements. + { + node_hash_set s = {1, 2, 3, 4, 5}; + erase_if(s, [](int k) { return k % 2 == 1; }); + EXPECT_THAT(s, UnorderedElementsAre(2, 4)); + } + // Predicate is function reference. + { + node_hash_set s = {1, 2, 3, 4, 5}; + erase_if(s, IsEven); + EXPECT_THAT(s, UnorderedElementsAre(1, 3, 5)); + } + // Predicate is function pointer. + { + node_hash_set s = {1, 2, 3, 4, 5}; + erase_if(s, &IsEven); + EXPECT_THAT(s, UnorderedElementsAre(1, 3, 5)); + } +} + } // namespace } // namespace container_internal ABSL_NAMESPACE_END diff --git a/absl/flags/BUILD.bazel b/absl/flags/BUILD.bazel index cf449198..504acde8 100644 --- a/absl/flags/BUILD.bazel +++ b/absl/flags/BUILD.bazel @@ -38,6 +38,7 @@ cc_library( linkopts = ABSL_DEFAULT_LINKOPTS, visibility = ["//visibility:private"], deps = [ + ":config", ":handle", ":registry", "//absl/base:core_headers", @@ -121,9 +122,6 @@ cc_library( cc_library( name = "handle", - srcs = [ - "internal/commandlineflag.cc", - ], hdrs = [ "internal/commandlineflag.h", ], diff --git a/absl/flags/CMakeLists.txt b/absl/flags/CMakeLists.txt index 3a7162f9..7c63821e 100644 --- a/absl/flags/CMakeLists.txt +++ b/absl/flags/CMakeLists.txt @@ -27,6 +27,7 @@ absl_cc_library( LINKOPTS ${ABSL_DEFAULT_LINKOPTS} DEPS + absl::flags_config absl::flags_handle absl::flags_registry absl::synchronization @@ -108,8 +109,6 @@ absl_cc_library( absl_cc_library( NAME flags_handle - SRCS - "internal/commandlineflag.cc" HDRS "internal/commandlineflag.h" COPTS diff --git a/absl/flags/flag.h b/absl/flags/flag.h index f18e9f56..326fb8ee 100644 --- a/absl/flags/flag.h +++ b/absl/flags/flag.h @@ -94,14 +94,14 @@ class Flag { // Visual Studio 2015 still requires the constructor for class to be // constexpr initializable. #if _MSC_VER <= 1900 - constexpr Flag(const char* name, const flags_internal::HelpGenFunc help_gen, - const char* filename, + constexpr Flag(const char* name, const char* filename, const flags_internal::FlagMarshallingOpFn marshalling_op, + const flags_internal::HelpGenFunc help_gen, const flags_internal::FlagDfltGenFunc default_value_gen) : name_(name), - help_gen_(help_gen), filename_(filename), marshalling_op_(marshalling_op), + help_gen_(help_gen), default_value_gen_(default_value_gen), inited_(false), impl_(nullptr) {} @@ -116,10 +116,10 @@ class Flag { } impl_ = new flags_internal::Flag( - name_, + name_, filename_, marshalling_op_, {flags_internal::FlagHelpSrc(help_gen_), flags_internal::FlagHelpSrcKind::kGenFunc}, - filename_, marshalling_op_, default_value_gen_); + default_value_gen_); inited_.store(true, std::memory_order_release); } @@ -155,9 +155,9 @@ class Flag { // The data members are logically private, but they need to be public for // this to be an aggregate type. const char* name_; - const flags_internal::HelpGenFunc help_gen_; const char* filename_; const flags_internal::FlagMarshallingOpFn marshalling_op_; + const flags_internal::HelpGenFunc help_gen_; const flags_internal::FlagDfltGenFunc default_value_gen_; mutable std::atomic inited_; @@ -342,26 +342,24 @@ ABSL_NAMESPACE_END ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value) \ ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, help); \ ABSL_CONST_INIT absl::Flag FLAGS_##name{ \ - ABSL_FLAG_IMPL_FLAGNAME(#name), \ - absl::flags_internal::HelpArg(0), \ - ABSL_FLAG_IMPL_FILENAME(), \ + ABSL_FLAG_IMPL_FLAGNAME(#name), ABSL_FLAG_IMPL_FILENAME(), \ &absl::flags_internal::FlagMarshallingOps, \ + absl::flags_internal::HelpArg(0), \ &AbslFlagsInitFlag##name}; \ extern bool FLAGS_no##name; \ bool FLAGS_no##name = ABSL_FLAG_IMPL_REGISTRAR(Type, FLAGS_##name) #else // MSVC version uses aggregate initialization. We also do not try to // optimize away help wrapper. -#define ABSL_FLAG_IMPL(Type, name, default_value, help) \ - namespace absl /* block flags in namespaces */ {} \ - ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value) \ - ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, help); \ - ABSL_CONST_INIT absl::Flag FLAGS_##name{ \ - ABSL_FLAG_IMPL_FLAGNAME(#name), &AbslFlagHelpGenFor##name::NonConst, \ - ABSL_FLAG_IMPL_FILENAME(), \ - &absl::flags_internal::FlagMarshallingOps, \ - &AbslFlagsInitFlag##name}; \ - extern bool FLAGS_no##name; \ +#define ABSL_FLAG_IMPL(Type, name, default_value, help) \ + namespace absl /* block flags in namespaces */ {} \ + ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value) \ + ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, help); \ + ABSL_CONST_INIT absl::Flag FLAGS_##name{ \ + ABSL_FLAG_IMPL_FLAGNAME(#name), ABSL_FLAG_IMPL_FILENAME(), \ + &absl::flags_internal::FlagMarshallingOps, \ + &AbslFlagHelpGenFor##name::NonConst, &AbslFlagsInitFlag##name}; \ + extern bool FLAGS_no##name; \ bool FLAGS_no##name = ABSL_FLAG_IMPL_REGISTRAR(Type, FLAGS_##name) #endif @@ -384,19 +382,11 @@ ABSL_NAMESPACE_END // // `default_value` is only used as a double check on the type. `explanation` is // unused. -// -// ABSL_RETIRED_FLAG support omitting the default value for default -// constructible value type, so that users can delete the code generatring this -// value. -// // TODO(rogeeff): Return an anonymous struct instead of bool, and place it into // the unnamed namespace. #define ABSL_RETIRED_FLAG(type, flagname, default_value, explanation) \ - ABSL_ATTRIBUTE_UNUSED static const bool ignored_##flagname = \ - ([] { \ - return absl::flags_internal::MakeFromDefaultValueOrEmpty( \ - default_value); \ - }, \ + ABSL_ATTRIBUTE_UNUSED static const bool ignored_##flagname = \ + ([] { return type(default_value); }, \ absl::flags_internal::RetiredFlag(#flagname)) #endif // ABSL_FLAGS_FLAG_H_ diff --git a/absl/flags/flag_test.cc b/absl/flags/flag_test.cc index 465f018c..28c513b0 100644 --- a/absl/flags/flag_test.cc +++ b/absl/flags/flag_test.cc @@ -43,16 +43,16 @@ template bool TestConstructionFor() { constexpr flags::HelpInitArg help_arg{flags::FlagHelpSrc("literal help"), flags::FlagHelpSrcKind::kLiteral}; - constexpr flags::Flag f1("f1", help_arg, "file", - &flags::FlagMarshallingOps, &TestMakeDflt); + constexpr flags::Flag f1("f1", "file", &flags::FlagMarshallingOps, + help_arg, &TestMakeDflt); EXPECT_EQ(f1.Name(), "f1"); EXPECT_EQ(f1.Help(), "literal help"); EXPECT_EQ(f1.Filename(), "file"); ABSL_CONST_INIT static flags::Flag f2( - "f2", + "f2", "file", &flags::FlagMarshallingOps, {flags::FlagHelpSrc(&TestHelpMsg), flags::FlagHelpSrcKind::kGenFunc}, - "file", &flags::FlagMarshallingOps, &TestMakeDflt); + &TestMakeDflt); flags::FlagRegistrar(&f2).OnUpdate(TestCallback); EXPECT_EQ(f2.Name(), "f2"); @@ -486,30 +486,11 @@ TEST_F(FlagTest, TestNonDefaultConstructibleType) { // -------------------------------------------------------------------- -struct Wrapper { - Wrapper() {} - - // NOLINTNEXTLINE(runtime/explicit) - Wrapper(const std::string& val) : val(val) {} - - // NOLINTNEXTLINE(runtime/explicit) - template - Wrapper(T&& t) : val(std::forward(t)) {} - - // NOLINTNEXTLINE(runtime/explicit) - operator std::string() const& { return val; } - - std::string val; -}; - } // namespace ABSL_RETIRED_FLAG(bool, old_bool_flag, true, "old descr"); ABSL_RETIRED_FLAG(int, old_int_flag, (int)std::sqrt(10), "old descr"); ABSL_RETIRED_FLAG(std::string, old_str_flag, "", absl::StrCat("old ", "descr")); -ABSL_RETIRED_FLAG(Wrapper, old_wrapper_flag, {}, "old wrapper"); -ABSL_RETIRED_FLAG(Wrapper, old_wrapper_no_default_flag, , - "old wrapper no default"); namespace { @@ -521,10 +502,6 @@ TEST_F(FlagTest, TestRetiredFlagRegistration) { EXPECT_FALSE(is_bool); EXPECT_TRUE(flags::IsRetiredFlag("old_str_flag", &is_bool)); EXPECT_FALSE(is_bool); - EXPECT_TRUE(flags::IsRetiredFlag("old_wrapper_flag", &is_bool)); - EXPECT_FALSE(is_bool); - EXPECT_TRUE(flags::IsRetiredFlag("old_wrapper_no_default_flag", &is_bool)); - EXPECT_FALSE(is_bool); EXPECT_FALSE(flags::IsRetiredFlag("some_other_flag", &is_bool)); } diff --git a/absl/flags/internal/commandlineflag.cc b/absl/flags/internal/commandlineflag.cc deleted file mode 100644 index 09249274..00000000 --- a/absl/flags/internal/commandlineflag.cc +++ /dev/null @@ -1,62 +0,0 @@ -// -// 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. - -#include "absl/flags/internal/commandlineflag.h" - -#include "absl/flags/usage_config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace flags_internal { - -// The help message indicating that the commandline flag has been -// 'stripped'. It will not show up when doing "-help" and its -// variants. The flag is stripped if ABSL_FLAGS_STRIP_HELP is set to 1 -// before including absl/flags/flag.h - -// This is used by this file, and also in commandlineflags_reporting.cc -const char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001"; - -absl::string_view CommandLineFlag::Typename() const { - // We do not store/report type in Abseil Flags, so that user do not rely on in - // at runtime - if (IsAbseilFlag() || IsRetired()) return ""; - -#define HANDLE_V1_BUILTIN_TYPE(t) \ - if (IsOfType()) { \ - return #t; \ - } - - HANDLE_V1_BUILTIN_TYPE(bool); - HANDLE_V1_BUILTIN_TYPE(int32_t); - HANDLE_V1_BUILTIN_TYPE(int64_t); - HANDLE_V1_BUILTIN_TYPE(uint64_t); - HANDLE_V1_BUILTIN_TYPE(double); -#undef HANDLE_V1_BUILTIN_TYPE - - if (IsOfType()) { - return "string"; - } - - return ""; -} - -std::string CommandLineFlag::Filename() const { - return flags_internal::GetUsageConfig().normalize_filename(filename_); -} - -} // namespace flags_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/absl/flags/internal/commandlineflag.h b/absl/flags/internal/commandlineflag.h index 49e13d1e..a0c18e80 100644 --- a/absl/flags/internal/commandlineflag.h +++ b/absl/flags/internal/commandlineflag.h @@ -61,8 +61,6 @@ enum ValueSource { kProgrammaticChange, }; -extern const char kStrippedFlagHelp[]; - // The per-type function template void* FlagOps(FlagOp op, const void* v1, void* v2) { @@ -155,8 +153,7 @@ class FlagStateInterface { // Holds all information for a flag. class CommandLineFlag { public: - constexpr CommandLineFlag(const char* name, const char* filename) - : name_(name), filename_(filename) {} + constexpr CommandLineFlag() = default; // Virtual destructor virtual void Destroy() = 0; @@ -166,9 +163,6 @@ class CommandLineFlag { CommandLineFlag& operator=(const CommandLineFlag&) = delete; // Non-polymorphic access methods. - absl::string_view Name() const { return name_; } - absl::string_view Typename() const; - std::string Filename() const; // Return true iff flag has type T. template @@ -190,8 +184,7 @@ class CommandLineFlag { // // 1. `U.value` has correct size and alignment for a value of type `T` // 2. The `U.value` constructor is not invoked since U's constructor does - // not - // do it explicitly. + // not do it explicitly. // 3. The `U.value` destructor is invoked since U's destructor does it // explicitly. This makes `U` a kind of RAII wrapper around non default // constructible value of T, which is destructed when we leave the @@ -213,9 +206,16 @@ class CommandLineFlag { // Polymorphic access methods - // Returns help message associated with this flag + // Returns name of this flag. + virtual absl::string_view Name() const = 0; + // Returns name of the file where this flag is defined. + virtual std::string Filename() const = 0; + // Returns name of the flag's value type for some built-in types or empty + // std::string. + virtual absl::string_view Typename() const = 0; + // Returns help message associated with this flag. virtual std::string Help() const = 0; - // Returns true iff this object corresponds to retired flag + // Returns true iff this object corresponds to retired flag. virtual bool IsRetired() const { return false; } // Returns true iff this is a handle to an Abseil Flag. virtual bool IsAbseilFlag() const { return true; } @@ -253,10 +253,6 @@ class CommandLineFlag { protected: ~CommandLineFlag() = default; - // Constant configuration for a particular flag. - const char* const name_; // Flags name passed to ABSL_FLAG as second arg. - const char* const filename_; // The file name where ABSL_FLAG resides. - private: // Copy-construct a new value of the flag's type in a memory referenced by // the dst based on the current flag's value. diff --git a/absl/flags/internal/flag.cc b/absl/flags/internal/flag.cc index 599bd7a4..bb9a98f3 100644 --- a/absl/flags/internal/flag.cc +++ b/absl/flags/internal/flag.cc @@ -16,17 +16,25 @@ #include "absl/flags/internal/flag.h" #include "absl/base/optimization.h" +#include "absl/flags/usage_config.h" #include "absl/synchronization/mutex.h" namespace absl { ABSL_NAMESPACE_BEGIN namespace flags_internal { + +// The help message indicating that the commandline flag has been +// 'stripped'. It will not show up when doing "-help" and its +// variants. The flag is stripped if ABSL_FLAGS_STRIP_HELP is set to 1 +// before including absl/flags/flag.h +const char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001"; + namespace { // Currently we only validate flag values for user-defined flag types. -bool ShouldValidateFlagValue(const CommandLineFlag& flag) { +bool ShouldValidateFlagValue(FlagOpFn flag_type_id) { #define DONT_VALIDATE(T) \ - if (flag.IsOfType()) return false; + if (flag_type_id == &flags_internal::FlagOps) return false; ABSL_FLAGS_INTERNAL_FOR_EACH_LOCK_FREE(DONT_VALIDATE) DONT_VALIDATE(std::string) DONT_VALIDATE(std::vector) @@ -123,6 +131,12 @@ std::unique_ptr FlagImpl::MakeInitValue() const { return {res, DynValueDeleter{op_}}; } +absl::string_view FlagImpl::Name() const { return name_; } + +std::string FlagImpl::Filename() const { + return flags_internal::GetUsageConfig().normalize_filename(filename_); +} + std::string FlagImpl::Help() const { return help_source_kind_ == FlagHelpSrcKind::kLiteral ? help_.literal : help_.gen_func(); @@ -186,16 +200,15 @@ void FlagImpl::InvokeCallback() const { cb(); } -bool FlagImpl::RestoreState(const CommandLineFlag& flag, const void* value, - bool modified, bool on_command_line, - int64_t counter) { +bool FlagImpl::RestoreState(const void* value, bool modified, + bool on_command_line, int64_t counter) { { absl::MutexLock l(DataGuard()); if (counter_ == counter) return false; } - Write(flag, value, op_); + Write(value, op_); { absl::MutexLock l(DataGuard()); @@ -211,18 +224,15 @@ bool FlagImpl::RestoreState(const CommandLineFlag& flag, const void* value, // argument. If parsing successful, this function replaces the dst with newly // parsed value. In case if any error is encountered in either step, the error // message is stored in 'err' -bool FlagImpl::TryParse(const CommandLineFlag& flag, void** dst, - absl::string_view value, std::string* err) const { +bool FlagImpl::TryParse(void** dst, absl::string_view value, + std::string* err) const { auto tentative_value = MakeInitValue(); std::string parse_err; if (!Parse(marshalling_op_, value, tentative_value.get(), &parse_err)) { - auto type_name = flag.Typename(); absl::string_view err_sep = parse_err.empty() ? "" : "; "; - absl::string_view typename_sep = type_name.empty() ? "" : " "; - *err = absl::StrCat("Illegal value '", value, "' specified for", - typename_sep, type_name, " flag '", flag.Name(), "'", - err_sep, parse_err); + *err = absl::StrCat("Illegal value '", value, "' specified for flag '", + Name(), "'", err_sep, parse_err); return false; } @@ -233,8 +243,7 @@ bool FlagImpl::TryParse(const CommandLineFlag& flag, void** dst, return true; } -void FlagImpl::Read(const CommandLineFlag& flag, void* dst, - const flags_internal::FlagOpFn dst_op) const { +void FlagImpl::Read(void* dst, const flags_internal::FlagOpFn dst_op) const { absl::ReaderMutexLock l(DataGuard()); // `dst_op` is the unmarshaling operation corresponding to the declaration @@ -243,7 +252,7 @@ void FlagImpl::Read(const CommandLineFlag& flag, void* dst, if (ABSL_PREDICT_FALSE(dst_op != op_)) { ABSL_INTERNAL_LOG( ERROR, - absl::StrCat("Flag '", flag.Name(), + absl::StrCat("Flag '", Name(), "' is defined as one type and declared as another")); } CopyConstruct(op_, cur_, dst); @@ -259,8 +268,7 @@ void FlagImpl::StoreAtomic() { } } -void FlagImpl::Write(const CommandLineFlag& flag, const void* src, - const flags_internal::FlagOpFn src_op) { +void FlagImpl::Write(const void* src, const flags_internal::FlagOpFn src_op) { absl::MutexLock l(DataGuard()); // `src_op` is the marshalling operation corresponding to the declaration @@ -269,18 +277,17 @@ void FlagImpl::Write(const CommandLineFlag& flag, const void* src, if (ABSL_PREDICT_FALSE(src_op != op_)) { ABSL_INTERNAL_LOG( ERROR, - absl::StrCat("Flag '", flag.Name(), + absl::StrCat("Flag '", Name(), "' is defined as one type and declared as another")); } - if (ShouldValidateFlagValue(flag)) { + if (ShouldValidateFlagValue(op_)) { void* obj = Clone(op_, src); std::string ignored_error; std::string src_as_str = Unparse(marshalling_op_, src); if (!Parse(marshalling_op_, src_as_str, obj, &ignored_error)) { - ABSL_INTERNAL_LOG(ERROR, - absl::StrCat("Attempt to set flag '", flag.Name(), - "' to invalid value ", src_as_str)); + ABSL_INTERNAL_LOG(ERROR, absl::StrCat("Attempt to set flag '", Name(), + "' to invalid value ", src_as_str)); } Delete(op_, obj); } @@ -301,15 +308,14 @@ void FlagImpl::Write(const CommandLineFlag& flag, const void* src, // * Update the flag's default value // * Update the current flag value if it was never set before // The mode is selected based on 'set_mode' parameter. -bool FlagImpl::SetFromString(const CommandLineFlag& flag, - absl::string_view value, FlagSettingMode set_mode, +bool FlagImpl::SetFromString(absl::string_view value, FlagSettingMode set_mode, ValueSource source, std::string* err) { absl::MutexLock l(DataGuard()); switch (set_mode) { case SET_FLAGS_VALUE: { // set or modify the flag's value - if (!TryParse(flag, &cur_, value, err)) return false; + if (!TryParse(&cur_, value, err)) return false; modified_ = true; counter_++; StoreAtomic(); @@ -323,7 +329,7 @@ bool FlagImpl::SetFromString(const CommandLineFlag& flag, case SET_FLAG_IF_DEFAULT: { // set the flag's value, but only if it hasn't been set by someone else if (!modified_) { - if (!TryParse(flag, &cur_, value, err)) return false; + if (!TryParse(&cur_, value, err)) return false; modified_ = true; counter_++; StoreAtomic(); @@ -341,12 +347,12 @@ bool FlagImpl::SetFromString(const CommandLineFlag& flag, } case SET_FLAGS_DEFAULT: { if (def_kind_ == FlagDefaultSrcKind::kDynamicValue) { - if (!TryParse(flag, &default_src_.dynamic_value, value, err)) { + if (!TryParse(&default_src_.dynamic_value, value, err)) { return false; } } else { void* new_default_val = nullptr; - if (!TryParse(flag, &new_default_val, value, err)) { + if (!TryParse(&new_default_val, value, err)) { return false; } @@ -367,8 +373,7 @@ bool FlagImpl::SetFromString(const CommandLineFlag& flag, return true; } -void FlagImpl::CheckDefaultValueParsingRoundtrip( - const CommandLineFlag& flag) const { +void FlagImpl::CheckDefaultValueParsingRoundtrip() const { std::string v = DefaultValue(); absl::MutexLock lock(DataGuard()); @@ -378,7 +383,7 @@ void FlagImpl::CheckDefaultValueParsingRoundtrip( if (!flags_internal::Parse(marshalling_op_, v, dst.get(), &error)) { ABSL_INTERNAL_LOG( FATAL, - absl::StrCat("Flag ", flag.Name(), " (from ", flag.Filename(), + absl::StrCat("Flag ", Name(), " (from ", Filename(), "): std::string form of default value '", v, "' could not be parsed; error=", error)); } diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h index 21a10c7f..7d5271c4 100644 --- a/absl/flags/internal/flag.h +++ b/absl/flags/internal/flag.h @@ -82,6 +82,8 @@ struct HelpInitArg { FlagHelpSrcKind kind; }; +extern const char kStrippedFlagHelp[]; + // HelpConstexprWrap is used by struct AbslFlagHelpGenFor##name generated by // ABSL_FLAG macro. It is only used to silence the compiler in the case where // help message expression is not constexpr and does not have type const char*. @@ -148,11 +150,14 @@ struct DynValueDeleter { // The class encapsulates the Flag's data and safe access to it. class FlagImpl { public: - constexpr FlagImpl(const flags_internal::FlagOpFn op, + constexpr FlagImpl(const char* name, const char* filename, + const flags_internal::FlagOpFn op, const flags_internal::FlagMarshallingOpFn marshalling_op, - const flags_internal::FlagDfltGenFunc default_value_gen, - const HelpInitArg help) - : op_(op), + const HelpInitArg help, + const flags_internal::FlagDfltGenFunc default_value_gen) + : name_(name), + filename_(filename), + op_(op), marshalling_op_(marshalling_op), help_(help.source), help_source_kind_(help.kind), @@ -164,18 +169,18 @@ class FlagImpl { void Destroy(); // Constant access methods + absl::string_view Name() const; + std::string Filename() const; std::string Help() const; bool IsModified() const ABSL_LOCKS_EXCLUDED(*DataGuard()); bool IsSpecifiedOnCommandLine() const ABSL_LOCKS_EXCLUDED(*DataGuard()); std::string DefaultValue() const ABSL_LOCKS_EXCLUDED(*DataGuard()); std::string CurrentValue() const ABSL_LOCKS_EXCLUDED(*DataGuard()); - void Read(const CommandLineFlag& flag, void* dst, - const flags_internal::FlagOpFn dst_op) const + void Read(void* dst, const flags_internal::FlagOpFn dst_op) const ABSL_LOCKS_EXCLUDED(*DataGuard()); // Attempts to parse supplied `value` std::string. If parsing is successful, then // it replaces `dst` with the new value. - bool TryParse(const CommandLineFlag& flag, void** dst, - absl::string_view value, std::string* err) const + bool TryParse(void** dst, absl::string_view value, std::string* err) const ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()); template bool AtomicGet(T* v) const { @@ -189,12 +194,11 @@ class FlagImpl { } // Mutating access methods - void Write(const CommandLineFlag& flag, const void* src, - const flags_internal::FlagOpFn src_op) + void Write(const void* src, const flags_internal::FlagOpFn src_op) + ABSL_LOCKS_EXCLUDED(*DataGuard()); + bool SetFromString(absl::string_view value, FlagSettingMode set_mode, + ValueSource source, std::string* err) ABSL_LOCKS_EXCLUDED(*DataGuard()); - bool SetFromString(const CommandLineFlag& flag, absl::string_view value, - FlagSettingMode set_mode, ValueSource source, - std::string* err) ABSL_LOCKS_EXCLUDED(*DataGuard()); // If possible, updates copy of the Flag's value that is stored in an // atomic word. void StoreAtomic() ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()); @@ -214,12 +218,11 @@ class FlagImpl { return absl::make_unique>( flag, std::move(cur_value), modified_, on_command_line_, counter_); } - bool RestoreState(const CommandLineFlag& flag, const void* value, - bool modified, bool on_command_line, int64_t counter) - ABSL_LOCKS_EXCLUDED(*DataGuard()); + bool RestoreState(const void* value, bool modified, bool on_command_line, + int64_t counter) ABSL_LOCKS_EXCLUDED(*DataGuard()); // Value validation interfaces. - void CheckDefaultValueParsingRoundtrip(const CommandLineFlag& flag) const + void CheckDefaultValueParsingRoundtrip() const ABSL_LOCKS_EXCLUDED(*DataGuard()); bool ValidateInputValue(absl::string_view value) const ABSL_LOCKS_EXCLUDED(*DataGuard()); @@ -235,7 +238,10 @@ class FlagImpl { ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()); // Immutable Flag's data. - const FlagOpFn op_; // Type-specific handler. + // Constant configuration for a particular flag. + const char* const name_; // Flags name passed to ABSL_FLAG as second arg. + const char* const filename_; // The file name where ABSL_FLAG resides. + const FlagOpFn op_; // Type-specific handler. const FlagMarshallingOpFn marshalling_op_; // Marshalling ops handler. const FlagHelpSrc help_; // Help message literal or function to generate it. // Indicates if help message was supplied as literal or generator func. @@ -286,13 +292,12 @@ class FlagImpl { template class Flag final : public flags_internal::CommandLineFlag { public: - constexpr Flag(const char* name, const flags_internal::HelpInitArg help, - const char* filename, + constexpr Flag(const char* name, const char* filename, const flags_internal::FlagMarshallingOpFn marshalling_op, - const flags_internal::FlagDfltGenFunc initial_value_gen) - : flags_internal::CommandLineFlag(name, filename), - impl_(&flags_internal::FlagOps, marshalling_op, initial_value_gen, - help) {} + const flags_internal::HelpInitArg help, + const flags_internal::FlagDfltGenFunc default_value_gen) + : impl_(name, filename, &flags_internal::FlagOps, marshalling_op, help, + default_value_gen) {} T Get() const { // See implementation notes in CommandLineFlag::Get(). @@ -303,19 +308,22 @@ class Flag final : public flags_internal::CommandLineFlag { }; U u; - impl_.Read(*this, &u.value, &flags_internal::FlagOps); + impl_.Read(&u.value, &flags_internal::FlagOps); return std::move(u.value); } bool AtomicGet(T* v) const { return impl_.AtomicGet(v); } - void Set(const T& v) { impl_.Write(*this, &v, &flags_internal::FlagOps); } + void Set(const T& v) { impl_.Write(&v, &flags_internal::FlagOps); } void SetCallback(const flags_internal::FlagCallback mutation_callback) { impl_.SetCallback(mutation_callback); } // CommandLineFlag interface + absl::string_view Name() const override { return impl_.Name(); } + std::string Filename() const override { return impl_.Filename(); } + absl::string_view Typename() const override { return ""; } std::string Help() const override { return impl_.Help(); } bool IsModified() const override { return impl_.IsModified(); } bool IsSpecifiedOnCommandLine() const override { @@ -338,20 +346,19 @@ class Flag final : public flags_internal::CommandLineFlag { // Restores the flag state to the supplied state object. If there is // nothing to restore returns false. Otherwise returns true. bool RestoreState(const flags_internal::FlagState& flag_state) { - return impl_.RestoreState(*this, &flag_state.cur_value_, - flag_state.modified_, flag_state.on_command_line_, - flag_state.counter_); + return impl_.RestoreState(&flag_state.cur_value_, flag_state.modified_, + flag_state.on_command_line_, flag_state.counter_); } bool SetFromString(absl::string_view value, flags_internal::FlagSettingMode set_mode, flags_internal::ValueSource source, std::string* error) override { - return impl_.SetFromString(*this, value, set_mode, source, error); + return impl_.SetFromString(value, set_mode, source, error); } void CheckDefaultValueParsingRoundtrip() const override { - impl_.CheckDefaultValueParsingRoundtrip(*this); + impl_.CheckDefaultValueParsingRoundtrip(); } private: @@ -360,7 +367,7 @@ class Flag final : public flags_internal::CommandLineFlag { void Destroy() override { impl_.Destroy(); } void Read(void* dst) const override { - impl_.Read(*this, dst, &flags_internal::FlagOps); + impl_.Read(dst, &flags_internal::FlagOps); } flags_internal::FlagOpFn TypeId() const override { return &flags_internal::FlagOps; @@ -416,20 +423,6 @@ T* MakeFromDefaultValue(EmptyBraces) { return new T; } -// MakeFromDefaultValueOrEmpty is basically the same as MakeFromDefaultValue. It -// also allows for empty macro parameter (hence no argument), which was somehow -// widely used for ABSL_RETIRED_FLAG(). - -template -T* MakeFromDefaultValueOrEmpty(T t) { - return MakeFromDefaultValue(std::move(t)); -} - -template -T* MakeFromDefaultValueOrEmpty() { - return MakeFromDefaultValue(EmptyBraces()); -} - } // namespace flags_internal ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/flags/internal/registry.cc b/absl/flags/internal/registry.cc index 5eae933c..ae5afd42 100644 --- a/absl/flags/internal/registry.cc +++ b/absl/flags/internal/registry.cc @@ -277,9 +277,7 @@ namespace { class RetiredFlagObj final : public flags_internal::CommandLineFlag { public: constexpr RetiredFlagObj(const char* name, FlagOpFn ops) - : flags_internal::CommandLineFlag(name, - /*filename=*/"RETIRED"), - op_(ops) {} + : name_(name), op_(ops) {} private: void Destroy() override { @@ -287,6 +285,9 @@ class RetiredFlagObj final : public flags_internal::CommandLineFlag { delete this; } + absl::string_view Name() const override { return name_; } + std::string Filename() const override { return "RETIRED"; } + absl::string_view Typename() const override { return ""; } flags_internal::FlagOpFn TypeId() const override { return op_; } std::string Help() const override { return ""; } bool IsRetired() const override { return true; } @@ -312,6 +313,7 @@ class RetiredFlagObj final : public flags_internal::CommandLineFlag { void Read(void*) const override {} // Data members + const char* const name_; const FlagOpFn op_; }; diff --git a/absl/strings/substitute.h b/absl/strings/substitute.h index 766aca42..4d0984d3 100644 --- a/absl/strings/substitute.h +++ b/absl/strings/substitute.h @@ -190,7 +190,12 @@ void SubstituteAndAppendArray(std::string* output, absl::string_view format, #if defined(ABSL_BAD_CALL_IF) constexpr int CalculateOneBit(const char* format) { - return (*format < '0' || *format > '9') ? 0 : (1 << (*format - '0')); + // Returns: + // * 2^N for '$N' when N is in [0-9] + // * 0 for correct '$' escaping: '$$'. + // * -1 otherwise. + return (*format < '0' || *format > '9') ? (*format == '$' ? 0 : -1) + : (1 << (*format - '0')); } constexpr const char* SkipNumber(const char* format) { diff --git a/absl/strings/substitute_test.cc b/absl/strings/substitute_test.cc index b005f0f4..450cd2bc 100644 --- a/absl/strings/substitute_test.cc +++ b/absl/strings/substitute_test.cc @@ -192,10 +192,10 @@ TEST(SubstituteDeathTest, SubstituteDeath) { "Invalid absl::Substitute\\(\\) format std::string: asked for \"\\$2\", " "but only 2 args were given."); EXPECT_DEBUG_DEATH( - static_cast(absl::Substitute("-$z-")), + static_cast(absl::Substitute(absl::string_view("-$z-"))), "Invalid absl::Substitute\\(\\) format std::string: \"-\\$z-\""); EXPECT_DEBUG_DEATH( - static_cast(absl::Substitute("-$")), + static_cast(absl::Substitute(absl::string_view("-$"))), "Invalid absl::Substitute\\(\\) format std::string: \"-\\$\""); } diff --git a/ci/cmake_install_test.sh b/ci/cmake_install_test.sh index 6a3c19bd..e85474c2 100755 --- a/ci/cmake_install_test.sh +++ b/ci/cmake_install_test.sh @@ -28,5 +28,5 @@ time docker run \ --rm \ -e CFLAGS="-Werror" \ -e CXXFLAGS="-Werror" \ - gcr.io/google.com/absl-177019/linux_gcc-latest:20191018 \ + gcr.io/google.com/absl-177019/linux_gcc-latest:20200102 \ /bin/bash CMake/install_test_project/test.sh $@ diff --git a/ci/linux_clang-latest_libcxx_asan_bazel.sh b/ci/linux_clang-latest_libcxx_asan_bazel.sh index fa38ff20..24efe3b7 100755 --- a/ci/linux_clang-latest_libcxx_asan_bazel.sh +++ b/ci/linux_clang-latest_libcxx_asan_bazel.sh @@ -36,7 +36,7 @@ if [ -z ${EXCEPTIONS_MODE:-} ]; then EXCEPTIONS_MODE="-fno-exceptions -fexceptions" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20191018" +readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20200102" # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. @@ -76,6 +76,7 @@ for std in ${STD}; do --copt="-fsanitize=float-divide-by-zero" \ --copt="-fsanitize=nullability" \ --copt="-fsanitize=undefined" \ + --copt="-fno-sanitize-blacklist" \ --copt=-Werror \ --keep_going \ --linkopt="-fsanitize=address" \ diff --git a/ci/linux_clang-latest_libcxx_bazel.sh b/ci/linux_clang-latest_libcxx_bazel.sh index c3319a1b..40a27c0b 100755 --- a/ci/linux_clang-latest_libcxx_bazel.sh +++ b/ci/linux_clang-latest_libcxx_bazel.sh @@ -36,7 +36,7 @@ if [ -z ${EXCEPTIONS_MODE:-} ]; then EXCEPTIONS_MODE="-fno-exceptions -fexceptions" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20191018" +readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20200102" # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. diff --git a/ci/linux_clang-latest_libcxx_tsan_bazel.sh b/ci/linux_clang-latest_libcxx_tsan_bazel.sh index 200541b9..00257b36 100755 --- a/ci/linux_clang-latest_libcxx_tsan_bazel.sh +++ b/ci/linux_clang-latest_libcxx_tsan_bazel.sh @@ -36,7 +36,7 @@ if [ -z ${EXCEPTIONS_MODE:-} ]; then EXCEPTIONS_MODE="-fno-exceptions -fexceptions" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20191018" +readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20200102" # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. @@ -73,6 +73,7 @@ for std in ${STD}; do --copt="-DDYNAMIC_ANNOTATIONS_ENABLED=1" \ --copt="-DTHREAD_SANITIZER" \ --copt="-fsanitize=thread" \ + --copt="-fno-sanitize-blacklist" \ --copt=-Werror \ --keep_going \ --linkopt="-fsanitize=thread" \ diff --git a/ci/linux_clang-latest_libstdcxx_bazel.sh b/ci/linux_clang-latest_libstdcxx_bazel.sh index 5ea18373..9fe71d37 100755 --- a/ci/linux_clang-latest_libstdcxx_bazel.sh +++ b/ci/linux_clang-latest_libstdcxx_bazel.sh @@ -36,7 +36,7 @@ if [ -z ${EXCEPTIONS_MODE:-} ]; then EXCEPTIONS_MODE="-fno-exceptions -fexceptions" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20191018" +readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20200102" # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. diff --git a/ci/linux_gcc-latest_libstdcxx_bazel.sh b/ci/linux_gcc-latest_libstdcxx_bazel.sh index a6efa197..70d24d79 100755 --- a/ci/linux_gcc-latest_libstdcxx_bazel.sh +++ b/ci/linux_gcc-latest_libstdcxx_bazel.sh @@ -36,7 +36,7 @@ if [ -z ${EXCEPTIONS_MODE:-} ]; then EXCEPTIONS_MODE="-fno-exceptions -fexceptions" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-latest:20191018" +readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-latest:20200102" # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. diff --git a/ci/linux_gcc-latest_libstdcxx_cmake.sh b/ci/linux_gcc-latest_libstdcxx_cmake.sh index ec328748..7effa0c0 100755 --- a/ci/linux_gcc-latest_libstdcxx_cmake.sh +++ b/ci/linux_gcc-latest_libstdcxx_cmake.sh @@ -47,7 +47,7 @@ for std in ${ABSL_CMAKE_CXX_STANDARDS}; do --rm \ -e CFLAGS="-Werror" \ -e CXXFLAGS="-Werror" \ - gcr.io/google.com/absl-177019/linux_gcc-latest:20191018 \ + gcr.io/google.com/absl-177019/linux_gcc-latest:20200102 \ /bin/bash -c " cd /buildfs && \ cmake /abseil-cpp \ -- cgit v1.2.3 From 092ed9793a1ad0e7e418f32c057bf3159a71cd04 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Fri, 20 Mar 2020 09:47:42 -0700 Subject: Export of internal Abseil changes -- 93dd18f415e54697965c56760612b4ff6c9d15d2 by Derek Mauro : Implement Bazel's --distdir flag avoid a dependency on GitHub being up. Move the Docker container identifiers to a common file. PiperOrigin-RevId: 302045549 -- 7b462d31139e3153462cd20ae63b161ac749e839 by Derek Mauro : Fix an unused variable warning in optional.h PiperOrigin-RevId: 301810782 -- 6b533ba9170eed065aec69e48ebab3279fcb3e09 by Abseil Team : Disable ASan and MSan instrumentation for AArch64 stack unwind functions. They read random locations on the stack and might step on sanitizer's redzones. PiperOrigin-RevId: 301674204 GitOrigin-RevId: 93dd18f415e54697965c56760612b4ff6c9d15d2 Change-Id: I2d84d66b054f90b851fb3a968679f112dfe84636 --- absl/debugging/internal/stacktrace_aarch64-inl.inc | 4 ++++ absl/types/optional.h | 4 ++-- ci/cmake_install_test.sh | 5 ++++- ci/linux_clang-latest_libcxx_asan_bazel.sh | 11 ++++++++++- ci/linux_clang-latest_libcxx_bazel.sh | 11 ++++++++++- ci/linux_clang-latest_libcxx_tsan_bazel.sh | 11 ++++++++++- ci/linux_clang-latest_libstdcxx_bazel.sh | 11 ++++++++++- ci/linux_docker_containers.sh | 21 +++++++++++++++++++++ ci/linux_gcc-4.9_libstdcxx_bazel.sh | 11 ++++++++++- ci/linux_gcc-latest_libstdcxx_bazel.sh | 11 ++++++++++- ci/linux_gcc-latest_libstdcxx_cmake.sh | 5 ++++- ci/linux_gcc_alpine_cmake.sh | 3 ++- 12 files changed, 97 insertions(+), 11 deletions(-) create mode 100644 ci/linux_docker_containers.sh (limited to 'ci/linux_clang-latest_libcxx_tsan_bazel.sh') diff --git a/absl/debugging/internal/stacktrace_aarch64-inl.inc b/absl/debugging/internal/stacktrace_aarch64-inl.inc index 411ea308..14a76f1e 100644 --- a/absl/debugging/internal/stacktrace_aarch64-inl.inc +++ b/absl/debugging/internal/stacktrace_aarch64-inl.inc @@ -74,6 +74,8 @@ static inline uintptr_t ComputeStackFrameSize(const T* low, // checks (the strictness of which is controlled by the boolean parameter // "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned. template +ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS // May read random elements from stack. +ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY // May read random elements from stack. static void **NextStackFrame(void **old_frame_pointer, const void *uc) { void **new_frame_pointer = reinterpret_cast(*old_frame_pointer); bool check_frame_size = true; @@ -123,6 +125,8 @@ static void **NextStackFrame(void **old_frame_pointer, const void *uc) { } template +ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS // May read random elements from stack. +ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY // May read random elements from stack. static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count, const void *ucp, int *min_dropped_frames) { #ifdef __GNUC__ diff --git a/absl/types/optional.h b/absl/types/optional.h index 01d747d7..afda69a0 100644 --- a/absl/types/optional.h +++ b/absl/types/optional.h @@ -136,10 +136,10 @@ class optional : private optional_internal::optional_data, constexpr optional(nullopt_t) noexcept {} // NOLINT(runtime/explicit) // Copy constructor, standard semantics - optional(const optional& src) = default; + optional(const optional&) = default; // Move constructor, standard semantics - optional(optional&& src) = default; + optional(optional&&) = default; // Constructs a non-empty `optional` direct-initialized value of type `T` from // the arguments `std::forward(args)...` within the `optional`. diff --git a/ci/cmake_install_test.sh b/ci/cmake_install_test.sh index 55fb4f12..4c748eb9 100755 --- a/ci/cmake_install_test.sh +++ b/ci/cmake_install_test.sh @@ -20,6 +20,9 @@ if [ -z ${ABSEIL_ROOT:-} ]; then ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" fi +source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh" +readonly DOCKER_CONTAINER=${LINUX_GCC_LATEST_CONTAINER} + time docker run \ --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \ --workdir=/abseil-cpp \ @@ -28,5 +31,5 @@ time docker run \ --rm \ -e CFLAGS="-Werror" \ -e CXXFLAGS="-Werror" \ - gcr.io/google.com/absl-177019/linux_gcc-latest:20200106 \ + ${DOCKER_CONTAINER} \ /bin/bash CMake/install_test_project/test.sh $@ diff --git a/ci/linux_clang-latest_libcxx_asan_bazel.sh b/ci/linux_clang-latest_libcxx_asan_bazel.sh index 24efe3b7..03463e2e 100755 --- a/ci/linux_clang-latest_libcxx_asan_bazel.sh +++ b/ci/linux_clang-latest_libcxx_asan_bazel.sh @@ -36,7 +36,8 @@ if [ -z ${EXCEPTIONS_MODE:-} ]; then EXCEPTIONS_MODE="-fno-exceptions -fexceptions" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20200102" +source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh" +readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER} # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. @@ -50,6 +51,14 @@ if [ ${USE_BAZEL_CACHE:-0} -ne 0 ]; then BAZEL_EXTRA_ARGS="--remote_http_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}" fi +# Avoid depending on external sites like GitHub by checking --distdir for +# external dependencies first. +# https://docs.bazel.build/versions/master/guide.html#distdir +if [ -z ${KOKORO_GFILE_DIR:-} && -d "${KOKORO_GFILE_DIR}/distdir" ]; then + DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}" + BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" +fi + for std in ${STD}; do for compilation_mode in ${COMPILATION_MODE}; do for exceptions_mode in ${EXCEPTIONS_MODE}; do diff --git a/ci/linux_clang-latest_libcxx_bazel.sh b/ci/linux_clang-latest_libcxx_bazel.sh index 127e7bc7..050a98c9 100755 --- a/ci/linux_clang-latest_libcxx_bazel.sh +++ b/ci/linux_clang-latest_libcxx_bazel.sh @@ -36,7 +36,8 @@ if [ -z ${EXCEPTIONS_MODE:-} ]; then EXCEPTIONS_MODE="-fno-exceptions -fexceptions" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20200102" +source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh" +readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER} # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. @@ -50,6 +51,14 @@ if [ ${USE_BAZEL_CACHE:-0} -ne 0 ]; then BAZEL_EXTRA_ARGS="--remote_http_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}" fi +# Avoid depending on external sites like GitHub by checking --distdir for +# external dependencies first. +# https://docs.bazel.build/versions/master/guide.html#distdir +if [ -z ${KOKORO_GFILE_DIR:-} && -d "${KOKORO_GFILE_DIR}/distdir" ]; then + DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}" + BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" +fi + for std in ${STD}; do for compilation_mode in ${COMPILATION_MODE}; do for exceptions_mode in ${EXCEPTIONS_MODE}; do diff --git a/ci/linux_clang-latest_libcxx_tsan_bazel.sh b/ci/linux_clang-latest_libcxx_tsan_bazel.sh index 00257b36..2f5fb12d 100755 --- a/ci/linux_clang-latest_libcxx_tsan_bazel.sh +++ b/ci/linux_clang-latest_libcxx_tsan_bazel.sh @@ -36,7 +36,8 @@ if [ -z ${EXCEPTIONS_MODE:-} ]; then EXCEPTIONS_MODE="-fno-exceptions -fexceptions" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20200102" +source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh" +readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER} # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. @@ -50,6 +51,14 @@ if [ ${USE_BAZEL_CACHE:-0} -ne 0 ]; then BAZEL_EXTRA_ARGS="--remote_http_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}" fi +# Avoid depending on external sites like GitHub by checking --distdir for +# external dependencies first. +# https://docs.bazel.build/versions/master/guide.html#distdir +if [ -z ${KOKORO_GFILE_DIR:-} && -d "${KOKORO_GFILE_DIR}/distdir" ]; then + DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}" + BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" +fi + for std in ${STD}; do for compilation_mode in ${COMPILATION_MODE}; do for exceptions_mode in ${EXCEPTIONS_MODE}; do diff --git a/ci/linux_clang-latest_libstdcxx_bazel.sh b/ci/linux_clang-latest_libstdcxx_bazel.sh index 9fe71d37..087f59ba 100755 --- a/ci/linux_clang-latest_libstdcxx_bazel.sh +++ b/ci/linux_clang-latest_libstdcxx_bazel.sh @@ -36,7 +36,8 @@ if [ -z ${EXCEPTIONS_MODE:-} ]; then EXCEPTIONS_MODE="-fno-exceptions -fexceptions" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20200102" +source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh" +readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER} # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. @@ -50,6 +51,14 @@ if [ ${USE_BAZEL_CACHE:-0} -ne 0 ]; then BAZEL_EXTRA_ARGS="--remote_http_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}" fi +# Avoid depending on external sites like GitHub by checking --distdir for +# external dependencies first. +# https://docs.bazel.build/versions/master/guide.html#distdir +if [ -z ${KOKORO_GFILE_DIR:-} && -d "${KOKORO_GFILE_DIR}/distdir" ]; then + DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}" + BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" +fi + for std in ${STD}; do for compilation_mode in ${COMPILATION_MODE}; do for exceptions_mode in ${EXCEPTIONS_MODE}; do diff --git a/ci/linux_docker_containers.sh b/ci/linux_docker_containers.sh new file mode 100644 index 00000000..2e81a6a7 --- /dev/null +++ b/ci/linux_docker_containers.sh @@ -0,0 +1,21 @@ +# 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. + +# The file contains Docker container identifiers currently used by test scripts. +# Test scripts should source this file to get the identifiers. + +readonly LINUX_ALPINE_CONTAINER="gcr.io/google.com/absl-177019/alpine:20191016" +readonly LINUX_CLANG_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20200102" +readonly LINUX_GCC_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-latest:20200102" +readonly LINUX_GCC_49_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-4.9:20191018" diff --git a/ci/linux_gcc-4.9_libstdcxx_bazel.sh b/ci/linux_gcc-4.9_libstdcxx_bazel.sh index f8102cc0..622ea84b 100755 --- a/ci/linux_gcc-4.9_libstdcxx_bazel.sh +++ b/ci/linux_gcc-4.9_libstdcxx_bazel.sh @@ -36,7 +36,8 @@ if [ -z ${EXCEPTIONS_MODE:-} ]; then EXCEPTIONS_MODE="-fno-exceptions -fexceptions" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-4.9:20191018" +source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh" +readonly DOCKER_CONTAINER=${LINUX_GCC_49_CONTAINER} # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. @@ -50,6 +51,14 @@ if [ ${USE_BAZEL_CACHE:-0} -ne 0 ]; then BAZEL_EXTRA_ARGS="--remote_http_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}" fi +# Avoid depending on external sites like GitHub by checking --distdir for +# external dependencies first. +# https://docs.bazel.build/versions/master/guide.html#distdir +if [ -z ${KOKORO_GFILE_DIR:-} && -d "${KOKORO_GFILE_DIR}/distdir" ]; then + DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}" + BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" +fi + for std in ${STD}; do for compilation_mode in ${COMPILATION_MODE}; do for exceptions_mode in ${EXCEPTIONS_MODE}; do diff --git a/ci/linux_gcc-latest_libstdcxx_bazel.sh b/ci/linux_gcc-latest_libstdcxx_bazel.sh index 59647031..f7dbd199 100755 --- a/ci/linux_gcc-latest_libstdcxx_bazel.sh +++ b/ci/linux_gcc-latest_libstdcxx_bazel.sh @@ -36,7 +36,8 @@ if [ -z ${EXCEPTIONS_MODE:-} ]; then EXCEPTIONS_MODE="-fno-exceptions -fexceptions" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-latest:20200106" +source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh" +readonly DOCKER_CONTAINER=${LINUX_GCC_LATEST_CONTAINER} # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. @@ -50,6 +51,14 @@ if [ ${USE_BAZEL_CACHE:-0} -ne 0 ]; then BAZEL_EXTRA_ARGS="--remote_http_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}" fi +# Avoid depending on external sites like GitHub by checking --distdir for +# external dependencies first. +# https://docs.bazel.build/versions/master/guide.html#distdir +if [ -z ${KOKORO_GFILE_DIR:-} && -d "${KOKORO_GFILE_DIR}/distdir" ]; then + DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}" + BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" +fi + for std in ${STD}; do for compilation_mode in ${COMPILATION_MODE}; do for exceptions_mode in ${EXCEPTIONS_MODE}; do diff --git a/ci/linux_gcc-latest_libstdcxx_cmake.sh b/ci/linux_gcc-latest_libstdcxx_cmake.sh index 38ad99f7..b5015449 100755 --- a/ci/linux_gcc-latest_libstdcxx_cmake.sh +++ b/ci/linux_gcc-latest_libstdcxx_cmake.sh @@ -34,6 +34,9 @@ if [ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]; then ABSL_CMAKE_BUILD_TYPES="Debug Release" fi +source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh" +readonly DOCKER_CONTAINER=${LINUX_GCC_LATEST_CONTAINER} + for std in ${ABSL_CMAKE_CXX_STANDARDS}; do for compilation_mode in ${ABSL_CMAKE_BUILD_TYPES}; do echo "--------------------------------------------------------------------" @@ -47,7 +50,7 @@ for std in ${ABSL_CMAKE_CXX_STANDARDS}; do --rm \ -e CFLAGS="-Werror" \ -e CXXFLAGS="-Werror" \ - gcr.io/google.com/absl-177019/linux_gcc-latest:20200106 \ + ${DOCKER_CONTAINER} \ /bin/bash -c " cd /buildfs && \ cmake /abseil-cpp \ diff --git a/ci/linux_gcc_alpine_cmake.sh b/ci/linux_gcc_alpine_cmake.sh index 830a1360..4496f8d4 100755 --- a/ci/linux_gcc_alpine_cmake.sh +++ b/ci/linux_gcc_alpine_cmake.sh @@ -34,7 +34,8 @@ if [ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]; then ABSL_CMAKE_BUILD_TYPES="Debug Release" fi -readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/alpine:20191016" +source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh" +readonly DOCKER_CONTAINER=${LINUX_ALPINE_CONTAINER} for std in ${ABSL_CMAKE_CXX_STANDARDS}; do for compilation_mode in ${ABSL_CMAKE_BUILD_TYPES}; do -- cgit v1.2.3 From d43b7997c0ca0f3312a51d1057fb73cfe934703b Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Fri, 3 Apr 2020 13:24:29 -0700 Subject: Export of internal Abseil changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -- 7a9e8d95f795be037aa2dce4e44809ad0166aaec by Samuel Benzaquen : Make end() iterator be nullptr. This makes the creation of and comparison with end() smaller and faster. `find()!=end()` becomes leaner. PiperOrigin-RevId: 304681605 -- 8f3024979446b391b79b1b60ada7d00a504d6aa6 by Derek Mauro : Fix Bazel's distdir detection and prefer double brackets (bash recommendation) PiperOrigin-RevId: 304615725 -- f1d709cb4b2b3743d548b814dd19602fb057a5e6 by Abseil Team : Internal change PiperOrigin-RevId: 304570545 -- 2bbfa5bda52057e1938a96c286ad33ff64e535e0 by Gennadiy Rozental : Implement general storage case as aligned buffer. Aside from eliminating dynamic memory allocation for flag storage, we also saving 11 bytes per int flag, 15 bytes per double and string flag. PiperOrigin-RevId: 304511965 -- 9e1aed2a95d7d060f8b906fe8c67fc3ba537b521 by Derek Mauro : Use reserve to make a bad_alloc less likely in endian_test This happened once and shouldn't have happened, so it was probably just a flake, but might as well make this change. PiperOrigin-RevId: 304505572 -- c2faf22ba2d4d66753390e6959494214895581f0 by Gennadiy Rozental : Use anonymous bit fields to enforce separation between const and mutable bit fields. We also move init_control field (which is now safe) to save 8 bytes per flag (based on size_tester output) PiperOrigin-RevId: 304505215 -- 7ec51250a84bb03e826b3caad64431e91748186a by Krzysztof KosiÅ„ski : Change the buffer size in AppendNumberUnit to constexpr. PiperOrigin-RevId: 304492779 -- a6c8db1be4f421ea7b7c02f7a01b4f48bad61883 by Gennadiy Rozental : Add test cases for two word storage. Some additional tests were added for other storage kinds as well. These came about after I started to look into a coverage output and noticed that some cases (like reading flag values via reflection) were not covered by this test at all. It does not make sense to just add tests for two word values, so I've covered other storage kinds as well. PiperOrigin-RevId: 304432511 -- 2644ecc32e1215cd6451efcb2f1054fd77e7c812 by Abseil Team : Internal change PiperOrigin-RevId: 304254681 -- 4949a6b20c2bb4b9b2c811f439ccb893abc08df5 by Abseil Team : Internal change PiperOrigin-RevId: 304250274 GitOrigin-RevId: 7a9e8d95f795be037aa2dce4e44809ad0166aaec Change-Id: I01623de87355bec5cf87cc5932a1ca44cade9aae --- absl/algorithm/BUILD.bazel | 4 +- absl/base/internal/endian_test.cc | 6 +- absl/base/optimization.h | 34 ++++++ absl/container/internal/raw_hash_set.h | 24 ++-- absl/flags/BUILD.bazel | 2 + absl/flags/CMakeLists.txt | 1 + absl/flags/flag.h | 6 +- absl/flags/flag_test.cc | 173 ++++++++++++++++++++++++---- absl/flags/internal/flag.cc | 73 +++++++----- absl/flags/internal/flag.h | 103 ++++++++--------- absl/random/internal/iostream_state_saver.h | 4 +- absl/random/internal/nanobenchmark_test.cc | 2 +- absl/random/internal/wide_multiply.h | 10 +- absl/time/duration.cc | 6 +- ci/cmake_install_test.sh | 2 +- ci/linux_clang-latest_libcxx_asan_bazel.sh | 12 +- ci/linux_clang-latest_libcxx_bazel.sh | 12 +- ci/linux_clang-latest_libcxx_tsan_bazel.sh | 12 +- ci/linux_clang-latest_libstdcxx_bazel.sh | 12 +- ci/linux_gcc-4.9_libstdcxx_bazel.sh | 12 +- ci/linux_gcc-latest_libstdcxx_bazel.sh | 14 +-- ci/linux_gcc-latest_libstdcxx_cmake.sh | 6 +- ci/linux_gcc_alpine_cmake.sh | 6 +- ci/macos_xcode_bazel.sh | 6 +- ci/macos_xcode_cmake.sh | 4 +- 25 files changed, 362 insertions(+), 184 deletions(-) (limited to 'ci/linux_clang-latest_libcxx_tsan_bazel.sh') diff --git a/absl/algorithm/BUILD.bazel b/absl/algorithm/BUILD.bazel index 6a96420b..229cd713 100644 --- a/absl/algorithm/BUILD.bazel +++ b/absl/algorithm/BUILD.bazel @@ -31,7 +31,9 @@ cc_library( hdrs = ["algorithm.h"], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, - deps = ["//absl/base:config"], + deps = [ + "//absl/base:config", + ], ) cc_test( diff --git a/absl/base/internal/endian_test.cc b/absl/base/internal/endian_test.cc index aa6b8496..678a0bf7 100644 --- a/absl/base/internal/endian_test.cc +++ b/absl/base/internal/endian_test.cc @@ -57,6 +57,7 @@ const uint16_t k16ValueBE{0x2301}; template std::vector GenerateAllValuesForType() { std::vector result; + result.reserve(size_t{1} << (sizeof(T) * 8)); T next = std::numeric_limits::min(); while (true) { result.push_back(next); @@ -68,10 +69,11 @@ std::vector GenerateAllValuesForType() { } template -std::vector GenerateRandomIntegers(size_t numValuesToTest) { +std::vector GenerateRandomIntegers(size_t num_values_to_test) { std::vector result; + result.reserve(num_values_to_test); std::mt19937_64 rng(kRandomSeed); - for (size_t i = 0; i < numValuesToTest; ++i) { + for (size_t i = 0; i < num_values_to_test; ++i) { result.push_back(rng()); } return result; diff --git a/absl/base/optimization.h b/absl/base/optimization.h index 646523b3..1541d7a8 100644 --- a/absl/base/optimization.h +++ b/absl/base/optimization.h @@ -178,4 +178,38 @@ #define ABSL_PREDICT_TRUE(x) (x) #endif +// ABSL_INTERNAL_ASSUME(cond) +// Informs the compiler than a condition is always true and that it can assume +// it to be true for optimization purposes. The call has undefined behavior if +// the condition is false. +// In !NDEBUG mode, the condition is checked with an assert(). +// NOTE: The expression must not have side effects, as it will only be evaluated +// in some compilation modes and not others. +// +// Example: +// +// int x = ...; +// ABSL_INTERNAL_ASSUME(x >= 0); +// // The compiler can optimize the division to a simple right shift using the +// // assumption specified above. +// int y = x / 16; +// +#if !defined(NDEBUG) +#define ABSL_INTERNAL_ASSUME(cond) assert(cond) +#elif ABSL_HAVE_BUILTIN(__builtin_assume) +#define ABSL_INTERNAL_ASSUME(cond) __builtin_assume(cond) +#elif defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable) +#define ABSL_INTERNAL_ASSUME(cond) \ + do { \ + if (!(cond)) __builtin_unreachable(); \ + } while (0) +#elif defined(_MSC_VER) +#define ABSL_INTERNAL_ASSUME(cond) __assume(cond) +#else +#define ABSL_INTERNAL_ASSUME(cond) \ + do { \ + static_cast(false && (cond)); \ + } while (0) +#endif + #endif // ABSL_BASE_OPTIMIZATION_H_ diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h index e47e1fed..df0f2b2b 100644 --- a/absl/container/internal/raw_hash_set.h +++ b/absl/container/internal/raw_hash_set.h @@ -104,7 +104,7 @@ #include "absl/base/internal/bits.h" #include "absl/base/internal/endian.h" -#include "absl/base/macros.h" +#include "absl/base/optimization.h" #include "absl/base/port.h" #include "absl/container/internal/common.h" #include "absl/container/internal/compressed_tuple.h" @@ -649,24 +649,26 @@ class raw_hash_set { } private: - iterator(ctrl_t* ctrl) : ctrl_(ctrl) {} // for end() - iterator(ctrl_t* ctrl, slot_type* slot) : ctrl_(ctrl), slot_(slot) {} + iterator(ctrl_t* ctrl, slot_type* slot) : ctrl_(ctrl), slot_(slot) { + // This assumption helps the compiler know that any non-end iterator is + // not equal to any end iterator. + ABSL_INTERNAL_ASSUME(ctrl != nullptr); + } - void assert_is_full() const { ABSL_HARDENING_ASSERT(IsFull(*ctrl_)); } + void assert_is_full() const { + ABSL_HARDENING_ASSERT(ctrl_ != nullptr && IsFull(*ctrl_)); + } void assert_is_valid() const { - ABSL_HARDENING_ASSERT(!ctrl_ || IsFull(*ctrl_) || *ctrl_ == kSentinel); + ABSL_HARDENING_ASSERT(ctrl_ == nullptr || IsFull(*ctrl_)); } void skip_empty_or_deleted() { while (IsEmptyOrDeleted(*ctrl_)) { - // ctrl is not necessarily aligned to Group::kWidth. It is also likely - // to read past the space for ctrl bytes and into slots. This is ok - // because ctrl has sizeof() == 1 and slot has sizeof() >= 1 so there - // is no way to read outside the combined slot array. uint32_t shift = Group{ctrl_}.CountLeadingEmptyOrDeleted(); ctrl_ += shift; slot_ += shift; } + if (ABSL_PREDICT_FALSE(*ctrl_ == kSentinel)) ctrl_ = nullptr; } ctrl_t* ctrl_ = nullptr; @@ -908,12 +910,12 @@ class raw_hash_set { it.skip_empty_or_deleted(); return it; } - iterator end() { return {ctrl_ + capacity_}; } + iterator end() { return {}; } const_iterator begin() const { return const_cast(this)->begin(); } - const_iterator end() const { return const_cast(this)->end(); } + const_iterator end() const { return {}; } const_iterator cbegin() const { return begin(); } const_iterator cend() const { return end(); } diff --git a/absl/flags/BUILD.bazel b/absl/flags/BUILD.bazel index 4b51d9d4..685e3954 100644 --- a/absl/flags/BUILD.bazel +++ b/absl/flags/BUILD.bazel @@ -326,7 +326,9 @@ cc_test( ":handle", ":registry", "//absl/base:core_headers", + "//absl/base:malloc_internal", "//absl/strings", + "//absl/time", "@com_google_googletest//:gtest_main", ], ) diff --git a/absl/flags/CMakeLists.txt b/absl/flags/CMakeLists.txt index 2204b0ff..ec82ee1e 100644 --- a/absl/flags/CMakeLists.txt +++ b/absl/flags/CMakeLists.txt @@ -304,6 +304,7 @@ absl_cc_test( absl::flags_internal absl::flags_registry absl::strings + absl::time gtest_main ) diff --git a/absl/flags/flag.h b/absl/flags/flag.h index 4cc8ae37..15061592 100644 --- a/absl/flags/flag.h +++ b/absl/flags/flag.h @@ -314,9 +314,9 @@ ABSL_NAMESPACE_END static std::string NonConst() { return ABSL_FLAG_IMPL_FLAGHELP(txt); } \ } -#define ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value) \ - static void* AbslFlagsInitFlag##name() { \ - return absl::flags_internal::MakeFromDefaultValue(default_value); \ +#define ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value) \ + static void AbslFlagsInitFlag##name(void* dst) { \ + absl::flags_internal::MakeFromDefaultValue(dst, default_value); \ } // ABSL_FLAG_IMPL diff --git a/absl/flags/flag_test.cc b/absl/flags/flag_test.cc index 377e3b2b..dbe94a2c 100644 --- a/absl/flags/flag_test.cc +++ b/absl/flags/flag_test.cc @@ -19,6 +19,7 @@ #include #include +#include // NOLINT #include #include "gtest/gtest.h" @@ -34,6 +35,7 @@ #include "absl/strings/str_cat.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" +#include "absl/time/time.h" ABSL_DECLARE_FLAG(int64_t, mistyped_int_flag); ABSL_DECLARE_FLAG(std::vector, mistyped_string_flag); @@ -44,8 +46,8 @@ namespace flags = absl::flags_internal; std::string TestHelpMsg() { return "dynamic help"; } template -void* TestMakeDflt() { - return new T{}; +void TestMakeDflt(void* dst) { + new (dst) T{}; } void TestCallback() {} @@ -74,6 +76,7 @@ class FlagTest : public testing::Test { #endif return std::string(fname); } + flags::FlagSaver flag_saver_; }; struct S1 { @@ -107,15 +110,15 @@ TEST_F(FlagTest, Traits) { flags::FlagValueStorageKind::kTwoWordsAtomic); #else EXPECT_EQ(flags::StorageKind(), - flags::FlagValueStorageKind::kHeapAllocated); + flags::FlagValueStorageKind::kAlignedBuffer); EXPECT_EQ(flags::StorageKind(), - flags::FlagValueStorageKind::kHeapAllocated); + flags::FlagValueStorageKind::kAlignedBuffer); #endif EXPECT_EQ(flags::StorageKind(), - flags::FlagValueStorageKind::kHeapAllocated); + flags::FlagValueStorageKind::kAlignedBuffer); EXPECT_EQ(flags::StorageKind>(), - flags::FlagValueStorageKind::kHeapAllocated); + flags::FlagValueStorageKind::kAlignedBuffer); } // -------------------------------------------------------------------- @@ -190,6 +193,7 @@ ABSL_DECLARE_FLAG(uint64_t, test_flag_08); ABSL_DECLARE_FLAG(double, test_flag_09); ABSL_DECLARE_FLAG(float, test_flag_10); ABSL_DECLARE_FLAG(std::string, test_flag_11); +ABSL_DECLARE_FLAG(absl::Duration, test_flag_12); namespace { @@ -208,6 +212,7 @@ TEST_F(FlagTest, TestFlagDeclaration) { EXPECT_EQ(FLAGS_test_flag_09.Name(), "test_flag_09"); EXPECT_EQ(FLAGS_test_flag_10.Name(), "test_flag_10"); EXPECT_EQ(FLAGS_test_flag_11.Name(), "test_flag_11"); + EXPECT_EQ(FLAGS_test_flag_12.Name(), "test_flag_12"); } #endif // !ABSL_FLAGS_STRIP_NAMES @@ -226,6 +231,7 @@ ABSL_FLAG(uint64_t, test_flag_08, 9876543, "test flag 08"); ABSL_FLAG(double, test_flag_09, -9.876e-50, "test flag 09"); ABSL_FLAG(float, test_flag_10, 1.234e12f, "test flag 10"); ABSL_FLAG(std::string, test_flag_11, "", "test flag 11"); +ABSL_FLAG(absl::Duration, test_flag_12, absl::Minutes(10), "test flag 12"); namespace { @@ -287,6 +293,11 @@ TEST_F(FlagTest, TestFlagDefinition) { EXPECT_EQ(FLAGS_test_flag_11.Help(), "test flag 11"); EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_11.Filename(), expected_file_name)) << FLAGS_test_flag_11.Filename(); + + EXPECT_EQ(FLAGS_test_flag_12.Name(), "test_flag_12"); + EXPECT_EQ(FLAGS_test_flag_12.Help(), "test flag 12"); + EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_12.Filename(), expected_file_name)) + << FLAGS_test_flag_12.Filename(); } #endif // !ABSL_FLAGS_STRIP_NAMES @@ -304,6 +315,20 @@ TEST_F(FlagTest, TestDefault) { EXPECT_EQ(FLAGS_test_flag_09.DefaultValue(), "-9.876e-50"); EXPECT_EQ(FLAGS_test_flag_10.DefaultValue(), "1.234e+12"); EXPECT_EQ(FLAGS_test_flag_11.DefaultValue(), ""); + EXPECT_EQ(FLAGS_test_flag_12.DefaultValue(), "10m"); + + EXPECT_EQ(FLAGS_test_flag_01.CurrentValue(), "true"); + EXPECT_EQ(FLAGS_test_flag_02.CurrentValue(), "1234"); + EXPECT_EQ(FLAGS_test_flag_03.CurrentValue(), "-34"); + EXPECT_EQ(FLAGS_test_flag_04.CurrentValue(), "189"); + EXPECT_EQ(FLAGS_test_flag_05.CurrentValue(), "10765"); + EXPECT_EQ(FLAGS_test_flag_06.CurrentValue(), "40000"); + EXPECT_EQ(FLAGS_test_flag_07.CurrentValue(), "-1234567"); + EXPECT_EQ(FLAGS_test_flag_08.CurrentValue(), "9876543"); + EXPECT_EQ(FLAGS_test_flag_09.CurrentValue(), "-9.876e-50"); + EXPECT_EQ(FLAGS_test_flag_10.CurrentValue(), "1.234e+12"); + EXPECT_EQ(FLAGS_test_flag_11.CurrentValue(), ""); + EXPECT_EQ(FLAGS_test_flag_12.CurrentValue(), "10m"); EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true); EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234); @@ -316,6 +341,7 @@ TEST_F(FlagTest, TestDefault) { EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), -9.876e-50, 1e-55); EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), 1.234e12f, 1e5f); EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), ""); + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Minutes(10)); } // -------------------------------------------------------------------- @@ -408,6 +434,38 @@ TEST_F(FlagTest, TestGetSet) { absl::SetFlag(&FLAGS_test_flag_11, "asdf"); EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "asdf"); + + absl::SetFlag(&FLAGS_test_flag_12, absl::Seconds(110)); + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Seconds(110)); +} + +// -------------------------------------------------------------------- + +TEST_F(FlagTest, TestGetViaReflection) { + auto* handle = flags::FindCommandLineFlag("test_flag_01"); + EXPECT_EQ(*handle->Get(), true); + handle = flags::FindCommandLineFlag("test_flag_02"); + EXPECT_EQ(*handle->Get(), 1234); + handle = flags::FindCommandLineFlag("test_flag_03"); + EXPECT_EQ(*handle->Get(), -34); + handle = flags::FindCommandLineFlag("test_flag_04"); + EXPECT_EQ(*handle->Get(), 189); + handle = flags::FindCommandLineFlag("test_flag_05"); + EXPECT_EQ(*handle->Get(), 10765); + handle = flags::FindCommandLineFlag("test_flag_06"); + EXPECT_EQ(*handle->Get(), 40000); + handle = flags::FindCommandLineFlag("test_flag_07"); + EXPECT_EQ(*handle->Get(), -1234567); + handle = flags::FindCommandLineFlag("test_flag_08"); + EXPECT_EQ(*handle->Get(), 9876543); + handle = flags::FindCommandLineFlag("test_flag_09"); + EXPECT_NEAR(*handle->Get(), -9.876e-50, 1e-55); + handle = flags::FindCommandLineFlag("test_flag_10"); + EXPECT_NEAR(*handle->Get(), 1.234e12f, 1e5f); + handle = flags::FindCommandLineFlag("test_flag_11"); + EXPECT_EQ(*handle->Get(), ""); + handle = flags::FindCommandLineFlag("test_flag_12"); + EXPECT_EQ(*handle->Get(), absl::Minutes(10)); } // -------------------------------------------------------------------- @@ -416,28 +474,32 @@ int GetDflt1() { return 1; } } // namespace -ABSL_FLAG(int, test_flag_12, GetDflt1(), "test flag 12"); -ABSL_FLAG(std::string, test_flag_13, absl::StrCat("AAA", "BBB"), - "test flag 13"); +ABSL_FLAG(int, test_int_flag_with_non_const_default, GetDflt1(), + "test int flag non const default"); +ABSL_FLAG(std::string, test_string_flag_with_non_const_default, + absl::StrCat("AAA", "BBB"), "test string flag non const default"); namespace { TEST_F(FlagTest, TestNonConstexprDefault) { - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), 1); - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_13), "AAABBB"); + EXPECT_EQ(absl::GetFlag(FLAGS_test_int_flag_with_non_const_default), 1); + EXPECT_EQ(absl::GetFlag(FLAGS_test_string_flag_with_non_const_default), + "AAABBB"); } // -------------------------------------------------------------------- } // namespace -ABSL_FLAG(bool, test_flag_14, true, absl::StrCat("test ", "flag ", "14")); +ABSL_FLAG(bool, test_flag_with_non_const_help, true, + absl::StrCat("test ", "flag ", "non const help")); namespace { #if !ABSL_FLAGS_STRIP_HELP TEST_F(FlagTest, TestNonConstexprHelp) { - EXPECT_EQ(FLAGS_test_flag_14.Help(), "test flag 14"); + EXPECT_EQ(FLAGS_test_flag_with_non_const_help.Help(), + "test flag non const help"); } #endif //! ABSL_FLAGS_STRIP_HELP @@ -503,14 +565,14 @@ std::string AbslUnparseFlag(const CustomUDT& f) { } // namespace -ABSL_FLAG(CustomUDT, test_flag_15, CustomUDT(), "test flag 15"); +ABSL_FLAG(CustomUDT, test_flag_custom_udt, CustomUDT(), "test flag custom UDT"); namespace { TEST_F(FlagTest, TestCustomUDT) { - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_15), CustomUDT(1, 1)); - absl::SetFlag(&FLAGS_test_flag_15, CustomUDT(2, 3)); - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_15), CustomUDT(2, 3)); + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_custom_udt), CustomUDT(1, 1)); + absl::SetFlag(&FLAGS_test_flag_custom_udt, CustomUDT(2, 3)); + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_custom_udt), CustomUDT(2, 3)); } // MSVC produces link error on the type mismatch. @@ -570,16 +632,17 @@ std::string AbslUnparseFlag(const ConversionTestVal& val) { // Flag default values can be specified with a value that converts to the flag // value type implicitly. -ABSL_FLAG(ConversionTestVal, test_flag_16, - ConversionTestVal::ViaImplicitConv::kTen, "test flag 16"); +ABSL_FLAG(ConversionTestVal, test_flag_implicit_conv, + ConversionTestVal::ViaImplicitConv::kTen, + "test flag init via implicit conversion"); namespace { TEST_F(FlagTest, CanSetViaImplicitConversion) { - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_16).a, 10); - absl::SetFlag(&FLAGS_test_flag_16, + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_implicit_conv).a, 10); + absl::SetFlag(&FLAGS_test_flag_implicit_conv, ConversionTestVal::ViaImplicitConv::kEleven); - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_16).a, 11); + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_implicit_conv).a, 11); } // -------------------------------------------------------------------- @@ -646,3 +709,69 @@ TEST_F(FlagTest, TestRetiredFlagRegistration) { } } // namespace + +// -------------------------------------------------------------------- + +namespace { + +// User-defined type with small alignment, but size exceeding 16. +struct SmallAlignUDT { + SmallAlignUDT() : c('A'), s(12) {} + char c; + int16_t s; + char bytes[14]; +}; + +bool AbslParseFlag(absl::string_view, SmallAlignUDT*, std::string*) { + return true; +} +std::string AbslUnparseFlag(const SmallAlignUDT&) { return ""; } + +// User-defined type with small size, but not trivially copyable. +struct NonTriviallyCopyableUDT { + NonTriviallyCopyableUDT() : c('A') {} + NonTriviallyCopyableUDT(const NonTriviallyCopyableUDT& rhs) : c(rhs.c) {} + NonTriviallyCopyableUDT& operator=(const NonTriviallyCopyableUDT& rhs) { + c = rhs.c; + return *this; + } + + char c; +}; + +bool AbslParseFlag(absl::string_view, NonTriviallyCopyableUDT*, std::string*) { + return true; +} +std::string AbslUnparseFlag(const NonTriviallyCopyableUDT&) { return ""; } + +} // namespace + +ABSL_FLAG(SmallAlignUDT, test_flag_sa_udt, {}, "help"); +ABSL_FLAG(NonTriviallyCopyableUDT, test_flag_ntc_udt, {}, "help"); + +namespace { + +TEST_F(FlagTest, TestSmallAlignUDT) { + SmallAlignUDT value = absl::GetFlag(FLAGS_test_flag_sa_udt); + EXPECT_EQ(value.c, 'A'); + EXPECT_EQ(value.s, 12); + + value.c = 'B'; + value.s = 45; + absl::SetFlag(&FLAGS_test_flag_sa_udt, value); + value = absl::GetFlag(FLAGS_test_flag_sa_udt); + EXPECT_EQ(value.c, 'B'); + EXPECT_EQ(value.s, 45); +} + +TEST_F(FlagTest, TestNonTriviallyCopyableUDT) { + NonTriviallyCopyableUDT value = absl::GetFlag(FLAGS_test_flag_ntc_udt); + EXPECT_EQ(value.c, 'A'); + + value.c = 'B'; + absl::SetFlag(&FLAGS_test_flag_ntc_udt, value); + value = absl::GetFlag(FLAGS_test_flag_ntc_udt); + EXPECT_EQ(value.c, 'B'); +} + +} // namespace diff --git a/absl/flags/internal/flag.cc b/absl/flags/internal/flag.cc index f3c424ad..089567f7 100644 --- a/absl/flags/internal/flag.cc +++ b/absl/flags/internal/flag.cc @@ -92,9 +92,9 @@ class FlagState : public flags_internal::FlagStateInterface { counter_(counter) {} ~FlagState() override { - if (flag_impl_->ValueStorageKind() != FlagValueStorageKind::kHeapAllocated) + if (flag_impl_->ValueStorageKind() != FlagValueStorageKind::kAlignedBuffer) return; - flags_internal::Delete(flag_impl_->op_, value_.dynamic); + flags_internal::Delete(flag_impl_->op_, value_.heap_allocated); } private: @@ -112,11 +112,11 @@ class FlagState : public flags_internal::FlagStateInterface { // Flag and saved flag data. FlagImpl* flag_impl_; union SavedValue { - explicit SavedValue(void* v) : dynamic(v) {} + explicit SavedValue(void* v) : heap_allocated(v) {} explicit SavedValue(int64_t v) : one_word(v) {} explicit SavedValue(flags_internal::AlignedTwoWords v) : two_words(v) {} - void* dynamic; + void* heap_allocated; int64_t one_word; flags_internal::AlignedTwoWords two_words; } value_; @@ -128,25 +128,33 @@ class FlagState : public flags_internal::FlagStateInterface { /////////////////////////////////////////////////////////////////////////////// // Flag implementation, which does not depend on flag value type. +DynValueDeleter::DynValueDeleter(FlagOpFn op_arg) : op(op_arg) {} + +void DynValueDeleter::operator()(void* ptr) const { + if (op == nullptr) return; + + Delete(op, ptr); +} + void FlagImpl::Init() { new (&data_guard_) absl::Mutex; // At this point the default_value_ always points to gen_func. - std::unique_ptr init_value( - (*default_value_.gen_func)(), DynValueDeleter{op_}); switch (ValueStorageKind()) { - case FlagValueStorageKind::kHeapAllocated: - HeapAllocatedValue() = init_value.release(); + case FlagValueStorageKind::kAlignedBuffer: + (*default_value_.gen_func)(AlignedBufferValue()); break; case FlagValueStorageKind::kOneWordAtomic: { - int64_t atomic_value; - std::memcpy(&atomic_value, init_value.get(), Sizeof(op_)); - OneWordValue().store(atomic_value, std::memory_order_release); + alignas(int64_t) std::array buf{}; + (*default_value_.gen_func)(buf.data()); + auto value = absl::bit_cast(buf); + OneWordValue().store(value, std::memory_order_release); break; } case FlagValueStorageKind::kTwoWordsAtomic: { - AlignedTwoWords atomic_value{0, 0}; - std::memcpy(&atomic_value, init_value.get(), Sizeof(op_)); + alignas(AlignedTwoWords) std::array buf{}; + (*default_value_.gen_func)(buf.data()); + auto atomic_value = absl::bit_cast(buf); TwoWordsValue().store(atomic_value, std::memory_order_release); break; } @@ -191,15 +199,16 @@ std::unique_ptr FlagImpl::MakeInitValue() const { if (DefaultKind() == FlagDefaultKind::kDynamicValue) { res = flags_internal::Clone(op_, default_value_.dynamic_value); } else { - res = (*default_value_.gen_func)(); + res = flags_internal::Alloc(op_); + (*default_value_.gen_func)(res); } return {res, DynValueDeleter{op_}}; } void FlagImpl::StoreValue(const void* src) { switch (ValueStorageKind()) { - case FlagValueStorageKind::kHeapAllocated: - Copy(op_, src, HeapAllocatedValue()); + case FlagValueStorageKind::kAlignedBuffer: + Copy(op_, src, AlignedBufferValue()); break; case FlagValueStorageKind::kOneWordAtomic: { int64_t one_word_val = 0; @@ -257,9 +266,9 @@ std::string FlagImpl::DefaultValue() const { std::string FlagImpl::CurrentValue() const { auto* guard = DataGuard(); // Make sure flag initialized switch (ValueStorageKind()) { - case FlagValueStorageKind::kHeapAllocated: { + case FlagValueStorageKind::kAlignedBuffer: { absl::MutexLock l(guard); - return flags_internal::Unparse(op_, HeapAllocatedValue()); + return flags_internal::Unparse(op_, AlignedBufferValue()); } case FlagValueStorageKind::kOneWordAtomic: { const auto one_word_val = @@ -318,9 +327,9 @@ std::unique_ptr FlagImpl::SaveState() { bool modified = modified_; bool on_command_line = on_command_line_; switch (ValueStorageKind()) { - case FlagValueStorageKind::kHeapAllocated: { + case FlagValueStorageKind::kAlignedBuffer: { return absl::make_unique( - this, flags_internal::Clone(op_, HeapAllocatedValue()), modified, + this, flags_internal::Clone(op_, AlignedBufferValue()), modified, on_command_line, counter_); } case FlagValueStorageKind::kOneWordAtomic: { @@ -345,8 +354,8 @@ bool FlagImpl::RestoreState(const FlagState& flag_state) { } switch (ValueStorageKind()) { - case FlagValueStorageKind::kHeapAllocated: - StoreValue(flag_state.value_.dynamic); + case FlagValueStorageKind::kAlignedBuffer: + StoreValue(flag_state.value_.heap_allocated); break; case FlagValueStorageKind::kOneWordAtomic: StoreValue(&flag_state.value_.one_word); @@ -363,25 +372,27 @@ bool FlagImpl::RestoreState(const FlagState& flag_state) { } template -typename StorageT::value_type& FlagImpl::OffsetValue() const { +StorageT* FlagImpl::OffsetValue() const { char* p = reinterpret_cast(const_cast(this)); // The offset is deduced via Flag value type specific op_. size_t offset = flags_internal::ValueOffset(op_); - return reinterpret_cast(p + offset)->value; + return reinterpret_cast(p + offset); } -void*& FlagImpl::HeapAllocatedValue() const { - assert(ValueStorageKind() == FlagValueStorageKind::kHeapAllocated); - return OffsetValue(); +void* FlagImpl::AlignedBufferValue() const { + assert(ValueStorageKind() == FlagValueStorageKind::kAlignedBuffer); + return OffsetValue(); } + std::atomic& FlagImpl::OneWordValue() const { assert(ValueStorageKind() == FlagValueStorageKind::kOneWordAtomic); - return OffsetValue(); + return OffsetValue()->value; } + std::atomic& FlagImpl::TwoWordsValue() const { assert(ValueStorageKind() == FlagValueStorageKind::kTwoWordsAtomic); - return OffsetValue(); + return OffsetValue()->value; } // Attempts to parse supplied `value` string using parsing routine in the `flag` @@ -406,9 +417,9 @@ std::unique_ptr FlagImpl::TryParse( void FlagImpl::Read(void* dst) const { auto* guard = DataGuard(); // Make sure flag initialized switch (ValueStorageKind()) { - case FlagValueStorageKind::kHeapAllocated: { + case FlagValueStorageKind::kAlignedBuffer: { absl::MutexLock l(guard); - flags_internal::CopyConstruct(op_, HeapAllocatedValue(), dst); + flags_internal::CopyConstruct(op_, AlignedBufferValue(), dst); break; } case FlagValueStorageKind::kOneWordAtomic: { diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h index ae42dedc..2ae3dce3 100644 --- a/absl/flags/internal/flag.h +++ b/absl/flags/internal/flag.h @@ -46,8 +46,8 @@ namespace flags_internal { // by function specific to that type with a signature matching FlagOpFn. enum class FlagOp { + kAlloc, kDelete, - kClone, kCopy, kCopyConstruct, kSizeof, @@ -63,13 +63,13 @@ using FlagOpFn = void* (*)(FlagOp, const void*, void*, void*); template void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3); -// Deletes memory interpreting obj as flag value type pointer. -inline void Delete(FlagOpFn op, const void* obj) { - op(FlagOp::kDelete, obj, nullptr, nullptr); +// Allocate aligned memory for a flag value. +inline void* Alloc(FlagOpFn op) { + return op(FlagOp::kAlloc, nullptr, nullptr, nullptr); } -// Makes a copy of flag value pointed by obj. -inline void* Clone(FlagOpFn op, const void* obj) { - return op(FlagOp::kClone, obj, nullptr, nullptr); +// Deletes memory interpreting obj as flag value type pointer. +inline void Delete(FlagOpFn op, void* obj) { + op(FlagOp::kDelete, nullptr, obj, nullptr); } // Copies src to dst interpreting as flag value type pointers. inline void Copy(FlagOpFn op, const void* src, void* dst) { @@ -80,6 +80,12 @@ inline void Copy(FlagOpFn op, const void* src, void* dst) { inline void CopyConstruct(FlagOpFn op, const void* src, void* dst) { op(FlagOp::kCopyConstruct, src, dst, nullptr); } +// Makes a copy of flag value pointed by obj. +inline void* Clone(FlagOpFn op, const void* obj) { + void* res = flags_internal::Alloc(op); + flags_internal::CopyConstruct(op, obj, res); + return res; +} // Returns true if parsing of input text is successfull. inline bool Parse(FlagOpFn op, absl::string_view text, void* dst, std::string* error) { @@ -195,7 +201,7 @@ constexpr FlagHelpArg HelpArg(char) { // Signature for the function generating the initial flag value (usually // based on default value supplied in flag's definition) -using FlagDfltGenFunc = void* (*)(); +using FlagDfltGenFunc = void (*)(void*); union FlagDefaultSrc { constexpr explicit FlagDefaultSrc(FlagDfltGenFunc gen_func_arg) @@ -253,46 +259,36 @@ using FlagUseTwoWordsStorage = #endif template -using FlagUseHeapStorage = +using FlagUseBufferStorage = std::integral_constant::value && !FlagUseTwoWordsStorage::value>; enum class FlagValueStorageKind : uint8_t { - kHeapAllocated = 0, + kAlignedBuffer = 0, kOneWordAtomic = 1, kTwoWordsAtomic = 2 }; template static constexpr FlagValueStorageKind StorageKind() { - return FlagUseHeapStorage::value - ? FlagValueStorageKind::kHeapAllocated + return FlagUseBufferStorage::value + ? FlagValueStorageKind::kAlignedBuffer : FlagUseOneWordStorage::value ? FlagValueStorageKind::kOneWordAtomic - : FlagUseTwoWordsStorage::value - ? FlagValueStorageKind::kTwoWordsAtomic - : FlagValueStorageKind::kHeapAllocated; + : FlagValueStorageKind::kTwoWordsAtomic; } -struct FlagHeapAllocatedValue { - using value_type = void*; - - value_type value; -}; - struct FlagOneWordValue { - using value_type = std::atomic; constexpr FlagOneWordValue() : value(UninitializedFlagValue()) {} - value_type value; + std::atomic value; }; struct FlagTwoWordsValue { - using value_type = std::atomic; constexpr FlagTwoWordsValue() : value(AlignedTwoWords{UninitializedFlagValue(), 0}) {} - value_type value; + std::atomic value; }; template -struct FlagValue - : FlagHeapAllocatedValue { +struct FlagValue { bool Get(T*) const { return false; } + + alignas(T) char value[sizeof(T)]; }; template @@ -347,10 +344,8 @@ struct FlagCallback { // The class encapsulates the Flag's data and access to it. struct DynValueDeleter { - explicit DynValueDeleter(FlagOpFn op_arg = nullptr) : op(op_arg) {} - void operator()(void* ptr) const { - if (op != nullptr) flags_internal::Delete(op, ptr); - } + explicit DynValueDeleter(FlagOpFn op_arg = nullptr); + void operator()(void* ptr) const; FlagOpFn op; }; @@ -416,10 +411,10 @@ class FlagImpl final : public flags_internal::CommandLineFlag { // it is only used inside the three routines below, which are defined in // flag.cc, we can define it in that file as well. template - typename StorageT::value_type& OffsetValue() const; - // This is an accessor for a value stored in heap allocated storage. - // Returns a mutable reference to a pointer to allow vlaue mutation. - void*& HeapAllocatedValue() const; + StorageT* OffsetValue() const; + // This is an accessor for a value stored in an aligned buffer storage. + // Returns a mutable pointer to the start of a buffer. + void* AlignedBufferValue() const; // This is an accessor for a value stored as one word atomic. Returns a // mutable reference to an atomic value. std::atomic& OneWordValue() const; @@ -492,17 +487,8 @@ class FlagImpl final : public flags_internal::CommandLineFlag { // Kind of storage this flag is using for the flag's value. const uint8_t value_storage_kind_ : 2; - // ------------------------------------------------------------------------ - // The bytes containing the const bitfields must not be shared with bytes - // containing the mutable bitfields. - // ------------------------------------------------------------------------ - - // Unique tag for absl::call_once call to initialize this flag. - // - // The placement of this variable between the immutable and mutable bitfields - // is important as prevents them from occupying the same byte. If you remove - // this variable, make sure to maintain this property. - absl::once_flag init_control_; + uint8_t : 0; // The bytes containing the const bitfields must not be + // shared with bytes containing the mutable bitfields. // Mutable flag's state (guarded by `data_guard_`). @@ -514,6 +500,9 @@ class FlagImpl final : public flags_internal::CommandLineFlag { // Has this flag been specified on command line. bool on_command_line_ : 1 ABSL_GUARDED_BY(*DataGuard()); + // Unique tag for absl::call_once call to initialize this flag. + absl::once_flag init_control_; + // Mutation counter int64_t counter_ ABSL_GUARDED_BY(*DataGuard()); // Optional flag's callback and absl::Mutex to guard the invocations. @@ -600,11 +589,17 @@ class Flag { template void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3) { switch (op) { - case FlagOp::kDelete: - delete static_cast(v1); + case FlagOp::kAlloc: { + std::allocator alloc; + return std::allocator_traits>::allocate(alloc, 1); + } + case FlagOp::kDelete: { + T* p = static_cast(v2); + p->~T(); + std::allocator alloc; + std::allocator_traits>::deallocate(alloc, p, 1); return nullptr; - case FlagOp::kClone: - return new T(*static_cast(v1)); + } case FlagOp::kCopy: *static_cast(v2) = *static_cast(v1); return nullptr; @@ -675,13 +670,13 @@ class FlagRegistrar { struct EmptyBraces {}; template -T* MakeFromDefaultValue(T t) { - return new T(std::move(t)); +void MakeFromDefaultValue(void* dst, T t) { + new (dst) T(std::move(t)); } template -T* MakeFromDefaultValue(EmptyBraces) { - return new T{}; +void MakeFromDefaultValue(void* dst, EmptyBraces) { + new (dst) T{}; } } // namespace flags_internal diff --git a/absl/random/internal/iostream_state_saver.h b/absl/random/internal/iostream_state_saver.h index 7378829a..e6e242ee 100644 --- a/absl/random/internal/iostream_state_saver.h +++ b/absl/random/internal/iostream_state_saver.h @@ -192,8 +192,8 @@ struct stream_u128_helper { template inline void write(absl::uint128 val, OStream& out) { - uint64_t h = Uint128High64(val); - uint64_t l = Uint128Low64(val); + uint64_t h = absl::Uint128High64(val); + uint64_t l = absl::Uint128Low64(val); out << h << out.fill() << l; } }; diff --git a/absl/random/internal/nanobenchmark_test.cc b/absl/random/internal/nanobenchmark_test.cc index ab824ef5..f1571e26 100644 --- a/absl/random/internal/nanobenchmark_test.cc +++ b/absl/random/internal/nanobenchmark_test.cc @@ -53,7 +53,7 @@ void RunAll(const int argc, char* argv[]) { // Avoid migrating between cores - important on multi-socket systems. int cpu = -1; if (argc == 2) { - if (!SimpleAtoi(argv[1], &cpu)) { + if (!absl::SimpleAtoi(argv[1], &cpu)) { ABSL_RAW_LOG(FATAL, "The optional argument must be a CPU number >= 0.\n"); } } diff --git a/absl/random/internal/wide_multiply.h b/absl/random/internal/wide_multiply.h index 6e4cf1be..0afcbe08 100644 --- a/absl/random/internal/wide_multiply.h +++ b/absl/random/internal/wide_multiply.h @@ -38,9 +38,9 @@ namespace random_internal { // MultiplyU64ToU128 multiplies two 64-bit values to a 128-bit value. // If an intrinsic is available, it is used, otherwise use native 32-bit // multiplies to construct the result. -inline uint128 MultiplyU64ToU128(uint64_t a, uint64_t b) { +inline absl::uint128 MultiplyU64ToU128(uint64_t a, uint64_t b) { #if defined(ABSL_HAVE_INTRINSIC_INT128) - return uint128(static_cast<__uint128_t>(a) * b); + return absl::uint128(static_cast<__uint128_t>(a) * b); #elif defined(ABSL_INTERNAL_USE_UMUL128) // uint64_t * uint64_t => uint128 multiply using imul intrinsic on MSVC. uint64_t high = 0; @@ -93,14 +93,14 @@ struct wide_multiply { template <> struct wide_multiply { using input_type = uint64_t; - using result_type = uint128; + using result_type = absl::uint128; static result_type multiply(uint64_t a, uint64_t b) { return MultiplyU64ToU128(a, b); } - static uint64_t hi(result_type r) { return Uint128High64(r); } - static uint64_t lo(result_type r) { return Uint128Low64(r); } + static uint64_t hi(result_type r) { return absl::Uint128High64(r); } + static uint64_t lo(result_type r) { return absl::Uint128Low64(r); } }; #endif diff --git a/absl/time/duration.cc b/absl/time/duration.cc index 1353fa0a..f0182559 100644 --- a/absl/time/duration.cc +++ b/absl/time/duration.cc @@ -732,9 +732,9 @@ void AppendNumberUnit(std::string* out, int64_t n, DisplayUnit unit) { // Note: unit.prec is limited to double's digits10 value (typically 15) so it // always fits in buf[]. void AppendNumberUnit(std::string* out, double n, DisplayUnit unit) { - const int buf_size = std::numeric_limits::digits10; - const int prec = std::min(buf_size, unit.prec); - char buf[buf_size]; // also large enough to hold integer part + constexpr int kBufferSize = std::numeric_limits::digits10; + const int prec = std::min(kBufferSize, unit.prec); + char buf[kBufferSize]; // also large enough to hold integer part char* ep = buf + sizeof(buf); double d = 0; int64_t frac_part = Round(std::modf(n, &d) * unit.pow10); diff --git a/ci/cmake_install_test.sh b/ci/cmake_install_test.sh index 4c748eb9..b31e4b8c 100755 --- a/ci/cmake_install_test.sh +++ b/ci/cmake_install_test.sh @@ -16,7 +16,7 @@ set -euox pipefail -if [ -z ${ABSEIL_ROOT:-} ]; then +if [[ -z ${ABSEIL_ROOT:-} ]]; then ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" fi diff --git a/ci/linux_clang-latest_libcxx_asan_bazel.sh b/ci/linux_clang-latest_libcxx_asan_bazel.sh index 03463e2e..88d2a97d 100755 --- a/ci/linux_clang-latest_libcxx_asan_bazel.sh +++ b/ci/linux_clang-latest_libcxx_asan_bazel.sh @@ -20,19 +20,19 @@ set -euox pipefail -if [ -z ${ABSEIL_ROOT:-} ]; then +if [[ -z ${ABSEIL_ROOT:-} ]]; then ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" fi -if [ -z ${STD:-} ]; then +if [[ -z ${STD:-} ]]; then STD="c++11 c++14 c++17" fi -if [ -z ${COMPILATION_MODE:-} ]; then +if [[ -z ${COMPILATION_MODE:-} ]]; then COMPILATION_MODE="fastbuild opt" fi -if [ -z ${EXCEPTIONS_MODE:-} ]; then +if [[ -z ${EXCEPTIONS_MODE:-} ]]; then EXCEPTIONS_MODE="-fno-exceptions -fexceptions" fi @@ -41,7 +41,7 @@ readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER} # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. -if [ ${USE_BAZEL_CACHE:-0} -ne 0 ]; then +if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}" # Bazel doesn't track changes to tools outside of the workspace # (e.g. /usr/bin/gcc), so by appending the docker container to the @@ -54,7 +54,7 @@ fi # Avoid depending on external sites like GitHub by checking --distdir for # external dependencies first. # https://docs.bazel.build/versions/master/guide.html#distdir -if [ -z ${KOKORO_GFILE_DIR:-} && -d "${KOKORO_GFILE_DIR}/distdir" ]; then +if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}" BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" fi diff --git a/ci/linux_clang-latest_libcxx_bazel.sh b/ci/linux_clang-latest_libcxx_bazel.sh index 050a98c9..f344a588 100755 --- a/ci/linux_clang-latest_libcxx_bazel.sh +++ b/ci/linux_clang-latest_libcxx_bazel.sh @@ -20,19 +20,19 @@ set -euox pipefail -if [ -z ${ABSEIL_ROOT:-} ]; then +if [[ -z ${ABSEIL_ROOT:-} ]]; then ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" fi -if [ -z ${STD:-} ]; then +if [[ -z ${STD:-} ]]; then STD="c++11 c++14 c++17" fi -if [ -z ${COMPILATION_MODE:-} ]; then +if [[ -z ${COMPILATION_MODE:-} ]]; then COMPILATION_MODE="fastbuild opt" fi -if [ -z ${EXCEPTIONS_MODE:-} ]; then +if [[ -z ${EXCEPTIONS_MODE:-} ]]; then EXCEPTIONS_MODE="-fno-exceptions -fexceptions" fi @@ -41,7 +41,7 @@ readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER} # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. -if [ ${USE_BAZEL_CACHE:-0} -ne 0 ]; then +if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}" # Bazel doesn't track changes to tools outside of the workspace # (e.g. /usr/bin/gcc), so by appending the docker container to the @@ -54,7 +54,7 @@ fi # Avoid depending on external sites like GitHub by checking --distdir for # external dependencies first. # https://docs.bazel.build/versions/master/guide.html#distdir -if [ -z ${KOKORO_GFILE_DIR:-} && -d "${KOKORO_GFILE_DIR}/distdir" ]; then +if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}" BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" fi diff --git a/ci/linux_clang-latest_libcxx_tsan_bazel.sh b/ci/linux_clang-latest_libcxx_tsan_bazel.sh index 2f5fb12d..f7238457 100755 --- a/ci/linux_clang-latest_libcxx_tsan_bazel.sh +++ b/ci/linux_clang-latest_libcxx_tsan_bazel.sh @@ -20,19 +20,19 @@ set -euox pipefail -if [ -z ${ABSEIL_ROOT:-} ]; then +if [[ -z ${ABSEIL_ROOT:-} ]]; then ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" fi -if [ -z ${STD:-} ]; then +if [[ -z ${STD:-} ]]; then STD="c++11 c++14 c++17" fi -if [ -z ${COMPILATION_MODE:-} ]; then +if [[ -z ${COMPILATION_MODE:-} ]]; then COMPILATION_MODE="fastbuild opt" fi -if [ -z ${EXCEPTIONS_MODE:-} ]; then +if [[ -z ${EXCEPTIONS_MODE:-} ]]; then EXCEPTIONS_MODE="-fno-exceptions -fexceptions" fi @@ -41,7 +41,7 @@ readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER} # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. -if [ ${USE_BAZEL_CACHE:-0} -ne 0 ]; then +if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}" # Bazel doesn't track changes to tools outside of the workspace # (e.g. /usr/bin/gcc), so by appending the docker container to the @@ -54,7 +54,7 @@ fi # Avoid depending on external sites like GitHub by checking --distdir for # external dependencies first. # https://docs.bazel.build/versions/master/guide.html#distdir -if [ -z ${KOKORO_GFILE_DIR:-} && -d "${KOKORO_GFILE_DIR}/distdir" ]; then +if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}" BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" fi diff --git a/ci/linux_clang-latest_libstdcxx_bazel.sh b/ci/linux_clang-latest_libstdcxx_bazel.sh index 087f59ba..62696293 100755 --- a/ci/linux_clang-latest_libstdcxx_bazel.sh +++ b/ci/linux_clang-latest_libstdcxx_bazel.sh @@ -20,19 +20,19 @@ set -euox pipefail -if [ -z ${ABSEIL_ROOT:-} ]; then +if [[ -z ${ABSEIL_ROOT:-} ]]; then ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" fi -if [ -z ${STD:-} ]; then +if [[ -z ${STD:-} ]]; then STD="c++11 c++14 c++17" fi -if [ -z ${COMPILATION_MODE:-} ]; then +if [[ -z ${COMPILATION_MODE:-} ]]; then COMPILATION_MODE="fastbuild opt" fi -if [ -z ${EXCEPTIONS_MODE:-} ]; then +if [[ -z ${EXCEPTIONS_MODE:-} ]]; then EXCEPTIONS_MODE="-fno-exceptions -fexceptions" fi @@ -41,7 +41,7 @@ readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER} # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. -if [ ${USE_BAZEL_CACHE:-0} -ne 0 ]; then +if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}" # Bazel doesn't track changes to tools outside of the workspace # (e.g. /usr/bin/gcc), so by appending the docker container to the @@ -54,7 +54,7 @@ fi # Avoid depending on external sites like GitHub by checking --distdir for # external dependencies first. # https://docs.bazel.build/versions/master/guide.html#distdir -if [ -z ${KOKORO_GFILE_DIR:-} && -d "${KOKORO_GFILE_DIR}/distdir" ]; then +if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}" BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" fi diff --git a/ci/linux_gcc-4.9_libstdcxx_bazel.sh b/ci/linux_gcc-4.9_libstdcxx_bazel.sh index 622ea84b..8e6540cf 100755 --- a/ci/linux_gcc-4.9_libstdcxx_bazel.sh +++ b/ci/linux_gcc-4.9_libstdcxx_bazel.sh @@ -20,19 +20,19 @@ set -euox pipefail -if [ -z ${ABSEIL_ROOT:-} ]; then +if [[ -z ${ABSEIL_ROOT:-} ]]; then ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" fi -if [ -z ${STD:-} ]; then +if [[ -z ${STD:-} ]]; then STD="c++11 c++14" fi -if [ -z ${COMPILATION_MODE:-} ]; then +if [[ -z ${COMPILATION_MODE:-} ]]; then COMPILATION_MODE="fastbuild opt" fi -if [ -z ${EXCEPTIONS_MODE:-} ]; then +if [[ -z ${EXCEPTIONS_MODE:-} ]]; then EXCEPTIONS_MODE="-fno-exceptions -fexceptions" fi @@ -41,7 +41,7 @@ readonly DOCKER_CONTAINER=${LINUX_GCC_49_CONTAINER} # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. -if [ ${USE_BAZEL_CACHE:-0} -ne 0 ]; then +if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}" # Bazel doesn't track changes to tools outside of the workspace # (e.g. /usr/bin/gcc), so by appending the docker container to the @@ -54,7 +54,7 @@ fi # Avoid depending on external sites like GitHub by checking --distdir for # external dependencies first. # https://docs.bazel.build/versions/master/guide.html#distdir -if [ -z ${KOKORO_GFILE_DIR:-} && -d "${KOKORO_GFILE_DIR}/distdir" ]; then +if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}" BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" fi diff --git a/ci/linux_gcc-latest_libstdcxx_bazel.sh b/ci/linux_gcc-latest_libstdcxx_bazel.sh index f7dbd199..337285b0 100755 --- a/ci/linux_gcc-latest_libstdcxx_bazel.sh +++ b/ci/linux_gcc-latest_libstdcxx_bazel.sh @@ -20,19 +20,19 @@ set -euox pipefail -if [ -z ${ABSEIL_ROOT:-} ]; then +if [[ -z ${ABSEIL_ROOT:-} ]]; then ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" fi -if [ -z ${STD:-} ]; then +if [[ -z ${STD:-} ]]; then STD="c++11 c++14 c++17" fi -if [ -z ${COMPILATION_MODE:-} ]; then +if [[ -z ${COMPILATION_MODE:-} ]]; then COMPILATION_MODE="fastbuild opt" fi -if [ -z ${EXCEPTIONS_MODE:-} ]; then +if [[ -z ${EXCEPTIONS_MODE:-} ]]; then EXCEPTIONS_MODE="-fno-exceptions -fexceptions" fi @@ -41,7 +41,7 @@ readonly DOCKER_CONTAINER=${LINUX_GCC_LATEST_CONTAINER} # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. -if [ ${USE_BAZEL_CACHE:-0} -ne 0 ]; then +if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}" # Bazel doesn't track changes to tools outside of the workspace # (e.g. /usr/bin/gcc), so by appending the docker container to the @@ -54,7 +54,7 @@ fi # Avoid depending on external sites like GitHub by checking --distdir for # external dependencies first. # https://docs.bazel.build/versions/master/guide.html#distdir -if [ -z ${KOKORO_GFILE_DIR:-} && -d "${KOKORO_GFILE_DIR}/distdir" ]; then +if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}" BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" fi @@ -75,7 +75,7 @@ for std in ${STD}; do ${DOCKER_CONTAINER} \ /bin/sh -c " cp -r /abseil-cpp-ro/* /abseil-cpp/ - if [ -n \"${ALTERNATE_OPTIONS:-}\" ]; then + if [[ -n \"${ALTERNATE_OPTIONS:-}\" ]]; then cp ${ALTERNATE_OPTIONS:-} absl/base/options.h || exit 1 fi /usr/local/bin/bazel test ... \ diff --git a/ci/linux_gcc-latest_libstdcxx_cmake.sh b/ci/linux_gcc-latest_libstdcxx_cmake.sh index b5015449..db5f6918 100755 --- a/ci/linux_gcc-latest_libstdcxx_cmake.sh +++ b/ci/linux_gcc-latest_libstdcxx_cmake.sh @@ -22,15 +22,15 @@ set -euox pipefail -if [ -z ${ABSEIL_ROOT:-} ]; then +if [[ -z ${ABSEIL_ROOT:-} ]]; then ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" fi -if [ -z ${ABSL_CMAKE_CXX_STANDARDS:-} ]; then +if [[ -z ${ABSL_CMAKE_CXX_STANDARDS:-} ]]; then ABSL_CMAKE_CXX_STANDARDS="11 14 17" fi -if [ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]; then +if [[ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]]; then ABSL_CMAKE_BUILD_TYPES="Debug Release" fi diff --git a/ci/linux_gcc_alpine_cmake.sh b/ci/linux_gcc_alpine_cmake.sh index 4496f8d4..f57ab12b 100755 --- a/ci/linux_gcc_alpine_cmake.sh +++ b/ci/linux_gcc_alpine_cmake.sh @@ -22,15 +22,15 @@ set -euox pipefail -if [ -z ${ABSEIL_ROOT:-} ]; then +if [[ -z ${ABSEIL_ROOT:-} ]]; then ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" fi -if [ -z ${ABSL_CMAKE_CXX_STANDARDS:-} ]; then +if [[ -z ${ABSL_CMAKE_CXX_STANDARDS:-} ]]; then ABSL_CMAKE_CXX_STANDARDS="11 14 17" fi -if [ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]; then +if [[ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]]; then ABSL_CMAKE_BUILD_TYPES="Debug Release" fi diff --git a/ci/macos_xcode_bazel.sh b/ci/macos_xcode_bazel.sh index f5f2d759..738adf94 100755 --- a/ci/macos_xcode_bazel.sh +++ b/ci/macos_xcode_bazel.sh @@ -19,13 +19,13 @@ set -euox pipefail -if [ -z ${ABSEIL_ROOT:-} ]; then +if [[ -z ${ABSEIL_ROOT:-} ]]; then ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" fi # If we are running on Kokoro, check for a versioned Bazel binary. KOKORO_GFILE_BAZEL_BIN="bazel-2.0.0-darwin-x86_64" -if [ ${KOKORO_GFILE_DIR:-} ] && [ -f ${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN} ]; then +if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f ${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN} ]]; then BAZEL_BIN="${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN}" chmod +x ${BAZEL_BIN} else @@ -41,7 +41,7 @@ echo "---------------" cd ${ABSEIL_ROOT} -if [ -n "${ALTERNATE_OPTIONS:-}" ]; then +if [[ -n "${ALTERNATE_OPTIONS:-}" ]]; then cp ${ALTERNATE_OPTIONS:-} absl/base/options.h || exit 1 fi diff --git a/ci/macos_xcode_cmake.sh b/ci/macos_xcode_cmake.sh index a1f4a857..cf78e207 100755 --- a/ci/macos_xcode_cmake.sh +++ b/ci/macos_xcode_cmake.sh @@ -19,12 +19,12 @@ set -euox pipefail -if [ -z ${ABSEIL_ROOT:-} ]; then +if [[ -z ${ABSEIL_ROOT:-} ]]; then ABSEIL_ROOT="$(dirname ${0})/.." fi ABSEIL_ROOT=$(realpath ${ABSEIL_ROOT}) -if [ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]; then +if [[ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]]; then ABSL_CMAKE_BUILD_TYPES="Debug" fi -- cgit v1.2.3 From db5773a721a50d1fc8c9b51efea0e70be4003d36 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Wed, 15 Apr 2020 15:13:54 -0700 Subject: Export of internal Abseil changes -- 0e867881e4b9f388a13d6fa8ed715192460130ab by Abseil Team : Minor wording change to header comment for Mutex::AwaitWithDeadline(). No functional changes. PiperOrigin-RevId: 306729491 -- fc64361fb831003fa5e6fbb84a9a89338fd2838c by Derek Mauro : Uses C++20 compatible allocator traits in Abseil types This merges both instances of CountingAllocator in the Abseil codebase. Makes the presubmits test C++20 mode. Fixes #651 PiperOrigin-RevId: 306728102 -- d759e5681b9dd6b7339fc019ed58fb5fdececdc3 by Derek Mauro : Makes btree's iterator comparisons C++20 compatible See https://stackoverflow.com/questions/60386792/c20-comparison-warning-about-ambiguous-reversed-operator PiperOrigin-RevId: 306702048 -- e9da5f409bc5ddb1bad308f9d8c41213c67a1d1e by Derek Mauro : Switch a few uses of at() that should have been data() in the implementation of InlinedVector. Use ABSL_HARDENING_ASSERT in resize(). PiperOrigin-RevId: 306670992 GitOrigin-RevId: 0e867881e4b9f388a13d6fa8ed715192460130ab Change-Id: If431f3e5d77097e9901654773552dcc01dface87 --- absl/container/BUILD.bazel | 1 + absl/container/CMakeLists.txt | 1 + absl/container/fixed_array.h | 14 +++--- absl/container/fixed_array_test.cc | 72 +++------------------------- absl/container/inlined_vector.h | 16 ++++--- absl/container/internal/btree.h | 6 +++ absl/container/internal/counting_allocator.h | 69 ++++++++++++++++++-------- absl/synchronization/mutex.h | 9 ++-- ci/linux_clang-latest_libcxx_asan_bazel.sh | 2 +- ci/linux_clang-latest_libcxx_bazel.sh | 2 +- ci/linux_clang-latest_libcxx_tsan_bazel.sh | 2 +- ci/linux_clang-latest_libstdcxx_bazel.sh | 2 +- ci/linux_gcc-latest_libstdcxx_bazel.sh | 2 +- 13 files changed, 90 insertions(+), 108 deletions(-) (limited to 'ci/linux_clang-latest_libcxx_tsan_bazel.sh') diff --git a/absl/container/BUILD.bazel b/absl/container/BUILD.bazel index 3606faa7..06921235 100644 --- a/absl/container/BUILD.bazel +++ b/absl/container/BUILD.bazel @@ -73,6 +73,7 @@ cc_test( copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ + ":counting_allocator", ":fixed_array", "//absl/base:config", "//absl/base:exception_testing", diff --git a/absl/container/CMakeLists.txt b/absl/container/CMakeLists.txt index 392f3284..13d96957 100644 --- a/absl/container/CMakeLists.txt +++ b/absl/container/CMakeLists.txt @@ -147,6 +147,7 @@ absl_cc_test( ${ABSL_TEST_COPTS} DEPS absl::fixed_array + absl::counting_allocator absl::config absl::exception_testing absl::hash_testing diff --git a/absl/container/fixed_array.h b/absl/container/fixed_array.h index 796dd629..adf0dc80 100644 --- a/absl/container/fixed_array.h +++ b/absl/container/fixed_array.h @@ -106,13 +106,13 @@ class FixedArray { public: using allocator_type = typename AllocatorTraits::allocator_type; - 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 value_type = typename AllocatorTraits::value_type; + using pointer = typename AllocatorTraits::pointer; + using const_pointer = typename AllocatorTraits::const_pointer; + using reference = value_type&; + using const_reference = const value_type&; + using size_type = typename AllocatorTraits::size_type; + using difference_type = typename AllocatorTraits::difference_type; using iterator = pointer; using const_iterator = const_pointer; using reverse_iterator = std::reverse_iterator; diff --git a/absl/container/fixed_array_test.cc b/absl/container/fixed_array_test.cc index 9b1c224f..90e950c7 100644 --- a/absl/container/fixed_array_test.cc +++ b/absl/container/fixed_array_test.cc @@ -29,6 +29,7 @@ #include "gtest/gtest.h" #include "absl/base/internal/exception_testing.h" #include "absl/base/options.h" +#include "absl/container/internal/counting_allocator.h" #include "absl/hash/hash_testing.h" #include "absl/memory/memory.h" @@ -638,70 +639,9 @@ TEST(FixedArrayTest, DefaultCtorDoesNotValueInit) { } #endif // __GNUC__ -// This is a stateful allocator, but the state lives outside of the -// allocator (in whatever test is using the allocator). This is odd -// but helps in tests where the allocator is propagated into nested -// containers - that chain of allocators uses the same state and is -// thus easier to query for aggregate allocation information. -template -class CountingAllocator : public std::allocator { - public: - using Alloc = std::allocator; - using pointer = typename Alloc::pointer; - using size_type = typename Alloc::size_type; - - CountingAllocator() : bytes_used_(nullptr), instance_count_(nullptr) {} - explicit CountingAllocator(int64_t* b) - : bytes_used_(b), instance_count_(nullptr) {} - CountingAllocator(int64_t* b, int64_t* a) - : bytes_used_(b), instance_count_(a) {} - - template - explicit CountingAllocator(const CountingAllocator& x) - : Alloc(x), - bytes_used_(x.bytes_used_), - instance_count_(x.instance_count_) {} - - pointer allocate(size_type n, const void* const hint = nullptr) { - assert(bytes_used_ != nullptr); - *bytes_used_ += n * sizeof(T); - return Alloc::allocate(n, hint); - } - - void deallocate(pointer p, size_type n) { - Alloc::deallocate(p, n); - assert(bytes_used_ != nullptr); - *bytes_used_ -= n * sizeof(T); - } - - template - void construct(pointer p, Args&&... args) { - Alloc::construct(p, absl::forward(args)...); - if (instance_count_) { - *instance_count_ += 1; - } - } - - void destroy(pointer p) { - Alloc::destroy(p); - if (instance_count_) { - *instance_count_ -= 1; - } - } - - template - class rebind { - public: - using other = CountingAllocator; - }; - - int64_t* bytes_used_; - int64_t* instance_count_; -}; - TEST(AllocatorSupportTest, CountInlineAllocations) { constexpr size_t inlined_size = 4; - using Alloc = CountingAllocator; + using Alloc = absl::container_internal::CountingAllocator; using AllocFxdArr = absl::FixedArray; int64_t allocated = 0; @@ -722,7 +662,7 @@ TEST(AllocatorSupportTest, CountInlineAllocations) { TEST(AllocatorSupportTest, CountOutoflineAllocations) { constexpr size_t inlined_size = 4; - using Alloc = CountingAllocator; + using Alloc = absl::container_internal::CountingAllocator; using AllocFxdArr = absl::FixedArray; int64_t allocated = 0; @@ -743,7 +683,7 @@ TEST(AllocatorSupportTest, CountOutoflineAllocations) { TEST(AllocatorSupportTest, CountCopyInlineAllocations) { constexpr size_t inlined_size = 4; - using Alloc = CountingAllocator; + using Alloc = absl::container_internal::CountingAllocator; using AllocFxdArr = absl::FixedArray; int64_t allocated1 = 0; @@ -771,7 +711,7 @@ TEST(AllocatorSupportTest, CountCopyInlineAllocations) { TEST(AllocatorSupportTest, CountCopyOutoflineAllocations) { constexpr size_t inlined_size = 4; - using Alloc = CountingAllocator; + using Alloc = absl::container_internal::CountingAllocator; using AllocFxdArr = absl::FixedArray; int64_t allocated1 = 0; @@ -803,7 +743,7 @@ TEST(AllocatorSupportTest, SizeValAllocConstructor) { using testing::SizeIs; constexpr size_t inlined_size = 4; - using Alloc = CountingAllocator; + using Alloc = absl::container_internal::CountingAllocator; using AllocFxdArr = absl::FixedArray; { diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h index 5f6f6154..36f388ae 100644 --- a/absl/container/inlined_vector.h +++ b/absl/container/inlined_vector.h @@ -351,14 +351,14 @@ class InlinedVector { // Returns a `reference` to the first element of the inlined vector. reference front() { ABSL_HARDENING_ASSERT(!empty()); - return at(0); + return data()[0]; } // Overload of `InlinedVector::front()` that returns a `const_reference` to // the first element of the inlined vector. const_reference front() const { ABSL_HARDENING_ASSERT(!empty()); - return at(0); + return data()[0]; } // `InlinedVector::back()` @@ -366,14 +366,14 @@ class InlinedVector { // Returns a `reference` to the last element of the inlined vector. reference back() { ABSL_HARDENING_ASSERT(!empty()); - return at(size() - 1); + return data()[size() - 1]; } // Overload of `InlinedVector::back()` that returns a `const_reference` to the // last element of the inlined vector. const_reference back() const { ABSL_HARDENING_ASSERT(!empty()); - return at(size() - 1); + return data()[size() - 1]; } // `InlinedVector::begin()` @@ -524,7 +524,7 @@ class InlinedVector { void assign(InputIterator first, InputIterator last) { size_type i = 0; for (; i < size() && first != last; ++i, static_cast(++first)) { - at(i) = *first; + data()[i] = *first; } erase(data() + i, data() + size()); @@ -537,7 +537,10 @@ class InlinedVector { // // NOTE: if `n` is smaller than `size()`, extra elements are destroyed. If `n` // is larger than `size()`, new elements are value-initialized. - void resize(size_type n) { storage_.Resize(DefaultValueAdapter(), n); } + void resize(size_type n) { + ABSL_HARDENING_ASSERT(n <= max_size()); + storage_.Resize(DefaultValueAdapter(), n); + } // Overload of `InlinedVector::resize(...)` that resizes the inlined vector to // contain `n` elements. @@ -545,6 +548,7 @@ class InlinedVector { // NOTE: if `n` is smaller than `size()`, extra elements are destroyed. If `n` // is larger than `size()`, new elements are copied-constructed from `v`. void resize(size_type n, const_reference v) { + ABSL_HARDENING_ASSERT(n <= max_size()); storage_.Resize(CopyValueAdapter(v), n); } diff --git a/absl/container/internal/btree.h b/absl/container/internal/btree.h index 4504e9ce..b23138f0 100644 --- a/absl/container/internal/btree.h +++ b/absl/container/internal/btree.h @@ -929,9 +929,15 @@ struct btree_iterator { void decrement_slow(); public: + bool operator==(const iterator &other) const { + return node == other.node && position == other.position; + } bool operator==(const const_iterator &other) const { return node == other.node && position == other.position; } + bool operator!=(const iterator &other) const { + return node != other.node || position != other.position; + } bool operator!=(const const_iterator &other) const { return node != other.node || position != other.position; } diff --git a/absl/container/internal/counting_allocator.h b/absl/container/internal/counting_allocator.h index 9efdc662..927cf082 100644 --- a/absl/container/internal/counting_allocator.h +++ b/absl/container/internal/counting_allocator.h @@ -15,7 +15,6 @@ #ifndef ABSL_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_ #define ABSL_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_ -#include #include #include @@ -31,33 +30,63 @@ namespace container_internal { // containers - that chain of allocators uses the same state and is // thus easier to query for aggregate allocation information. template -class CountingAllocator : public std::allocator { +class CountingAllocator { public: - using Alloc = std::allocator; - using pointer = typename Alloc::pointer; - using size_type = typename Alloc::size_type; + using Allocator = std::allocator; + using AllocatorTraits = std::allocator_traits; + using value_type = typename AllocatorTraits::value_type; + using pointer = typename AllocatorTraits::pointer; + using const_pointer = typename AllocatorTraits::const_pointer; + using size_type = typename AllocatorTraits::size_type; + using difference_type = typename AllocatorTraits::difference_type; - CountingAllocator() : bytes_used_(nullptr) {} - explicit CountingAllocator(int64_t* b) : bytes_used_(b) {} + CountingAllocator() = default; + explicit CountingAllocator(int64_t* bytes_used) : bytes_used_(bytes_used) {} + CountingAllocator(int64_t* bytes_used, int64_t* instance_count) + : bytes_used_(bytes_used), instance_count_(instance_count) {} template CountingAllocator(const CountingAllocator& x) - : Alloc(x), bytes_used_(x.bytes_used_) {} + : bytes_used_(x.bytes_used_), instance_count_(x.instance_count_) {} - pointer allocate(size_type n, - std::allocator::const_pointer hint = nullptr) { - assert(bytes_used_ != nullptr); - *bytes_used_ += n * sizeof(T); - return Alloc::allocate(n, hint); + pointer allocate( + size_type n, + typename AllocatorTraits::const_void_pointer hint = nullptr) { + Allocator allocator; + pointer ptr = AllocatorTraits::allocate(allocator, n, hint); + if (bytes_used_ != nullptr) { + *bytes_used_ += n * sizeof(T); + } + return ptr; } void deallocate(pointer p, size_type n) { - Alloc::deallocate(p, n); - assert(bytes_used_ != nullptr); - *bytes_used_ -= n * sizeof(T); + Allocator allocator; + AllocatorTraits::deallocate(allocator, p, n); + if (bytes_used_ != nullptr) { + *bytes_used_ -= n * sizeof(T); + } } - template + template + void construct(U* p, Args&&... args) { + Allocator allocator; + AllocatorTraits::construct(allocator, p, std::forward(args)...); + if (instance_count_ != nullptr) { + *instance_count_ += 1; + } + } + + template + void destroy(U* p) { + Allocator allocator; + AllocatorTraits::destroy(allocator, p); + if (instance_count_ != nullptr) { + *instance_count_ -= 1; + } + } + + template class rebind { public: using other = CountingAllocator; @@ -65,7 +94,8 @@ class CountingAllocator : public std::allocator { friend bool operator==(const CountingAllocator& a, const CountingAllocator& b) { - return a.bytes_used_ == b.bytes_used_; + return a.bytes_used_ == b.bytes_used_ && + a.instance_count_ == b.instance_count_; } friend bool operator!=(const CountingAllocator& a, @@ -73,7 +103,8 @@ class CountingAllocator : public std::allocator { return !(a == b); } - int64_t* bytes_used_; + int64_t* bytes_used_ = nullptr; + int64_t* instance_count_ = nullptr; }; } // namespace container_internal diff --git a/absl/synchronization/mutex.h b/absl/synchronization/mutex.h index 8c70c4ce..961ff52b 100644 --- a/absl/synchronization/mutex.h +++ b/absl/synchronization/mutex.h @@ -331,17 +331,16 @@ class ABSL_LOCKABLE Mutex { // Mutex::AwaitWithTimeout() // Mutex::AwaitWithDeadline() // - // If `cond` is initially true, do nothing, or act as though `cond` is - // initially false. - // - // If `cond` is initially false, unlock this `Mutex` and block until - // simultaneously: + // Unlocks this `Mutex` and blocks until simultaneously: // - either `cond` is true or the {timeout has expired, deadline has passed} // and // - this `Mutex` can be reacquired, // then reacquire this `Mutex` in the same mode in which it was previously // held, returning `true` iff `cond` is `true` on return. // + // If the condition is initially `true`, the implementation *may* skip the + // release/re-acquire step and return immediately. + // // Deadlines in the past are equivalent to an immediate deadline. // Negative timeouts are equivalent to a zero timeout. // diff --git a/ci/linux_clang-latest_libcxx_asan_bazel.sh b/ci/linux_clang-latest_libcxx_asan_bazel.sh index 88d2a97d..44794eb5 100755 --- a/ci/linux_clang-latest_libcxx_asan_bazel.sh +++ b/ci/linux_clang-latest_libcxx_asan_bazel.sh @@ -25,7 +25,7 @@ if [[ -z ${ABSEIL_ROOT:-} ]]; then fi if [[ -z ${STD:-} ]]; then - STD="c++11 c++14 c++17" + STD="c++11 c++14 c++17 c++20" fi if [[ -z ${COMPILATION_MODE:-} ]]; then diff --git a/ci/linux_clang-latest_libcxx_bazel.sh b/ci/linux_clang-latest_libcxx_bazel.sh index f344a588..eb04e69e 100755 --- a/ci/linux_clang-latest_libcxx_bazel.sh +++ b/ci/linux_clang-latest_libcxx_bazel.sh @@ -25,7 +25,7 @@ if [[ -z ${ABSEIL_ROOT:-} ]]; then fi if [[ -z ${STD:-} ]]; then - STD="c++11 c++14 c++17" + STD="c++11 c++14 c++17 c++20" fi if [[ -z ${COMPILATION_MODE:-} ]]; then diff --git a/ci/linux_clang-latest_libcxx_tsan_bazel.sh b/ci/linux_clang-latest_libcxx_tsan_bazel.sh index f7238457..c2eb5bae 100755 --- a/ci/linux_clang-latest_libcxx_tsan_bazel.sh +++ b/ci/linux_clang-latest_libcxx_tsan_bazel.sh @@ -25,7 +25,7 @@ if [[ -z ${ABSEIL_ROOT:-} ]]; then fi if [[ -z ${STD:-} ]]; then - STD="c++11 c++14 c++17" + STD="c++11 c++14 c++17 c++20" fi if [[ -z ${COMPILATION_MODE:-} ]]; then diff --git a/ci/linux_clang-latest_libstdcxx_bazel.sh b/ci/linux_clang-latest_libstdcxx_bazel.sh index d3920741..0192ee49 100755 --- a/ci/linux_clang-latest_libstdcxx_bazel.sh +++ b/ci/linux_clang-latest_libstdcxx_bazel.sh @@ -25,7 +25,7 @@ if [[ -z ${ABSEIL_ROOT:-} ]]; then fi if [[ -z ${STD:-} ]]; then - STD="c++11 c++14 c++17" + STD="c++11 c++14 c++17 c++20" fi if [[ -z ${COMPILATION_MODE:-} ]]; then diff --git a/ci/linux_gcc-latest_libstdcxx_bazel.sh b/ci/linux_gcc-latest_libstdcxx_bazel.sh index 337285b0..3ec02262 100755 --- a/ci/linux_gcc-latest_libstdcxx_bazel.sh +++ b/ci/linux_gcc-latest_libstdcxx_bazel.sh @@ -25,7 +25,7 @@ if [[ -z ${ABSEIL_ROOT:-} ]]; then fi if [[ -z ${STD:-} ]]; then - STD="c++11 c++14 c++17" + STD="c++11 c++14 c++17 c++2a" fi if [[ -z ${COMPILATION_MODE:-} ]]; then -- cgit v1.2.3 From 184cf2524101310a0ba315c743e82cf45fccccf8 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Thu, 30 Jul 2020 13:58:50 -0700 Subject: Export of internal Abseil changes -- 587e6db882749fa7faa12815e614afab04d218b9 by Derek Mauro : Use attribute detection for other sanitizer related attributes PiperOrigin-RevId: 324077073 -- 3ee55e4935b4235516b1fcac3c55945e510f7afc by Evan Brown : Simplify CordRepExternal allocation/deallocation. I think this can save some memory when `Releaser` is empty and when on platforms where alignof(CordRepExternal) < (default `::operator new` alignment). We no longer need the API requirement that alignof(Releaser) <= (default `::operator new` alignment). Also remove another static_assert from a TODO in cord_internal.h and fix some warnings about calling std::move on a forwarding reference. PiperOrigin-RevId: 324053720 -- 9fc78436565eb3b204d4aa425ee3773354392f45 by Derek Mauro : Use auto-detected sanitizer attributes for ASAN, MSAN, and TSAN builds PiperOrigin-RevId: 323831461 GitOrigin-RevId: 587e6db882749fa7faa12815e614afab04d218b9 Change-Id: Ie0e4a2846d7f66988a2d81a5e50721b62fdb3d6d --- absl/base/BUILD.bazel | 2 + absl/base/CMakeLists.txt | 2 + absl/base/attributes.h | 54 +++++----------- absl/base/internal/dynamic_annotations.h | 11 ++-- absl/base/internal/tsan_mutex_interface.h | 4 +- absl/base/internal/unaligned_access.h | 4 +- absl/base/spinlock_test_common.cc | 3 +- absl/container/BUILD.bazel | 5 ++ absl/container/CMakeLists.txt | 5 ++ absl/container/fixed_array.h | 13 ++-- absl/container/fixed_array_test.cc | 5 +- absl/container/internal/container_memory.h | 25 ++++---- absl/container/internal/layout.h | 12 ++-- absl/container/internal/layout_test.cc | 4 +- absl/container/internal/raw_hash_set_test.cc | 5 +- absl/debugging/BUILD.bazel | 2 + absl/debugging/CMakeLists.txt | 2 + absl/debugging/failure_signal_handler.cc | 4 +- absl/debugging/internal/demangle_test.cc | 8 ++- absl/debugging/symbolize_test.cc | 5 +- absl/strings/BUILD.bazel | 3 +- absl/strings/CMakeLists.txt | 1 + absl/strings/cord.cc | 74 ++++------------------ absl/strings/cord.h | 57 ++--------------- absl/strings/internal/cord_internal.h | 65 +++++++++++++------ absl/strings/string_view_test.cc | 4 +- absl/synchronization/BUILD.bazel | 3 + absl/synchronization/CMakeLists.txt | 2 + absl/synchronization/internal/mutex_nonprod.cc | 3 +- .../internal/per_thread_sem_test.cc | 1 + absl/synchronization/internal/waiter.h | 2 +- absl/synchronization/mutex.cc | 8 +-- absl/synchronization/mutex_benchmark.cc | 3 +- absl/synchronization/mutex_test.cc | 7 +- absl/time/BUILD.bazel | 1 + absl/time/CMakeLists.txt | 1 + absl/time/internal/test_util.cc | 1 + ci/linux_clang-latest_libcxx_asan_bazel.sh | 2 - ci/linux_clang-latest_libcxx_tsan_bazel.sh | 2 - 39 files changed, 180 insertions(+), 235 deletions(-) (limited to 'ci/linux_clang-latest_libcxx_tsan_bazel.sh') diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel index ad29bb0d..2c4887b3 100644 --- a/absl/base/BUILD.bazel +++ b/absl/base/BUILD.bazel @@ -415,6 +415,7 @@ cc_library( deps = [ ":base", ":base_internal", + ":config", ":core_headers", "//absl/synchronization", "@com_google_googletest//:gtest", @@ -431,6 +432,7 @@ cc_test( deps = [ ":base", ":base_internal", + ":config", ":core_headers", "//absl/synchronization", "@com_google_googletest//:gtest_main", diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt index f5cfc792..9ff5aa24 100644 --- a/absl/base/CMakeLists.txt +++ b/absl/base/CMakeLists.txt @@ -384,6 +384,7 @@ absl_cc_library( ${ABSL_TEST_COPTS} DEPS absl::base + absl::config absl::base_internal absl::core_headers absl::synchronization @@ -402,6 +403,7 @@ absl_cc_test( DEPS absl::base absl::base_internal + absl::config absl::core_headers absl::synchronization gtest_main diff --git a/absl/base/attributes.h b/absl/base/attributes.h index 2cf4b1e8..046fbea3 100644 --- a/absl/base/attributes.h +++ b/absl/base/attributes.h @@ -32,34 +32,12 @@ // of them are not supported in older version of Clang. Thus, we check // `__has_attribute()` first. If the check fails, we check if we are on GCC and // assume the attribute exists on GCC (which is verified on GCC 4.7). -// -// ----------------------------------------------------------------------------- -// Sanitizer Attributes -// ----------------------------------------------------------------------------- -// -// Sanitizer-related attributes are not "defined" in this file (and indeed -// are not defined as such in any file). To utilize the following -// sanitizer-related attributes within your builds, define the following macros -// within your build using a `-D` flag, along with the given value for -// `-fsanitize`: -// -// * `ADDRESS_SANITIZER` + `-fsanitize=address` (Clang, GCC 4.8) -// * `MEMORY_SANITIZER` + `-fsanitize=memory` (Clang-only) -// * `THREAD_SANITIZER` + `-fsanitize=thread` (Clang, GCC 4.8+) -// * `UNDEFINED_BEHAVIOR_SANITIZER` + `-fsanitize=undefined` (Clang, GCC 4.9+) -// * `CONTROL_FLOW_INTEGRITY` + `-fsanitize=cfi` (Clang-only) -// -// Example: -// -// // Enable branches in the Abseil code that are tagged for ASan: -// $ bazel build --copt=-DADDRESS_SANITIZER --copt=-fsanitize=address -// --linkopt=-fsanitize=address *target* -// -// Since these macro names are only supported by GCC and Clang, we only check -// for `__GNUC__` (GCC or Clang) and the above macros. + #ifndef ABSL_BASE_ATTRIBUTES_H_ #define ABSL_BASE_ATTRIBUTES_H_ +#include "absl/base/config.h" + // ABSL_HAVE_ATTRIBUTE // // A function-like feature checking macro that is a wrapper around @@ -234,7 +212,7 @@ // out of bounds or does other scary things with memory. // NOTE: GCC supports AddressSanitizer(asan) since 4.8. // https://gcc.gnu.org/gcc-4.8/changes.html -#if defined(__GNUC__) +#if ABSL_HAVE_ATTRIBUTE(no_sanitize_address) #define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) #else #define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS @@ -242,13 +220,13 @@ // ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY // -// Tells the MemorySanitizer to relax the handling of a given function. All -// "Use of uninitialized value" warnings from such functions will be suppressed, -// and all values loaded from memory will be considered fully initialized. -// This attribute is similar to the ADDRESS_SANITIZER attribute above, but deals -// with initialized-ness rather than addressability issues. +// Tells the MemorySanitizer to relax the handling of a given function. All "Use +// of uninitialized value" warnings from such functions will be suppressed, and +// all values loaded from memory will be considered fully initialized. This +// attribute is similar to the ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS attribute +// above, but deals with initialized-ness rather than addressability issues. // NOTE: MemorySanitizer(msan) is supported by Clang but not GCC. -#if defined(__clang__) +#if ABSL_HAVE_ATTRIBUTE(no_sanitize_memory) #define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory)) #else #define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY @@ -259,7 +237,7 @@ // Tells the ThreadSanitizer to not instrument a given function. // NOTE: GCC supports ThreadSanitizer(tsan) since 4.8. // https://gcc.gnu.org/gcc-4.8/changes.html -#if defined(__GNUC__) +#if ABSL_HAVE_ATTRIBUTE(no_sanitize_thread) #define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread)) #else #define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD @@ -271,8 +249,10 @@ // where certain behavior (eg. division by zero) is being used intentionally. // NOTE: GCC supports UndefinedBehaviorSanitizer(ubsan) since 4.9. // https://gcc.gnu.org/gcc-4.9/changes.html -#if defined(__GNUC__) && \ - (defined(UNDEFINED_BEHAVIOR_SANITIZER) || defined(ADDRESS_SANITIZER)) +#if ABSL_HAVE_ATTRIBUTE(no_sanitize_undefined) +#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \ + __attribute__((no_sanitize_undefined)) +#elif ABSL_HAVE_ATTRIBUTE(no_sanitize) #define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \ __attribute__((no_sanitize("undefined"))) #else @@ -283,7 +263,7 @@ // // Tells the ControlFlowIntegrity sanitizer to not instrument a given function. // See https://clang.llvm.org/docs/ControlFlowIntegrity.html for details. -#if defined(__GNUC__) && defined(CONTROL_FLOW_INTEGRITY) +#if ABSL_HAVE_ATTRIBUTE(no_sanitize) #define ABSL_ATTRIBUTE_NO_SANITIZE_CFI __attribute__((no_sanitize("cfi"))) #else #define ABSL_ATTRIBUTE_NO_SANITIZE_CFI @@ -293,7 +273,7 @@ // // Tells the SafeStack to not instrument a given function. // See https://clang.llvm.org/docs/SafeStack.html for details. -#if defined(__GNUC__) && defined(SAFESTACK_SANITIZER) +#if ABSL_HAVE_ATTRIBUTE(no_sanitize) #define ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK \ __attribute__((no_sanitize("safe-stack"))) #else diff --git a/absl/base/internal/dynamic_annotations.h b/absl/base/internal/dynamic_annotations.h index 7d80f41c..b69c1301 100644 --- a/absl/base/internal/dynamic_annotations.h +++ b/absl/base/internal/dynamic_annotations.h @@ -91,12 +91,9 @@ #endif // Memory annotations are also made available to LLVM's Memory Sanitizer -#if defined(MEMORY_SANITIZER) && defined(__has_feature) && \ - !defined(__native_client__) -#if __has_feature(memory_sanitizer) +#if defined(ABSL_HAVE_MEMORY_SANITIZER) && !defined(__native_client__) #define ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED 1 #endif -#endif #ifndef ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED #define ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED 0 @@ -162,7 +159,7 @@ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreate)(__FILE__, __LINE__, lock) // Report that a linker initialized lock has been created at address `lock`. -#ifdef THREAD_SANITIZER +#ifdef ABSL_HAVE_THREAD_SANITIZER #define ANNOTATE_RWLOCK_CREATE_STATIC(lock) \ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreateStatic) \ (__FILE__, __LINE__, lock) @@ -367,7 +364,7 @@ // ------------------------------------------------------------------------- // Address sanitizer annotations -#ifdef ADDRESS_SANITIZER +#ifdef ABSL_HAVE_ADDRESS_SANITIZER // Describe the current state of a contiguous container such as e.g. // std::vector or std::string. For more details see // sanitizer/common_interface_defs.h, which is provided by the compiler. @@ -385,7 +382,7 @@ #define ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid) #define ADDRESS_SANITIZER_REDZONE(name) static_assert(true, "") -#endif // ADDRESS_SANITIZER +#endif // ABSL_HAVE_ADDRESS_SANITIZER // ------------------------------------------------------------------------- // Undefine the macros intended only for this file. diff --git a/absl/base/internal/tsan_mutex_interface.h b/absl/base/internal/tsan_mutex_interface.h index 2a510603..39207d8a 100644 --- a/absl/base/internal/tsan_mutex_interface.h +++ b/absl/base/internal/tsan_mutex_interface.h @@ -19,6 +19,8 @@ #ifndef ABSL_BASE_INTERNAL_TSAN_MUTEX_INTERFACE_H_ #define ABSL_BASE_INTERNAL_TSAN_MUTEX_INTERFACE_H_ +#include "absl/base/config.h" + // ABSL_INTERNAL_HAVE_TSAN_INTERFACE // Macro intended only for internal use. // @@ -28,7 +30,7 @@ #error "ABSL_INTERNAL_HAVE_TSAN_INTERFACE cannot be directly set." #endif -#if defined(THREAD_SANITIZER) && defined(__has_include) +#if defined(ABSL_HAVE_THREAD_SANITIZER) && defined(__has_include) #if __has_include() #define ABSL_INTERNAL_HAVE_TSAN_INTERFACE 1 #endif diff --git a/absl/base/internal/unaligned_access.h b/absl/base/internal/unaligned_access.h index 6be56c86..dd5250de 100644 --- a/absl/base/internal/unaligned_access.h +++ b/absl/base/internal/unaligned_access.h @@ -32,8 +32,8 @@ // (namespaces, inline) which are absent or incompatible in C. #if defined(__cplusplus) -#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) ||\ - defined(MEMORY_SANITIZER) +#if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \ + defined(ABSL_HAVE_THREAD_SANITIZER) || defined(ABSL_HAVE_MEMORY_SANITIZER) // Consider we have an unaligned load/store of 4 bytes from address 0x...05. // AddressSanitizer will treat it as a 3-byte access to the range 05:07 and // will miss a bug if 08 is the first unaddressable byte. diff --git a/absl/base/spinlock_test_common.cc b/absl/base/spinlock_test_common.cc index b33c54ba..dee266e4 100644 --- a/absl/base/spinlock_test_common.cc +++ b/absl/base/spinlock_test_common.cc @@ -25,6 +25,7 @@ #include "gtest/gtest.h" #include "absl/base/attributes.h" +#include "absl/base/config.h" #include "absl/base/internal/low_level_scheduling.h" #include "absl/base/internal/scheduling_mode.h" #include "absl/base/internal/spinlock.h" @@ -104,7 +105,7 @@ static void ThreadedTest(SpinLock* spinlock) { } } -#ifndef THREAD_SANITIZER +#ifndef ABSL_HAVE_THREAD_SANITIZER static_assert(std::is_trivially_destructible(), ""); #endif diff --git a/absl/container/BUILD.bazel b/absl/container/BUILD.bazel index 06921235..cca5d441 100644 --- a/absl/container/BUILD.bazel +++ b/absl/container/BUILD.bazel @@ -60,6 +60,7 @@ cc_library( deps = [ ":compressed_tuple", "//absl/algorithm", + "//absl/base:config", "//absl/base:core_headers", "//absl/base:dynamic_annotations", "//absl/base:throw_delegate", @@ -368,6 +369,7 @@ cc_library( copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ + "//absl/base:config", "//absl/memory", "//absl/meta:type_traits", "//absl/utility", @@ -620,6 +622,7 @@ cc_test( ":hashtable_debug", ":raw_hash_set", "//absl/base", + "//absl/base:config", "//absl/base:core_headers", "//absl/base:raw_logging_internal", "//absl/strings", @@ -647,6 +650,7 @@ cc_library( copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ + "//absl/base:config", "//absl/base:core_headers", "//absl/meta:type_traits", "//absl/strings", @@ -665,6 +669,7 @@ cc_test( visibility = ["//visibility:private"], deps = [ ":layout", + "//absl/base:config", "//absl/base:core_headers", "//absl/base:raw_logging_internal", "//absl/types:span", diff --git a/absl/container/CMakeLists.txt b/absl/container/CMakeLists.txt index 13d96957..eb202c45 100644 --- a/absl/container/CMakeLists.txt +++ b/absl/container/CMakeLists.txt @@ -131,6 +131,7 @@ absl_cc_library( DEPS absl::compressed_tuple absl::algorithm + absl::config absl::core_headers absl::dynamic_annotations absl::throw_delegate @@ -423,6 +424,7 @@ absl_cc_library( COPTS ${ABSL_DEFAULT_COPTS} DEPS + absl::config absl::memory absl::type_traits absl::utility @@ -696,6 +698,7 @@ absl_cc_test( absl::hashtable_debug absl::raw_hash_set absl::base + absl::config absl::core_headers absl::raw_logging_internal absl::strings @@ -724,6 +727,7 @@ absl_cc_library( COPTS ${ABSL_DEFAULT_COPTS} DEPS + absl::config absl::core_headers absl::meta absl::strings @@ -741,6 +745,7 @@ absl_cc_test( ${ABSL_TEST_COPTS} DEPS absl::layout + absl::config absl::core_headers absl::raw_logging_internal absl::span diff --git a/absl/container/fixed_array.h b/absl/container/fixed_array.h index e74802a4..c8fe8d96 100644 --- a/absl/container/fixed_array.h +++ b/absl/container/fixed_array.h @@ -41,6 +41,7 @@ #include #include "absl/algorithm/algorithm.h" +#include "absl/base/config.h" #include "absl/base/dynamic_annotations.h" #include "absl/base/internal/throw_delegate.h" #include "absl/base/macros.h" @@ -422,10 +423,10 @@ class FixedArray { void AnnotateConstruct(size_type n); void AnnotateDestruct(size_type n); -#ifdef ADDRESS_SANITIZER +#ifdef ABSL_HAVE_ADDRESS_SANITIZER void* RedzoneBegin() { return &redzone_begin_; } void* RedzoneEnd() { return &redzone_end_ + 1; } -#endif // ADDRESS_SANITIZER +#endif // ABSL_HAVE_ADDRESS_SANITIZER private: ABSL_ADDRESS_SANITIZER_REDZONE(redzone_begin_); @@ -503,26 +504,26 @@ constexpr typename FixedArray::size_type template void FixedArray::NonEmptyInlinedStorage::AnnotateConstruct( typename FixedArray::size_type n) { -#ifdef ADDRESS_SANITIZER +#ifdef ABSL_HAVE_ADDRESS_SANITIZER if (!n) return; ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), RedzoneEnd(), data() + n); ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), data(), RedzoneBegin()); -#endif // ADDRESS_SANITIZER +#endif // ABSL_HAVE_ADDRESS_SANITIZER static_cast(n); // Mark used when not in asan mode } template void FixedArray::NonEmptyInlinedStorage::AnnotateDestruct( typename FixedArray::size_type n) { -#ifdef ADDRESS_SANITIZER +#ifdef ABSL_HAVE_ADDRESS_SANITIZER if (!n) return; ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), data() + n, RedzoneEnd()); ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), RedzoneBegin(), data()); -#endif // ADDRESS_SANITIZER +#endif // ABSL_HAVE_ADDRESS_SANITIZER static_cast(n); // Mark used when not in asan mode } ABSL_NAMESPACE_END diff --git a/absl/container/fixed_array_test.cc b/absl/container/fixed_array_test.cc index 064a88a2..49598e7a 100644 --- a/absl/container/fixed_array_test.cc +++ b/absl/container/fixed_array_test.cc @@ -27,6 +27,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +#include "absl/base/config.h" #include "absl/base/internal/exception_testing.h" #include "absl/base/options.h" #include "absl/container/internal/counting_allocator.h" @@ -767,7 +768,7 @@ TEST(AllocatorSupportTest, SizeValAllocConstructor) { } } -#ifdef ADDRESS_SANITIZER +#ifdef ABSL_HAVE_ADDRESS_SANITIZER TEST(FixedArrayTest, AddressSanitizerAnnotations1) { absl::FixedArray a(10); int* raw = a.data(); @@ -814,7 +815,7 @@ TEST(FixedArrayTest, AddressSanitizerAnnotations4) { // so reading raw[21] should still trigger the correct warning. EXPECT_DEATH_IF_SUPPORTED(raw[21] = ThreeInts(), "container-overflow"); } -#endif // ADDRESS_SANITIZER +#endif // ABSL_HAVE_ADDRESS_SANITIZER TEST(FixedArrayTest, AbslHashValueWorks) { using V = absl::FixedArray; diff --git a/absl/container/internal/container_memory.h b/absl/container/internal/container_memory.h index 92a61cc0..c7777a93 100644 --- a/absl/container/internal/container_memory.h +++ b/absl/container/internal/container_memory.h @@ -15,14 +15,6 @@ #ifndef ABSL_CONTAINER_INTERNAL_CONTAINER_MEMORY_H_ #define ABSL_CONTAINER_INTERNAL_CONTAINER_MEMORY_H_ -#ifdef ADDRESS_SANITIZER -#include -#endif - -#ifdef MEMORY_SANITIZER -#include -#endif - #include #include #include @@ -30,10 +22,19 @@ #include #include +#include "absl/base/config.h" #include "absl/memory/memory.h" #include "absl/meta/type_traits.h" #include "absl/utility/utility.h" +#ifdef ABSL_HAVE_ADDRESS_SANITIZER +#include +#endif + +#ifdef ABSL_HAVE_MEMORY_SANITIZER +#include +#endif + namespace absl { ABSL_NAMESPACE_BEGIN namespace container_internal { @@ -209,10 +210,10 @@ DecomposeValue(F&& f, Arg&& arg) { // Helper functions for asan and msan. inline void SanitizerPoisonMemoryRegion(const void* m, size_t s) { -#ifdef ADDRESS_SANITIZER +#ifdef ABSL_HAVE_ADDRESS_SANITIZER ASAN_POISON_MEMORY_REGION(m, s); #endif -#ifdef MEMORY_SANITIZER +#ifdef ABSL_HAVE_MEMORY_SANITIZER __msan_poison(m, s); #endif (void)m; @@ -220,10 +221,10 @@ inline void SanitizerPoisonMemoryRegion(const void* m, size_t s) { } inline void SanitizerUnpoisonMemoryRegion(const void* m, size_t s) { -#ifdef ADDRESS_SANITIZER +#ifdef ABSL_HAVE_ADDRESS_SANITIZER ASAN_UNPOISON_MEMORY_REGION(m, s); #endif -#ifdef MEMORY_SANITIZER +#ifdef ABSL_HAVE_MEMORY_SANITIZER __msan_unpoison(m, s); #endif (void)m; diff --git a/absl/container/internal/layout.h b/absl/container/internal/layout.h index 69cc85dd..23367833 100644 --- a/absl/container/internal/layout.h +++ b/absl/container/internal/layout.h @@ -163,6 +163,7 @@ #include #include #include + #include #include #include @@ -170,15 +171,16 @@ #include #include -#ifdef ADDRESS_SANITIZER -#include -#endif - +#include "absl/base/config.h" #include "absl/meta/type_traits.h" #include "absl/strings/str_cat.h" #include "absl/types/span.h" #include "absl/utility/utility.h" +#ifdef ABSL_HAVE_ADDRESS_SANITIZER +#include +#endif + #if defined(__GXX_RTTI) #define ABSL_INTERNAL_HAS_CXA_DEMANGLE #endif @@ -614,7 +616,7 @@ class LayoutImpl, absl::index_sequence, void PoisonPadding(const Char* p) const { static_assert(N < NumOffsets, "Index out of bounds"); (void)p; -#ifdef ADDRESS_SANITIZER +#ifdef ABSL_HAVE_ADDRESS_SANITIZER PoisonPadding(p); // The `if` is an optimization. It doesn't affect the observable behaviour. if (ElementAlignment::value % ElementAlignment::value) { diff --git a/absl/container/internal/layout_test.cc b/absl/container/internal/layout_test.cc index 8f3628a1..757272f1 100644 --- a/absl/container/internal/layout_test.cc +++ b/absl/container/internal/layout_test.cc @@ -17,6 +17,7 @@ // We need ::max_align_t because some libstdc++ versions don't provide // std::max_align_t #include + #include #include #include @@ -24,6 +25,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +#include "absl/base/config.h" #include "absl/base/internal/raw_logging.h" #include "absl/types/span.h" @@ -1314,7 +1316,7 @@ struct Region { }; void ExpectRegionPoisoned(const unsigned char* p, size_t n, bool poisoned) { -#ifdef ADDRESS_SANITIZER +#ifdef ABSL_HAVE_ADDRESS_SANITIZER for (size_t i = 0; i != n; ++i) { EXPECT_EQ(poisoned, __asan_address_is_poisoned(p + i)); } diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc index 6befa960..e3279301 100644 --- a/absl/container/internal/raw_hash_set_test.cc +++ b/absl/container/internal/raw_hash_set_test.cc @@ -26,6 +26,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/base/attributes.h" +#include "absl/base/config.h" #include "absl/base/internal/cycleclock.h" #include "absl/base/internal/raw_logging.h" #include "absl/container/internal/container_memory.h" @@ -1839,7 +1840,7 @@ TEST(RawHashSamplerTest, DoNotSampleCustomAllocators) { 0.00, 0.001); } -#ifdef ADDRESS_SANITIZER +#ifdef ABSL_HAVE_ADDRESS_SANITIZER TEST(Sanitizer, PoisoningUnused) { IntTable t; t.reserve(5); @@ -1863,7 +1864,7 @@ TEST(Sanitizer, PoisoningOnErase) { t.erase(0); EXPECT_TRUE(__asan_address_is_poisoned(&v)); } -#endif // ADDRESS_SANITIZER +#endif // ABSL_HAVE_ADDRESS_SANITIZER } // namespace } // namespace container_internal diff --git a/absl/debugging/BUILD.bazel b/absl/debugging/BUILD.bazel index bdc50e09..9098ca4a 100644 --- a/absl/debugging/BUILD.bazel +++ b/absl/debugging/BUILD.bazel @@ -97,6 +97,7 @@ cc_test( ":stack_consumption", ":symbolize", "//absl/base", + "//absl/base:config", "//absl/base:core_headers", "//absl/base:raw_logging_internal", "//absl/memory", @@ -204,6 +205,7 @@ cc_test( deps = [ ":demangle_internal", ":stack_consumption", + "//absl/base:config", "//absl/base:core_headers", "//absl/base:raw_logging_internal", "//absl/memory", diff --git a/absl/debugging/CMakeLists.txt b/absl/debugging/CMakeLists.txt index c597df86..074b44cf 100644 --- a/absl/debugging/CMakeLists.txt +++ b/absl/debugging/CMakeLists.txt @@ -82,6 +82,7 @@ absl_cc_test( absl::stack_consumption absl::symbolize absl::base + absl::config absl::core_headers absl::memory absl::raw_logging_internal @@ -189,6 +190,7 @@ absl_cc_test( DEPS absl::demangle_internal absl::stack_consumption + absl::config absl::core_headers absl::memory absl::raw_logging_internal diff --git a/absl/debugging/failure_signal_handler.cc b/absl/debugging/failure_signal_handler.cc index 1f69bfa8..5d13bdbb 100644 --- a/absl/debugging/failure_signal_handler.cc +++ b/absl/debugging/failure_signal_handler.cc @@ -136,8 +136,8 @@ static bool SetupAlternateStackOnce() { const size_t page_mask = sysconf(_SC_PAGESIZE) - 1; #endif size_t stack_size = (std::max(SIGSTKSZ, 65536) + page_mask) & ~page_mask; -#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \ - defined(THREAD_SANITIZER) +#if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \ + defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER) // Account for sanitizer instrumentation requiring additional stack space. stack_size *= 5; #endif diff --git a/absl/debugging/internal/demangle_test.cc b/absl/debugging/internal/demangle_test.cc index c6f1ce18..0bed7359 100644 --- a/absl/debugging/internal/demangle_test.cc +++ b/absl/debugging/internal/demangle_test.cc @@ -18,6 +18,7 @@ #include #include "gtest/gtest.h" +#include "absl/base/config.h" #include "absl/base/internal/raw_logging.h" #include "absl/debugging/internal/stack_consumption.h" #include "absl/memory/memory.h" @@ -82,9 +83,10 @@ TEST(Demangle, Clones) { // Tests that verify that Demangle footprint is within some limit. // They are not to be run under sanitizers as the sanitizers increase // stack consumption by about 4x. -#if defined(ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION) && \ - !defined(ADDRESS_SANITIZER) && !defined(MEMORY_SANITIZER) && \ - !defined(THREAD_SANITIZER) +#if defined(ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION) && \ + !defined(ABSL_HAVE_ADDRESS_SANITIZER) && \ + !defined(ABSL_HAVE_MEMORY_SANITIZER) && \ + !defined(ABSL_HAVE_THREAD_SANITIZER) static const char *g_mangled; static char g_demangle_buffer[4096]; diff --git a/absl/debugging/symbolize_test.cc b/absl/debugging/symbolize_test.cc index 43f65549..a2dd4956 100644 --- a/absl/debugging/symbolize_test.cc +++ b/absl/debugging/symbolize_test.cc @@ -27,6 +27,7 @@ #include "gtest/gtest.h" #include "absl/base/attributes.h" #include "absl/base/casts.h" +#include "absl/base/config.h" #include "absl/base/internal/per_thread_tls.h" #include "absl/base/internal/raw_logging.h" #include "absl/base/optimization.h" @@ -220,8 +221,8 @@ static const char *SymbolizeStackConsumption(void *pc, int *stack_consumed) { static int GetStackConsumptionUpperLimit() { // Symbolize stack consumption should be within 2kB. int stack_consumption_upper_limit = 2048; -#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \ - defined(THREAD_SANITIZER) +#if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \ + defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER) // Account for sanitizer instrumentation requiring additional stack space. stack_consumption_upper_limit *= 5; #endif diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel index ef412639..64a13cef 100644 --- a/absl/strings/BUILD.bazel +++ b/absl/strings/BUILD.bazel @@ -258,6 +258,8 @@ cc_library( visibility = ["//visibility:private"], deps = [ ":strings", + "//absl/base:base_internal", + "//absl/container:compressed_tuple", "//absl/meta:type_traits", ], ) @@ -277,7 +279,6 @@ cc_library( ":str_format", ":strings", "//absl/base", - "//absl/base:base_internal", "//absl/base:core_headers", "//absl/base:endian", "//absl/base:raw_logging_internal", diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt index d7237231..d6c2126d 100644 --- a/absl/strings/CMakeLists.txt +++ b/absl/strings/CMakeLists.txt @@ -548,6 +548,7 @@ absl_cc_library( DEPS absl::base absl::base_internal + absl::compressed_tuple absl::core_headers absl::endian absl::fixed_array diff --git a/absl/strings/cord.cc b/absl/strings/cord.cc index 920dcc67..763dcc45 100644 --- a/absl/strings/cord.cc +++ b/absl/strings/cord.cc @@ -61,48 +61,6 @@ enum CordRepKind { FLAT = 3, }; -namespace { - -// Type used with std::allocator for allocating and deallocating -// `CordRepExternal`. std::allocator is used because it opaquely handles the -// different new / delete overloads available on a given platform. -struct alignas(absl::cord_internal::ExternalRepAlignment()) ExternalAllocType { - unsigned char value[absl::cord_internal::ExternalRepAlignment()]; -}; - -// Returns the number of objects to pass in to std::allocator -// allocate() and deallocate() to create enough room for `CordRepExternal` with -// `releaser_size` bytes on the end. -constexpr size_t GetExternalAllocNumObjects(size_t releaser_size) { - // Be sure to round up since `releaser_size` could be smaller than - // `sizeof(ExternalAllocType)`. - return (sizeof(CordRepExternal) + releaser_size + sizeof(ExternalAllocType) - - 1) / - sizeof(ExternalAllocType); -} - -// Allocates enough memory for `CordRepExternal` and a releaser with size -// `releaser_size` bytes. -void* AllocateExternal(size_t releaser_size) { - return std::allocator().allocate( - GetExternalAllocNumObjects(releaser_size)); -} - -// Deallocates the memory for a `CordRepExternal` assuming it was allocated with -// a releaser of given size and alignment. -void DeallocateExternal(CordRepExternal* p, size_t releaser_size) { - std::allocator().deallocate( - reinterpret_cast(p), - GetExternalAllocNumObjects(releaser_size)); -} - -// Returns a pointer to the type erased releaser for the given CordRepExternal. -void* GetExternalReleaser(CordRepExternal* rep) { - return rep + 1; -} - -} // namespace - namespace cord_internal { inline CordRepConcat* CordRep::concat() { @@ -304,11 +262,7 @@ static void UnrefInternal(CordRep* rep) { } } else if (rep->tag == EXTERNAL) { CordRepExternal* rep_external = rep->external(); - absl::string_view data(rep_external->base, rep->length); - void* releaser = GetExternalReleaser(rep_external); - size_t releaser_size = rep_external->releaser_invoker(releaser, data); - rep_external->~CordRepExternal(); - DeallocateExternal(rep_external, releaser_size); + rep_external->releaser_invoker(rep_external); rep = nullptr; } else if (rep->tag == SUBSTRING) { CordRepSubstring* rep_substring = rep->substring(); @@ -458,18 +412,12 @@ static CordRep* NewTree(const char* data, namespace cord_internal { -ExternalRepReleaserPair NewExternalWithUninitializedReleaser( - absl::string_view data, ExternalReleaserInvoker invoker, - size_t releaser_size) { +void InitializeCordRepExternal(absl::string_view data, CordRepExternal* rep) { assert(!data.empty()); - - void* raw_rep = AllocateExternal(releaser_size); - auto* rep = new (raw_rep) CordRepExternal(); rep->length = data.size(); rep->tag = EXTERNAL; rep->base = data.data(); - rep->releaser_invoker = invoker; - return {VerifyTree(rep), GetExternalReleaser(rep)}; + VerifyTree(rep); } } // namespace cord_internal @@ -721,12 +669,12 @@ Cord::Cord(T&& src) { std::string data; }; const absl::string_view original_data = src; - CordRepExternal* rep = - static_cast(absl::cord_internal::NewExternalRep( - original_data, StringReleaser{std::move(src)})); + auto* rep = static_cast< + ::absl::cord_internal::CordRepExternalImpl*>( + absl::cord_internal::NewExternalRep( + original_data, StringReleaser{std::forward(src)})); // Moving src may have invalidated its data pointer, so adjust it. - rep->base = - static_cast(GetExternalReleaser(rep))->data.data(); + rep->base = rep->template get<0>().data.data(); contents_.set_tree(rep); } } @@ -775,7 +723,7 @@ Cord& Cord::operator=(T&& src) { if (src.size() <= kMaxBytesToCopy) { *this = absl::string_view(src); } else { - *this = Cord(std::move(src)); + *this = Cord(std::forward(src)); } return *this; } @@ -898,7 +846,7 @@ void Cord::Append(T&& src) { if (src.size() <= kMaxBytesToCopy) { Append(absl::string_view(src)); } else { - Append(Cord(std::move(src))); + Append(Cord(std::forward(src))); } } @@ -938,7 +886,7 @@ inline void Cord::Prepend(T&& src) { if (src.size() <= kMaxBytesToCopy) { Prepend(absl::string_view(src)); } else { - Prepend(Cord(std::move(src))); + Prepend(Cord(std::forward(src))); } } diff --git a/absl/strings/cord.h b/absl/strings/cord.h index 8580d803..a0db2797 100644 --- a/absl/strings/cord.h +++ b/absl/strings/cord.h @@ -71,7 +71,6 @@ #include #include "absl/base/internal/endian.h" -#include "absl/base/internal/invoke.h" #include "absl/base/internal/per_thread_tls.h" #include "absl/base/macros.h" #include "absl/base/port.h" @@ -173,10 +172,6 @@ class Cord { // // * be move constructible // * support `void operator()(absl::string_view) const` or `void operator()` - // * not have alignment requirement greater than what is guaranteed by - // `::operator new`. This alignment is dictated by - // `alignof(std::max_align_t)` (pre-C++17 code) or - // `__STDCPP_DEFAULT_NEW_ALIGNMENT__` (C++17 code). // // Example: // @@ -842,47 +837,15 @@ inline void SmallMemmove(char* dst, const char* src, size_t n, } } -struct ExternalRepReleaserPair { - CordRep* rep; - void* releaser_address; -}; - -// Allocates a new external `CordRep` and returns a pointer to it and a pointer -// to `releaser_size` bytes where the desired releaser can be constructed. +// Does non-template-specific `CordRepExternal` initialization. // Expects `data` to be non-empty. -ExternalRepReleaserPair NewExternalWithUninitializedReleaser( - absl::string_view data, ExternalReleaserInvoker invoker, - size_t releaser_size); - -struct Rank1 {}; -struct Rank0 : Rank1 {}; - -template > -void InvokeReleaser(Rank0, Releaser&& releaser, absl::string_view data) { - ::absl::base_internal::invoke(std::forward(releaser), data); -} - -template > -void InvokeReleaser(Rank1, Releaser&& releaser, absl::string_view) { - ::absl::base_internal::invoke(std::forward(releaser)); -} +void InitializeCordRepExternal(absl::string_view data, CordRepExternal* rep); // Creates a new `CordRep` that owns `data` and `releaser` and returns a pointer // to it, or `nullptr` if `data` was empty. template // NOLINTNEXTLINE - suppress clang-tidy raw pointer return. CordRep* NewExternalRep(absl::string_view data, Releaser&& releaser) { - static_assert( -#if defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__) - alignof(Releaser) <= __STDCPP_DEFAULT_NEW_ALIGNMENT__, -#else - alignof(Releaser) <= alignof(max_align_t), -#endif - "Releasers with alignment requirement greater than what is returned by " - "default `::operator new()` are not supported."); - using ReleaserType = absl::decay_t; if (data.empty()) { // Never create empty external nodes. @@ -891,18 +854,10 @@ CordRep* NewExternalRep(absl::string_view data, Releaser&& releaser) { return nullptr; } - auto releaser_invoker = [](void* type_erased_releaser, absl::string_view d) { - auto* my_releaser = static_cast(type_erased_releaser); - InvokeReleaser(Rank0{}, std::move(*my_releaser), d); - my_releaser->~ReleaserType(); - return sizeof(Releaser); - }; - - ExternalRepReleaserPair external = NewExternalWithUninitializedReleaser( - data, releaser_invoker, sizeof(releaser)); - ::new (external.releaser_address) - ReleaserType(std::forward(releaser)); - return external.rep; + CordRepExternal* rep = new CordRepExternalImpl( + std::forward(releaser), 0); + InitializeCordRepExternal(data, rep); + return rep; } // Overload for function reference types that dispatches using a function diff --git a/absl/strings/internal/cord_internal.h b/absl/strings/internal/cord_internal.h index 830ceaf4..d456eef8 100644 --- a/absl/strings/internal/cord_internal.h +++ b/absl/strings/internal/cord_internal.h @@ -21,6 +21,8 @@ #include #include +#include "absl/base/internal/invoke.h" +#include "absl/container/internal/compressed_tuple.h" #include "absl/meta/type_traits.h" #include "absl/strings/string_view.h" @@ -114,35 +116,56 @@ struct CordRepSubstring : public CordRep { CordRep* child; }; -// TODO(strel): replace the following logic (and related functions in cord.cc) -// with container_internal::Layout. - -// Alignment requirement for CordRepExternal so that the type erased releaser -// will be stored at a suitably aligned address. -constexpr size_t ExternalRepAlignment() { -#if defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__) - return __STDCPP_DEFAULT_NEW_ALIGNMENT__; -#else - return alignof(max_align_t); -#endif -} - -// Type for function pointer that will invoke and destroy the type-erased -// releaser function object. Accepts a pointer to the releaser and the -// `string_view` that were passed in to `NewExternalRep` below. The return value -// is the size of the `Releaser` type. -using ExternalReleaserInvoker = size_t (*)(void*, absl::string_view); +// Type for function pointer that will invoke the releaser function and also +// delete the `CordRepExternalImpl` corresponding to the passed in +// `CordRepExternal`. +using ExternalReleaserInvoker = void (*)(CordRepExternal*); // External CordReps are allocated together with a type erased releaser. The // releaser is stored in the memory directly following the CordRepExternal. -struct alignas(ExternalRepAlignment()) CordRepExternal : public CordRep { +struct CordRepExternal : public CordRep { const char* base; // Pointer to function that knows how to call and destroy the releaser. ExternalReleaserInvoker releaser_invoker; }; -// TODO(strel): look into removing, it doesn't seem like anything relies on this -static_assert(sizeof(CordRepConcat) == sizeof(CordRepSubstring), ""); +struct Rank1 {}; +struct Rank0 : Rank1 {}; + +template > +void InvokeReleaser(Rank0, Releaser&& releaser, absl::string_view data) { + ::absl::base_internal::invoke(std::forward(releaser), data); +} + +template > +void InvokeReleaser(Rank1, Releaser&& releaser, absl::string_view) { + ::absl::base_internal::invoke(std::forward(releaser)); +} + +// We use CompressedTuple so that we can benefit from EBCO. +template +struct CordRepExternalImpl + : public CordRepExternal, + public ::absl::container_internal::CompressedTuple { + // The extra int arg is so that we can avoid interfering with copy/move + // constructors while still benefitting from perfect forwarding. + template + CordRepExternalImpl(T&& releaser, int) + : CordRepExternalImpl::CompressedTuple(std::forward(releaser)) { + this->releaser_invoker = &Release; + } + + ~CordRepExternalImpl() { + InvokeReleaser(Rank0{}, std::move(this->template get<0>()), + absl::string_view(base, length)); + } + + static void Release(CordRepExternal* rep) { + delete static_cast(rep); + } +}; } // namespace cord_internal ABSL_NAMESPACE_END diff --git a/absl/strings/string_view_test.cc b/absl/strings/string_view_test.cc index 41dbc97b..dcebb150 100644 --- a/absl/strings/string_view_test.cc +++ b/absl/strings/string_view_test.cc @@ -1177,7 +1177,7 @@ TEST(FindOneCharTest, EdgeCases) { EXPECT_EQ(absl::string_view::npos, a.rfind('x')); } -#ifndef THREAD_SANITIZER // Allocates too much memory for tsan. +#ifndef ABSL_HAVE_THREAD_SANITIZER // Allocates too much memory for tsan. TEST(HugeStringView, TwoPointTwoGB) { if (sizeof(size_t) <= 4) return; @@ -1191,7 +1191,7 @@ TEST(HugeStringView, TwoPointTwoGB) { sp.remove_suffix(2); EXPECT_EQ(size - 1 - 2, sp.length()); } -#endif // THREAD_SANITIZER +#endif // ABSL_HAVE_THREAD_SANITIZER #if !defined(NDEBUG) && !defined(ABSL_USES_STD_STRING_VIEW) TEST(NonNegativeLenTest, NonNegativeLen) { diff --git a/absl/synchronization/BUILD.bazel b/absl/synchronization/BUILD.bazel index 2cd5ae20..1a5c02ab 100644 --- a/absl/synchronization/BUILD.bazel +++ b/absl/synchronization/BUILD.bazel @@ -190,6 +190,7 @@ cc_test( ":synchronization", ":thread_pool", "//absl/base", + "//absl/base:config", "//absl/base:core_headers", "//absl/base:raw_logging_internal", "//absl/memory", @@ -211,6 +212,7 @@ cc_library( ":synchronization", ":thread_pool", "//absl/base", + "//absl/base:config", "@com_github_google_benchmark//:benchmark_main", ], alwayslink = 1, @@ -249,6 +251,7 @@ cc_library( deps = [ ":synchronization", "//absl/base", + "//absl/base:config", "//absl/strings", "//absl/time", "@com_google_googletest//:gtest", diff --git a/absl/synchronization/CMakeLists.txt b/absl/synchronization/CMakeLists.txt index dfe5d05d..e5bc52fb 100644 --- a/absl/synchronization/CMakeLists.txt +++ b/absl/synchronization/CMakeLists.txt @@ -149,6 +149,7 @@ absl_cc_test( absl::synchronization absl::thread_pool absl::base + absl::config absl::core_headers absl::memory absl::raw_logging_internal @@ -179,6 +180,7 @@ absl_cc_library( DEPS absl::synchronization absl::base + absl::config absl::strings absl::time gmock diff --git a/absl/synchronization/internal/mutex_nonprod.cc b/absl/synchronization/internal/mutex_nonprod.cc index 1732f836..334c3bc0 100644 --- a/absl/synchronization/internal/mutex_nonprod.cc +++ b/absl/synchronization/internal/mutex_nonprod.cc @@ -27,6 +27,7 @@ #include +#include "absl/base/config.h" #include "absl/base/internal/raw_logging.h" #include "absl/time/time.h" @@ -278,7 +279,7 @@ bool CondVar::WaitWithTimeout(Mutex* mu, absl::Duration timeout) { void CondVar::EnableDebugLog(const char*) {} -#ifdef THREAD_SANITIZER +#ifdef ABSL_HAVE_THREAD_SANITIZER extern "C" void __tsan_read1(void *addr); #else #define __tsan_read1(addr) // do nothing if TSan not enabled diff --git a/absl/synchronization/internal/per_thread_sem_test.cc b/absl/synchronization/internal/per_thread_sem_test.cc index b5a2f6d4..8cf59e64 100644 --- a/absl/synchronization/internal/per_thread_sem_test.cc +++ b/absl/synchronization/internal/per_thread_sem_test.cc @@ -23,6 +23,7 @@ #include // NOLINT(build/c++11) #include "gtest/gtest.h" +#include "absl/base/config.h" #include "absl/base/internal/cycleclock.h" #include "absl/base/internal/thread_identity.h" #include "absl/strings/str_cat.h" diff --git a/absl/synchronization/internal/waiter.h b/absl/synchronization/internal/waiter.h index ae83907b..887f9b1b 100644 --- a/absl/synchronization/internal/waiter.h +++ b/absl/synchronization/internal/waiter.h @@ -100,7 +100,7 @@ class Waiter { } // How many periods to remain idle before releasing resources -#ifndef THREAD_SANITIZER +#ifndef ABSL_HAVE_THREAD_SANITIZER static constexpr int kIdlePeriods = 60; #else // Memory consumption under ThreadSanitizer is a serious concern, diff --git a/absl/synchronization/mutex.cc b/absl/synchronization/mutex.cc index aafeb674..9b7f088a 100644 --- a/absl/synchronization/mutex.cc +++ b/absl/synchronization/mutex.cc @@ -77,7 +77,7 @@ ABSL_NAMESPACE_BEGIN namespace { -#if defined(THREAD_SANITIZER) +#if defined(ABSL_HAVE_THREAD_SANITIZER) constexpr OnDeadlockCycle kDeadlockDetectionDefault = OnDeadlockCycle::kIgnore; #else constexpr OnDeadlockCycle kDeadlockDetectionDefault = OnDeadlockCycle::kAbort; @@ -705,7 +705,7 @@ static constexpr bool kDebugMode = false; static constexpr bool kDebugMode = true; #endif -#ifdef THREAD_SANITIZER +#ifdef ABSL_HAVE_THREAD_SANITIZER static unsigned TsanFlags(Mutex::MuHow how) { return how == kShared ? __tsan_mutex_read_lock : 0; } @@ -1767,7 +1767,7 @@ static inline bool EvalConditionAnnotated(const Condition *cond, Mutex *mu, // All memory accesses are ignored inside of mutex operations + for unlock // operation tsan considers that we've already released the mutex. bool res = false; -#ifdef THREAD_SANITIZER +#ifdef ABSL_HAVE_THREAD_SANITIZER const int flags = read_lock ? __tsan_mutex_read_lock : 0; const int tryflags = flags | (trylock ? __tsan_mutex_try_lock : 0); #endif @@ -2683,7 +2683,7 @@ void ReleasableMutexLock::Release() { this->mu_ = nullptr; } -#ifdef THREAD_SANITIZER +#ifdef ABSL_HAVE_THREAD_SANITIZER extern "C" void __tsan_read1(void *addr); #else #define __tsan_read1(addr) // do nothing if TSan not enabled diff --git a/absl/synchronization/mutex_benchmark.cc b/absl/synchronization/mutex_benchmark.cc index ab188001..933ea14f 100644 --- a/absl/synchronization/mutex_benchmark.cc +++ b/absl/synchronization/mutex_benchmark.cc @@ -16,6 +16,7 @@ #include // NOLINT(build/c++11) #include +#include "absl/base/config.h" #include "absl/base/internal/cycleclock.h" #include "absl/base/internal/spinlock.h" #include "absl/synchronization/blocking_counter.h" @@ -213,7 +214,7 @@ void BM_ConditionWaiters(benchmark::State& state) { } // Some configurations have higher thread limits than others. -#if defined(__linux__) && !defined(THREAD_SANITIZER) +#if defined(__linux__) && !defined(ABSL_HAVE_THREAD_SANITIZER) constexpr int kMaxConditionWaiters = 8192; #else constexpr int kMaxConditionWaiters = 1024; diff --git a/absl/synchronization/mutex_test.cc b/absl/synchronization/mutex_test.cc index afb363af..307d0e3f 100644 --- a/absl/synchronization/mutex_test.cc +++ b/absl/synchronization/mutex_test.cc @@ -30,6 +30,7 @@ #include "gtest/gtest.h" #include "absl/base/attributes.h" +#include "absl/base/config.h" #include "absl/base/internal/raw_logging.h" #include "absl/base/internal/sysinfo.h" #include "absl/memory/memory.h" @@ -815,7 +816,7 @@ TEST(Mutex, MutexReaderDecrementBug) ABSL_NO_THREAD_SAFETY_ANALYSIS { // Test that we correctly handle the situation when a lock is // held and then destroyed (w/o unlocking). -#ifdef THREAD_SANITIZER +#ifdef ABSL_HAVE_THREAD_SANITIZER // TSAN reports errors when locked Mutexes are destroyed. TEST(Mutex, DISABLED_LockedMutexDestructionBug) NO_THREAD_SAFETY_ANALYSIS { #else @@ -1067,7 +1068,7 @@ class ScopedDisableBazelTestWarnings { const char ScopedDisableBazelTestWarnings::kVarName[] = "TEST_WARNINGS_OUTPUT_FILE"; -#ifdef THREAD_SANITIZER +#ifdef ABSL_HAVE_THREAD_SANITIZER // This test intentionally creates deadlocks to test the deadlock detector. TEST(Mutex, DISABLED_DeadlockDetectorBazelWarning) { #else @@ -1119,7 +1120,7 @@ TEST(Mutex, DeadlockDetectorStessTest) ABSL_NO_THREAD_SAFETY_ANALYSIS { } } -#ifdef THREAD_SANITIZER +#ifdef ABSL_HAVE_THREAD_SANITIZER // TSAN reports errors when locked Mutexes are destroyed. TEST(Mutex, DISABLED_DeadlockIdBug) NO_THREAD_SAFETY_ANALYSIS { #else diff --git a/absl/time/BUILD.bazel b/absl/time/BUILD.bazel index 9ab2adb8..1d69f598 100644 --- a/absl/time/BUILD.bazel +++ b/absl/time/BUILD.bazel @@ -70,6 +70,7 @@ cc_library( ], deps = [ ":time", + "//absl/base:config", "//absl/base:raw_logging_internal", "//absl/time/internal/cctz:time_zone", "@com_google_googletest//:gtest", diff --git a/absl/time/CMakeLists.txt b/absl/time/CMakeLists.txt index 853563e8..00bdd499 100644 --- a/absl/time/CMakeLists.txt +++ b/absl/time/CMakeLists.txt @@ -99,6 +99,7 @@ absl_cc_library( ${ABSL_DEFAULT_COPTS} DEPS absl::time + absl::config absl::raw_logging_internal absl::time_zone gmock diff --git a/absl/time/internal/test_util.cc b/absl/time/internal/test_util.cc index 9bffe121..9a485a07 100644 --- a/absl/time/internal/test_util.cc +++ b/absl/time/internal/test_util.cc @@ -18,6 +18,7 @@ #include #include +#include "absl/base/config.h" #include "absl/base/internal/raw_logging.h" #include "absl/time/internal/cctz/include/cctz/zone_info_source.h" diff --git a/ci/linux_clang-latest_libcxx_asan_bazel.sh b/ci/linux_clang-latest_libcxx_asan_bazel.sh index 0c250a62..2aed43cf 100755 --- a/ci/linux_clang-latest_libcxx_asan_bazel.sh +++ b/ci/linux_clang-latest_libcxx_asan_bazel.sh @@ -78,8 +78,6 @@ for std in ${STD}; do /usr/local/bin/bazel test ... \ --compilation_mode="${compilation_mode}" \ --copt="${exceptions_mode}" \ - --copt="-DADDRESS_SANITIZER" \ - --copt="-DUNDEFINED_BEHAVIOR_SANITIZER" \ --copt="-fsanitize=address" \ --copt="-fsanitize=float-divide-by-zero" \ --copt="-fsanitize=nullability" \ diff --git a/ci/linux_clang-latest_libcxx_tsan_bazel.sh b/ci/linux_clang-latest_libcxx_tsan_bazel.sh index c2eb5bae..b39eaf74 100755 --- a/ci/linux_clang-latest_libcxx_tsan_bazel.sh +++ b/ci/linux_clang-latest_libcxx_tsan_bazel.sh @@ -79,8 +79,6 @@ for std in ${STD}; do --build_tag_filters="-notsan" \ --compilation_mode="${compilation_mode}" \ --copt="${exceptions_mode}" \ - --copt="-DDYNAMIC_ANNOTATIONS_ENABLED=1" \ - --copt="-DTHREAD_SANITIZER" \ --copt="-fsanitize=thread" \ --copt="-fno-sanitize-blacklist" \ --copt=-Werror \ -- cgit v1.2.3 From 4b915e70929ca2d6152240facc83d3d38c5d5f28 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Mon, 19 Oct 2020 15:25:26 -0700 Subject: Export of internal Abseil changes -- 77c85460dc3c46593b231c5161ac55273bb0c7ef by Abseil Team : Support int128 in SimpleAtoi. PiperOrigin-RevId: 337946262 -- 0be53049ccf8309650e4e22f23b290e5f75ee828 by Gennadiy Rozental : Update build scripts to use --mount instead of --volume to mount the host data into a container. This is somewhat more verbose, but more readable and flexible. More importantly this is what docker documentation is recomending to use now. PiperOrigin-RevId: 337898761 -- 3bc877f1679fdf61ecbf4365287a0403cfc9b53e by Samuel Benzaquen : Add Cord constructor for constinit instances. PiperOrigin-RevId: 337871148 -- 8b87701892b9c325e78ad4e8e4f16b785a744622 by Chris Kennelly : Use the address of kSeed, rather than its value. We initialize kSeed with &kSeed, so these are equivalent, but kSeed requires a load from memory while &kSeed can be formed as a RIP-relative lea. PiperOrigin-RevId: 337868415 GitOrigin-RevId: 77c85460dc3c46593b231c5161ac55273bb0c7ef Change-Id: I3d06c18a123f1be29dad5801e8625952dc41cd95 --- CMake/AbseilDll.cmake | 1 + absl/hash/internal/hash.h | 7 ++ absl/strings/BUILD.bazel | 14 +++ absl/strings/CMakeLists.txt | 14 +++ absl/strings/cord.cc | 2 + absl/strings/cord.h | 26 ++++++ absl/strings/cord_test.cc | 82 ++++++++++++++++++ absl/strings/internal/cord_internal.h | 82 +++++++++++++++--- absl/strings/internal/string_constant.h | 70 +++++++++++++++ absl/strings/internal/string_constant_test.cc | 60 +++++++++++++ absl/strings/numbers.cc | 120 +++++++++++++++++++++++++- absl/strings/numbers.h | 7 ++ absl/strings/numbers_test.cc | 76 +++++++++++++++- ci/cmake_install_test.sh | 2 +- ci/linux_clang-latest_libcxx_asan_bazel.sh | 6 +- ci/linux_clang-latest_libcxx_bazel.sh | 6 +- ci/linux_clang-latest_libcxx_tsan_bazel.sh | 6 +- ci/linux_clang-latest_libstdcxx_bazel.sh | 6 +- ci/linux_gcc-4.9_libstdcxx_bazel.sh | 6 +- ci/linux_gcc-latest_libstdcxx_bazel.sh | 6 +- ci/linux_gcc-latest_libstdcxx_cmake.sh | 2 +- ci/linux_gcc_alpine_cmake.sh | 2 +- 22 files changed, 567 insertions(+), 36 deletions(-) create mode 100644 absl/strings/internal/string_constant.h create mode 100644 absl/strings/internal/string_constant_test.cc (limited to 'ci/linux_clang-latest_libcxx_tsan_bazel.sh') diff --git a/CMake/AbseilDll.cmake b/CMake/AbseilDll.cmake index d67c4399..e0ff2492 100644 --- a/CMake/AbseilDll.cmake +++ b/CMake/AbseilDll.cmake @@ -196,6 +196,7 @@ set(ABSL_INTERNAL_DLL_FILES "strings/internal/charconv_parse.cc" "strings/internal/charconv_parse.h" "strings/internal/stl_type_traits.h" + "strings/internal/string_constant.h" "strings/match.cc" "strings/match.h" "strings/numbers.cc" diff --git a/absl/hash/internal/hash.h b/absl/hash/internal/hash.h index 9e608f7c..b0132da2 100644 --- a/absl/hash/internal/hash.h +++ b/absl/hash/internal/hash.h @@ -855,7 +855,14 @@ class ABSL_DLL CityHashState // On other platforms this is still going to be non-deterministic but most // probably per-build and not per-process. ABSL_ATTRIBUTE_ALWAYS_INLINE static uint64_t Seed() { +#if (!defined(__clang__) || __clang_major__ > 11) && \ + !defined(__apple_build_version__) + return static_cast(reinterpret_cast(&kSeed)); +#else + // Workaround the absence of + // https://github.com/llvm/llvm-project/commit/bc15bf66dcca76cc06fe71fca35b74dc4d521021. return static_cast(reinterpret_cast(kSeed)); +#endif } static const void* const kSeed; diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel index 64a13cef..30a8dd28 100644 --- a/absl/strings/BUILD.bazel +++ b/absl/strings/BUILD.bazel @@ -54,6 +54,7 @@ cc_library( "ascii.h", "charconv.h", "escaping.h", + "internal/string_constant.h", "match.h", "numbers.h", "str_cat.h", @@ -222,6 +223,19 @@ cc_test( ], ) +cc_test( + name = "string_constant_test", + size = "small", + srcs = ["internal/string_constant_test.cc"], + copts = ABSL_TEST_COPTS, + visibility = ["//visibility:private"], + deps = [ + ":strings", + "//absl/meta:type_traits", + "@com_google_googletest//:gtest_main", + ], +) + cc_test( name = "string_view_benchmark", srcs = ["string_view_benchmark.cc"], diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt index d6c2126d..2b994a71 100644 --- a/absl/strings/CMakeLists.txt +++ b/absl/strings/CMakeLists.txt @@ -21,6 +21,7 @@ absl_cc_library( "ascii.h" "charconv.h" "escaping.h" + "internal/string_constant.h" "match.h" "numbers.h" "str_cat.h" @@ -158,6 +159,19 @@ absl_cc_test( gmock_main ) +absl_cc_test( + NAME + string_constant_test + SRCS + "internal/string_constant_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::strings + absl::type_traits + gmock_main +) + absl_cc_test( NAME string_view_test diff --git a/absl/strings/cord.cc b/absl/strings/cord.cc index 5092fd14..9efd1357 100644 --- a/absl/strings/cord.cc +++ b/absl/strings/cord.cc @@ -241,6 +241,7 @@ static void UnrefInternal(CordRep* rep) { absl::InlinedVector pending; while (true) { + assert(!rep->refcount.IsImmortal()); if (rep->tag == CONCAT) { CordRepConcat* rep_concat = rep->concat(); CordRep* right = rep_concat->right; @@ -256,6 +257,7 @@ static void UnrefInternal(CordRep* rep) { } } else if (rep->tag == EXTERNAL) { CordRepExternal* rep_external = rep->external(); + assert(rep_external->releaser_invoker != nullptr); rep_external->releaser_invoker(rep_external); rep = nullptr; } else if (rep->tag == SUBSTRING) { diff --git a/absl/strings/cord.h b/absl/strings/cord.h index 653a1181..5d5c897e 100644 --- a/absl/strings/cord.h +++ b/absl/strings/cord.h @@ -79,6 +79,7 @@ #include "absl/meta/type_traits.h" #include "absl/strings/internal/cord_internal.h" #include "absl/strings/internal/resize_uninitialized.h" +#include "absl/strings/internal/string_constant.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" @@ -624,6 +625,14 @@ class Cord { return c.HashFragmented(std::move(hash_state)); } + // Create a Cord with the contents of StringConstant::value. + // No allocations will be done and no data will be copied. + // This is an INTERNAL API and subject to change or removal. This API can only + // be used by spelling absl::strings_internal::MakeStringConstant, which is + // also an internal API. + template + explicit constexpr Cord(strings_internal::StringConstant); + private: friend class CordTestPeer; friend bool operator==(const Cord& lhs, const Cord& rhs); @@ -655,6 +664,8 @@ class Cord { InlineRep& operator=(const InlineRep& src); InlineRep& operator=(InlineRep&& src) noexcept; + explicit constexpr InlineRep(cord_internal::InlineData data); + void Swap(InlineRep* rhs); bool empty() const; size_t size() const; @@ -884,6 +895,9 @@ Cord MakeCordFromExternal(absl::string_view data, Releaser&& releaser) { return cord; } +constexpr Cord::InlineRep::InlineRep(cord_internal::InlineData data) + : data_(data) {} + inline Cord::InlineRep::InlineRep(const Cord::InlineRep& src) { data_ = src.data_; } @@ -981,6 +995,18 @@ inline void Cord::InlineRep::CopyToArray(char* dst) const { constexpr inline Cord::Cord() noexcept {} +template +constexpr Cord::Cord(strings_internal::StringConstant) + : contents_(strings_internal::StringConstant::value.size() <= + cord_internal::kMaxInline + ? cord_internal::InlineData( + strings_internal::StringConstant::value) + : cord_internal::InlineData(cord_internal::AsTree{ + &cord_internal::ConstInitExternalStorage< + strings_internal::StringConstant>::value, + {}, + cord_internal::kTreeFlag})) {} + inline Cord& Cord::operator=(const Cord& x) { contents_ = x.contents_; return *this; diff --git a/absl/strings/cord_test.cc b/absl/strings/cord_test.cc index dbed3e9a..7942bfc0 100644 --- a/absl/strings/cord_test.cc +++ b/absl/strings/cord_test.cc @@ -181,6 +181,8 @@ class CordTestPeer { const Cord& c, absl::FunctionRef callback) { c.ForEachChunk(callback); } + + static bool IsTree(const Cord& c) { return c.contents_.is_tree(); } }; ABSL_NAMESPACE_END @@ -1627,3 +1629,83 @@ TEST(CordDeathTest, Hardening) { EXPECT_DEATH_IF_SUPPORTED(static_cast(cord.chunk_end()->empty()), ""); EXPECT_DEATH_IF_SUPPORTED(++cord.chunk_end(), ""); } + +class AfterExitCordTester { + public: + bool Set(absl::Cord* cord, absl::string_view expected) { + cord_ = cord; + expected_ = expected; + return true; + } + + ~AfterExitCordTester() { + EXPECT_EQ(*cord_, expected_); + } + private: + absl::Cord* cord_; + absl::string_view expected_; +}; + +template +void TestConstinitConstructor(Str) { + const auto expected = Str::value; + // Defined before `cord` to be destroyed after it. + static AfterExitCordTester exit_tester; // NOLINT + ABSL_CONST_INIT static absl::Cord cord(Str{}); // NOLINT + static bool init_exit_tester = exit_tester.Set(&cord, expected); + (void)init_exit_tester; + + EXPECT_EQ(cord, expected); + // Copy the object and test the copy, and the original. + { + absl::Cord copy = cord; + EXPECT_EQ(copy, expected); + } + // The original still works + EXPECT_EQ(cord, expected); + + // Try making adding more structure to the tree. + { + absl::Cord copy = cord; + std::string expected_copy(expected); + for (int i = 0; i < 10; ++i) { + copy.Append(cord); + absl::StrAppend(&expected_copy, expected); + EXPECT_EQ(copy, expected_copy); + } + } + + // Make sure we are using the right branch during constant evaluation. + EXPECT_EQ(absl::CordTestPeer::IsTree(cord), cord.size() >= 16); + + for (int i = 0; i < 10; ++i) { + // Make a few more Cords from the same global rep. + // This tests what happens when the refcount for it gets below 1. + EXPECT_EQ(expected, absl::Cord(Str{})); + } +} + +constexpr int SimpleStrlen(const char* p) { + return *p ? 1 + SimpleStrlen(p + 1) : 0; +} + +struct ShortView { + constexpr absl::string_view operator()() const { + return absl::string_view("SSO string", SimpleStrlen("SSO string")); + } +}; + +struct LongView { + constexpr absl::string_view operator()() const { + return absl::string_view("String that does not fit SSO.", + SimpleStrlen("String that does not fit SSO.")); + } +}; + + +TEST(Cord, ConstinitConstructor) { + TestConstinitConstructor( + absl::strings_internal::MakeStringConstant(ShortView{})); + TestConstinitConstructor( + absl::strings_internal::MakeStringConstant(LongView{})); +} diff --git a/absl/strings/internal/cord_internal.h b/absl/strings/internal/cord_internal.h index 00b9baa9..aa91a691 100644 --- a/absl/strings/internal/cord_internal.h +++ b/absl/strings/internal/cord_internal.h @@ -33,14 +33,17 @@ namespace cord_internal { // Wraps std::atomic for reference counting. class Refcount { public: - Refcount() : count_{1} {} - ~Refcount() {} + constexpr Refcount() : count_{kRefIncrement} {} + struct Immortal {}; + explicit constexpr Refcount(Immortal) : count_(kImmortalTag) {} - // Increments the reference count by 1. Imposes no memory ordering. - inline void Increment() { count_.fetch_add(1, std::memory_order_relaxed); } + // Increments the reference count. Imposes no memory ordering. + inline void Increment() { + count_.fetch_add(kRefIncrement, std::memory_order_relaxed); + } // Asserts that the current refcount is greater than 0. If the refcount is - // greater than 1, decrements the reference count by 1. + // greater than 1, decrements the reference count. // // Returns false if there are no references outstanding; true otherwise. // Inserts barriers to ensure that state written before this method returns @@ -48,19 +51,24 @@ class Refcount { // false. inline bool Decrement() { int32_t refcount = count_.load(std::memory_order_acquire); - assert(refcount > 0); - return refcount != 1 && count_.fetch_sub(1, std::memory_order_acq_rel) != 1; + assert(refcount > 0 || refcount & kImmortalTag); + return refcount != kRefIncrement && + count_.fetch_sub(kRefIncrement, std::memory_order_acq_rel) != + kRefIncrement; } // Same as Decrement but expect that refcount is greater than 1. inline bool DecrementExpectHighRefcount() { - int32_t refcount = count_.fetch_sub(1, std::memory_order_acq_rel); - assert(refcount > 0); - return refcount != 1; + int32_t refcount = + count_.fetch_sub(kRefIncrement, std::memory_order_acq_rel); + assert(refcount > 0 || refcount & kImmortalTag); + return refcount != kRefIncrement; } // Returns the current reference count using acquire semantics. - inline int32_t Get() const { return count_.load(std::memory_order_acquire); } + inline int32_t Get() const { + return count_.load(std::memory_order_acquire) >> kImmortalShift; + } // Returns whether the atomic integer is 1. // If the reference count is used in the conventional way, a @@ -70,9 +78,27 @@ class Refcount { // performs the memory barrier needed for the owning thread // to act on the object, knowing that it has exclusive access to the // object. - inline bool IsOne() { return count_.load(std::memory_order_acquire) == 1; } + inline bool IsOne() { + return count_.load(std::memory_order_acquire) == kRefIncrement; + } + + bool IsImmortal() const { + return (count_.load(std::memory_order_relaxed) & kImmortalTag) != 0; + } private: + // We reserve the bottom bit to tag a reference count as immortal. + // By making it `1` we ensure that we never reach `0` when adding/subtracting + // `2`, thus it never looks as if it should be destroyed. + // These are used for the StringConstant constructor where we do not increase + // the refcount at construction time (due to constinit requirements) but we + // will still decrease it at destruction time to avoid branching on Unref. + enum { + kImmortalShift = 1, + kRefIncrement = 1 << kImmortalShift, + kImmortalTag = kRefIncrement - 1 + }; + std::atomic count_; }; @@ -97,6 +123,10 @@ enum CordRepKind { }; struct CordRep { + CordRep() = default; + constexpr CordRep(Refcount::Immortal immortal, size_t l) + : length(l), refcount(immortal), tag(EXTERNAL), data{} {} + // The following three fields have to be less than 32 bytes since // that is the smallest supported flat node size. size_t length; @@ -135,6 +165,12 @@ using ExternalReleaserInvoker = void (*)(CordRepExternal*); // External CordReps are allocated together with a type erased releaser. The // releaser is stored in the memory directly following the CordRepExternal. struct CordRepExternal : public CordRep { + CordRepExternal() = default; + explicit constexpr CordRepExternal(absl::string_view str) + : CordRep(Refcount::Immortal{}, str.size()), + base(str.data()), + releaser_invoker(nullptr) {} + const char* base; // Pointer to function that knows how to call and destroy the releaser. ExternalReleaserInvoker releaser_invoker; @@ -178,6 +214,14 @@ struct CordRepExternalImpl } }; +template +struct ConstInitExternalStorage { + ABSL_CONST_INIT static CordRepExternal value; +}; + +template +CordRepExternal ConstInitExternalStorage::value(Str::value); + enum { kMaxInline = 15, // Tag byte & kMaxInline means we are storing a pointer. @@ -195,9 +239,23 @@ struct AsTree { char padding[kMaxInline + 1 - sizeof(absl::cord_internal::CordRep*) - 1]; char tagged_size; }; + +constexpr char GetOrNull(absl::string_view data, size_t pos) { + return pos < data.size() ? data[pos] : '\0'; +} + union InlineData { constexpr InlineData() : as_chars{} {} explicit constexpr InlineData(AsTree tree) : as_tree(tree) {} + explicit constexpr InlineData(absl::string_view chars) + : as_chars{GetOrNull(chars, 0), GetOrNull(chars, 1), + GetOrNull(chars, 2), GetOrNull(chars, 3), + GetOrNull(chars, 4), GetOrNull(chars, 5), + GetOrNull(chars, 6), GetOrNull(chars, 7), + GetOrNull(chars, 8), GetOrNull(chars, 9), + GetOrNull(chars, 10), GetOrNull(chars, 11), + GetOrNull(chars, 12), GetOrNull(chars, 13), + GetOrNull(chars, 14), static_cast(chars.size())} {} AsTree as_tree; char as_chars[kMaxInline + 1]; diff --git a/absl/strings/internal/string_constant.h b/absl/strings/internal/string_constant.h new file mode 100644 index 00000000..b15f1d9b --- /dev/null +++ b/absl/strings/internal/string_constant.h @@ -0,0 +1,70 @@ +// Copyright 2020 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_STRINGS_INTERNAL_STRING_CONSTANT_H_ +#define ABSL_STRINGS_INTERNAL_STRING_CONSTANT_H_ + +#include "absl/meta/type_traits.h" +#include "absl/strings/string_view.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace strings_internal { + +// StringConstant represents a compile time string constant. +// It can be accessed via its `absl::string_view value` static member. +// It is guaranteed that the `string_view` returned has constant `.data()`, +// constant `.size()` and constant `value[i]` for all `0 <= i < .size()` +// +// The `T` is an opaque type. It is guaranteed that different string constants +// will have different values of `T`. This allows users to associate the string +// constant with other static state at compile time. +// +// Instances should be made using the `MakeStringConstant()` factory function +// below. +template +struct StringConstant { + private: + // Returns true if `view` points to constant data. + // Otherwise, it can't be constant evaluated. + static constexpr bool ValidateConstant(absl::string_view view) { + return view.empty() || 2 * view[0] != 1; + } + + public: + static constexpr absl::string_view value = T{}(); + constexpr absl::string_view operator()() const { return value; } + + static_assert(ValidateConstant(value), + "The input string_view must point to constant data."); +}; + +template +constexpr absl::string_view StringConstant::value; // NOLINT + +// Factory function for `StringConstant` instances. +// It supports callables that have a constexpr default constructor and a +// constexpr operator(). +// It must return an `absl::string_view` or `const char*` pointing to constant +// data. This is validated at compile time. +template +constexpr StringConstant MakeStringConstant(T) { + return {}; +} + +} // namespace strings_internal +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_STRINGS_INTERNAL_STRING_CONSTANT_H_ diff --git a/absl/strings/internal/string_constant_test.cc b/absl/strings/internal/string_constant_test.cc new file mode 100644 index 00000000..392833cf --- /dev/null +++ b/absl/strings/internal/string_constant_test.cc @@ -0,0 +1,60 @@ +// Copyright 2020 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. + +#include "absl/strings/internal/string_constant.h" + +#include "absl/meta/type_traits.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace { + +using absl::strings_internal::MakeStringConstant; + +struct Callable { + constexpr absl::string_view operator()() const { + return absl::string_view("Callable", 8); + } +}; + +TEST(StringConstant, Traits) { + constexpr auto str = MakeStringConstant(Callable{}); + using T = decltype(str); + + EXPECT_TRUE(std::is_empty::value); + EXPECT_TRUE(std::is_trivial::value); + EXPECT_TRUE(absl::is_trivially_default_constructible::value); + EXPECT_TRUE(absl::is_trivially_copy_constructible::value); + EXPECT_TRUE(absl::is_trivially_move_constructible::value); + EXPECT_TRUE(absl::is_trivially_destructible::value); +} + +TEST(StringConstant, MakeFromCallable) { + constexpr auto str = MakeStringConstant(Callable{}); + using T = decltype(str); + EXPECT_EQ(Callable{}(), T::value); + EXPECT_EQ(Callable{}(), str()); +} + +TEST(StringConstant, MakeFromStringConstant) { + // We want to make sure the StringConstant itself is a valid input to the + // factory function. + constexpr auto str = MakeStringConstant(Callable{}); + constexpr auto str2 = MakeStringConstant(str); + using T = decltype(str2); + EXPECT_EQ(Callable{}(), T::value); + EXPECT_EQ(Callable{}(), str2()); +} + +} // namespace diff --git a/absl/strings/numbers.cc b/absl/strings/numbers.cc index 68c26dd6..3da1059c 100644 --- a/absl/strings/numbers.cc +++ b/absl/strings/numbers.cc @@ -736,9 +736,18 @@ struct LookupTables { X / 35, X / 36, \ } +// This kVmaxOverBase is generated with +// for (int base = 2; base < 37; ++base) { +// absl::uint128 max = std::numeric_limits::max(); +// auto result = max / base; +// std::cout << " MakeUint128(" << absl::Uint128High64(result) << "u, " +// << absl::Uint128Low64(result) << "u),\n"; +// } +// See https://godbolt.org/z/aneYsb +// // uint128& operator/=(uint128) is not constexpr, so hardcode the resulting // array to avoid a static initializer. -template <> +template<> const uint128 LookupTables::kVmaxOverBase[] = { 0, 0, @@ -779,6 +788,111 @@ const uint128 LookupTables::kVmaxOverBase[] = { MakeUint128(512409557603043100u, 8198552921648689607u), }; +// This kVmaxOverBase generated with +// for (int base = 2; base < 37; ++base) { +// absl::int128 max = std::numeric_limits::max(); +// auto result = max / base; +// std::cout << "\tMakeInt128(" << absl::Int128High64(result) << ", " +// << absl::Int128Low64(result) << "u),\n"; +// } +// See https://godbolt.org/z/7djYWz +// +// int128& operator/=(int128) is not constexpr, so hardcode the resulting array +// to avoid a static initializer. +template<> +const int128 LookupTables::kVmaxOverBase[] = { + 0, + 0, + MakeInt128(4611686018427387903, 18446744073709551615u), + MakeInt128(3074457345618258602, 12297829382473034410u), + MakeInt128(2305843009213693951, 18446744073709551615u), + MakeInt128(1844674407370955161, 11068046444225730969u), + MakeInt128(1537228672809129301, 6148914691236517205u), + MakeInt128(1317624576693539401, 2635249153387078802u), + MakeInt128(1152921504606846975, 18446744073709551615u), + MakeInt128(1024819115206086200, 16397105843297379214u), + MakeInt128(922337203685477580, 14757395258967641292u), + MakeInt128(838488366986797800, 13415813871788764811u), + MakeInt128(768614336404564650, 12297829382473034410u), + MakeInt128(709490156681136600, 11351842506898185609u), + MakeInt128(658812288346769700, 10540996613548315209u), + MakeInt128(614891469123651720, 9838263505978427528u), + MakeInt128(576460752303423487, 18446744073709551615u), + MakeInt128(542551296285575047, 9765923333140350855u), + MakeInt128(512409557603043100, 8198552921648689607u), + MakeInt128(485440633518672410, 17475862806672206794u), + MakeInt128(461168601842738790, 7378697629483820646u), + MakeInt128(439208192231179800, 7027331075698876806u), + MakeInt128(419244183493398900, 6707906935894382405u), + MakeInt128(401016175515425035, 2406097053092550210u), + MakeInt128(384307168202282325, 6148914691236517205u), + MakeInt128(368934881474191032, 5902958103587056517u), + MakeInt128(354745078340568300, 5675921253449092804u), + MakeInt128(341606371735362066, 17763531330238827482u), + MakeInt128(329406144173384850, 5270498306774157604u), + MakeInt128(318047311615681924, 7633135478776366185u), + MakeInt128(307445734561825860, 4919131752989213764u), + MakeInt128(297528130221121800, 4760450083537948804u), + MakeInt128(288230376151711743, 18446744073709551615u), + MakeInt128(279496122328932600, 4471937957262921603u), + MakeInt128(271275648142787523, 14106333703424951235u), + MakeInt128(263524915338707880, 4216398645419326083u), + MakeInt128(256204778801521550, 4099276460824344803u), +}; + +// This kVminOverBase generated with +// for (int base = 2; base < 37; ++base) { +// absl::int128 min = std::numeric_limits::min(); +// auto result = min / base; +// std::cout << "\tMakeInt128(" << absl::Int128High64(result) << ", " +// << absl::Int128Low64(result) << "u),\n"; +// } +// +// See https://godbolt.org/z/7djYWz +// +// int128& operator/=(int128) is not constexpr, so hardcode the resulting array +// to avoid a static initializer. +template<> +const int128 LookupTables::kVminOverBase[] = { + 0, + 0, + MakeInt128(-4611686018427387904, 0u), + MakeInt128(-3074457345618258603, 6148914691236517206u), + MakeInt128(-2305843009213693952, 0u), + MakeInt128(-1844674407370955162, 7378697629483820647u), + MakeInt128(-1537228672809129302, 12297829382473034411u), + MakeInt128(-1317624576693539402, 15811494920322472814u), + MakeInt128(-1152921504606846976, 0u), + MakeInt128(-1024819115206086201, 2049638230412172402u), + MakeInt128(-922337203685477581, 3689348814741910324u), + MakeInt128(-838488366986797801, 5030930201920786805u), + MakeInt128(-768614336404564651, 6148914691236517206u), + MakeInt128(-709490156681136601, 7094901566811366007u), + MakeInt128(-658812288346769701, 7905747460161236407u), + MakeInt128(-614891469123651721, 8608480567731124088u), + MakeInt128(-576460752303423488, 0u), + MakeInt128(-542551296285575048, 8680820740569200761u), + MakeInt128(-512409557603043101, 10248191152060862009u), + MakeInt128(-485440633518672411, 970881267037344822u), + MakeInt128(-461168601842738791, 11068046444225730970u), + MakeInt128(-439208192231179801, 11419412998010674810u), + MakeInt128(-419244183493398901, 11738837137815169211u), + MakeInt128(-401016175515425036, 16040647020617001406u), + MakeInt128(-384307168202282326, 12297829382473034411u), + MakeInt128(-368934881474191033, 12543785970122495099u), + MakeInt128(-354745078340568301, 12770822820260458812u), + MakeInt128(-341606371735362067, 683212743470724134u), + MakeInt128(-329406144173384851, 13176245766935394012u), + MakeInt128(-318047311615681925, 10813608594933185431u), + MakeInt128(-307445734561825861, 13527612320720337852u), + MakeInt128(-297528130221121801, 13686293990171602812u), + MakeInt128(-288230376151711744, 0u), + MakeInt128(-279496122328932601, 13974806116446630013u), + MakeInt128(-271275648142787524, 4340410370284600381u), + MakeInt128(-263524915338707881, 14230345428290225533u), + MakeInt128(-256204778801521551, 14347467612885206813u), +}; + template const IntType LookupTables::kVmaxOverBase[] = X_OVER_BASE_INITIALIZER(std::numeric_limits::max()); @@ -948,6 +1062,10 @@ bool safe_strto64_base(absl::string_view text, int64_t* value, int base) { return safe_int_internal(text, value, base); } +bool safe_strto128_base(absl::string_view text, int128* value, int base) { + return safe_int_internal(text, value, base); +} + bool safe_strtou32_base(absl::string_view text, uint32_t* value, int base) { return safe_uint_internal(text, value, base); } diff --git a/absl/strings/numbers.h b/absl/strings/numbers.h index d872cca5..2e004b44 100644 --- a/absl/strings/numbers.h +++ b/absl/strings/numbers.h @@ -127,6 +127,8 @@ inline void PutTwoDigits(size_t i, char* buf) { // safe_strto?() functions for implementing SimpleAtoi() bool safe_strto32_base(absl::string_view text, int32_t* value, int base); bool safe_strto64_base(absl::string_view text, int64_t* value, int base); +bool safe_strto128_base(absl::string_view text, absl::int128* value, + int base); bool safe_strtou32_base(absl::string_view text, uint32_t* value, int base); bool safe_strtou64_base(absl::string_view text, uint64_t* value, int base); bool safe_strtou128_base(absl::string_view text, absl::uint128* value, @@ -255,6 +257,11 @@ ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view str, int_type* out) { return numbers_internal::safe_strtoi_base(str, out, 10); } +ABSL_MUST_USE_RESULT inline bool SimpleAtoi(absl::string_view str, + absl::int128* out) { + return numbers_internal::safe_strto128_base(str, out, 10); +} + ABSL_MUST_USE_RESULT inline bool SimpleAtoi(absl::string_view str, absl::uint128* out) { return numbers_internal::safe_strtou128_base(str, out, 10); diff --git a/absl/strings/numbers_test.cc b/absl/strings/numbers_test.cc index c2f03b63..4ab67fb6 100644 --- a/absl/strings/numbers_test.cc +++ b/absl/strings/numbers_test.cc @@ -251,7 +251,7 @@ TEST(Numbers, TestFastPrints) { template void VerifySimpleAtoiGood(in_val_type in_value, int_type exp_value) { std::string s; - // uint128 can be streamed but not StrCat'd + // (u)int128 can be streamed but not StrCat'd. absl::strings_internal::OStringStream(&s) << in_value; int_type x = static_cast(~exp_value); EXPECT_TRUE(SimpleAtoi(s, &x)) @@ -264,7 +264,9 @@ void VerifySimpleAtoiGood(in_val_type in_value, int_type exp_value) { template void VerifySimpleAtoiBad(in_val_type in_value) { - std::string s = absl::StrCat(in_value); + std::string s; + // (u)int128 can be streamed but not StrCat'd. + absl::strings_internal::OStringStream(&s) << in_value; int_type x; EXPECT_FALSE(SimpleAtoi(s, &x)); EXPECT_FALSE(SimpleAtoi(s.c_str(), &x)); @@ -347,6 +349,31 @@ TEST(NumbersTest, Atoi) { std::numeric_limits::max(), std::numeric_limits::max()); + // SimpleAtoi(absl::string_view, absl::int128) + VerifySimpleAtoiGood(0, 0); + VerifySimpleAtoiGood(42, 42); + VerifySimpleAtoiGood(-42, -42); + + VerifySimpleAtoiGood(std::numeric_limits::min(), + std::numeric_limits::min()); + VerifySimpleAtoiGood(std::numeric_limits::max(), + std::numeric_limits::max()); + VerifySimpleAtoiGood(std::numeric_limits::max(), + std::numeric_limits::max()); + VerifySimpleAtoiGood(std::numeric_limits::min(), + std::numeric_limits::min()); + VerifySimpleAtoiGood(std::numeric_limits::max(), + std::numeric_limits::max()); + VerifySimpleAtoiGood(std::numeric_limits::max(), + std::numeric_limits::max()); + VerifySimpleAtoiGood( + std::numeric_limits::min(), + std::numeric_limits::min()); + VerifySimpleAtoiGood( + std::numeric_limits::max(), + std::numeric_limits::max()); + VerifySimpleAtoiBad(std::numeric_limits::max()); + // Some other types VerifySimpleAtoiGood(-42, -42); VerifySimpleAtoiGood(-42, -42); @@ -725,6 +752,51 @@ TEST(stringtest, safe_strtou128_random) { EXPECT_FALSE(parse_func(s, &parsed_value, base)); } } +TEST(stringtest, safe_strto128_random) { + // random number generators don't work for int128, and + // int128 can be streamed but not StrCat'd, so this code must be custom + // implemented for int128, but is generally the same as what's above. + // test_random_integer_parse_base( + // &absl::numbers_internal::safe_strto128_base); + using RandomEngine = std::minstd_rand0; + using IntType = absl::int128; + constexpr auto parse_func = &absl::numbers_internal::safe_strto128_base; + + std::random_device rd; + RandomEngine rng(rd()); + std::uniform_int_distribution random_int64( + std::numeric_limits::min()); + std::uniform_int_distribution random_uint64( + std::numeric_limits::min()); + std::uniform_int_distribution random_base(2, 35); + + for (size_t i = 0; i < kNumRandomTests; ++i) { + int64_t high = random_int64(rng); + uint64_t low = random_uint64(rng); + IntType value = absl::MakeInt128(high, low); + + int base = random_base(rng); + std::string str_value; + EXPECT_TRUE(Itoa(value, base, &str_value)); + IntType parsed_value; + + // Test successful parse + EXPECT_TRUE(parse_func(str_value, &parsed_value, base)); + EXPECT_EQ(parsed_value, value); + + // Test overflow + std::string s; + absl::strings_internal::OStringStream(&s) + << std::numeric_limits::max() << value; + EXPECT_FALSE(parse_func(s, &parsed_value, base)); + + // Test underflow + s.clear(); + absl::strings_internal::OStringStream(&s) + << std::numeric_limits::min() << value; + EXPECT_FALSE(parse_func(s, &parsed_value, base)); + } +} TEST(stringtest, safe_strtou32_base) { for (int i = 0; strtouint32_test_cases()[i].str != nullptr; ++i) { diff --git a/ci/cmake_install_test.sh b/ci/cmake_install_test.sh index b31e4b8c..78eb41d9 100755 --- a/ci/cmake_install_test.sh +++ b/ci/cmake_install_test.sh @@ -24,7 +24,7 @@ source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh" readonly DOCKER_CONTAINER=${LINUX_GCC_LATEST_CONTAINER} time docker run \ - --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \ + --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \ --workdir=/abseil-cpp \ --tmpfs=/buildfs:exec \ --cap-add=SYS_PTRACE \ diff --git a/ci/linux_clang-latest_libcxx_asan_bazel.sh b/ci/linux_clang-latest_libcxx_asan_bazel.sh index 2aed43cf..da922a59 100755 --- a/ci/linux_clang-latest_libcxx_asan_bazel.sh +++ b/ci/linux_clang-latest_libcxx_asan_bazel.sh @@ -42,7 +42,7 @@ readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER} # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then - DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}" + DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}" # Bazel doesn't track changes to tools outside of the workspace # (e.g. /usr/bin/gcc), so by appending the docker container to the # remote_http_cache url, we make changes to the container part of @@ -55,7 +55,7 @@ fi # external dependencies first. # https://docs.bazel.build/versions/master/guide.html#distdir if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then - DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}" + DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}" BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" fi @@ -64,7 +64,7 @@ for std in ${STD}; do for exceptions_mode in ${EXCEPTIONS_MODE}; do echo "--------------------------------------------------------------------" time docker run \ - --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \ + --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \ --workdir=/abseil-cpp \ --cap-add=SYS_PTRACE \ --rm \ diff --git a/ci/linux_clang-latest_libcxx_bazel.sh b/ci/linux_clang-latest_libcxx_bazel.sh index eb04e69e..06eaac55 100755 --- a/ci/linux_clang-latest_libcxx_bazel.sh +++ b/ci/linux_clang-latest_libcxx_bazel.sh @@ -42,7 +42,7 @@ readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER} # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then - DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}" + DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}" # Bazel doesn't track changes to tools outside of the workspace # (e.g. /usr/bin/gcc), so by appending the docker container to the # remote_http_cache url, we make changes to the container part of @@ -55,7 +55,7 @@ fi # external dependencies first. # https://docs.bazel.build/versions/master/guide.html#distdir if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then - DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}" + DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}" BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" fi @@ -64,7 +64,7 @@ for std in ${STD}; do for exceptions_mode in ${EXCEPTIONS_MODE}; do echo "--------------------------------------------------------------------" time docker run \ - --volume="${ABSEIL_ROOT}:/abseil-cpp-ro:ro" \ + --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp-ro,readonly \ --tmpfs=/abseil-cpp \ --workdir=/abseil-cpp \ --cap-add=SYS_PTRACE \ diff --git a/ci/linux_clang-latest_libcxx_tsan_bazel.sh b/ci/linux_clang-latest_libcxx_tsan_bazel.sh index b39eaf74..b2e722c5 100755 --- a/ci/linux_clang-latest_libcxx_tsan_bazel.sh +++ b/ci/linux_clang-latest_libcxx_tsan_bazel.sh @@ -42,7 +42,7 @@ readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER} # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then - DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}" + DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}" # Bazel doesn't track changes to tools outside of the workspace # (e.g. /usr/bin/gcc), so by appending the docker container to the # remote_http_cache url, we make changes to the container part of @@ -55,7 +55,7 @@ fi # external dependencies first. # https://docs.bazel.build/versions/master/guide.html#distdir if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then - DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}" + DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}" BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" fi @@ -64,7 +64,7 @@ for std in ${STD}; do for exceptions_mode in ${EXCEPTIONS_MODE}; do echo "--------------------------------------------------------------------" time docker run \ - --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \ + --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \ --workdir=/abseil-cpp \ --cap-add=SYS_PTRACE \ --rm \ diff --git a/ci/linux_clang-latest_libstdcxx_bazel.sh b/ci/linux_clang-latest_libstdcxx_bazel.sh index 4e490676..f8ce3c6a 100755 --- a/ci/linux_clang-latest_libstdcxx_bazel.sh +++ b/ci/linux_clang-latest_libstdcxx_bazel.sh @@ -42,7 +42,7 @@ readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER} # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then - DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}" + DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}" # Bazel doesn't track changes to tools outside of the workspace # (e.g. /usr/bin/gcc), so by appending the docker container to the # remote_http_cache url, we make changes to the container part of @@ -55,7 +55,7 @@ fi # external dependencies first. # https://docs.bazel.build/versions/master/guide.html#distdir if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then - DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}" + DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}" BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" fi @@ -64,7 +64,7 @@ for std in ${STD}; do for exceptions_mode in ${EXCEPTIONS_MODE}; do echo "--------------------------------------------------------------------" time docker run \ - --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \ + --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \ --workdir=/abseil-cpp \ --cap-add=SYS_PTRACE \ --rm \ diff --git a/ci/linux_gcc-4.9_libstdcxx_bazel.sh b/ci/linux_gcc-4.9_libstdcxx_bazel.sh index 8e6540cf..16f927bd 100755 --- a/ci/linux_gcc-4.9_libstdcxx_bazel.sh +++ b/ci/linux_gcc-4.9_libstdcxx_bazel.sh @@ -42,7 +42,7 @@ readonly DOCKER_CONTAINER=${LINUX_GCC_49_CONTAINER} # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then - DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}" + DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}" # Bazel doesn't track changes to tools outside of the workspace # (e.g. /usr/bin/gcc), so by appending the docker container to the # remote_http_cache url, we make changes to the container part of @@ -55,7 +55,7 @@ fi # external dependencies first. # https://docs.bazel.build/versions/master/guide.html#distdir if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then - DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}" + DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}" BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" fi @@ -64,7 +64,7 @@ for std in ${STD}; do for exceptions_mode in ${EXCEPTIONS_MODE}; do echo "--------------------------------------------------------------------" time docker run \ - --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \ + --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \ --workdir=/abseil-cpp \ --cap-add=SYS_PTRACE \ --rm \ diff --git a/ci/linux_gcc-latest_libstdcxx_bazel.sh b/ci/linux_gcc-latest_libstdcxx_bazel.sh index b327405c..37d89d9f 100755 --- a/ci/linux_gcc-latest_libstdcxx_bazel.sh +++ b/ci/linux_gcc-latest_libstdcxx_bazel.sh @@ -42,7 +42,7 @@ readonly DOCKER_CONTAINER=${LINUX_GCC_LATEST_CONTAINER} # USE_BAZEL_CACHE=1 only works on Kokoro. # Without access to the credentials this won't work. if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then - DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}" + DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}" # Bazel doesn't track changes to tools outside of the workspace # (e.g. /usr/bin/gcc), so by appending the docker container to the # remote_http_cache url, we make changes to the container part of @@ -55,7 +55,7 @@ fi # external dependencies first. # https://docs.bazel.build/versions/master/guide.html#distdir if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then - DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}" + DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}" BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" fi @@ -64,7 +64,7 @@ for std in ${STD}; do for exceptions_mode in ${EXCEPTIONS_MODE}; do echo "--------------------------------------------------------------------" time docker run \ - --volume="${ABSEIL_ROOT}:/abseil-cpp-ro:ro" \ + --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp-ro,readonly \ --tmpfs=/abseil-cpp \ --workdir=/abseil-cpp \ --cap-add=SYS_PTRACE \ diff --git a/ci/linux_gcc-latest_libstdcxx_cmake.sh b/ci/linux_gcc-latest_libstdcxx_cmake.sh index 26415e23..1bf5fdab 100755 --- a/ci/linux_gcc-latest_libstdcxx_cmake.sh +++ b/ci/linux_gcc-latest_libstdcxx_cmake.sh @@ -45,7 +45,7 @@ for std in ${ABSL_CMAKE_CXX_STANDARDS}; do for compilation_mode in ${ABSL_CMAKE_BUILD_TYPES}; do for build_shared in ${ABSL_CMAKE_BUILD_SHARED}; do time docker run \ - --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \ + --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \ --workdir=/abseil-cpp \ --tmpfs=/buildfs:exec \ --cap-add=SYS_PTRACE \ diff --git a/ci/linux_gcc_alpine_cmake.sh b/ci/linux_gcc_alpine_cmake.sh index b3b8e7a7..c8f173da 100755 --- a/ci/linux_gcc_alpine_cmake.sh +++ b/ci/linux_gcc_alpine_cmake.sh @@ -45,7 +45,7 @@ for std in ${ABSL_CMAKE_CXX_STANDARDS}; do for compilation_mode in ${ABSL_CMAKE_BUILD_TYPES}; do for build_shared in ${ABSL_CMAKE_BUILD_SHARED}; do time docker run \ - --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \ + --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \ --workdir=/abseil-cpp \ --tmpfs=/buildfs:exec \ --cap-add=SYS_PTRACE \ -- cgit v1.2.3 From e9b9e38f67a008d66133535a72ada843bd66013f Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Wed, 28 Oct 2020 09:57:00 -0700 Subject: Export of internal Abseil changes -- 0e3e8be75b3ab243991c9b28a27623d86e4511e6 by Abseil Team : Add constructor overloads with signature (Mutex*, const Condition&) to MutexLock, ReaderMutexLock, WriterMutexLock, ReleasableMutexLock, MaybeMutexLock. These overloads call Mutex::LockWhen, Mutex::ReaderLockWhen, Mutex::WriterLockWhen. Using the guard classes with these new constructors replaces both manual LockWhen/Unlock sequences and the less-efficient, but popular current pattern of "absl::MutexLock lock(&mu); mu.Await(cond);". PiperOrigin-RevId: 339480213 -- ff999bc08360f5bd95557147c97b0e7b200fe3a8 by Jorg Brown : ConvertibleToStringView wastes a lot of cycles initializing members just to reset them immediately after. Only initialize the string storage when needed. This makes StrSplit() 0-30% faster depending on the use case. PiperOrigin-RevId: 339479046 -- 0a773bfb8bc141433a41388731357001fdb34881 by Derek Mauro : Remove the compiler upgrade fiasco inducing -Weverything -Werror. Switch to a curated set of warnings that may be expanded in the future. PiperOrigin-RevId: 339472677 -- eab54e3e11b126283d33f64c914b200038d215a4 by Abseil Team : Change execute permission to match presence of the shebang remove execute permission for cmake_common.sh add execute permission for conanfile.py PiperOrigin-RevId: 339453550 -- 7f9726fb605ed20f17f3e221dbce0df03d6904c6 by Abseil Team : Internal change PiperOrigin-RevId: 339385761 -- f3210dbee3e8a719cf31706963721722203f90e0 by Derek Mauro : Switch clang compiler detection to use to the Bazel supported mechanism When Abseil launched, we relied on the compiler string "llvm", which we manually set when we used the automatic crosstool generation by using the environment variable BAZEL_COMPILER. Today, Bazel detects clang and automatically sets the compiler string to "clang". Fixes #732 PiperOrigin-RevId: 339360688 -- 413211f59e5e671bf5774efa63ab4df185c74248 by Abseil Team : Minor comment clarifications and cosmetic tweaks. PiperOrigin-RevId: 339344301 GitOrigin-RevId: 0e3e8be75b3ab243991c9b28a27623d86e4511e6 Change-Id: Ia5b7224cd3d274c79ec7f5514fef63014f458f0f --- CMake/AbseilHelpers.cmake | 4 +- absl/BUILD.bazel | 13 ++-- absl/compiler_config_setting.bzl | 38 ---------- absl/copts/GENERATED_AbseilCopts.cmake | 107 +++++++------------------- absl/copts/GENERATED_copts.bzl | 107 +++++++------------------- absl/copts/configure_copts.bzl | 6 +- absl/copts/copts.py | 117 ++++++++++------------------- absl/debugging/BUILD.bazel | 6 +- absl/strings/internal/str_split_internal.h | 51 ++++++++----- absl/synchronization/mutex.h | 83 ++++++++++++++++---- absl/synchronization/mutex_test.cc | 34 +++++++++ ci/cmake_common.sh | 0 ci/linux_clang-latest_libcxx_asan_bazel.sh | 1 - ci/linux_clang-latest_libcxx_bazel.sh | 1 - ci/linux_clang-latest_libcxx_tsan_bazel.sh | 1 - ci/linux_clang-latest_libstdcxx_bazel.sh | 1 - conanfile.py | 0 17 files changed, 244 insertions(+), 326 deletions(-) delete mode 100644 absl/compiler_config_setting.bzl mode change 100755 => 100644 ci/cmake_common.sh mode change 100644 => 100755 conanfile.py (limited to 'ci/linux_clang-latest_libcxx_tsan_bazel.sh') diff --git a/CMake/AbseilHelpers.cmake b/CMake/AbseilHelpers.cmake index e63db3a8..c8060709 100644 --- a/CMake/AbseilHelpers.cmake +++ b/CMake/AbseilHelpers.cmake @@ -160,7 +160,7 @@ function(absl_cc_library) set(PC_CFLAGS "${PC_CFLAGS} ${cflag}") endif() endforeach() - FILE(GENERATE OUTPUT "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig/absl_${_NAME}.pc" CONTENT "\ + FILE(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/lib/pkgconfig/absl_${_NAME}.pc" CONTENT "\ prefix=${CMAKE_INSTALL_PREFIX}\n\ exec_prefix=\${prefix}\n\ libdir=\${prefix}/lib\n\ @@ -173,6 +173,8 @@ Version: ${PC_VERSION}\n\ Requires.private:${PC_DEPS}\n\ Libs: -L\${libdir} $ $<$>:-labsl_${_NAME}>\n\ Cflags: -I\${includedir}${PC_CFLAGS}\n") + INSTALL(FILES "${CMAKE_BINARY_DIR}/lib/pkgconfig/absl_${_NAME}.pc" + DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig") endif() endif() diff --git a/absl/BUILD.bazel b/absl/BUILD.bazel index 0b772df4..6da20c49 100644 --- a/absl/BUILD.bazel +++ b/absl/BUILD.bazel @@ -12,19 +12,16 @@ # 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( - ":compiler_config_setting.bzl", - "create_llvm_config", -) package(default_visibility = ["//visibility:public"]) licenses(["notice"]) -create_llvm_config( - name = "llvm_compiler", +config_setting( + name = "clang_compiler", + flag_values = { + "@bazel_tools//tools/cpp:compiler": "clang", + }, visibility = [":__subpackages__"], ) diff --git a/absl/compiler_config_setting.bzl b/absl/compiler_config_setting.bzl deleted file mode 100644 index 66962294..00000000 --- a/absl/compiler_config_setting.bzl +++ /dev/null @@ -1,38 +0,0 @@ -# -# Copyright 2018 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. - -"""Creates config_setting that allows selecting based on 'compiler' value.""" - -def create_llvm_config(name, visibility): - # The "do_not_use_tools_cpp_compiler_present" attribute exists to - # distinguish between older versions of Bazel that do not support - # "@bazel_tools//tools/cpp:compiler" flag_value, and newer ones that do. - # In the future, the only way to select on the compiler will be through - # flag_values{"@bazel_tools//tools/cpp:compiler"} and the else branch can - # be removed. - if hasattr(cc_common, "do_not_use_tools_cpp_compiler_present"): - native.config_setting( - name = name, - flag_values = { - "@bazel_tools//tools/cpp:compiler": "llvm", - }, - visibility = visibility, - ) - else: - native.config_setting( - name = name, - values = {"compiler": "llvm"}, - visibility = visibility, - ) diff --git a/absl/copts/GENERATED_AbseilCopts.cmake b/absl/copts/GENERATED_AbseilCopts.cmake index beb3799e..51742c9b 100644 --- a/absl/copts/GENERATED_AbseilCopts.cmake +++ b/absl/copts/GENERATED_AbseilCopts.cmake @@ -5,46 +5,6 @@ list(APPEND ABSL_CLANG_CL_FLAGS "/W3" - "-Wno-c++98-compat-pedantic" - "-Wno-conversion" - "-Wno-covered-switch-default" - "-Wno-deprecated" - "-Wno-disabled-macro-expansion" - "-Wno-double-promotion" - "-Wno-comma" - "-Wno-extra-semi" - "-Wno-extra-semi-stmt" - "-Wno-packed" - "-Wno-padded" - "-Wno-float-conversion" - "-Wno-float-equal" - "-Wno-format-nonliteral" - "-Wno-gcc-compat" - "-Wno-global-constructors" - "-Wno-exit-time-destructors" - "-Wno-non-modular-include-in-module" - "-Wno-old-style-cast" - "-Wno-range-loop-analysis" - "-Wno-reserved-id-macro" - "-Wno-shorten-64-to-32" - "-Wno-switch-enum" - "-Wno-thread-safety-negative" - "-Wno-unknown-warning-option" - "-Wno-unreachable-code" - "-Wno-unused-macros" - "-Wno-weak-vtables" - "-Wno-zero-as-null-pointer-constant" - "-Wbitfield-enum-conversion" - "-Wbool-conversion" - "-Wconstant-conversion" - "-Wenum-conversion" - "-Wint-conversion" - "-Wliteral-conversion" - "-Wnon-literal-null-conversion" - "-Wnull-conversion" - "-Wobjc-literal-conversion" - "-Wno-sign-conversion" - "-Wstring-conversion" "/DNOMINMAX" "/DWIN32_LEAN_AND_MEAN" "/D_CRT_SECURE_NO_WARNINGS" @@ -77,6 +37,7 @@ list(APPEND ABSL_GCC_FLAGS "-Wextra" "-Wcast-qual" "-Wconversion-null" + "-Wformat-security" "-Wmissing-declarations" "-Woverlength-strings" "-Wpointer-arith" @@ -86,7 +47,6 @@ list(APPEND ABSL_GCC_FLAGS "-Wvarargs" "-Wvla" "-Wwrite-strings" - "-Wno-missing-field-initializers" "-DNOMINMAX" ) @@ -103,47 +63,36 @@ list(APPEND ABSL_GCC_TEST_FLAGS list(APPEND ABSL_LLVM_FLAGS "-Wall" "-Wextra" - "-Weverything" - "-Wno-c++98-compat-pedantic" - "-Wno-conversion" - "-Wno-covered-switch-default" - "-Wno-deprecated" - "-Wno-disabled-macro-expansion" - "-Wno-double-promotion" - "-Wno-comma" - "-Wno-extra-semi" - "-Wno-extra-semi-stmt" - "-Wno-packed" - "-Wno-padded" + "-Wcast-qual" + "-Wconversion" + "-Wfloat-overflow-conversion" + "-Wfloat-zero-conversion" + "-Wfor-loop-analysis" + "-Wformat-security" + "-Wgnu-redeclared-enum" + "-Winfinite-recursion" + "-Wliteral-conversion" + "-Wmissing-declarations" + "-Woverlength-strings" + "-Wpointer-arith" + "-Wself-assign" + "-Wshadow" + "-Wstring-conversion" + "-Wtautological-overlap-compare" + "-Wundef" + "-Wuninitialized" + "-Wunreachable-code" + "-Wunused-comparison" + "-Wunused-local-typedefs" + "-Wunused-result" + "-Wvla" + "-Wwrite-strings" "-Wno-float-conversion" - "-Wno-float-equal" - "-Wno-format-nonliteral" - "-Wno-gcc-compat" - "-Wno-global-constructors" - "-Wno-exit-time-destructors" - "-Wno-non-modular-include-in-module" - "-Wno-old-style-cast" - "-Wno-range-loop-analysis" - "-Wno-reserved-id-macro" + "-Wno-implicit-float-conversion" + "-Wno-implicit-int-float-conversion" + "-Wno-implicit-int-conversion" "-Wno-shorten-64-to-32" - "-Wno-switch-enum" - "-Wno-thread-safety-negative" - "-Wno-unknown-warning-option" - "-Wno-unreachable-code" - "-Wno-unused-macros" - "-Wno-weak-vtables" - "-Wno-zero-as-null-pointer-constant" - "-Wbitfield-enum-conversion" - "-Wbool-conversion" - "-Wconstant-conversion" - "-Wenum-conversion" - "-Wint-conversion" - "-Wliteral-conversion" - "-Wnon-literal-null-conversion" - "-Wnull-conversion" - "-Wobjc-literal-conversion" "-Wno-sign-conversion" - "-Wstring-conversion" "-DNOMINMAX" ) diff --git a/absl/copts/GENERATED_copts.bzl b/absl/copts/GENERATED_copts.bzl index ff729d74..6707488f 100644 --- a/absl/copts/GENERATED_copts.bzl +++ b/absl/copts/GENERATED_copts.bzl @@ -6,46 +6,6 @@ ABSL_CLANG_CL_FLAGS = [ "/W3", - "-Wno-c++98-compat-pedantic", - "-Wno-conversion", - "-Wno-covered-switch-default", - "-Wno-deprecated", - "-Wno-disabled-macro-expansion", - "-Wno-double-promotion", - "-Wno-comma", - "-Wno-extra-semi", - "-Wno-extra-semi-stmt", - "-Wno-packed", - "-Wno-padded", - "-Wno-float-conversion", - "-Wno-float-equal", - "-Wno-format-nonliteral", - "-Wno-gcc-compat", - "-Wno-global-constructors", - "-Wno-exit-time-destructors", - "-Wno-non-modular-include-in-module", - "-Wno-old-style-cast", - "-Wno-range-loop-analysis", - "-Wno-reserved-id-macro", - "-Wno-shorten-64-to-32", - "-Wno-switch-enum", - "-Wno-thread-safety-negative", - "-Wno-unknown-warning-option", - "-Wno-unreachable-code", - "-Wno-unused-macros", - "-Wno-weak-vtables", - "-Wno-zero-as-null-pointer-constant", - "-Wbitfield-enum-conversion", - "-Wbool-conversion", - "-Wconstant-conversion", - "-Wenum-conversion", - "-Wint-conversion", - "-Wliteral-conversion", - "-Wnon-literal-null-conversion", - "-Wnull-conversion", - "-Wobjc-literal-conversion", - "-Wno-sign-conversion", - "-Wstring-conversion", "/DNOMINMAX", "/DWIN32_LEAN_AND_MEAN", "/D_CRT_SECURE_NO_WARNINGS", @@ -78,6 +38,7 @@ ABSL_GCC_FLAGS = [ "-Wextra", "-Wcast-qual", "-Wconversion-null", + "-Wformat-security", "-Wmissing-declarations", "-Woverlength-strings", "-Wpointer-arith", @@ -87,7 +48,6 @@ ABSL_GCC_FLAGS = [ "-Wvarargs", "-Wvla", "-Wwrite-strings", - "-Wno-missing-field-initializers", "-DNOMINMAX", ] @@ -104,47 +64,36 @@ ABSL_GCC_TEST_FLAGS = [ ABSL_LLVM_FLAGS = [ "-Wall", "-Wextra", - "-Weverything", - "-Wno-c++98-compat-pedantic", - "-Wno-conversion", - "-Wno-covered-switch-default", - "-Wno-deprecated", - "-Wno-disabled-macro-expansion", - "-Wno-double-promotion", - "-Wno-comma", - "-Wno-extra-semi", - "-Wno-extra-semi-stmt", - "-Wno-packed", - "-Wno-padded", + "-Wcast-qual", + "-Wconversion", + "-Wfloat-overflow-conversion", + "-Wfloat-zero-conversion", + "-Wfor-loop-analysis", + "-Wformat-security", + "-Wgnu-redeclared-enum", + "-Winfinite-recursion", + "-Wliteral-conversion", + "-Wmissing-declarations", + "-Woverlength-strings", + "-Wpointer-arith", + "-Wself-assign", + "-Wshadow", + "-Wstring-conversion", + "-Wtautological-overlap-compare", + "-Wundef", + "-Wuninitialized", + "-Wunreachable-code", + "-Wunused-comparison", + "-Wunused-local-typedefs", + "-Wunused-result", + "-Wvla", + "-Wwrite-strings", "-Wno-float-conversion", - "-Wno-float-equal", - "-Wno-format-nonliteral", - "-Wno-gcc-compat", - "-Wno-global-constructors", - "-Wno-exit-time-destructors", - "-Wno-non-modular-include-in-module", - "-Wno-old-style-cast", - "-Wno-range-loop-analysis", - "-Wno-reserved-id-macro", + "-Wno-implicit-float-conversion", + "-Wno-implicit-int-float-conversion", + "-Wno-implicit-int-conversion", "-Wno-shorten-64-to-32", - "-Wno-switch-enum", - "-Wno-thread-safety-negative", - "-Wno-unknown-warning-option", - "-Wno-unreachable-code", - "-Wno-unused-macros", - "-Wno-weak-vtables", - "-Wno-zero-as-null-pointer-constant", - "-Wbitfield-enum-conversion", - "-Wbool-conversion", - "-Wconstant-conversion", - "-Wenum-conversion", - "-Wint-conversion", - "-Wliteral-conversion", - "-Wnon-literal-null-conversion", - "-Wnull-conversion", - "-Wobjc-literal-conversion", "-Wno-sign-conversion", - "-Wstring-conversion", "-DNOMINMAX", ] diff --git a/absl/copts/configure_copts.bzl b/absl/copts/configure_copts.bzl index ff9a5ea9..4d342544 100644 --- a/absl/copts/configure_copts.bzl +++ b/absl/copts/configure_copts.bzl @@ -23,15 +23,13 @@ load( ABSL_DEFAULT_COPTS = select({ "//absl:windows": ABSL_MSVC_FLAGS, - "//absl:llvm_compiler": ABSL_LLVM_FLAGS, + "//absl:clang_compiler": ABSL_LLVM_FLAGS, "//conditions:default": ABSL_GCC_FLAGS, }) -# in absence of modules (--compiler=gcc or -c opt), cc_tests leak their copts -# to their (included header) dependencies and fail to build outside absl ABSL_TEST_COPTS = ABSL_DEFAULT_COPTS + select({ "//absl:windows": ABSL_MSVC_TEST_FLAGS, - "//absl:llvm_compiler": ABSL_LLVM_TEST_FLAGS, + "//absl:clang_compiler": ABSL_LLVM_TEST_FLAGS, "//conditions:default": ABSL_GCC_TEST_FLAGS, }) diff --git a/absl/copts/copts.py b/absl/copts/copts.py index 55b5fb10..cf52981c 100644 --- a/absl/copts/copts.py +++ b/absl/copts/copts.py @@ -16,73 +16,6 @@ MSVC_BIG_WARNING_FLAGS = [ "/W3", ] -LLVM_BIG_WARNING_FLAGS = [ - "-Wall", - "-Wextra", - "-Weverything", -] - -# Docs on single flags is preceded by a comment. -# Docs on groups of flags is preceded by ###. -LLVM_DISABLE_WARNINGS_FLAGS = [ - # Abseil does not support C++98 - "-Wno-c++98-compat-pedantic", - # Turns off all implicit conversion warnings. Most are re-enabled below. - "-Wno-conversion", - "-Wno-covered-switch-default", - "-Wno-deprecated", - "-Wno-disabled-macro-expansion", - "-Wno-double-promotion", - ### - # Turned off as they include valid C++ code. - "-Wno-comma", - "-Wno-extra-semi", - "-Wno-extra-semi-stmt", - "-Wno-packed", - "-Wno-padded", - ### - "-Wno-float-conversion", - "-Wno-float-equal", - "-Wno-format-nonliteral", - # Too aggressive: warns on Clang extensions enclosed in Clang-only - # compilation paths. - "-Wno-gcc-compat", - ### - # Some internal globals are necessary. Don't do this at home. - "-Wno-global-constructors", - "-Wno-exit-time-destructors", - ### - "-Wno-non-modular-include-in-module", - "-Wno-old-style-cast", - # Warns on preferred usage of non-POD types such as string_view - "-Wno-range-loop-analysis", - "-Wno-reserved-id-macro", - "-Wno-shorten-64-to-32", - "-Wno-switch-enum", - "-Wno-thread-safety-negative", - "-Wno-unknown-warning-option", - "-Wno-unreachable-code", - # Causes warnings on include guards - "-Wno-unused-macros", - "-Wno-weak-vtables", - # Causes warnings on usage of types/compare.h comparison operators. - "-Wno-zero-as-null-pointer-constant", - ### - # Implicit conversion warnings turned off by -Wno-conversion - # which are re-enabled below. - "-Wbitfield-enum-conversion", - "-Wbool-conversion", - "-Wconstant-conversion", - "-Wenum-conversion", - "-Wint-conversion", - "-Wliteral-conversion", - "-Wnon-literal-null-conversion", - "-Wnull-conversion", - "-Wobjc-literal-conversion", - "-Wno-sign-conversion", - "-Wstring-conversion", -] - LLVM_TEST_DISABLE_WARNINGS_FLAGS = [ "-Wno-c99-extensions", "-Wno-deprecated-declarations", @@ -121,6 +54,7 @@ COPT_VARS = { "-Wextra", "-Wcast-qual", "-Wconversion-null", + "-Wformat-security", "-Wmissing-declarations", "-Woverlength-strings", "-Wpointer-arith", @@ -130,10 +64,6 @@ 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", # Don't define min and max macros (Build on Windows using gcc) "-DNOMINMAX", ], @@ -146,15 +76,48 @@ COPT_VARS = { "-Wno-unused-parameter", "-Wno-unused-private-field", ], - "ABSL_LLVM_FLAGS": - LLVM_BIG_WARNING_FLAGS + LLVM_DISABLE_WARNINGS_FLAGS + [ - # Don't define min and max macros (Build on Windows using clang) - "-DNOMINMAX", - ], + "ABSL_LLVM_FLAGS": [ + "-Wall", + "-Wextra", + "-Wcast-qual", + "-Wconversion", + "-Wfloat-overflow-conversion", + "-Wfloat-zero-conversion", + "-Wfor-loop-analysis", + "-Wformat-security", + "-Wgnu-redeclared-enum", + "-Winfinite-recursion", + "-Wliteral-conversion", + "-Wmissing-declarations", + "-Woverlength-strings", + "-Wpointer-arith", + "-Wself-assign", + "-Wshadow", + "-Wstring-conversion", + "-Wtautological-overlap-compare", + "-Wundef", + "-Wuninitialized", + "-Wunreachable-code", + "-Wunused-comparison", + "-Wunused-local-typedefs", + "-Wunused-result", + "-Wvla", + "-Wwrite-strings", + # Warnings that are enabled by group warning flags like -Wall that we + # explicitly disable. + "-Wno-float-conversion", + "-Wno-implicit-float-conversion", + "-Wno-implicit-int-float-conversion", + "-Wno-implicit-int-conversion", + "-Wno-shorten-64-to-32", + "-Wno-sign-conversion", + # Don't define min and max macros (Build on Windows using clang) + "-DNOMINMAX", + ], "ABSL_LLVM_TEST_FLAGS": LLVM_TEST_DISABLE_WARNINGS_FLAGS, "ABSL_CLANG_CL_FLAGS": - (MSVC_BIG_WARNING_FLAGS + LLVM_DISABLE_WARNINGS_FLAGS + MSVC_DEFINES), + (MSVC_BIG_WARNING_FLAGS + MSVC_DEFINES), "ABSL_CLANG_CL_TEST_FLAGS": LLVM_TEST_DISABLE_WARNINGS_FLAGS, "ABSL_MSVC_FLAGS": diff --git a/absl/debugging/BUILD.bazel b/absl/debugging/BUILD.bazel index 86faac9b..cd6e4543 100644 --- a/absl/debugging/BUILD.bazel +++ b/absl/debugging/BUILD.bazel @@ -239,7 +239,7 @@ cc_library( # These targets exists for use in tests only, explicitly configuring the # LEAK_SANITIZER macro. It must be linked with -fsanitize=leak for lsan. ABSL_LSAN_LINKOPTS = select({ - "//absl:llvm_compiler": ["-fsanitize=leak"], + "//absl:clang_compiler": ["-fsanitize=leak"], "//conditions:default": [], }) @@ -249,7 +249,7 @@ cc_library( srcs = ["leak_check.cc"], hdrs = ["leak_check.h"], copts = select({ - "//absl:llvm_compiler": ["-DLEAK_SANITIZER"], + "//absl:clang_compiler": ["-DLEAK_SANITIZER"], "//conditions:default": [], }), linkopts = ABSL_DEFAULT_LINKOPTS, @@ -276,7 +276,7 @@ cc_test( name = "leak_check_test", srcs = ["leak_check_test.cc"], copts = select({ - "//absl:llvm_compiler": ["-DABSL_EXPECT_LEAK_SANITIZER"], + "//absl:clang_compiler": ["-DABSL_EXPECT_LEAK_SANITIZER"], "//conditions:default": [], }), linkopts = ABSL_LSAN_LINKOPTS + ABSL_DEFAULT_LINKOPTS, diff --git a/absl/strings/internal/str_split_internal.h b/absl/strings/internal/str_split_internal.h index 49ec5392..76924771 100644 --- a/absl/strings/internal/str_split_internal.h +++ b/absl/strings/internal/str_split_internal.h @@ -66,41 +66,56 @@ class ConvertibleToStringView { // Matches rvalue strings and moves their data to a member. ConvertibleToStringView(std::string&& s) // NOLINT(runtime/explicit) - : copy_(std::move(s)), value_(copy_) {} + : copy_(std::move(s)), value_(copy_), self_referential_(true) {} ConvertibleToStringView(const ConvertibleToStringView& other) - : copy_(other.copy_), - value_(other.IsSelfReferential() ? copy_ : other.value_) {} + : value_(other.value_), self_referential_(other.self_referential_) { + if (other.self_referential_) { + new (©_) std::string(other.copy_); + value_ = copy_; + } + } - ConvertibleToStringView(ConvertibleToStringView&& other) { - StealMembers(std::move(other)); + ConvertibleToStringView(ConvertibleToStringView&& other) + : value_(other.value_), self_referential_(other.self_referential_) { + if (other.self_referential_) { + new (©_) std::string(std::move(other.copy_)); + value_ = copy_; + } } ConvertibleToStringView& operator=(ConvertibleToStringView other) { - StealMembers(std::move(other)); + this->~ConvertibleToStringView(); + new (this) ConvertibleToStringView(std::move(other)); return *this; } absl::string_view value() const { return value_; } - private: - // Returns true if ctsp's value refers to its internal copy_ member. - bool IsSelfReferential() const { return value_.data() == copy_.data(); } + ~ConvertibleToStringView() { MaybeReleaseCopy(); } - void StealMembers(ConvertibleToStringView&& other) { - if (other.IsSelfReferential()) { - copy_ = std::move(other.copy_); - value_ = copy_; - other.value_ = other.copy_; - } else { - value_ = other.value_; + private: + void MaybeReleaseCopy() { + if (self_referential_) { + // An explicit destructor call cannot be a qualified name such as + // std::string. The "using" declaration works around this + // issue by creating an unqualified name for the destructor. + using string_type = std::string; + copy_.~string_type(); } } - + struct Unused { // MSVC disallows unions with only 1 member. + }; // Holds the data moved from temporary std::string arguments. Declared first // so that 'value' can refer to 'copy_'. - std::string copy_; + union { + std::string copy_; + Unused unused_; + }; + absl::string_view value_; + // true if value_ refers to the internal copy_ member. + bool self_referential_ = false; }; // An iterator that enumerates the parts of a string from a Splitter. The text diff --git a/absl/synchronization/mutex.h b/absl/synchronization/mutex.h index f686c4df..598d1e06 100644 --- a/absl/synchronization/mutex.h +++ b/absl/synchronization/mutex.h @@ -31,22 +31,23 @@ // // MutexLock - An RAII wrapper to acquire and release a `Mutex` for exclusive/ // write access within the current scope. +// // ReaderMutexLock // - An RAII wrapper to acquire and release a `Mutex` for shared/read // access within the current scope. // // WriterMutexLock -// - Alias for `MutexLock` above, designed for use in distinguishing -// reader and writer locks within code. +// - Effectively an alias for `MutexLock` above, designed for use in +// distinguishing reader and writer locks within code. // // In addition to simple mutex locks, this file also defines ways to perform // locking under certain conditions. // -// Condition - (Preferred) Used to wait for a particular predicate that -// depends on state protected by the `Mutex` to become true. -// CondVar - A lower-level variant of `Condition` that relies on -// application code to explicitly signal the `CondVar` when -// a condition has been met. +// Condition - (Preferred) Used to wait for a particular predicate that +// depends on state protected by the `Mutex` to become true. +// CondVar - A lower-level variant of `Condition` that relies on +// application code to explicitly signal the `CondVar` when +// a condition has been met. // // See below for more information on using `Condition` or `CondVar`. // @@ -506,22 +507,36 @@ class ABSL_LOCKABLE Mutex { // Example: // // Class Foo { -// +// public: // Foo::Bar* Baz() { -// MutexLock l(&lock_); +// MutexLock lock(&mu_); // ... // return bar; // } // // private: -// Mutex lock_; +// Mutex mu_; // }; class ABSL_SCOPED_LOCKABLE MutexLock { public: + // Constructors + + // Calls `mu->Lock()` and returns when that call returns. That is, `*mu` is + // guaranteed to be locked when this object is constructed. Requires that + // `mu` be dereferenceable. explicit MutexLock(Mutex *mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) { this->mu_->Lock(); } + // Like above, but calls `mu->LockWhen(cond)` instead. That is, in addition to + // the above, the condition given by `cond` is also guaranteed to hold when + // this object is constructed. + explicit MutexLock(Mutex *mu, const Condition &cond) + ABSL_EXCLUSIVE_LOCK_FUNCTION(mu) + : mu_(mu) { + this->mu_->LockWhen(cond); + } + MutexLock(const MutexLock &) = delete; // NOLINT(runtime/mutex) MutexLock(MutexLock&&) = delete; // NOLINT(runtime/mutex) MutexLock& operator=(const MutexLock&) = delete; @@ -543,6 +558,12 @@ class ABSL_SCOPED_LOCKABLE ReaderMutexLock { mu->ReaderLock(); } + explicit ReaderMutexLock(Mutex *mu, const Condition &cond) + ABSL_SHARED_LOCK_FUNCTION(mu) + : mu_(mu) { + mu->ReaderLockWhen(cond); + } + ReaderMutexLock(const ReaderMutexLock&) = delete; ReaderMutexLock(ReaderMutexLock&&) = delete; ReaderMutexLock& operator=(const ReaderMutexLock&) = delete; @@ -565,6 +586,12 @@ class ABSL_SCOPED_LOCKABLE WriterMutexLock { mu->WriterLock(); } + explicit WriterMutexLock(Mutex *mu, const Condition &cond) + ABSL_EXCLUSIVE_LOCK_FUNCTION(mu) + : mu_(mu) { + mu->WriterLockWhen(cond); + } + WriterMutexLock(const WriterMutexLock&) = delete; WriterMutexLock(WriterMutexLock&&) = delete; WriterMutexLock& operator=(const WriterMutexLock&) = delete; @@ -603,16 +630,26 @@ class ABSL_SCOPED_LOCKABLE WriterMutexLock { // `noexcept`; until then this requirement cannot be enforced in the // type system.) // -// Note: to use a `Condition`, you need only construct it and pass it within the -// appropriate `Mutex' member function, such as `Mutex::Await()`. +// Note: to use a `Condition`, you need only construct it and pass it to a +// suitable `Mutex' member function, such as `Mutex::Await()`, or to the +// constructor of one of the scope guard classes. // -// Example: +// Example using LockWhen/Unlock: // // // assume count_ is not internal reference count // int count_ ABSL_GUARDED_BY(mu_); +// Condition count_is_zero(+[](int *count) { return *count == 0; }, &count_); // -// mu_.LockWhen(Condition(+[](int* count) { return *count == 0; }, -// &count_)); +// mu_.LockWhen(count_is_zero); +// // ... +// mu_.Unlock(); +// +// Example using a scope guard: +// +// { +// MutexLock lock(&mu_, count_is_zero); +// // ... +// } // // When multiple threads are waiting on exactly the same condition, make sure // that they are constructed with the same parameters (same pointer to function @@ -844,6 +881,15 @@ class ABSL_SCOPED_LOCKABLE MutexLockMaybe { this->mu_->Lock(); } } + + explicit MutexLockMaybe(Mutex *mu, const Condition &cond) + ABSL_EXCLUSIVE_LOCK_FUNCTION(mu) + : mu_(mu) { + if (this->mu_ != nullptr) { + this->mu_->LockWhen(cond); + } + } + ~MutexLockMaybe() ABSL_UNLOCK_FUNCTION() { if (this->mu_ != nullptr) { this->mu_->Unlock(); } } @@ -866,6 +912,13 @@ class ABSL_SCOPED_LOCKABLE ReleasableMutexLock { : mu_(mu) { this->mu_->Lock(); } + + explicit ReleasableMutexLock(Mutex *mu, const Condition &cond) + ABSL_EXCLUSIVE_LOCK_FUNCTION(mu) + : mu_(mu) { + this->mu_->LockWhen(cond); + } + ~ReleasableMutexLock() ABSL_UNLOCK_FUNCTION() { if (this->mu_ != nullptr) { this->mu_->Unlock(); } } diff --git a/absl/synchronization/mutex_test.cc b/absl/synchronization/mutex_test.cc index 66d5f2aa..058f757b 100644 --- a/absl/synchronization/mutex_test.cc +++ b/absl/synchronization/mutex_test.cc @@ -707,6 +707,40 @@ TEST(Mutex, LockWhen) { t.join(); } +TEST(Mutex, LockWhenGuard) { + absl::Mutex mu; + int n = 30; + bool done = false; + + // We don't inline the lambda because the conversion is ambiguous in MSVC. + bool (*cond_eq_10)(int *) = [](int *p) { return *p == 10; }; + bool (*cond_lt_10)(int *) = [](int *p) { return *p < 10; }; + + std::thread t1([&mu, &n, &done, cond_eq_10]() { + absl::ReaderMutexLock lock(&mu, absl::Condition(cond_eq_10, &n)); + done = true; + }); + + std::thread t2[10]; + for (std::thread &t : t2) { + t = std::thread([&mu, &n, cond_lt_10]() { + absl::WriterMutexLock lock(&mu, absl::Condition(cond_lt_10, &n)); + ++n; + }); + } + + { + absl::MutexLock lock(&mu); + n = 0; + } + + for (std::thread &t : t2) t.join(); + t1.join(); + + EXPECT_TRUE(done); + EXPECT_EQ(n, 10); +} + // -------------------------------------------------------- // The following test requires Mutex::ReaderLock to be a real shared // lock, which is not the case in all builds. diff --git a/ci/cmake_common.sh b/ci/cmake_common.sh old mode 100755 new mode 100644 diff --git a/ci/linux_clang-latest_libcxx_asan_bazel.sh b/ci/linux_clang-latest_libcxx_asan_bazel.sh index da922a59..ffbb8327 100755 --- a/ci/linux_clang-latest_libcxx_asan_bazel.sh +++ b/ci/linux_clang-latest_libcxx_asan_bazel.sh @@ -69,7 +69,6 @@ for std in ${STD}; do --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" \ diff --git a/ci/linux_clang-latest_libcxx_bazel.sh b/ci/linux_clang-latest_libcxx_bazel.sh index 06eaac55..f6a2221e 100755 --- a/ci/linux_clang-latest_libcxx_bazel.sh +++ b/ci/linux_clang-latest_libcxx_bazel.sh @@ -70,7 +70,6 @@ for std in ${STD}; do --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" \ diff --git a/ci/linux_clang-latest_libcxx_tsan_bazel.sh b/ci/linux_clang-latest_libcxx_tsan_bazel.sh index b2e722c5..e70e8214 100755 --- a/ci/linux_clang-latest_libcxx_tsan_bazel.sh +++ b/ci/linux_clang-latest_libcxx_tsan_bazel.sh @@ -69,7 +69,6 @@ for std in ${STD}; do --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-tsan/lib:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/libcxx-tsan/lib" \ -e CPLUS_INCLUDE_PATH="/opt/llvm/libcxx-tsan/include/c++/v1" \ diff --git a/ci/linux_clang-latest_libstdcxx_bazel.sh b/ci/linux_clang-latest_libstdcxx_bazel.sh index f8ce3c6a..0986ff40 100755 --- a/ci/linux_clang-latest_libstdcxx_bazel.sh +++ b/ci/linux_clang-latest_libstdcxx_bazel.sh @@ -69,7 +69,6 @@ for std in ${STD}; do --cap-add=SYS_PTRACE \ --rm \ -e CC="/opt/llvm/clang/bin/clang" \ - -e BAZEL_COMPILER="llvm" \ -e BAZEL_CXXOPTS="-std=${std}" \ ${DOCKER_EXTRA_ARGS:-} \ ${DOCKER_CONTAINER} \ diff --git a/conanfile.py b/conanfile.py old mode 100644 new mode 100755 -- cgit v1.2.3