diff options
author | Abseil Team <absl-team@google.com> | 2018-05-14 13:41:38 -0700 |
---|---|---|
committer | jueminyang <jueminyang@google.com> | 2018-05-15 11:00:30 -0400 |
commit | 04dd99d8c1813ded74cd2a9c90ecb7eaa2d68ab1 (patch) | |
tree | bcbac48462be4c3d39c1dcf933b55ea98f3928e8 | |
parent | add89fd0e4bfd7d874bb55b67f4e13bf8beca762 (diff) |
- 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
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | absl/base/exception_safety_testing_test.cc | 2 | ||||
-rw-r--r-- | absl/base/internal/exception_safety_testing.cc | 7 | ||||
-rw-r--r-- | absl/base/internal/exception_safety_testing.h | 42 | ||||
-rw-r--r-- | absl/debugging/leak_check.h | 8 | ||||
-rw-r--r-- | absl/debugging/stacktrace.h | 178 | ||||
-rw-r--r-- | absl/debugging/symbolize.h | 78 | ||||
-rw-r--r-- | absl/strings/BUILD.bazel | 1 | ||||
-rw-r--r-- | absl/strings/CMakeLists.txt | 1 | ||||
-rw-r--r-- | absl/strings/internal/bits.h | 53 | ||||
-rw-r--r-- | absl/strings/numbers.cc | 17 | ||||
-rw-r--r-- | absl/synchronization/CMakeLists.txt | 2 | ||||
-rw-r--r-- | absl/types/any_exception_safety_test.cc | 6 |
13 files changed, 279 insertions, 117 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a8f8622..744241ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,7 +53,6 @@ list(APPEND ABSL_COMMON_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}) # -std=X set(CMAKE_CXX_FLAGS "${ABSL_STD_CXX_FLAG} ${CMAKE_CXX_FLAGS}") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_WARNING_VLA} ${CMAKE_CXX_FLAGS} ") # -fexceptions set(ABSL_EXCEPTIONS_FLAG "${CMAKE_CXX_EXCEPTIONS}") diff --git a/absl/base/exception_safety_testing_test.cc b/absl/base/exception_safety_testing_test.cc index 4507b946..a8b82b73 100644 --- a/absl/base/exception_safety_testing_test.cc +++ b/absl/base/exception_safety_testing_test.cc @@ -405,7 +405,7 @@ TEST(ThrowingAllocatorTest, NonThrowingConstruction) { SetCountdown(); ExpectNoThrow( - [&]() { nothrow_alloc.construct(ptr, 2, testing::no_throw_ctor); }); + [&]() { nothrow_alloc.construct(ptr, 2, testing::nothrow_ctor); }); EXPECT_EQ(ptr->Get(), 2); nothrow_alloc.destroy(ptr); diff --git a/absl/base/internal/exception_safety_testing.cc b/absl/base/internal/exception_safety_testing.cc index c92d07bc..d3e94074 100644 --- a/absl/base/internal/exception_safety_testing.cc +++ b/absl/base/internal/exception_safety_testing.cc @@ -19,7 +19,12 @@ 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; namespace exceptions_internal { diff --git a/absl/base/internal/exception_safety_testing.h b/absl/base/internal/exception_safety_testing.h index bec3ab30..c3ff34c5 100644 --- a/absl/base/internal/exception_safety_testing.h +++ b/absl/base/internal/exception_safety_testing.h @@ -227,7 +227,9 @@ inline absl::optional<testing::AssertionResult> TestAllInvariantsAtCountdown( } // 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; // 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 - * 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. * * kEverythingThrows: Every operation can throw an exception @@ -341,22 +343,22 @@ class ThrowingValue : private exceptions_internal::TrackedObject { // Arithmetic Operators ThrowingValue operator+(const ThrowingValue& other) const { exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return ThrowingValue(dummy_ + other.dummy_, no_throw_ctor); + return ThrowingValue(dummy_ + other.dummy_, nothrow_ctor); } ThrowingValue operator+() const { exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return ThrowingValue(dummy_, no_throw_ctor); + return ThrowingValue(dummy_, nothrow_ctor); } ThrowingValue operator-(const ThrowingValue& other) const { exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return ThrowingValue(dummy_ - other.dummy_, no_throw_ctor); + return ThrowingValue(dummy_ - other.dummy_, nothrow_ctor); } ThrowingValue operator-() const { exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return ThrowingValue(-dummy_, no_throw_ctor); + return ThrowingValue(-dummy_, nothrow_ctor); } ThrowingValue& operator++() { @@ -367,7 +369,7 @@ class ThrowingValue : private exceptions_internal::TrackedObject { ThrowingValue operator++(int) { exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - auto out = ThrowingValue(dummy_, no_throw_ctor); + auto out = ThrowingValue(dummy_, nothrow_ctor); ++dummy_; return out; } @@ -380,34 +382,34 @@ class ThrowingValue : private exceptions_internal::TrackedObject { ThrowingValue operator--(int) { exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - auto out = ThrowingValue(dummy_, no_throw_ctor); + auto out = ThrowingValue(dummy_, nothrow_ctor); --dummy_; return out; } ThrowingValue operator*(const ThrowingValue& other) const { 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 { 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 { 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 { exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return ThrowingValue(dummy_ << shift, no_throw_ctor); + return ThrowingValue(dummy_ << shift, nothrow_ctor); } ThrowingValue operator>>(int shift) const { exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return ThrowingValue(dummy_ >> shift, no_throw_ctor); + return ThrowingValue(dummy_ >> shift, nothrow_ctor); } // Comparison Operators @@ -463,22 +465,22 @@ class ThrowingValue : private exceptions_internal::TrackedObject { // Bitwise Logical Operators ThrowingValue operator~() const { exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return ThrowingValue(~dummy_, no_throw_ctor); + return ThrowingValue(~dummy_, nothrow_ctor); } ThrowingValue operator&(const ThrowingValue& other) const { 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 { 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 { exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return ThrowingValue(dummy_ ^ other.dummy_, no_throw_ctor); + return ThrowingValue(dummy_ ^ other.dummy_, nothrow_ctor); } // Compound Assignment operators @@ -1034,12 +1036,6 @@ MakeExceptionSafetyTester() { 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 #endif // ABSL_BASE_INTERNAL_EXCEPTION_SAFETY_TESTING_H_ diff --git a/absl/debugging/leak_check.h b/absl/debugging/leak_check.h index f67fe88a..c930684e 100644 --- a/absl/debugging/leak_check.h +++ b/absl/debugging/leak_check.h @@ -1,5 +1,4 @@ -// -// Copyright 2017 The Abseil Authors. +// 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. @@ -13,15 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. // - // ----------------------------------------------------------------------------- // 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 // 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. // Note: this leak checking API is not yet supported in MSVC. // Leak checking is enabled by default in all ASan builds. diff --git a/absl/debugging/stacktrace.h b/absl/debugging/stacktrace.h index 82da3f15..8b831e26 100644 --- a/absl/debugging/stacktrace.h +++ b/absl/debugging/stacktrace.h @@ -1,5 +1,4 @@ -// -// Copyright 2017 The Abseil Authors. +// 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. @@ -13,26 +12,37 @@ // See the License for the specific language governing permissions and // limitations under the License. // - -// Routines to extract the current stack trace. These functions are -// thread-safe and async-signal-safe. +// ----------------------------------------------------------------------------- +// File: stacktrace.h +// ----------------------------------------------------------------------------- +// +// 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 -// additional support from the compiler/build system in many cases. (That is, -// this generally only works on platforms/builds that have been specifically -// configured to support it.) +// additional support from the compiler/build system in most cases. (That is, +// this functionality generally only works on platforms/builds that have been +// 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_ #define ABSL_DEBUGGING_STACKTRACE_H_ namespace absl { -// Skips the most recent "skip_count" stack frames (also skips the -// frame generated for the "absl::GetStackFrames" routine itself), and then -// records the pc values for up to the next "max_depth" frames in -// "result", and the corresponding stack frame sizes in "sizes". -// Returns the number of values recorded in "result"/"sizes". +// GetStackFrames() +// +// Records program counter values for up to `max_depth` frames, skipping the +// most recent `skip_count` stack frames, and stores their corresponding values +// and sizes in `results` and `sizes` buffers. (Note that the frame generated +// for the `absl::GetStackFrames()` routine itself is also skipped.) +// routine itself. // // Example: +// // main() { foo(); } // foo() { bar(); } // bar() { @@ -41,41 +51,66 @@ namespace absl { // int depth = absl::GetStackFrames(result, sizes, 10, 1); // } // -// The absl::GetStackFrames call will skip the frame for "bar". It will -// return 2 and will produce pc values that map to the following -// procedures: -// result[0] foo -// result[1] main -// (Actually, there may be a few more entries after "main" to account for -// startup procedures.) -// And corresponding stack frame sizes will also be recorded: +// The current stack frame would consist of three function calls: `bar()`, +// `foo()`, and then `main()`; however, since the `GetStackFrames()` call sets +// `skip_count` to `1`, it will skip the frame for `bar()`, the most recently +// invoked function call. It will therefore return two program counters and will +// produce values that map to the following function calls: +// +// result[0] foo() +// 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[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 // be identified. // // 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, int skip_count); -// Same as above, but to be used from a signal handler. The "uc" parameter -// 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 -// lower bound on the number of dropped stack frames. The stored value is -// guaranteed to be >= 0. The number of real stack frames is guaranteed to -// be >= skip_count + max_depth + *min_dropped_frames. +// GetStackFramesWithContext() +// +// Records program counter values obtained from a signal handler. Records +// program counter values for up to `max_depth` frames, skipping the most recent +// `skip_count` stack frames, and stores their corresponding values and sizes in +// `results` and `sizes` buffers. (Note that the frame generated for the +// `absl::GetStackFramesWithContext()` routine itself is also skipped.) +// +// 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, int skip_count, const void* uc, int* min_dropped_frames); -// This is similar to the absl::GetStackFrames routine, except that it returns -// the stack trace only, and not the stack frame sizes as well. +// GetStackTrace() +// +// Records program counter values for up to `max_depth` frames, skipping the +// most recent `skip_count` stack frames, and stores their corresponding values +// in `results`. Note that this function is similar to `absl::GetStackFrames()` +// except that it returns the stack trace only, and not stack frame sizes. +// // Example: +// // main() { foo(); } // foo() { bar(); } // bar() { @@ -84,42 +119,57 @@ extern int GetStackFramesWithContext(void** result, int* sizes, int max_depth, // } // // This produces: +// // result[0] foo // result[1] main // .... ... // -// "result" must not be null. +// `result` must not be null. 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 -// 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 -// lower bound on the number of dropped stack frames. The stored value is -// guaranteed to be >= 0. The number of real stack frames is guaranteed to -// be >= skip_count + max_depth + *min_dropped_frames. +// GetStackTraceWithContext() +// +// Records program counter values obtained from a signal handler. Records +// program counter values for up to `max_depth` frames, skipping the most recent +// `skip_count` stack frames, and stores their corresponding values in +// `results`. (Note that the frame generated for the +// `absl::GetStackFramesWithContext()` routine itself is also skipped.) +// +// 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, int skip_count, const void* uc, int* min_dropped_frames); -// Call this to provide a custom function for unwinding stack frames -// that will be used every time someone invokes one of the static +// SetStackUnwinder() +// +// 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. // // 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. // -// 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 // 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 // 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. // Therefore do not clean up any state that may be needed by an old // unwinder. -// **************************************************************** +// ***************************************************************************** extern void SetStackUnwinder(int (*unwinder)(void** pcs, int* sizes, int max_depth, int skip_count, const void* uc, int* min_dropped_frames)); -// Function that exposes built-in stack-unwinding behavior, ignoring -// any calls to absl::SetStackUnwinder(). +// DefaultStackUnwinder() +// +// 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. // -// pcs must NOT be null. +// If you have set your own stack unwinder (with the `SetStackUnwinder()` +// function above, you can still get the default stack unwinder by calling +// `DefaultStackUnwinder()`, which will ignore any previously set stack unwinder +// and use the default one instead. // -// sizes may be null. -// uc may be null. -// min_dropped_frames may be null. +// Because this function is generic, only `pcs` is guaranteed to be non-null +// 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: +// 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 // |==========================================================| diff --git a/absl/debugging/symbolize.h b/absl/debugging/symbolize.h index 073a4479..24e6e647 100644 --- a/absl/debugging/symbolize.h +++ b/absl/debugging/symbolize.h @@ -11,7 +11,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. - +// +// ----------------------------------------------------------------------------- +// 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_ #define ABSL_DEBUGGING_SYMBOLIZE_H_ @@ -19,15 +56,40 @@ namespace absl { -// Initializes this module. Symbolize() may fail prior calling this function. -// `argv0` is the path to this program, which is usually obtained in main() -// though argv[0]. +// InitializeSymbolizer() +// +// 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); -// Symbolizes a program counter. On success, returns true and write the -// symbol name to "out". The symbol name is demangled if possible -// (supports symbols generated by GCC 3.x or newer), may be truncated, and -// will be '\0' terminated. Otherwise, returns false. +// Symbolize() +// +// Symbolizes a program counter (instruction pointer value) `pc` and, on +// 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); } // namespace absl diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel index 13badb7b..1e52312b 100644 --- a/absl/strings/BUILD.bazel +++ b/absl/strings/BUILD.bazel @@ -84,6 +84,7 @@ cc_library( "internal/utf8.cc", ], hdrs = [ + "internal/bits.h", "internal/char_map.h", "internal/ostringstream.h", "internal/resize_uninitialized.h", diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt index 83cb934d..9dc47328 100644 --- a/absl/strings/CMakeLists.txt +++ b/absl/strings/CMakeLists.txt @@ -31,6 +31,7 @@ list(APPEND STRINGS_PUBLIC_HEADERS list(APPEND STRINGS_INTERNAL_HEADERS + "internal/bits.h" "internal/char_map.h" "internal/memutil.h" "internal/ostringstream.h" diff --git a/absl/strings/internal/bits.h b/absl/strings/internal/bits.h new file mode 100644 index 00000000..901082cc --- /dev/null +++ b/absl/strings/internal/bits.h @@ -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_ diff --git a/absl/strings/numbers.cc b/absl/strings/numbers.cc index b4140b36..68ef7999 100644 --- a/absl/strings/numbers.cc +++ b/absl/strings/numbers.cc @@ -32,6 +32,7 @@ #include "absl/base/internal/raw_logging.h" #include "absl/strings/ascii.h" +#include "absl/strings/internal/bits.h" #include "absl/strings/internal/memutil.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); } -// 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, // 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. @@ -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); 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 hi = (bits64_127 >> shift) + (bits128_up << (64 - shift)); 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}; result = Mul32(result, powers_of_five[expfive & 15]); - int shift = CountLeadingZeros64(result.first); + int shift = strings_internal::CountLeadingZeros64(result.first); if (shift != 0) { result.first = (result.first << shift) + (result.second >> (64 - shift)); result.second = (result.second << shift); diff --git a/absl/synchronization/CMakeLists.txt b/absl/synchronization/CMakeLists.txt index 6886c1ca..c19f5725 100644 --- a/absl/synchronization/CMakeLists.txt +++ b/absl/synchronization/CMakeLists.txt @@ -33,7 +33,7 @@ list(APPEND SYNCHRONIZATION_INTERNAL_HEADERS -# syncrhonisation library +# synchronization library list(APPEND SYNCHRONIZATION_SRC "barrier.cc" "blocking_counter.cc" diff --git a/absl/types/any_exception_safety_test.cc b/absl/types/any_exception_safety_test.cc index daa82e72..36955f6c 100644 --- a/absl/types/any_exception_safety_test.cc +++ b/absl/types/any_exception_safety_test.cc @@ -99,7 +99,7 @@ TEST(AnyExceptionSafety, Ctors) { TEST(AnyExceptionSafety, Assignment) { 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) { return testing::AssertionResult(ap->has_value() && absl::any_cast<Thrower>(original) == @@ -139,14 +139,14 @@ TEST(AnyExceptionSafety, Assignment) { #if !defined(ABSL_HAVE_STD_ANY) TEST(AnyExceptionSafety, Emplace) { 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() .WithInitialValue(initial_val) .WithInvariants(AnyInvariants, AnyIsEmpty); auto emp_thrower = [](absl::any* ap) { ap->emplace<Thrower>(2); }; 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); }; auto emp_movethrower = [](absl::any* ap) { |