Export of internal Abseil changes

--
8e75347c10d85112296811be6ef35761744ad9bc by Derek Mauro <dmauro@google.com>:

Big update to LTS release process
  * Add create_lts.py script to to the LTS modification
    This is simpler than copybara since very few changes are needed
  * Use the default installation paths instead of a versioned path.
    If a versioned path is needed, this is easy to change on the commandline.
  * Make the integration test use the LTS transformed version
  * Test both static and dynamic linking (fixes pkg-config dynamic linking)

PiperOrigin-RevId: 363566934

--
e00e971a2de3138861f5e1900201c9cc7788f714 by Laramie Leavitt <lar@google.com>:

Add a non-compile test to absl::BitGenRef for temporaries.

PiperOrigin-RevId: 363437284

--
3685644ec115d99789de32aceb76c32a00756fea by Derek Mauro <dmauro@google.com>:

Make OSS code consistent with internal code by using the forward
declaration of absl::Status that contains ABSL_MUST_USE_RESULT.

PiperOrigin-RevId: 363426906

--
b85fec142c3aa3f632fa985f9f8f73a253819723 by Evan Brown <ezb@google.com>:

Move raw_hash_set::infoz_ into raw_hash_set::settings_. This reduces the size of raw_hash_sets by alignof(size_t) bytes when hashtablez is disabled.

PiperOrigin-RevId: 363034264

--
c6fde3b17e5845191eb8b2bfc1760c8bfb9573ff by Mark Barolak <mbar@google.com>:

Internal change

PiperOrigin-RevId: 362990378

--
81713cf964905b43d1cbe32ce5fed97539029625 by Abseil Team <absl-team@google.com>:

Fix typo in comment (execeptions -> exceptions).

PiperOrigin-RevId: 362946191

--
3ee92ca470feca44da417b03ee45a915c6eb5155 by Abseil Team <absl-team@google.com>:

Add absl::FindAndReportLeaks and routes it to the corresponding
__lsan_do_recoverable_leak_check.

PiperOrigin-RevId: 362622199

--
b95b7194b20e02c20d72289fbc79a0d35b82e256 by Abseil Team <absl-team@google.com>:

Add `kWithEverything` to StatusToStringMode

PiperOrigin-RevId: 362595218

--
0a960d96a0014eab7e1c55b479269450ed8e98d7 by Abseil Team <absl-team@google.com>:

Accept e.g. ".__uniq" as a valid clone name.  Further, bring the implementation
on par with libiberty's demangler grammar.

Clang introduced option -funique-internal-linkage-names that adds the suffix
".__uniq.[0-9]+" to internal linkage functions to give them a globally unique
identifier.  The suffix was designed to work with existing demanglers which do
recognize a "_" along with the alphanumeric string. This change enhances the
demangler to allow "_" with the alphanumeric string.

Please refer to libiberty's cp-demangle.c where function d_clone_suffix
implements the demangling of clone suffixes :

1.  '_' is accepted as a valid character with the alphanumeric sequence.
2.  The alphanumberic sequence is optional.
3.  The digit sequence is optional.

PiperOrigin-RevId: 362557420

--
2ac5ea212c150afd2f58025a5cab8c45d16949c6 by Abseil Team <absl-team@google.com>:

Change variable name 'slots' to 'slot_count' to avoid name-clash with Qt builds.

PiperOrigin-RevId: 362556289

--
934f0f409c9c548716a46363d6e243406fad4028 by Mark Barolak <mbar@google.com>:

Clarify the comment on ABSL_CACHELINE_SIZE to indicate that the macro definition itself shouldn't change, but rather that call sites should change when possible.

This addresses the request for improved documentation in https://github.com/abseil/abseil-cpp/pull/842.

PiperOrigin-RevId: 362354288
GitOrigin-RevId: 8e75347c10d85112296811be6ef35761744ad9bc
Change-Id: I33ec8561d8d645c3353e9d2dd447501d0e1825a7
pull/920/head
Abseil Team 4 years ago committed by Dino Radaković
parent 2e9532cc6c
commit dcf4899377
  1. 9
      CMake/AbseilDll.cmake
  2. 22
      CMake/AbseilHelpers.cmake
  3. 20
      CMake/AbseilInstallDirs.cmake
  4. 138
      CMake/install_test_project/test.sh
  5. 14
      CMakeLists.txt
  6. 5
      absl/base/optimization.h
  7. 8
      absl/container/internal/btree.h
  8. 57
      absl/container/internal/raw_hash_set.h
  9. 39
      absl/container/internal/raw_hash_set_test.cc
  10. 28
      absl/debugging/internal/demangle.cc
  11. 30
      absl/debugging/internal/demangle_test.cc
  12. 1
      absl/debugging/leak_check.cc
  13. 13
      absl/debugging/leak_check.h
  14. 11
      absl/status/internal/status_internal.h
  15. 9
      absl/status/status.h
  16. 4
      absl/status/status_test.cc
  17. 2
      absl/status/statusor.h
  18. 1
      absl/strings/numbers.h
  19. 18
      ci/cmake_install_test.sh
  20. 121
      create_lts.py

