Export of internal Abseil changes

--
587e6db882749fa7faa12815e614afab04d218b9 by Derek Mauro <dmauro@google.com>:

Use attribute detection for other sanitizer related attributes

PiperOrigin-RevId: 324077073

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

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 <dmauro@google.com>:

Use auto-detected sanitizer attributes for ASAN, MSAN, and TSAN builds

PiperOrigin-RevId: 323831461
GitOrigin-RevId: 587e6db882749fa7faa12815e614afab04d218b9
Change-Id: Ie0e4a2846d7f66988a2d81a5e50721b62fdb3d6d
pull/754/head
Abseil Team 4 years ago committed by Mark Barolak
parent 82302f1e05
commit 184cf25241
  1. 2
      absl/base/BUILD.bazel
  2. 2
      absl/base/CMakeLists.txt
  3. 54
      absl/base/attributes.h
  4. 11
      absl/base/internal/dynamic_annotations.h
  5. 4
      absl/base/internal/tsan_mutex_interface.h
  6. 4
      absl/base/internal/unaligned_access.h
  7. 3
      absl/base/spinlock_test_common.cc
  8. 5
      absl/container/BUILD.bazel
  9. 5
      absl/container/CMakeLists.txt
  10. 13
      absl/container/fixed_array.h
  11. 5
      absl/container/fixed_array_test.cc
  12. 25
      absl/container/internal/container_memory.h
  13. 12
      absl/container/internal/layout.h
  14. 4
      absl/container/internal/layout_test.cc
  15. 5
      absl/container/internal/raw_hash_set_test.cc
  16. 2
      absl/debugging/BUILD.bazel
  17. 2
      absl/debugging/CMakeLists.txt
  18. 4
      absl/debugging/failure_signal_handler.cc
  19. 8
      absl/debugging/internal/demangle_test.cc
  20. 5
      absl/debugging/symbolize_test.cc
  21. 3
      absl/strings/BUILD.bazel
  22. 1
      absl/strings/CMakeLists.txt
  23. 74
      absl/strings/cord.cc
  24. 57
      absl/strings/cord.h
  25. 65
      absl/strings/internal/cord_internal.h
  26. 4
      absl/strings/string_view_test.cc
  27. 3
      absl/synchronization/BUILD.bazel
  28. 2
      absl/synchronization/CMakeLists.txt
  29. 3
      absl/synchronization/internal/mutex_nonprod.cc
  30. 1
      absl/synchronization/internal/per_thread_sem_test.cc
  31. 2
      absl/synchronization/internal/waiter.h
  32. 8
      absl/synchronization/mutex.cc
  33. 3
      absl/synchronization/mutex_benchmark.cc
  34. 7
      absl/synchronization/mutex_test.cc
  35. 1
      absl/time/BUILD.bazel
  36. 1
      absl/time/CMakeLists.txt
  37. 1
      absl/time/internal/test_util.cc
  38. 2
      ci/linux_clang-latest_libcxx_asan_bazel.sh
  39. 2
      ci/linux_clang-latest_libcxx_tsan_bazel.sh

@ -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",

@ -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

@ -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

@ -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.

@ -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(<sanitizer/tsan_interface.h>)
#define ABSL_INTERNAL_HAVE_TSAN_INTERFACE 1
#endif

@ -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.

@ -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<SpinLock>(), "");
#endif

@ -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",

@ -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

@ -41,6 +41,7 @@
#include <type_traits>
#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<T, N, A>::size_type
template <typename T, size_t N, typename A>
void FixedArray<T, N, A>::NonEmptyInlinedStorage::AnnotateConstruct(
typename FixedArray<T, N, A>::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<void>(n); // Mark used when not in asan mode
}
template <typename T, size_t N, typename A>
void FixedArray<T, N, A>::NonEmptyInlinedStorage::AnnotateDestruct(
typename FixedArray<T, N, A>::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<void>(n); // Mark used when not in asan mode
}
ABSL_NAMESPACE_END

@ -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<int, 32> 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<int>;

@ -15,14 +15,6 @@
#ifndef ABSL_CONTAINER_INTERNAL_CONTAINER_MEMORY_H_
#define ABSL_CONTAINER_INTERNAL_CONTAINER_MEMORY_H_
#ifdef ADDRESS_SANITIZER
#include <sanitizer/asan_interface.h>
#endif
#ifdef MEMORY_SANITIZER
#include <sanitizer/msan_interface.h>
#endif
#include <cassert>
#include <cstddef>
#include <memory>
@ -30,10 +22,19 @@
#include <type_traits>
#include <utility>
#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 <sanitizer/asan_interface.h>
#endif
#ifdef ABSL_HAVE_MEMORY_SANITIZER
#include <sanitizer/msan_interface.h>
#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;

