- abe587c2360b21f085b7d65a77d840015bc04cf6 Factor an internal interface into its own header, as it w... by Greg Falcon <gfalcon@google.com>
- 2201f1644336e64280dbd20207d8fbc3bfea2bf4 Internal change. by Abseil Team <absl-team@google.com> - 94e6b5b20d2cc754c99a18c575a4f1f3cd1f28d4 Rename no_throw_ctor to nothrow_ctor to match the standar... by Abseil Team <absl-team@google.com> - 86aa34d2129c4914c5133b7b619480aae786288e Update header files in debugging target by Tom Manshreck <shreck@google.com> - ed234519ced458724a7267b8fdf184eaae1c97c7 Remove CMAKE_CXX_WARNING_VLA from our c++ flags in the cm... by Jon Cohen <cohenjon@google.com> GitOrigin-RevId: abe587c2360b21f085b7d65a77d840015bc04cf6 Change-Id: I92f9301c69419d3830c358b88984967185aa33f6
This commit is contained in:
parent
add89fd0e4
commit
04dd99d8c1
13 changed files with 277 additions and 115 deletions
|
@ -53,7 +53,6 @@ list(APPEND ABSL_COMMON_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
# -std=X
|
# -std=X
|
||||||
set(CMAKE_CXX_FLAGS "${ABSL_STD_CXX_FLAG} ${CMAKE_CXX_FLAGS}")
|
set(CMAKE_CXX_FLAGS "${ABSL_STD_CXX_FLAG} ${CMAKE_CXX_FLAGS}")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_WARNING_VLA} ${CMAKE_CXX_FLAGS} ")
|
|
||||||
|
|
||||||
# -fexceptions
|
# -fexceptions
|
||||||
set(ABSL_EXCEPTIONS_FLAG "${CMAKE_CXX_EXCEPTIONS}")
|
set(ABSL_EXCEPTIONS_FLAG "${CMAKE_CXX_EXCEPTIONS}")
|
||||||
|
|
|
@ -405,7 +405,7 @@ TEST(ThrowingAllocatorTest, NonThrowingConstruction) {
|
||||||
|
|
||||||
SetCountdown();
|
SetCountdown();
|
||||||
ExpectNoThrow(
|
ExpectNoThrow(
|
||||||
[&]() { nothrow_alloc.construct(ptr, 2, testing::no_throw_ctor); });
|
[&]() { nothrow_alloc.construct(ptr, 2, testing::nothrow_ctor); });
|
||||||
|
|
||||||
EXPECT_EQ(ptr->Get(), 2);
|
EXPECT_EQ(ptr->Get(), 2);
|
||||||
nothrow_alloc.destroy(ptr);
|
nothrow_alloc.destroy(ptr);
|
||||||
|
|
|
@ -19,7 +19,12 @@
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
|
||||||
exceptions_internal::NoThrowTag no_throw_ctor;
|
exceptions_internal::NoThrowTag nothrow_ctor;
|
||||||
|
|
||||||
|
bool nothrow_guarantee(const void*) {
|
||||||
|
return ::testing::AssertionFailure()
|
||||||
|
<< "Exception thrown violating NoThrow Guarantee";
|
||||||
|
}
|
||||||
exceptions_internal::StrongGuaranteeTagType strong_guarantee;
|
exceptions_internal::StrongGuaranteeTagType strong_guarantee;
|
||||||
|
|
||||||
namespace exceptions_internal {
|
namespace exceptions_internal {
|
||||||
|
|
|
@ -227,7 +227,9 @@ inline absl::optional<testing::AssertionResult> TestAllInvariantsAtCountdown(
|
||||||
|
|
||||||
} // namespace exceptions_internal
|
} // namespace exceptions_internal
|
||||||
|
|
||||||
extern exceptions_internal::NoThrowTag no_throw_ctor;
|
extern exceptions_internal::NoThrowTag nothrow_ctor;
|
||||||
|
|
||||||
|
bool nothrow_guarantee(const void*);
|
||||||
extern exceptions_internal::StrongGuaranteeTagType strong_guarantee;
|
extern exceptions_internal::StrongGuaranteeTagType strong_guarantee;
|
||||||
|
|
||||||
// A test class which is convertible to bool. The conversion can be
|
// A test class which is convertible to bool. The conversion can be
|
||||||
|
@ -246,7 +248,7 @@ class ThrowingBool {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Configuration enum for the ThrowingValue type that defines behavior for the
|
* Configuration enum for the ThrowingValue type that defines behavior for the
|
||||||
* lifetime of the instance. Use testing::no_throw_ctor to prevent the integer
|
* lifetime of the instance. Use testing::nothrow_ctor to prevent the integer
|
||||||
* constructor from throwing.
|
* constructor from throwing.
|
||||||
*
|
*
|
||||||
* kEverythingThrows: Every operation can throw an exception
|
* kEverythingThrows: Every operation can throw an exception
|
||||||
|
@ -341,22 +343,22 @@ class ThrowingValue : private exceptions_internal::TrackedObject {
|
||||||
// Arithmetic Operators
|
// Arithmetic Operators
|
||||||
ThrowingValue operator+(const ThrowingValue& other) const {
|
ThrowingValue operator+(const ThrowingValue& other) const {
|
||||||
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
|
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
|
||||||
return ThrowingValue(dummy_ + other.dummy_, no_throw_ctor);
|
return ThrowingValue(dummy_ + other.dummy_, nothrow_ctor);
|
||||||
}
|
}
|
||||||
|
|
||||||
ThrowingValue operator+() const {
|
ThrowingValue operator+() const {
|
||||||
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
|
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
|
||||||
return ThrowingValue(dummy_, no_throw_ctor);
|
return ThrowingValue(dummy_, nothrow_ctor);
|
||||||
}
|
}
|
||||||
|
|
||||||
ThrowingValue operator-(const ThrowingValue& other) const {
|
ThrowingValue operator-(const ThrowingValue& other) const {
|
||||||
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
|
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
|
||||||
return ThrowingValue(dummy_ - other.dummy_, no_throw_ctor);
|
return ThrowingValue(dummy_ - other.dummy_, nothrow_ctor);
|
||||||
}
|
}
|
||||||
|
|
||||||
ThrowingValue operator-() const {
|
ThrowingValue operator-() const {
|
||||||
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
|
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
|
||||||
return ThrowingValue(-dummy_, no_throw_ctor);
|
return ThrowingValue(-dummy_, nothrow_ctor);
|
||||||
}
|
}
|
||||||
|
|
||||||
ThrowingValue& operator++() {
|
ThrowingValue& operator++() {
|
||||||
|
@ -367,7 +369,7 @@ class ThrowingValue : private exceptions_internal::TrackedObject {
|
||||||
|
|
||||||
ThrowingValue operator++(int) {
|
ThrowingValue operator++(int) {
|
||||||
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
|
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
|
||||||
auto out = ThrowingValue(dummy_, no_throw_ctor);
|
auto out = ThrowingValue(dummy_, nothrow_ctor);
|
||||||
++dummy_;
|
++dummy_;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
@ -380,34 +382,34 @@ class ThrowingValue : private exceptions_internal::TrackedObject {
|
||||||
|
|
||||||
ThrowingValue operator--(int) {
|
ThrowingValue operator--(int) {
|
||||||
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
|
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
|
||||||
auto out = ThrowingValue(dummy_, no_throw_ctor);
|
auto out = ThrowingValue(dummy_, nothrow_ctor);
|
||||||
--dummy_;
|
--dummy_;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ThrowingValue operator*(const ThrowingValue& other) const {
|
ThrowingValue operator*(const ThrowingValue& other) const {
|
||||||
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
|
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
|
||||||
return ThrowingValue(dummy_ * other.dummy_, no_throw_ctor);
|
return ThrowingValue(dummy_ * other.dummy_, nothrow_ctor);
|
||||||
}
|
}
|
||||||
|
|
||||||
ThrowingValue operator/(const ThrowingValue& other) const {
|
ThrowingValue operator/(const ThrowingValue& other) const {
|
||||||
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
|
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
|
||||||
return ThrowingValue(dummy_ / other.dummy_, no_throw_ctor);
|
return ThrowingValue(dummy_ / other.dummy_, nothrow_ctor);
|
||||||
}
|
}
|
||||||
|
|
||||||
ThrowingValue operator%(const ThrowingValue& other) const {
|
ThrowingValue operator%(const ThrowingValue& other) const {
|
||||||
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
|
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
|
||||||
return ThrowingValue(dummy_ % other.dummy_, no_throw_ctor);
|
return ThrowingValue(dummy_ % other.dummy_, nothrow_ctor);
|
||||||
}
|
}
|
||||||
|
|
||||||
ThrowingValue operator<<(int shift) const {
|
ThrowingValue operator<<(int shift) const {
|
||||||
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
|
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
|
||||||
return ThrowingValue(dummy_ << shift, no_throw_ctor);
|
return ThrowingValue(dummy_ << shift, nothrow_ctor);
|
||||||
}
|
}
|
||||||
|
|
||||||
ThrowingValue operator>>(int shift) const {
|
ThrowingValue operator>>(int shift) const {
|
||||||
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
|
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
|
||||||
return ThrowingValue(dummy_ >> shift, no_throw_ctor);
|
return ThrowingValue(dummy_ >> shift, nothrow_ctor);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comparison Operators
|
// Comparison Operators
|
||||||
|
@ -463,22 +465,22 @@ class ThrowingValue : private exceptions_internal::TrackedObject {
|
||||||
// Bitwise Logical Operators
|
// Bitwise Logical Operators
|
||||||
ThrowingValue operator~() const {
|
ThrowingValue operator~() const {
|
||||||
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
|
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
|
||||||
return ThrowingValue(~dummy_, no_throw_ctor);
|
return ThrowingValue(~dummy_, nothrow_ctor);
|
||||||
}
|
}
|
||||||
|
|
||||||
ThrowingValue operator&(const ThrowingValue& other) const {
|
ThrowingValue operator&(const ThrowingValue& other) const {
|
||||||
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
|
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
|
||||||
return ThrowingValue(dummy_ & other.dummy_, no_throw_ctor);
|
return ThrowingValue(dummy_ & other.dummy_, nothrow_ctor);
|
||||||
}
|
}
|
||||||
|
|
||||||
ThrowingValue operator|(const ThrowingValue& other) const {
|
ThrowingValue operator|(const ThrowingValue& other) const {
|
||||||
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
|
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
|
||||||
return ThrowingValue(dummy_ | other.dummy_, no_throw_ctor);
|
return ThrowingValue(dummy_ | other.dummy_, nothrow_ctor);
|
||||||
}
|
}
|
||||||
|
|
||||||
ThrowingValue operator^(const ThrowingValue& other) const {
|
ThrowingValue operator^(const ThrowingValue& other) const {
|
||||||
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
|
exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
|
||||||
return ThrowingValue(dummy_ ^ other.dummy_, no_throw_ctor);
|
return ThrowingValue(dummy_ ^ other.dummy_, nothrow_ctor);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compound Assignment operators
|
// Compound Assignment operators
|
||||||
|
@ -1034,12 +1036,6 @@ MakeExceptionSafetyTester() {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always return false, intended to be used as a checker with
|
|
||||||
// TestExceptionSafety() to check that no exception is thrown.
|
|
||||||
inline bool nothrow_guarantee(const void*) {
|
|
||||||
return ::testing::AssertionFailure() << "Violating NoThrowGuarantee";
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
#endif // ABSL_BASE_INTERNAL_EXCEPTION_SAFETY_TESTING_H_
|
#endif // ABSL_BASE_INTERNAL_EXCEPTION_SAFETY_TESTING_H_
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
//
|
// Copyright 2018 The Abseil Authors.
|
||||||
// Copyright 2017 The Abseil Authors.
|
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -13,15 +12,14 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// File: leak_check.h
|
// File: leak_check.h
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// This package contains functions that affect leak checking behavior within
|
// This file contains functions that affect leak checking behavior within
|
||||||
// targets built with the LeakSanitizer (LSan), a memory leak detector that is
|
// targets built with the LeakSanitizer (LSan), a memory leak detector that is
|
||||||
// integrated within the AddressSanitizer (ASan) as an additional component, or
|
// integrated within the AddressSanitizer (ASan) as an additional component, or
|
||||||
// which can be used standalone. LSan and ASan are included or can be provided
|
// which can be used standalone. LSan and ASan are included (or can be provided)
|
||||||
// as additional components for most compilers such as Clang, gcc and MSVC.
|
// as additional components for most compilers such as Clang, gcc and MSVC.
|
||||||
// Note: this leak checking API is not yet supported in MSVC.
|
// Note: this leak checking API is not yet supported in MSVC.
|
||||||
// Leak checking is enabled by default in all ASan builds.
|
// Leak checking is enabled by default in all ASan builds.
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
//
|
// Copyright 2018 The Abseil Authors.
|
||||||
// Copyright 2017 The Abseil Authors.
|
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -13,26 +12,37 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
// Routines to extract the current stack trace. These functions are
|
// File: stacktrace.h
|
||||||
// thread-safe and async-signal-safe.
|
// -----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// This file contains routines to extract the current stack trace and associated
|
||||||
|
// stack frames. These functions are thread-safe and async-signal-safe.
|
||||||
|
//
|
||||||
// Note that stack trace functionality is platform dependent and requires
|
// Note that stack trace functionality is platform dependent and requires
|
||||||
// additional support from the compiler/build system in many cases. (That is,
|
// additional support from the compiler/build system in most cases. (That is,
|
||||||
// this generally only works on platforms/builds that have been specifically
|
// this functionality generally only works on platforms/builds that have been
|
||||||
// configured to support it.)
|
// specifically configured to support it.)
|
||||||
|
//
|
||||||
|
// Note: stack traces in Abseil that do not utilize a symbolizer will result in
|
||||||
|
// frames consisting of function addresses rather than human-readable function
|
||||||
|
// names. (See symbolize.h for information on symbolizing these values.)
|
||||||
|
|
||||||
#ifndef ABSL_DEBUGGING_STACKTRACE_H_
|
#ifndef ABSL_DEBUGGING_STACKTRACE_H_
|
||||||
#define ABSL_DEBUGGING_STACKTRACE_H_
|
#define ABSL_DEBUGGING_STACKTRACE_H_
|
||||||
|
|
||||||
namespace absl {
|
namespace absl {
|
||||||
|
|
||||||
// Skips the most recent "skip_count" stack frames (also skips the
|
// GetStackFrames()
|
||||||
// frame generated for the "absl::GetStackFrames" routine itself), and then
|
//
|
||||||
// records the pc values for up to the next "max_depth" frames in
|
// Records program counter values for up to `max_depth` frames, skipping the
|
||||||
// "result", and the corresponding stack frame sizes in "sizes".
|
// most recent `skip_count` stack frames, and stores their corresponding values
|
||||||
// Returns the number of values recorded in "result"/"sizes".
|
// and sizes in `results` and `sizes` buffers. (Note that the frame generated
|
||||||
|
// for the `absl::GetStackFrames()` routine itself is also skipped.)
|
||||||
|
// routine itself.
|
||||||
//
|
//
|
||||||
// Example:
|
// Example:
|
||||||
|
//
|
||||||
// main() { foo(); }
|
// main() { foo(); }
|
||||||
// foo() { bar(); }
|
// foo() { bar(); }
|
||||||
// bar() {
|
// bar() {
|
||||||
|
@ -41,41 +51,66 @@ namespace absl {
|
||||||
// int depth = absl::GetStackFrames(result, sizes, 10, 1);
|
// int depth = absl::GetStackFrames(result, sizes, 10, 1);
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// The absl::GetStackFrames call will skip the frame for "bar". It will
|
// The current stack frame would consist of three function calls: `bar()`,
|
||||||
// return 2 and will produce pc values that map to the following
|
// `foo()`, and then `main()`; however, since the `GetStackFrames()` call sets
|
||||||
// procedures:
|
// `skip_count` to `1`, it will skip the frame for `bar()`, the most recently
|
||||||
// result[0] foo
|
// invoked function call. It will therefore return two program counters and will
|
||||||
// result[1] main
|
// produce values that map to the following function calls:
|
||||||
// (Actually, there may be a few more entries after "main" to account for
|
//
|
||||||
// startup procedures.)
|
// result[0] foo()
|
||||||
// And corresponding stack frame sizes will also be recorded:
|
// result[1] main()
|
||||||
|
//
|
||||||
|
// (Note: in practice, a few more entries after `main()` may be added to account
|
||||||
|
// for startup processes.)
|
||||||
|
//
|
||||||
|
// Corresponding stack frame sizes will also be recorded:
|
||||||
|
//
|
||||||
// sizes[0] 16
|
// sizes[0] 16
|
||||||
// sizes[1] 16
|
// sizes[1] 16
|
||||||
// (Stack frame sizes of 16 above are just for illustration purposes.)
|
//
|
||||||
|
// (Stack frame sizes of `16` above are just for illustration purposes.)
|
||||||
|
//
|
||||||
// Stack frame sizes of 0 or less indicate that those frame sizes couldn't
|
// Stack frame sizes of 0 or less indicate that those frame sizes couldn't
|
||||||
// be identified.
|
// be identified.
|
||||||
//
|
//
|
||||||
// This routine may return fewer stack frame entries than are
|
// This routine may return fewer stack frame entries than are
|
||||||
// available. Also note that "result" and "sizes" must both be non-null.
|
// available. Also note that `result` and `sizes` must both be non-null.
|
||||||
extern int GetStackFrames(void** result, int* sizes, int max_depth,
|
extern int GetStackFrames(void** result, int* sizes, int max_depth,
|
||||||
int skip_count);
|
int skip_count);
|
||||||
|
|
||||||
// Same as above, but to be used from a signal handler. The "uc" parameter
|
// GetStackFramesWithContext()
|
||||||
// should be the pointer to ucontext_t which was passed as the 3rd parameter
|
|
||||||
// to sa_sigaction signal handler. It may help the unwinder to get a
|
|
||||||
// better stack trace under certain conditions. The "uc" may safely be null.
|
|
||||||
//
|
//
|
||||||
// If min_dropped_frames is not null, stores in *min_dropped_frames a
|
// Records program counter values obtained from a signal handler. Records
|
||||||
// lower bound on the number of dropped stack frames. The stored value is
|
// program counter values for up to `max_depth` frames, skipping the most recent
|
||||||
// guaranteed to be >= 0. The number of real stack frames is guaranteed to
|
// `skip_count` stack frames, and stores their corresponding values and sizes in
|
||||||
// be >= skip_count + max_depth + *min_dropped_frames.
|
// `results` and `sizes` buffers. (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
|
||||||
|
// `sigaction` struct. (See
|
||||||
|
// http://man7.org/linux/man-pages/man2/sigaction.2.html.) The `uc` value may
|
||||||
|
// help a stack unwinder to provide a better stack trace under certain
|
||||||
|
// conditions. `uc` may safely be null.
|
||||||
|
//
|
||||||
|
// The `min_dropped_frames` output parameter, if non-null, points to the
|
||||||
|
// location to note any dropped stack frames, if any, due to buffer limitations
|
||||||
|
// or other reasons. (This value will be set to `0` if no frames were dropped.)
|
||||||
|
// The number of total stack frames is guaranteed to be >= skip_count +
|
||||||
|
// max_depth + *min_dropped_frames.
|
||||||
extern int GetStackFramesWithContext(void** result, int* sizes, int max_depth,
|
extern int GetStackFramesWithContext(void** result, int* sizes, int max_depth,
|
||||||
int skip_count, const void* uc,
|
int skip_count, const void* uc,
|
||||||
int* min_dropped_frames);
|
int* min_dropped_frames);
|
||||||
|
|
||||||
// This is similar to the absl::GetStackFrames routine, except that it returns
|
// GetStackTrace()
|
||||||
// the stack trace only, and not the stack frame sizes as well.
|
//
|
||||||
|
// 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()`
|
||||||
|
// except that it returns the stack trace only, and not stack frame sizes.
|
||||||
|
//
|
||||||
// Example:
|
// Example:
|
||||||
|
//
|
||||||
// main() { foo(); }
|
// main() { foo(); }
|
||||||
// foo() { bar(); }
|
// foo() { bar(); }
|
||||||
// bar() {
|
// bar() {
|
||||||
|
@ -84,42 +119,57 @@ extern int GetStackFramesWithContext(void** result, int* sizes, int max_depth,
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// This produces:
|
// This produces:
|
||||||
|
//
|
||||||
// result[0] foo
|
// result[0] foo
|
||||||
// result[1] main
|
// result[1] main
|
||||||
// .... ...
|
// .... ...
|
||||||
//
|
//
|
||||||
// "result" must not be null.
|
// `result` must not be null.
|
||||||
extern int GetStackTrace(void** result, int max_depth, int skip_count);
|
extern int GetStackTrace(void** result, int max_depth, int skip_count);
|
||||||
|
|
||||||
// Same as above, but to be used from a signal handler. The "uc" parameter
|
// GetStackTraceWithContext()
|
||||||
// should be the pointer to ucontext_t which was passed as the 3rd parameter
|
|
||||||
// to sa_sigaction signal handler. It may help the unwinder to get a
|
|
||||||
// better stack trace under certain conditions. The "uc" may safely be null.
|
|
||||||
//
|
//
|
||||||
// If min_dropped_frames is not null, stores in *min_dropped_frames a
|
// Records program counter values obtained from a signal handler. Records
|
||||||
// lower bound on the number of dropped stack frames. The stored value is
|
// program counter values for up to `max_depth` frames, skipping the most recent
|
||||||
// guaranteed to be >= 0. The number of real stack frames is guaranteed to
|
// `skip_count` stack frames, and stores their corresponding values in
|
||||||
// be >= skip_count + max_depth + *min_dropped_frames.
|
// `results`. (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
|
||||||
|
// `sigaction` struct. (See
|
||||||
|
// http://man7.org/linux/man-pages/man2/sigaction.2.html.) The `uc` value may
|
||||||
|
// help a stack unwinder to provide a better stack trace under certain
|
||||||
|
// conditions. `uc` may safely be null.
|
||||||
|
//
|
||||||
|
// The `min_dropped_frames` output parameter, if non-null, points to the
|
||||||
|
// location to note any dropped stack frames, if any, due to buffer limitations
|
||||||
|
// or other reasons. (This value will be set to `0` if no frames were dropped.)
|
||||||
|
// The number of total stack frames is guaranteed to be >= skip_count +
|
||||||
|
// max_depth + *min_dropped_frames.
|
||||||
extern int GetStackTraceWithContext(void** result, int max_depth,
|
extern int GetStackTraceWithContext(void** result, int max_depth,
|
||||||
int skip_count, const void* uc,
|
int skip_count, const void* uc,
|
||||||
int* min_dropped_frames);
|
int* min_dropped_frames);
|
||||||
|
|
||||||
// Call this to provide a custom function for unwinding stack frames
|
// SetStackUnwinder()
|
||||||
// that will be used every time someone invokes one of the static
|
//
|
||||||
|
// Provides a custom function for unwinding stack frames that will be used in
|
||||||
|
// place of the default stack unwinder when invoking the static
|
||||||
// GetStack{Frames,Trace}{,WithContext}() functions above.
|
// GetStack{Frames,Trace}{,WithContext}() functions above.
|
||||||
//
|
//
|
||||||
// The arguments passed to the unwinder function will match the
|
// The arguments passed to the unwinder function will match the
|
||||||
// arguments passed to absl::GetStackFramesWithContext() except that sizes
|
// arguments passed to `absl::GetStackFramesWithContext()` except that sizes
|
||||||
// will be non-null iff the caller is interested in frame sizes.
|
// will be non-null iff the caller is interested in frame sizes.
|
||||||
//
|
//
|
||||||
// If unwinder is null, we revert to the default stack-tracing behavior.
|
// If unwinder is set to null, we revert to the default stack-tracing behavior.
|
||||||
//
|
//
|
||||||
// ****************************************************************
|
// *****************************************************************************
|
||||||
// WARNINGS
|
// WARNING
|
||||||
|
// *****************************************************************************
|
||||||
//
|
//
|
||||||
// absl::SetStackUnwinder is not suitable for general purpose use. It is
|
// absl::SetStackUnwinder is not suitable for general purpose use. It is
|
||||||
// provided for custom runtimes.
|
// provided for custom runtimes.
|
||||||
// Some things to watch out for when calling absl::SetStackUnwinder:
|
// Some things to watch out for when calling `absl::SetStackUnwinder()`:
|
||||||
//
|
//
|
||||||
// (a) The unwinder may be called from within signal handlers and
|
// (a) The unwinder may be called from within signal handlers and
|
||||||
// therefore must be async-signal-safe.
|
// therefore must be async-signal-safe.
|
||||||
|
@ -128,23 +178,31 @@ extern int GetStackTraceWithContext(void** result, int max_depth,
|
||||||
// threads may still be in the process of using that unwinder.
|
// threads may still be in the process of using that unwinder.
|
||||||
// Therefore do not clean up any state that may be needed by an old
|
// Therefore do not clean up any state that may be needed by an old
|
||||||
// unwinder.
|
// unwinder.
|
||||||
// ****************************************************************
|
// *****************************************************************************
|
||||||
extern void SetStackUnwinder(int (*unwinder)(void** pcs, int* sizes,
|
extern void SetStackUnwinder(int (*unwinder)(void** pcs, int* sizes,
|
||||||
int max_depth, int skip_count,
|
int max_depth, int skip_count,
|
||||||
const void* uc,
|
const void* uc,
|
||||||
int* min_dropped_frames));
|
int* min_dropped_frames));
|
||||||
|
|
||||||
// Function that exposes built-in stack-unwinding behavior, ignoring
|
// DefaultStackUnwinder()
|
||||||
// any calls to absl::SetStackUnwinder().
|
|
||||||
//
|
//
|
||||||
// pcs must NOT be null.
|
// Records program counter values of up to `max_depth` frames, skipping the most
|
||||||
|
// recent `skip_count` stack frames, and stores their corresponding values in
|
||||||
|
// `pcs`. (Note that the frame generated for this call itself is also skipped.)
|
||||||
|
// This function acts as a generic stack-unwinder; prefer usage of the more
|
||||||
|
// specific `GetStack{Trace,Frames}{,WithContext}()` functions above.
|
||||||
//
|
//
|
||||||
// sizes may be null.
|
// If you have set your own stack unwinder (with the `SetStackUnwinder()`
|
||||||
// uc may be null.
|
// function above, you can still get the default stack unwinder by calling
|
||||||
// min_dropped_frames may be null.
|
// `DefaultStackUnwinder()`, which will ignore any previously set stack unwinder
|
||||||
|
// and use the default one instead.
|
||||||
//
|
//
|
||||||
// The semantics are the same as the corresponding GetStack*() function in the
|
// Because this function is generic, only `pcs` is guaranteed to be non-null
|
||||||
// case where absl::SetStackUnwinder() was never called. Equivalents are:
|
// upon return. It is legal for `sizes`, `uc`, and `min_dropped_frames` to all
|
||||||
|
// be null when called.
|
||||||
|
//
|
||||||
|
// The semantics are the same as the corresponding `GetStack*()` function in the
|
||||||
|
// case where `absl::SetStackUnwinder()` was never called. Equivalents are:
|
||||||
//
|
//
|
||||||
// null sizes | non-nullptr sizes
|
// null sizes | non-nullptr sizes
|
||||||
// |==========================================================|
|
// |==========================================================|
|
||||||
|
|
|
@ -11,7 +11,44 @@
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// File: symbolize.h
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// This file configures the Abseil symbolizer for use in converting instruction
|
||||||
|
// pointer addresses (program counters) into human-readable names (function
|
||||||
|
// calls, etc.) within Abseil code.
|
||||||
|
//
|
||||||
|
// The symbolizer may be invoked from several sources:
|
||||||
|
//
|
||||||
|
// * Implicitly, through the installation of an Abseil failure signal handler.
|
||||||
|
// (See failure_signal_handler.h for more information.)
|
||||||
|
// * By calling `Symbolize()` directly on a program counter you obtain through
|
||||||
|
// `absl::GetStackTrace()` or `absl::GetStackFrames()`. (See stacktrace.h
|
||||||
|
// for more information.
|
||||||
|
// * By calling `Symbolize()` directly on a program counter you obtain through
|
||||||
|
// other means (which would be platform-dependent).
|
||||||
|
//
|
||||||
|
// In all of the above cases, the symbolizer must first be initialized before
|
||||||
|
// any program counter values can be symbolized. If you are installing a failure
|
||||||
|
// signal handler, initialize the symbolizer before you do so.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// int main(int argc, char** argv) {
|
||||||
|
// // Initialize the Symbolizer before installing the failure signal handler
|
||||||
|
// absl::InitializeSymbolizer(argv[0]);
|
||||||
|
//
|
||||||
|
// // Now you may install the failure signal handler
|
||||||
|
// absl::FailureSignalHandlerOptions options;
|
||||||
|
// absl::InstallFailureSignalHandler(options);
|
||||||
|
//
|
||||||
|
// // Start running your main program
|
||||||
|
// ...
|
||||||
|
// return 0;
|
||||||
|
// }
|
||||||
|
//
|
||||||
#ifndef ABSL_DEBUGGING_SYMBOLIZE_H_
|
#ifndef ABSL_DEBUGGING_SYMBOLIZE_H_
|
||||||
#define ABSL_DEBUGGING_SYMBOLIZE_H_
|
#define ABSL_DEBUGGING_SYMBOLIZE_H_
|
||||||
|
|
||||||
|
@ -19,15 +56,40 @@
|
||||||
|
|
||||||
namespace absl {
|
namespace absl {
|
||||||
|
|
||||||
// Initializes this module. Symbolize() may fail prior calling this function.
|
// InitializeSymbolizer()
|
||||||
// `argv0` is the path to this program, which is usually obtained in main()
|
//
|
||||||
// though argv[0].
|
// Initializes the program counter symbolizer, given the path of the program
|
||||||
|
// (typically obtained through `main()`s `argv[0]`). The Abseil symbolizer
|
||||||
|
// allows you to read program counters (instruction pointer values) using their
|
||||||
|
// human-readable names within output such as stack traces.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// int main(int argc, char *argv[]) {
|
||||||
|
// absl::InitializeSymbolizer(argv[0]);
|
||||||
|
// // Now you can use the symbolizer
|
||||||
|
// }
|
||||||
void InitializeSymbolizer(const char* argv0);
|
void InitializeSymbolizer(const char* argv0);
|
||||||
|
|
||||||
// Symbolizes a program counter. On success, returns true and write the
|
// Symbolize()
|
||||||
// symbol name to "out". The symbol name is demangled if possible
|
//
|
||||||
// (supports symbols generated by GCC 3.x or newer), may be truncated, and
|
// Symbolizes a program counter (instruction pointer value) `pc` and, on
|
||||||
// will be '\0' terminated. Otherwise, returns false.
|
// success, writes the name to `out`. The symbol name is demangled, if possible.
|
||||||
|
// Note that the symbolized name may be truncated and will be NUL-terminated.
|
||||||
|
// Demangling is supported for symbols generated by GCC 3.x or newer). Returns
|
||||||
|
// `false` on failure.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// // Print a program counter and its symbol name.
|
||||||
|
// static void DumpPCAndSymbol(void *pc) {
|
||||||
|
// char tmp[1024];
|
||||||
|
// const char *symbol = "(unknown)";
|
||||||
|
// if (absl::Symbolize(pc, tmp, sizeof(tmp))) {
|
||||||
|
// symbol = tmp;
|
||||||
|
// }
|
||||||
|
// absl::PrintF("%*p %s\n", pc, symbol);
|
||||||
|
// }
|
||||||
bool Symbolize(const void *pc, char *out, int out_size);
|
bool Symbolize(const void *pc, char *out, int out_size);
|
||||||
|
|
||||||
} // namespace absl
|
} // namespace absl
|
||||||
|
|
|
@ -84,6 +84,7 @@ cc_library(
|
||||||
"internal/utf8.cc",
|
"internal/utf8.cc",
|
||||||
],
|
],
|
||||||
hdrs = [
|
hdrs = [
|
||||||
|
"internal/bits.h",
|
||||||
"internal/char_map.h",
|
"internal/char_map.h",
|
||||||
"internal/ostringstream.h",
|
"internal/ostringstream.h",
|
||||||
"internal/resize_uninitialized.h",
|
"internal/resize_uninitialized.h",
|
||||||
|
|
|
@ -31,6 +31,7 @@ list(APPEND STRINGS_PUBLIC_HEADERS
|
||||||
|
|
||||||
|
|
||||||
list(APPEND STRINGS_INTERNAL_HEADERS
|
list(APPEND STRINGS_INTERNAL_HEADERS
|
||||||
|
"internal/bits.h"
|
||||||
"internal/char_map.h"
|
"internal/char_map.h"
|
||||||
"internal/memutil.h"
|
"internal/memutil.h"
|
||||||
"internal/ostringstream.h"
|
"internal/ostringstream.h"
|
||||||
|
|
53
absl/strings/internal/bits.h
Normal file
53
absl/strings/internal/bits.h
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
// http://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_BITS_H_
|
||||||
|
#define ABSL_STRINGS_INTERNAL_BITS_H_
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && defined(_M_X64)
|
||||||
|
#include <intrin.h>
|
||||||
|
#pragma intrinsic(_BitScanReverse64)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace absl {
|
||||||
|
namespace strings_internal {
|
||||||
|
|
||||||
|
// Returns the number of leading 0 bits in a 64-bit value.
|
||||||
|
inline int CountLeadingZeros64(uint64_t n) {
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
static_assert(sizeof(unsigned long long) == sizeof(n), // NOLINT(runtime/int)
|
||||||
|
"__builtin_clzll does not take 64bit arg");
|
||||||
|
return n == 0 ? 64 : __builtin_clzll(n);
|
||||||
|
#elif defined(_MSC_VER) && defined(_M_X64)
|
||||||
|
unsigned long result; // NOLINT(runtime/int)
|
||||||
|
if (_BitScanReverse64(&result, n)) {
|
||||||
|
return 63 - result;
|
||||||
|
}
|
||||||
|
return 64;
|
||||||
|
#else
|
||||||
|
int zeroes = 60;
|
||||||
|
if (n >> 32) zeroes -= 32, n >>= 32;
|
||||||
|
if (n >> 16) zeroes -= 16, n >>= 16;
|
||||||
|
if (n >> 8) zeroes -= 8, n >>= 8;
|
||||||
|
if (n >> 4) zeroes -= 4, n >>= 4;
|
||||||
|
return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0\0"[n] + zeroes;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace strings_internal
|
||||||
|
} // namespace absl
|
||||||
|
|
||||||
|
#endif // ABSL_STRINGS_INTERNAL_BITS_H_
|
|
@ -32,6 +32,7 @@
|
||||||
|
|
||||||
#include "absl/base/internal/raw_logging.h"
|
#include "absl/base/internal/raw_logging.h"
|
||||||
#include "absl/strings/ascii.h"
|
#include "absl/strings/ascii.h"
|
||||||
|
#include "absl/strings/internal/bits.h"
|
||||||
#include "absl/strings/internal/memutil.h"
|
#include "absl/strings/internal/memutil.h"
|
||||||
#include "absl/strings/str_cat.h"
|
#include "absl/strings/str_cat.h"
|
||||||
|
|
||||||
|
@ -302,18 +303,6 @@ char* numbers_internal::FastIntToBuffer(int64_t i, char* buffer) {
|
||||||
return numbers_internal::FastIntToBuffer(u, buffer);
|
return numbers_internal::FastIntToBuffer(u, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of leading 0 bits in a 64-bit value.
|
|
||||||
// TODO(jorg): Replace with builtin_clzll if available.
|
|
||||||
// Are we shipping util/bits in absl?
|
|
||||||
static inline int CountLeadingZeros64(uint64_t n) {
|
|
||||||
int zeroes = 60;
|
|
||||||
if (n >> 32) zeroes -= 32, n >>= 32;
|
|
||||||
if (n >> 16) zeroes -= 16, n >>= 16;
|
|
||||||
if (n >> 8) zeroes -= 8, n >>= 8;
|
|
||||||
if (n >> 4) zeroes -= 4, n >>= 4;
|
|
||||||
return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0\0"[n] + zeroes;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Given a 128-bit number expressed as a pair of uint64_t, high half first,
|
// Given a 128-bit number expressed as a pair of uint64_t, high half first,
|
||||||
// return that number multiplied by the given 32-bit value. If the result is
|
// return that number multiplied by the given 32-bit value. If the result is
|
||||||
// too large to fit in a 128-bit number, divide it by 2 until it fits.
|
// too large to fit in a 128-bit number, divide it by 2 until it fits.
|
||||||
|
@ -351,7 +340,7 @@ static std::pair<uint64_t, uint64_t> Mul32(std::pair<uint64_t, uint64_t> num,
|
||||||
uint64_t bits128_up = (bits96_127 >> 32) + (bits64_127 < bits64_95);
|
uint64_t bits128_up = (bits96_127 >> 32) + (bits64_127 < bits64_95);
|
||||||
if (bits128_up == 0) return {bits64_127, bits0_63};
|
if (bits128_up == 0) return {bits64_127, bits0_63};
|
||||||
|
|
||||||
int shift = 64 - CountLeadingZeros64(bits128_up);
|
int shift = 64 - strings_internal::CountLeadingZeros64(bits128_up);
|
||||||
uint64_t lo = (bits0_63 >> shift) + (bits64_127 << (64 - shift));
|
uint64_t lo = (bits0_63 >> shift) + (bits64_127 << (64 - shift));
|
||||||
uint64_t hi = (bits64_127 >> shift) + (bits128_up << (64 - shift));
|
uint64_t hi = (bits64_127 >> shift) + (bits128_up << (64 - shift));
|
||||||
return {hi, lo};
|
return {hi, lo};
|
||||||
|
@ -382,7 +371,7 @@ static std::pair<uint64_t, uint64_t> PowFive(uint64_t num, int expfive) {
|
||||||
5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
|
5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
|
||||||
5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5};
|
5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5};
|
||||||
result = Mul32(result, powers_of_five[expfive & 15]);
|
result = Mul32(result, powers_of_five[expfive & 15]);
|
||||||
int shift = CountLeadingZeros64(result.first);
|
int shift = strings_internal::CountLeadingZeros64(result.first);
|
||||||
if (shift != 0) {
|
if (shift != 0) {
|
||||||
result.first = (result.first << shift) + (result.second >> (64 - shift));
|
result.first = (result.first << shift) + (result.second >> (64 - shift));
|
||||||
result.second = (result.second << shift);
|
result.second = (result.second << shift);
|
||||||
|
|
|
@ -33,7 +33,7 @@ list(APPEND SYNCHRONIZATION_INTERNAL_HEADERS
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# syncrhonisation library
|
# synchronization library
|
||||||
list(APPEND SYNCHRONIZATION_SRC
|
list(APPEND SYNCHRONIZATION_SRC
|
||||||
"barrier.cc"
|
"barrier.cc"
|
||||||
"blocking_counter.cc"
|
"blocking_counter.cc"
|
||||||
|
|
|
@ -99,7 +99,7 @@ TEST(AnyExceptionSafety, Ctors) {
|
||||||
|
|
||||||
TEST(AnyExceptionSafety, Assignment) {
|
TEST(AnyExceptionSafety, Assignment) {
|
||||||
auto original =
|
auto original =
|
||||||
absl::any(absl::in_place_type_t<Thrower>(), 1, testing::no_throw_ctor);
|
absl::any(absl::in_place_type_t<Thrower>(), 1, testing::nothrow_ctor);
|
||||||
auto any_is_strong = [original](absl::any* ap) {
|
auto any_is_strong = [original](absl::any* ap) {
|
||||||
return testing::AssertionResult(ap->has_value() &&
|
return testing::AssertionResult(ap->has_value() &&
|
||||||
absl::any_cast<Thrower>(original) ==
|
absl::any_cast<Thrower>(original) ==
|
||||||
|
@ -139,14 +139,14 @@ TEST(AnyExceptionSafety, Assignment) {
|
||||||
#if !defined(ABSL_HAVE_STD_ANY)
|
#if !defined(ABSL_HAVE_STD_ANY)
|
||||||
TEST(AnyExceptionSafety, Emplace) {
|
TEST(AnyExceptionSafety, Emplace) {
|
||||||
auto initial_val =
|
auto initial_val =
|
||||||
absl::any{absl::in_place_type_t<Thrower>(), 1, testing::no_throw_ctor};
|
absl::any{absl::in_place_type_t<Thrower>(), 1, testing::nothrow_ctor};
|
||||||
auto one_tester = testing::MakeExceptionSafetyTester()
|
auto one_tester = testing::MakeExceptionSafetyTester()
|
||||||
.WithInitialValue(initial_val)
|
.WithInitialValue(initial_val)
|
||||||
.WithInvariants(AnyInvariants, AnyIsEmpty);
|
.WithInvariants(AnyInvariants, AnyIsEmpty);
|
||||||
|
|
||||||
auto emp_thrower = [](absl::any* ap) { ap->emplace<Thrower>(2); };
|
auto emp_thrower = [](absl::any* ap) { ap->emplace<Thrower>(2); };
|
||||||
auto emp_throwervec = [](absl::any* ap) {
|
auto emp_throwervec = [](absl::any* ap) {
|
||||||
std::initializer_list<Thrower> il{Thrower(2, testing::no_throw_ctor)};
|
std::initializer_list<Thrower> il{Thrower(2, testing::nothrow_ctor)};
|
||||||
ap->emplace<ThrowerVec>(il);
|
ap->emplace<ThrowerVec>(il);
|
||||||
};
|
};
|
||||||
auto emp_movethrower = [](absl::any* ap) {
|
auto emp_movethrower = [](absl::any* ap) {
|
||||||
|
|
Loading…
Reference in a new issue