@ -1,4 +1,5 @@
include(CMakeParseArguments)
include(GNUInstallDirs)
set(ABSL_INTERNAL_DLL_FILES
"algorithm/algorithm.h"
@ -500,7 +501,7 @@ function(absl_make_dll)
abseil_dll
PUBLIC
"$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>"
$<INSTALL_INTERFACE:${ABSL_INSTALL_INCLUDEDIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
target_compile_options(
@ -518,8 +519,8 @@ function(absl_make_dll)
${ABSL_CC_LIB_DEFINES}
)
install(TARGETS abseil_dll EXPORT ${PROJECT_NAME}Targets
RUNTIME DESTINATION ${ABSL_INSTALL_BINDIR}
LIBRARY DESTINATION ${ABSL_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${ABSL_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
endfunction()

@ -17,7 +17,6 @@
include(CMakeParseArguments)
include(AbseilConfigureCopts)
include(AbseilDll)
include(AbseilInstallDirs)
# The IDE folder for Abseil that will be used if Abseil is included in a CMake
# project that sets
@ -151,6 +150,10 @@ function(absl_cc_library)
endif()
foreach(dep ${ABSL_CC_LIB_DEPS})
if(${dep} MATCHES "^absl::(.*)")
# Join deps with commas.
if(PC_DEPS)
set(PC_DEPS "${PC_DEPS},")
endif()
set(PC_DEPS "${PC_DEPS} absl_${CMAKE_MATCH_1} = ${PC_VERSION}")
endif()
endforeach()
@ -167,14 +170,14 @@ function(absl_cc_library)
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\
includedir=\${prefix}/include\n\
libdir=\${prefix}/${CMAKE_INSTALL_LIBDIR}\n\
includedir=\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}\n\
\n\
Name: absl_${_NAME}\n\
Description: Abseil ${_NAME} library\n\
URL: https://abseil.io/\n\
Version: ${PC_VERSION}\n\
Requires.private:${PC_DEPS}\n\
Requires:${PC_DEPS}\n\
Libs: -L\${libdir} $<JOIN:${ABSL_CC_LIB_LINKOPTS}, > $<$<NOT:$<BOOL:${ABSL_CC_LIB_IS_INTERFACE}>>:-labsl_${_NAME}>\n\
Cflags: -I\${includedir}${PC_CFLAGS}\n")
INSTALL(FILES "${CMAKE_BINARY_DIR}/lib/pkgconfig/absl_${_NAME}.pc"
@ -235,7 +238,7 @@ Cflags: -I\${includedir}${PC_CFLAGS}\n")
target_include_directories(${_NAME}
PUBLIC
"$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>"
$<INSTALL_INTERFACE:${ABSL_INSTALL_INCLUDEDIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
target_compile_options(${_NAME}
PRIVATE ${ABSL_CC_LIB_COPTS})
@ -260,7 +263,6 @@ Cflags: -I\${includedir}${PC_CFLAGS}\n")
if(ABSL_ENABLE_INSTALL)
set_target_properties(${_NAME} PROPERTIES
OUTPUT_NAME "absl_${_NAME}"
# TODO(b/173696973): Figure out how to set SOVERSION for LTS releases.
SOVERSION 0
)
endif()
@ -270,7 +272,7 @@ Cflags: -I\${includedir}${PC_CFLAGS}\n")
target_include_directories(${_NAME}
INTERFACE
"$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>"
$<INSTALL_INTERFACE:${ABSL_INSTALL_INCLUDEDIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
if (_build_type STREQUAL "dll")
@ -290,9 +292,9 @@ Cflags: -I\${includedir}${PC_CFLAGS}\n")
# installed abseil can't be tested.
if(NOT ABSL_CC_LIB_TESTONLY AND ABSL_ENABLE_INSTALL)
install(TARGETS ${_NAME} EXPORT ${PROJECT_NAME}Targets
RUNTIME DESTINATION ${ABSL_INSTALL_BINDIR}
LIBRARY DESTINATION ${ABSL_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${ABSL_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
endif()

@ -1,20 +0,0 @@
include(GNUInstallDirs)
# absl_VERSION is only set if we are an LTS release being installed, in which
# case it may be into a system directory and so we need to make subdirectories
# for each installed version of Abseil. This mechanism is implemented in
# Abseil's internal Copybara (https://github.com/google/copybara) workflows and
# isn't visible in the CMake buildsystem itself.
if(absl_VERSION)
set(ABSL_SUBDIR "${PROJECT_NAME}_${PROJECT_VERSION}")
set(ABSL_INSTALL_BINDIR "${CMAKE_INSTALL_BINDIR}/${ABSL_SUBDIR}")
set(ABSL_INSTALL_CONFIGDIR "${CMAKE_INSTALL_LIBDIR}/cmake/${ABSL_SUBDIR}")
set(ABSL_INSTALL_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}/${ABSL_SUBDIR}")
set(ABSL_INSTALL_LIBDIR "${CMAKE_INSTALL_LIBDIR}/${ABSL_SUBDIR}")
else()
set(ABSL_INSTALL_BINDIR "${CMAKE_INSTALL_BINDIR}")
set(ABSL_INSTALL_CONFIGDIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
set(ABSL_INSTALL_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}")
set(ABSL_INSTALL_LIBDIR "${CMAKE_INSTALL_LIBDIR}")
endif()

@ -13,70 +13,44 @@
# 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.
# "Unit" and integration tests for Absl CMake installation
# TODO(absl-team): This script isn't fully hermetic because
# -DABSL_USE_GOOGLETEST_HEAD=ON means that this script isn't pinned to a fixed
# version of GoogleTest. This means that an upstream change to GoogleTest could
# break this test. Fix this by allowing this script to pin to a known-good
# version of GoogleTest.
#
# Unit and integration tests for Abseil LTS CMake installation
# Fail on any error. Treat unset variables an error. Print commands as executed.
set -euox pipefail
install_absl() {
pushd "${absl_build_dir}"
if [[ "${#}" -eq 1 ]]; then
cmake -DCMAKE_INSTALL_PREFIX="${1}" "${absl_dir}"
else
cmake "${absl_dir}"
fi
cmake --build . --target install -- -j
popd
}
uninstall_absl() {
xargs rm < "${absl_build_dir}"/install_manifest.txt
rm -rf "${absl_build_dir}"
mkdir -p "${absl_build_dir}"
}
lts_install=""
while getopts ":l" lts; do
case "${lts}" in
l )
lts_install="true"
;;
esac
done
source ci/cmake_common.sh
absl_dir=/abseil-cpp
absl_build_dir=/buildfs/absl-build
absl_build_dir=/buildfs
project_dir="${absl_dir}"/CMake/install_test_project
project_build_dir=/buildfs/project-build
mkdir -p "${absl_build_dir}"
mkdir -p "${project_build_dir}"
if [[ "${lts_install}" ]]; then
install_dir="/usr/local"
else
install_dir="${project_build_dir}"/install
build_shared_libs="OFF"
if [ "${LINK_TYPE:-}" = "DYNAMIC" ]; then
build_shared_libs="ON"
fi
mkdir -p "${install_dir}"
# Test build, install, and link against installed abseil
pushd "${project_build_dir}"
if [[ "${lts_install}" ]]; then
install_absl
cmake "${project_dir}"
else
install_absl "${install_dir}"
cmake "${project_dir}" -DCMAKE_PREFIX_PATH="${install_dir}"
fi
# Run the LTS transformations
./create_lts.py 99998877
# Install Abseil
pushd "${absl_build_dir}"
cmake "${absl_dir}" \
-DABSL_GOOGLETEST_DOWNLOAD_URL="${ABSL_GOOGLETEST_DOWNLOAD_URL}" \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_TESTING=ON \
-DBUILD_SHARED_LIBS="${build_shared_libs}"
make -j $(nproc)
ctest -j $(nproc)
make install
ldconfig
popd
# Test the project against the installed Abseil
mkdir -p "${project_build_dir}"
pushd "${project_build_dir}"
cmake "${project_dir}"
cmake --build . --target simple
output="$(${project_build_dir}/simple "printme" 2>&1)"
@ -88,32 +62,8 @@ fi
popd
# Test that we haven't accidentally made absl::abslblah
pushd "${install_dir}"
# Starting in CMake 3.12 the default install dir is lib$bit_width
if [[ -d lib64 ]]; then
libdir="lib64"
elif [[ -d lib ]]; then
libdir="lib"
else
echo "ls *, */*, */*/*:"
ls *
ls */*
ls */*/*
echo "unknown lib dir"
fi
if [[ "${lts_install}" ]]; then
# LTS versions append the date of the release to the subdir.
# 9999/99/99 is the dummy date used in the local_lts workflow.
absl_subdir="absl_99999999"
else
absl_subdir="absl"
fi
if ! grep absl::strings "${libdir}/cmake/${absl_subdir}/abslTargets.cmake"; then
cat "${libdir}"/cmake/absl/abslTargets.cmake
if ! grep absl::strings "/usr/local/lib/cmake/absl/abslTargets.cmake"; then
cat "/usr/local/lib/cmake/absl/abslTargets.cmake"
echo "CMake targets named incorrectly"
exit 1
fi
@ -129,34 +79,18 @@ int main(int argc, char **argv) {
return EXIT_SUCCESS;
}
EOF
export PKG_CONFIG_PATH="${install_dir}/${libdir}/pkgconfig"
pc_args=($(pkg-config --cflags --libs --static absl_str_format))
g++ -static -o hello-abseil hello-abseil.cc "${pc_args[@]}"
if [ "${LINK_TYPE:-}" != "DYNAMIC" ]; then
pc_args=($(pkg-config --cflags --libs --static absl_str_format))
g++ -static -o hello-abseil hello-abseil.cc "${pc_args[@]}"
else
pc_args=($(pkg-config --cflags --libs absl_str_format))
g++ -o hello-abseil hello-abseil.cc "${pc_args[@]}"
fi
hello="$(./hello-abseil)"
[[ "${hello}" == "Hello Abseil!" ]]
popd
uninstall_absl
popd
if [[ ! "${lts_install}" ]]; then
# Test that we warn if installed without a prefix or a system prefix
output="$(install_absl 2>&1)"
if [[ "${output}" != *"Please set CMAKE_INSTALL_PREFIX"* ]]; then
echo "Install without prefix didn't warn as expected. Output:"
echo "${output}"
exit 1
fi
uninstall_absl
output="$(install_absl /usr 2>&1)"
if [[ "${output}" != *"Please set CMAKE_INSTALL_PREFIX"* ]]; then
echo "Install with /usr didn't warn as expected. Output:"
echo "${output}"
exit 1
fi
uninstall_absl
fi
echo "Install test complete!"
exit 0

@ -45,7 +45,7 @@ endif (POLICY CMP0077)
# This must come before the project() and include(CTest) lines.
OPTION(BUILD_TESTING "Build tests" OFF)
project(absl CXX)
project(absl LANGUAGES CXX)
include(CTest)
# Output directory is correct by default for most build setups. However, when
@ -67,8 +67,8 @@ list(APPEND CMAKE_MODULE_PATH
${CMAKE_CURRENT_LIST_DIR}/absl/copts
)
include(AbseilInstallDirs)
include(CMakePackageConfigHelpers)
include(GNUInstallDirs)
include(AbseilDll)
include(AbseilHelpers)
@ -159,16 +159,16 @@ if(ABSL_ENABLE_INSTALL)
# install as a subdirectory only
install(EXPORT ${PROJECT_NAME}Targets
NAMESPACE absl::
DESTINATION "${ABSL_INSTALL_CONFIGDIR}"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
)
configure_package_config_file(
CMake/abslConfig.cmake.in
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
INSTALL_DESTINATION "${ABSL_INSTALL_CONFIGDIR}"
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
)
install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
DESTINATION "${ABSL_INSTALL_CONFIGDIR}"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
)
# Abseil only has a version in LTS releases. This mechanism is accomplished
@ -181,12 +181,12 @@ if(ABSL_ENABLE_INSTALL)
)
install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
DESTINATION ${ABSL_INSTALL_CONFIGDIR}
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
)
endif() # absl_VERSION
install(DIRECTORY absl
DESTINATION ${ABSL_INSTALL_INCLUDEDIR}
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILES_MATCHING
PATTERN "*.inc"
PATTERN "*.h"

@ -106,9 +106,10 @@
// Cacheline aligning objects properly allows constructive memory sharing and
// prevents destructive (or "false") memory sharing.
//
// NOTE: this macro should be replaced with usage of `alignas()` using
// NOTE: callers should replace uses of this macro with `alignas()` using
// `std::hardware_constructive_interference_size` and/or
// `std::hardware_destructive_interference_size` when available within C++17.
// `std::hardware_destructive_interference_size` when C++17 becomes available to
// them.
//
// See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0154r1.html
// for more information.

@ -579,10 +579,10 @@ class btree_node {
};
// Leaves can have less than kNodeSlots values.
constexpr static layout_type LeafLayout(const int slots = kNodeSlots) {
constexpr static layout_type LeafLayout(const int slot_count = kNodeSlots) {
return layout_type(/*parent*/ 1,
/*position, start, finish, max_count*/ 4,
/*slots*/ slots,
/*slots*/ slot_count,
/*children*/ 0);
}
constexpr static layout_type InternalLayout() {
@ -591,8 +591,8 @@ class btree_node {
/*slots*/ kNodeSlots,
/*children*/ kNodeSlots + 1);
}
constexpr static size_type LeafSize(const int slots = kNodeSlots) {
return LeafLayout(slots).AllocSize();
constexpr static size_type LeafSize(const int slot_count = kNodeSlots) {
return LeafLayout(slot_count).AllocSize();
}
constexpr static size_type InternalSize() {
return InternalLayout().AllocSize();

@ -792,7 +792,8 @@ class raw_hash_set {
explicit raw_hash_set(size_t bucket_count, const hasher& hash = hasher(),
const key_equal& eq = key_equal(),
const allocator_type& alloc = allocator_type())
: ctrl_(EmptyGroup()), settings_(0, hash, eq, alloc) {
: ctrl_(EmptyGroup()),
settings_(0, HashtablezInfoHandle(), hash, eq, alloc) {
if (bucket_count) {
capacity_ = NormalizeCapacity(bucket_count);
initialize_slots();
@ -903,7 +904,7 @@ class raw_hash_set {
auto target = find_first_non_full(ctrl_, hash, capacity_);
set_ctrl(target.offset, H2(hash));
emplace_at(target.offset, v);
infoz_.RecordInsert(hash, target.probe_length);
infoz().RecordInsert(hash, target.probe_length);
}
size_ = that.size();
growth_left() -= that.size();
@ -917,28 +918,27 @@ class raw_hash_set {
slots_(absl::exchange(that.slots_, nullptr)),
size_(absl::exchange(that.size_, 0)),
capacity_(absl::exchange(that.capacity_, 0)),
infoz_(absl::exchange(that.infoz_, HashtablezInfoHandle())),
// Hash, equality and allocator are copied instead of moved because
// `that` must be left valid. If Hash is std::function<Key>, moving it
// would create a nullptr functor that cannot be called.
settings_(that.settings_) {
// growth_left was copied above, reset the one from `that`.
that.growth_left() = 0;
}
settings_(absl::exchange(that.growth_left(), 0),
absl::exchange(that.infoz(), HashtablezInfoHandle()),
that.hash_ref(), that.eq_ref(), that.alloc_ref()) {}
raw_hash_set(raw_hash_set&& that, const allocator_type& a)
: ctrl_(EmptyGroup()),
slots_(nullptr),
size_(0),
capacity_(0),
settings_(0, that.hash_ref(), that.eq_ref(), a) {
settings_(0, HashtablezInfoHandle(), that.hash_ref(), that.eq_ref(),
a) {
if (a == that.alloc_ref()) {
std::swap(ctrl_, that.ctrl_);
std::swap(slots_, that.slots_);
std::swap(size_, that.size_);
std::swap(capacity_, that.capacity_);
std::swap(growth_left(), that.growth_left());
std::swap(infoz_, that.infoz_);
std::swap(infoz(), that.infoz());
} else {
reserve(that.size());
// Note: this will copy elements of dense_set and unordered_set instead of
@ -1009,7 +1009,7 @@ class raw_hash_set {
reset_growth_left();
}
assert(empty());
infoz_.RecordStorageChanged(0, capacity_);
infoz().RecordStorageChanged(0, capacity_);
}
// This overload kicks in when the argument is an rvalue of insertable and
@ -1301,7 +1301,7 @@ class raw_hash_set {
swap(growth_left(), that.growth_left());
swap(hash_ref(), that.hash_ref());
swap(eq_ref(), that.eq_ref());
swap(infoz_, that.infoz_);
swap(infoz(), that.infoz());
SwapAlloc(alloc_ref(), that.alloc_ref(),
typename AllocTraits::propagate_on_container_swap{});
}
@ -1310,7 +1310,7 @@ class raw_hash_set {
if (n == 0 && capacity_ == 0) return;
if (n == 0 && size_ == 0) {
destroy_slots();
infoz_.RecordStorageChanged(0, 0);
infoz().RecordStorageChanged(0, 0);
return;
}
// bitor is a faster way of doing `max` here. We will round up to the next
@ -1528,7 +1528,7 @@ class raw_hash_set {
set_ctrl(index, was_never_full ? kEmpty : kDeleted);
growth_left() += was_never_full;
infoz_.RecordErase();
infoz().RecordErase();
}
void initialize_slots() {
@ -1545,7 +1545,7 @@ class raw_hash_set {
// bound more carefully.
if (std::is_same<SlotAlloc, std::allocator<slot_type>>::value &&
slots_ == nullptr) {
infoz_ = Sample();
infoz() = Sample();
}
auto layout = MakeLayout(capacity_);
@ -1555,7 +1555,7 @@ class raw_hash_set {
slots_ = layout.template Pointer<1>(mem);
reset_ctrl();
reset_growth_left();
infoz_.RecordStorageChanged(size_, capacity_);
infoz().RecordStorageChanged(size_, capacity_);
}
void destroy_slots() {
@ -1603,7 +1603,7 @@ class raw_hash_set {
Deallocate<Layout::Alignment()>(&alloc_ref(), old_ctrl,
layout.AllocSize());
}
infoz_.RecordRehash(total_probe_length);
infoz().RecordRehash(total_probe_length);
}
void drop_deletes_without_resize() ABSL_ATTRIBUTE_NOINLINE {
@ -1669,7 +1669,7 @@ class raw_hash_set {
}
}
reset_growth_left();
infoz_.RecordRehash(total_probe_length);
infoz().RecordRehash(total_probe_length);
}
void rehash_and_grow_if_necessary() {
@ -1743,7 +1743,7 @@ class raw_hash_set {
++size_;
growth_left() -= IsEmpty(ctrl_[target.offset]);
set_ctrl(target.offset, H2(hash));
infoz_.RecordInsert(hash, target.probe_length);
infoz().RecordInsert(hash, target.probe_length);
return target.offset;
}
@ -1800,13 +1800,15 @@ class raw_hash_set {
size_t& growth_left() { return settings_.template get<0>(); }
hasher& hash_ref() { return settings_.template get<1>(); }
const hasher& hash_ref() const { return settings_.template get<1>(); }
key_equal& eq_ref() { return settings_.template get<2>(); }
const key_equal& eq_ref() const { return settings_.template get<2>(); }
allocator_type& alloc_ref() { return settings_.template get<3>(); }
HashtablezInfoHandle& infoz() { return settings_.template get<1>(); }
hasher& hash_ref() { return settings_.template get<2>(); }
const hasher& hash_ref() const { return settings_.template get<2>(); }
key_equal& eq_ref() { return settings_.template get<3>(); }
const key_equal& eq_ref() const { return settings_.template get<3>(); }
allocator_type& alloc_ref() { return settings_.template get<4>(); }
const allocator_type& alloc_ref() const {
return settings_.template get<3>();
return settings_.template get<4>();
}
// TODO(alkis): Investigate removing some of these fields:
@ -1816,10 +1818,11 @@ class raw_hash_set {
slot_type* slots_ = nullptr; // [capacity * slot_type]
size_t size_ = 0; // number of full slots
size_t capacity_ = 0; // total number of slots
HashtablezInfoHandle infoz_;
absl::container_internal::CompressedTuple<size_t /* growth_left */, hasher,
absl::container_internal::CompressedTuple<size_t /* growth_left */,
HashtablezInfoHandle, hasher,
key_equal, allocator_type>
settings_{0, hasher{}, key_equal{}, allocator_type{}};
settings_{0, HashtablezInfoHandle{}, hasher{}, key_equal{},
allocator_type{}};
};
// Erases all elements that satisfy the predicate `pred` from the container `c`.

@ -419,6 +419,13 @@ TEST(Table, EmptyFunctorOptimization) {
size_t growth_left;
void* infoz;
};
struct MockTableInfozDisabled {
void* ctrl;
void* slots;
size_t size;
size_t capacity;
size_t growth_left;
};
struct StatelessHash {
size_t operator()(absl::string_view) const { return 0; }
};
@ -426,17 +433,27 @@ TEST(Table, EmptyFunctorOptimization) {
size_t dummy;
};
EXPECT_EQ(
sizeof(MockTable),
sizeof(
raw_hash_set<StringPolicy, StatelessHash,
std::equal_to<absl::string_view>, std::allocator<int>>));
EXPECT_EQ(
sizeof(MockTable) + sizeof(StatefulHash),
sizeof(
raw_hash_set<StringPolicy, StatefulHash,
std::equal_to<absl::string_view>, std::allocator<int>>));
if (std::is_empty<HashtablezInfoHandle>::value) {
EXPECT_EQ(sizeof(MockTableInfozDisabled),
sizeof(raw_hash_set<StringPolicy, StatelessHash,
std::equal_to<absl::string_view>,
std::allocator<int>>));
EXPECT_EQ(sizeof(MockTableInfozDisabled) + sizeof(StatefulHash),
sizeof(raw_hash_set<StringPolicy, StatefulHash,
std::equal_to<absl::string_view>,
std::allocator<int>>));
} else {
EXPECT_EQ(sizeof(MockTable),
sizeof(raw_hash_set<StringPolicy, StatelessHash,
std::equal_to<absl::string_view>,
std::allocator<int>>));
EXPECT_EQ(sizeof(MockTable) + sizeof(StatefulHash),
sizeof(raw_hash_set<StringPolicy, StatefulHash,
std::equal_to<absl::string_view>,
std::allocator<int>>));
}
}
TEST(Table, Empty) {

@ -386,24 +386,28 @@ static bool IsDigit(char c) { return c >= '0' && c <= '9'; }
// by GCC 4.5.x and later versions (and our locally-modified version of GCC
// 4.4.x) to indicate functions which have been cloned during optimization.
// We treat any sequence (.<alpha>+.<digit>+)+ as a function clone suffix.
// Additionally, '_' is allowed along with the alphanumeric sequence.
static bool IsFunctionCloneSuffix(const char *str) {
size_t i = 0;
while (str[i] != '\0') {
// Consume a single .<alpha>+.<digit>+ sequence.
if (str[i] != '.' || !IsAlpha(str[i + 1])) {
return false;
bool parsed = false;
// Consume a single [.<alpha> | _]*[.<digit>]* sequence.
if (str[i] == '.' && (IsAlpha(str[i + 1]) || str[i + 1] == '_')) {
parsed = true;
i += 2;
while (IsAlpha(str[i]) || str[i] == '_') {
++i;
}
}
i += 2;
while (IsAlpha(str[i])) {
++i;
if (str[i] == '.' && IsDigit(str[i + 1])) {
parsed = true;
i += 2;
while (IsDigit(str[i])) {
++i;
}
}
if (str[i] != '.' || !IsDigit(str[i + 1])) {
if (!parsed)
return false;
}
i += 2;
while (IsDigit(str[i])) {
++i;
}
}
return true; // Consumed everything in "str".
}

@ -70,12 +70,34 @@ TEST(Demangle, Clones) {
EXPECT_STREQ("Foo()", tmp);
EXPECT_TRUE(Demangle("_ZL3Foov.isra.2.constprop.18", tmp, sizeof(tmp)));
EXPECT_STREQ("Foo()", tmp);
// Invalid (truncated), should not demangle.
EXPECT_FALSE(Demangle("_ZL3Foov.clo", tmp, sizeof(tmp)));
// Demangle suffixes produced by -funique-internal-linkage-names.
EXPECT_TRUE(Demangle("_ZL3Foov.__uniq.12345", tmp, sizeof(tmp)));
EXPECT_STREQ("Foo()", tmp);
EXPECT_TRUE(Demangle("_ZL3Foov.__uniq.12345.isra.2.constprop.18", tmp,
sizeof(tmp)));
EXPECT_STREQ("Foo()", tmp);
// Suffixes without the number should also demangle.
EXPECT_TRUE(Demangle("_ZL3Foov.clo", tmp, sizeof(tmp)));
EXPECT_STREQ("Foo()", tmp);
// Suffixes with just the number should also demangle.
EXPECT_TRUE(Demangle("_ZL3Foov.123", tmp, sizeof(tmp)));
EXPECT_STREQ("Foo()", tmp);
// (.clone. followed by non-number), should also demangle.
EXPECT_TRUE(Demangle("_ZL3Foov.clone.foo", tmp, sizeof(tmp)));
EXPECT_STREQ("Foo()", tmp);
// (.clone. followed by multiple numbers), should also demangle.
EXPECT_TRUE(Demangle("_ZL3Foov.clone.123.456", tmp, sizeof(tmp)));
EXPECT_STREQ("Foo()", tmp);
// (a long valid suffix), should demangle.
EXPECT_TRUE(Demangle("_ZL3Foov.part.9.165493.constprop.775.31805", tmp,
sizeof(tmp)));
EXPECT_STREQ("Foo()", tmp);
// Invalid (. without anything else), should not demangle.
EXPECT_FALSE(Demangle("_ZL3Foov.", tmp, sizeof(tmp)));
// Invalid (. with mix of alpha and digits), should not demangle.
EXPECT_FALSE(Demangle("_ZL3Foov.abc123", tmp, sizeof(tmp)));
// Invalid (.clone. not followed by number), should not demangle.
EXPECT_FALSE(Demangle("_ZL3Foov.clone.", tmp, sizeof(tmp)));
// Invalid (.clone. followed by non-number), should not demangle.
EXPECT_FALSE(Demangle("_ZL3Foov.clone.foo", tmp, sizeof(tmp)));
// Invalid (.constprop. not followed by number), should not demangle.
EXPECT_FALSE(Demangle("_ZL3Foov.isra.2.constprop.", tmp, sizeof(tmp)));
}

@ -38,6 +38,7 @@ ABSL_NAMESPACE_END
namespace absl {
ABSL_NAMESPACE_BEGIN
bool HaveLeakSanitizer() { return true; }
bool FindAndReportLeaks() { return __lsan_do_recoverable_leak_check(); }
void DoIgnoreLeak(const void* ptr) { __lsan_ignore_object(ptr); }
void RegisterLivePointers(const void* ptr, size_t size) {
__lsan_register_root_region(ptr, size);

@ -71,6 +71,19 @@ T* IgnoreLeak(T* ptr) {
return ptr;
}
// FindAndReportLeaks()
//
// If any leaks are detected, prints a leak report and returns true. This
// function may be called repeatedly, and does not affect end-of-process leak
// checking.
//
// Example:
// if (FindAndReportLeaks()) {
// ... diagnostic already printed. Exit with failure code.
// exit(1)
// }
bool FindAndReportLeaks();
// LeakCheckDisabler
//
// This helper class indicates that any heap allocations done in the code block

@ -19,6 +19,17 @@
#include "absl/container/inlined_vector.h"
#include "absl/strings/cord.h"
#ifndef SWIG
// Disabled for SWIG as it doesn't parse attributes correctly.
namespace absl {
ABSL_NAMESPACE_BEGIN
// Returned Status objects may not be ignored. Codesearch doesn't handle ifdefs
// as part of a class definitions (b/6995610), so we use a forward declaration.
class ABSL_MUST_USE_RESULT Status;
ABSL_NAMESPACE_END
} // namespace absl
#endif // !SWIG
namespace absl {
ABSL_NAMESPACE_BEGIN

@ -291,6 +291,8 @@ enum class StatusToStringMode : int {
kWithNoExtraData = 0,
// ToString will contain the payloads.
kWithPayload = 1 << 0,
// ToString will include all the extra data this Status has.
kWithEverything = ~kWithNoExtraData,
};
// absl::StatusToStringMode is specified as a bitmask type, which means the
@ -410,7 +412,12 @@ inline StatusToStringMode& operator^=(StatusToStringMode& lhs,
// return result;
// }
//
class ABSL_MUST_USE_RESULT Status final {
// For documentation see https://abseil.io/docs/cpp/guides/status.
//
// Returned Status objects may not be ignored. status_internal.h has a forward
// declaration of the form
// class ABSL_MUST_USE_RESULT Status;
class Status final {
public:
// Constructors

@ -292,6 +292,10 @@ TEST(Status, ToStringMode) {
AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"),
HasSubstr("[bar='\\xff']")));
EXPECT_THAT(s.ToString(absl::StatusToStringMode::kWithEverything),
AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"),
HasSubstr("[bar='\\xff']")));
EXPECT_THAT(s.ToString(~absl::StatusToStringMode::kWithPayload),
AllOf(HasSubstr("INTERNAL: fail"), Not(HasSubstr("[foo='bar']")),
Not(HasSubstr("[bar='\\xff']"))));

@ -135,7 +135,7 @@ class ABSL_MUST_USE_RESULT StatusOr;
//
// NOTE: using `absl::StatusOr<T>::value()` when no valid value is present will
// throw an exception if exceptions are enabled or terminate the process when
// execeptions are not enabled.
// exceptions are not enabled.
//
// Example:
//

@ -124,6 +124,7 @@ 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,

@ -20,18 +20,24 @@ if [[ -z ${ABSEIL_ROOT:-} ]]; then
ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
fi
if [[ -z ${LINK_TYPE:-} ]]; then
LINK_TYPE="STATIC DYNAMIC"
fi
source "${ABSEIL_ROOT}/ci/cmake_common.sh"
source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh"
readonly DOCKER_CONTAINER=${LINUX_GCC_LATEST_CONTAINER}
time docker run \
--mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \
--workdir=/abseil-cpp \
for link_type in ${LINK_TYPE}; do
time docker run \
--mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp-ro,readonly \
--tmpfs=/buildfs:exec \
--tmpfs=/abseil-cpp:exec \
--workdir=/abseil-cpp \
--cap-add=SYS_PTRACE \
-e "LINK_TYPE=${link_type}" \
--rm \
-e CFLAGS="-Werror" \
-e CXXFLAGS="-Werror" \
${DOCKER_CONTAINER} \
/bin/bash CMake/install_test_project/test.sh $@
/bin/bash -c "cp -r /abseil-cpp-ro/* . && CMake/install_test_project/test.sh"
done

@ -0,0 +1,121 @@
#!/usr/bin/env python
#
# Copyright 2021 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.
"""A script to do source transformations to create a new LTS release.
Usage: ./create_lts.py YYYYMMDD
"""
import sys
def ReplaceStringsInFile(filename, replacement_dict):
"""Performs textual replacements in a file.
Rewrites filename with the keys in replacement_dict replaced with
their values. This function assumes the file can fit in memory.
Args:
filename: the filename to perform the replacement on
replacement_dict: a dictionary of key strings to be replaced with their
values
Raises:
Exception: A failure occured
"""
f = open(filename, 'r')
content = f.read()
f.close()
for key, value in replacement_dict.items():
original = content
content = content.replace(key, value)
if content == original:
raise Exception('Failed to find {} in {}'.format(key, filename))
f = open(filename, 'w')
f.write(content)
f.close()
def StripContentBetweenTags(filename, strip_begin_tag, strip_end_tag):
"""Strip contents from a file.
Rewrites filename with by removing all content between
strip_begin_tag and strip_end_tag, including the tags themselves.
Args:
filename: the filename to perform the replacement on
strip_begin_tag: the start of the content to be removed
strip_end_tag: the end of the content to be removed
Raises:
Exception: A failure occured
"""
f = open(filename, 'r')
content = f.read()
f.close()
while True:
begin = content.find(strip_begin_tag)
if begin == -1:
break
end = content.find(strip_end_tag, begin + len(strip_begin_tag))
if end == -1:
raise Exception('{}: imbalanced strip begin ({}) and '
'end ({}) tags'.format(filename, strip_begin_tag,
strip_end_tag))
content = content.replace(content[begin:end + len(strip_end_tag)], '')
f = open(filename, 'w')
f.write(content)
f.close()
def main(argv):
if len(argv) != 2:
print('Usage: {} YYYYMMDD'.format(sys.argv[0], file=sys.stderr))
sys.exit(1)
datestamp = sys.argv[1]
if len(datestamp) != 8 or not datestamp.isdigit():
raise Exception(
'datestamp={} is not in the YYYYMMDD format'.format(datestamp))
# Replacement directives go here.
ReplaceStringsInFile(
'absl/base/options.h', {
'#define ABSL_OPTION_USE_INLINE_NAMESPACE 0':
'#define ABSL_OPTION_USE_INLINE_NAMESPACE 1',
'#define ABSL_OPTION_INLINE_NAMESPACE_NAME head':
'#define ABSL_OPTION_INLINE_NAMESPACE_NAME lts_{}'.format(
datestamp)
})
ReplaceStringsInFile(
'CMakeLists.txt', {
'project(absl LANGUAGES CXX)':
'project(absl LANGUAGES CXX VERSION {})'.format(datestamp)
})
# Set the SOVERSION to YYYYMMDD.0.0 - The first 0 means we only have
# ABI compatible changes, and the second 0 means we can increment it
# to mark changes as ABI-compatible, for patch releases.
ReplaceStringsInFile('CMake/AbseilHelpers.cmake',
{'SOVERSION 0': 'SOVERSION "{}.0.0"'.format(datestamp)})
StripContentBetweenTags('CMakeLists.txt', '# absl:lts-remove-begin',
'# absl:lts-remove-end')
if __name__ == '__main__':
main(sys.argv)
Loading…
Cancel
Save