@ -163,6 +163,7 @@
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <ostream>
#include <string>
#include <tuple>
@ -170,15 +171,16 @@
#include <typeinfo>
#include <utility>
#ifdef ADDRESS_SANITIZER
#include <sanitizer/asan_interface.h>
#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 <sanitizer/asan_interface.h>
#endif
#if defined(__GXX_RTTI)
#define ABSL_INTERNAL_HAS_CXA_DEMANGLE
#endif
@ -614,7 +616,7 @@ class LayoutImpl<std::tuple<Elements...>, absl::index_sequence<SizeSeq...>,
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<Char, N - 1>(p);
// The `if` is an optimization. It doesn't affect the observable behaviour.
if (ElementAlignment<N - 1>::value % ElementAlignment<N>::value) {

@ -17,6 +17,7 @@
// We need ::max_align_t because some libstdc++ versions don't provide
// std::max_align_t
#include <stddef.h>
#include <cstdint>
#include <memory>
#include <sstream>
@ -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));
}

@ -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

@ -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",

@ -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

@ -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

@ -18,6 +18,7 @@
#include <string>
#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];

@ -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

@ -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",

@ -548,6 +548,7 @@ absl_cc_library(
DEPS
absl::base
absl::base_internal
absl::compressed_tuple
absl::core_headers
absl::endian
absl::fixed_array

@ -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<ExternalAllocType>
// 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<ExternalAllocType>().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<ExternalAllocType>().deallocate(
reinterpret_cast<ExternalAllocType*>(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<CordRepExternal*>(absl::cord_internal::NewExternalRep(
original_data, StringReleaser{std::move(src)}));
auto* rep = static_cast<
::absl::cord_internal::CordRepExternalImpl<StringReleaser>*>(
absl::cord_internal::NewExternalRep(
original_data, StringReleaser{std::forward<T>(src)}));
// Moving src may have invalidated its data pointer, so adjust it.
rep->base =
static_cast<StringReleaser*>(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<T>(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<T>(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<T>(src)));
}
}

@ -71,7 +71,6 @@
#include <type_traits>
#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 <typename Releaser, typename = ::absl::base_internal::invoke_result_t<
Releaser, absl::string_view>>
void InvokeReleaser(Rank0, Releaser&& releaser, absl::string_view data) {
::absl::base_internal::invoke(std::forward<Releaser>(releaser), data);
}
template <typename Releaser,
typename = ::absl::base_internal::invoke_result_t<Releaser>>
void InvokeReleaser(Rank1, Releaser&& releaser, absl::string_view) {
::absl::base_internal::invoke(std::forward<Releaser>(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 <typename Releaser>
// 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<Releaser>;
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<ReleaserType*>(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>(releaser));
return external.rep;
CordRepExternal* rep = new CordRepExternalImpl<ReleaserType>(
std::forward<Releaser>(releaser), 0);
InitializeCordRepExternal(data, rep);
return rep;
}
// Overload for function reference types that dispatches using a function

@ -21,6 +21,8 @@
#include <cstdint>
#include <type_traits>
#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 <typename Releaser, typename = ::absl::base_internal::invoke_result_t<
Releaser, absl::string_view>>
void InvokeReleaser(Rank0, Releaser&& releaser, absl::string_view data) {
::absl::base_internal::invoke(std::forward<Releaser>(releaser), data);
}
template <typename Releaser,
typename = ::absl::base_internal::invoke_result_t<Releaser>>
void InvokeReleaser(Rank1, Releaser&& releaser, absl::string_view) {
::absl::base_internal::invoke(std::forward<Releaser>(releaser));
}
// We use CompressedTuple so that we can benefit from EBCO.
template <typename Releaser>
struct CordRepExternalImpl
: public CordRepExternal,
public ::absl::container_internal::CompressedTuple<Releaser> {
// The extra int arg is so that we can avoid interfering with copy/move
// constructors while still benefitting from perfect forwarding.
template <typename T>
CordRepExternalImpl(T&& releaser, int)
: CordRepExternalImpl::CompressedTuple(std::forward<T>(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<CordRepExternalImpl*>(rep);
}
};
} // namespace cord_internal
ABSL_NAMESPACE_END

@ -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) {

@ -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",

@ -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

@ -27,6 +27,7 @@
#include <algorithm>
#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

@ -23,6 +23,7 @@
#include <thread> // 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"

@ -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,

@ -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

@ -16,6 +16,7 @@
#include <mutex> // NOLINT(build/c++11)
#include <vector>
#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;

@ -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

@ -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",

@ -99,6 +99,7 @@ absl_cc_library(
${ABSL_DEFAULT_COPTS}
DEPS
absl::time
absl::config
absl::raw_logging_internal
absl::time_zone
gmock

@ -18,6 +18,7 @@
#include <cstddef>
#include <cstring>
#include "absl/base/config.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/time/internal/cctz/include/cctz/zone_info_source.h"

@ -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" \

@ -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 \

Loading…
Cancel
Save