diff options
Diffstat (limited to 'absl/base')
24 files changed, 522 insertions, 358 deletions
diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel index 743add7e0127..9bb7bfa14efb 100644 --- a/absl/base/BUILD.bazel +++ b/absl/base/BUILD.bazel @@ -82,7 +82,6 @@ cc_library( srcs = ["internal/malloc_extension.cc"], hdrs = [ "internal/malloc_extension.h", - "internal/malloc_extension_c.h", ], copts = ABSL_DEFAULT_COPTS, visibility = [ @@ -129,6 +128,7 @@ cc_library( name = "base_internal", hdrs = [ "internal/identity.h", + "internal/inline_variable.h", "internal/invoke.h", ], copts = ABSL_DEFAULT_COPTS, @@ -152,7 +152,6 @@ cc_library( "casts.h", "internal/atomic_hook.h", "internal/cycleclock.h", - "internal/log_severity.h", "internal/low_level_scheduling.h", "internal/per_thread_tls.h", "internal/raw_logging.h", @@ -161,6 +160,7 @@ cc_library( "internal/thread_identity.h", "internal/tsan_mutex_interface.h", "internal/unscaledcycleclock.h", + "log_severity.h", ], copts = ABSL_DEFAULT_COPTS, deps = [ @@ -236,6 +236,7 @@ cc_library( hdrs = ["internal/exception_safety_testing.h"], copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG, deps = [ + ":base", ":config", ":pretty_function", "//absl/memory", @@ -258,6 +259,22 @@ cc_test( ) cc_test( + name = "inline_variable_test", + size = "small", + srcs = [ + "inline_variable_test.cc", + "inline_variable_test_a.cc", + "inline_variable_test_b.cc", + "internal/inline_variable_testing.h", + ], + copts = ABSL_TEST_COPTS, + deps = [ + ":base_internal", + "@com_google_googletest//:gtest_main", + ], +) + +cc_test( name = "invoke_test", size = "small", srcs = ["invoke_test.cc"], diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt index 3e94d51fef8e..9d2de55fea90 100644 --- a/absl/base/CMakeLists.txt +++ b/absl/base/CMakeLists.txt @@ -20,6 +20,7 @@ list(APPEND BASE_PUBLIC_HEADERS "casts.h" "config.h" "dynamic_annotations.h" + "log_severity.h" "macros.h" "optimization.h" "policy_checks.h" @@ -33,17 +34,18 @@ list(APPEND BASE_INTERNAL_HEADERS "internal/cycleclock.h" "internal/endian.h" "internal/exception_testing.h" + "internal/exception_safety_testing.h" "internal/identity.h" "internal/invoke.h" - "internal/log_severity.h" + "internal/inline_variable.h" "internal/low_level_alloc.h" "internal/low_level_scheduling.h" - "internal/malloc_extension_c.h" "internal/malloc_extension.h" "internal/malloc_hook_c.h" "internal/malloc_hook.h" "internal/malloc_hook_invoke.h" "internal/per_thread_tls.h" + "internal/pretty_function.h" "internal/raw_logging.h" "internal/scheduling_mode.h" "internal/spinlock.h" @@ -58,8 +60,9 @@ list(APPEND BASE_INTERNAL_HEADERS # absl_base main library -list(APPEND BASE_SRC +list(APPEND BASE_SRC "internal/cycleclock.cc" + "internal/exception_safety_testing.cc" "internal/raw_logging.cc" "internal/spinlock.cc" "internal/sysinfo.cc" @@ -212,6 +215,26 @@ absl_test( ) +# test inline_variable_test +list(APPEND INLINE_VARIABLE_TEST_SRC + "internal/inline_variable_testing.h" + "inline_variable_test.cc" + "inline_variable_test_a.cc" + "inline_variable_test_b.cc" +) + +set(INLINE_VARIABLE_TEST_PUBLIC_LIBRARIES absl::base) + +absl_test( + TARGET + inline_variable_test + SOURCES + ${INLINE_VARIABLE_TEST_SRC} + PUBLIC_LIBRARIES + ${INLINE_VARIABLE_TEST_PUBLIC_LIBRARIES} +) + + # test spinlock_test_common set(SPINLOCK_TEST_COMMON_SRC "spinlock_test_common.cc") set(SPINLOCK_TEST_COMMON_PUBLIC_LIBRARIES absl::base absl::synchronization) @@ -319,6 +342,20 @@ absl_test( ${THREAD_IDENTITY_TEST_PUBLIC_LIBRARIES} ) +#test exceptions_safety_testing_test +set(EXCEPTION_SAFETY_TESTING_TEST_SRC "exception_safety_testing_test.cc") +set(EXCEPTION_SAFETY_TESTING_TEST_PUBLIC_LIBRARIES absl::base absl::memory absl::meta absl::strings absl::optional) + +absl_test( + TARGET + absl_exception_safety_testing_test + SOURCES + ${EXCEPTION_SAFETY_TESTING_TEST_SRC} + PUBLIC_LIBRARIES + ${EXCEPTION_SAFETY_TESTING_TEST_PUBLIC_LIBRARIES} + PRIVATE_COMPILE_FLAGS + ${ABSL_EXCEPTIONS_FLAG} +) # test absl_malloc_extension_system_malloc_test set(MALLOC_EXTENSION_SYSTEM_MALLOC_TEST_SRC "internal/malloc_extension_test.cc") diff --git a/absl/base/attributes.h b/absl/base/attributes.h index 02bb030f5e5a..4e1fc8b550d1 100644 --- a/absl/base/attributes.h +++ b/absl/base/attributes.h @@ -281,6 +281,18 @@ #define ABSL_ATTRIBUTE_NO_SANITIZE_CFI #endif +// ABSL_ATTRIBUTE_RETURNS_NONNULL +// +// Tells the compiler that a particular function never returns a null pointer. +#if ABSL_HAVE_ATTRIBUTE(returns_nonnull) || \ + (defined(__GNUC__) && \ + (__GNUC__ > 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)) && \ + !defined(__clang__)) +#define ABSL_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull)) +#else +#define ABSL_ATTRIBUTE_RETURNS_NONNULL +#endif + // ABSL_HAVE_ATTRIBUTE_SECTION // // Indicates whether labeled sections are supported. Labeled sections are not diff --git a/absl/base/config.h b/absl/base/config.h index 3f3b8b3a64e3..6703d0eac715 100644 --- a/absl/base/config.h +++ b/absl/base/config.h @@ -138,9 +138,10 @@ // supported. #ifdef ABSL_HAVE_THREAD_LOCAL #error ABSL_HAVE_THREAD_LOCAL cannot be directly set -#elif !defined(__apple_build_version__) || \ - ((__apple_build_version__ >= 8000042) && \ - !(TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0)) +#elif (!defined(__apple_build_version__) || \ + (__apple_build_version__ >= 8000042)) && \ + !(defined(__APPLE__) && TARGET_OS_IPHONE && \ + __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0) // Notes: Xcode's clang did not support `thread_local` until version // 8, and even then not for all iOS < 9.0. #define ABSL_HAVE_THREAD_LOCAL 1 diff --git a/absl/base/exception_safety_testing_test.cc b/absl/base/exception_safety_testing_test.cc index 1fc03861784e..5477b40a5bed 100644 --- a/absl/base/exception_safety_testing_test.cc +++ b/absl/base/exception_safety_testing_test.cc @@ -63,7 +63,7 @@ TEST_F(ThrowingValueTest, Throws) { // the countdown doesn't hit 0, and doesn't modify the state of the // ThrowingValue if it throws template <typename F> -void TestOp(F&& f) { +void TestOp(const F& f) { UnsetCountdown(); ExpectNoThrow(f); @@ -153,11 +153,21 @@ TEST_F(ThrowingValueTest, ThrowingStreamOps) { TestOp([&]() { std::cout << bomb; }); } +template <typename F> +void TestAllocatingOp(const F& f) { + UnsetCountdown(); + ExpectNoThrow(f); + + SetCountdown(); + EXPECT_THROW(f(), exceptions_internal::TestBadAllocException); + UnsetCountdown(); +} + TEST_F(ThrowingValueTest, ThrowingAllocatingOps) { // make_unique calls unqualified operator new, so these exercise the // ThrowingValue overloads. - TestOp([]() { return absl::make_unique<ThrowingValue<>>(1); }); - TestOp([]() { return absl::make_unique<ThrowingValue<>[]>(2); }); + TestAllocatingOp([]() { return absl::make_unique<ThrowingValue<>>(1); }); + TestAllocatingOp([]() { return absl::make_unique<ThrowingValue<>[]>(2); }); } TEST_F(ThrowingValueTest, NonThrowingMoveCtor) { @@ -399,7 +409,8 @@ struct CallOperator { }; struct NonNegative { - friend testing::AssertionResult AbslCheckInvariants(NonNegative* g) { + friend testing::AssertionResult AbslCheckInvariants( + NonNegative* g, absl::InternalAbslNamespaceFinder) { if (g->i >= 0) return testing::AssertionSuccess(); return testing::AssertionFailure() << "i should be non-negative but is " << g->i; @@ -503,7 +514,8 @@ struct HasReset : public NonNegative { void reset() { i = 0; } - friend bool AbslCheckInvariants(HasReset* h) { + friend bool AbslCheckInvariants(HasReset* h, + absl::InternalAbslNamespaceFinder) { h->reset(); return h->i == 0; } @@ -591,7 +603,8 @@ struct ExhaustivenessTester { return true; } - friend testing::AssertionResult AbslCheckInvariants(ExhaustivenessTester*) { + friend testing::AssertionResult AbslCheckInvariants( + ExhaustivenessTester*, absl::InternalAbslNamespaceFinder) { return testing::AssertionSuccess(); } diff --git a/absl/base/inline_variable_test.cc b/absl/base/inline_variable_test.cc new file mode 100644 index 000000000000..5499189a3da9 --- /dev/null +++ b/absl/base/inline_variable_test.cc @@ -0,0 +1,62 @@ +// Copyright 2017 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. + +#include <type_traits> + +#include "absl/base/internal/inline_variable.h" +#include "absl/base/internal/inline_variable_testing.h" + +#include "gtest/gtest.h" + +namespace absl { +namespace inline_variable_testing_internal { +namespace { + +TEST(InlineVariableTest, Constexpr) { + static_assert(inline_variable_foo.value == 5, ""); + static_assert(other_inline_variable_foo.value == 5, ""); + static_assert(inline_variable_int == 5, ""); + static_assert(other_inline_variable_int == 5, ""); +} + +TEST(InlineVariableTest, DefaultConstructedIdentityEquality) { + EXPECT_EQ(get_foo_a().value, 5); + EXPECT_EQ(get_foo_b().value, 5); + EXPECT_EQ(&get_foo_a(), &get_foo_b()); +} + +TEST(InlineVariableTest, DefaultConstructedIdentityInequality) { + EXPECT_NE(&inline_variable_foo, &other_inline_variable_foo); +} + +TEST(InlineVariableTest, InitializedIdentityEquality) { + EXPECT_EQ(get_int_a(), 5); + EXPECT_EQ(get_int_b(), 5); + EXPECT_EQ(&get_int_a(), &get_int_b()); +} + +TEST(InlineVariableTest, InitializedIdentityInequality) { + EXPECT_NE(&inline_variable_int, &other_inline_variable_int); +} + +TEST(InlineVariableTest, FunPtrType) { + static_assert( + std::is_same<void(*)(), + std::decay<decltype(inline_variable_fun_ptr)>::type>::value, + ""); +} + +} // namespace +} // namespace inline_variable_testing_internal +} // namespace absl diff --git a/absl/base/internal/log_severity.cc b/absl/base/inline_variable_test_a.cc index 430ac45848a0..a3bf3b68b3cf 100644 --- a/absl/base/internal/log_severity.cc +++ b/absl/base/inline_variable_test_a.cc @@ -12,4 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "absl/base/internal/log_severity.h" +#include "absl/base/internal/inline_variable_testing.h" + +namespace absl { +namespace inline_variable_testing_internal { + +const Foo& get_foo_a() { return inline_variable_foo; } + +const int& get_int_a() { return inline_variable_int; } + +} // namespace inline_variable_testing_internal +} // namespace absl diff --git a/absl/base/inline_variable_test_b.cc b/absl/base/inline_variable_test_b.cc new file mode 100644 index 000000000000..b4b9393a5585 --- /dev/null +++ b/absl/base/inline_variable_test_b.cc @@ -0,0 +1,25 @@ +// Copyright 2017 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. + +#include "absl/base/internal/inline_variable_testing.h" + +namespace absl { +namespace inline_variable_testing_internal { + +const Foo& get_foo_b() { return inline_variable_foo; } + +const int& get_int_b() { return inline_variable_int; } + +} // namespace inline_variable_testing_internal +} // namespace absl diff --git a/absl/base/internal/exception_safety_testing.cc b/absl/base/internal/exception_safety_testing.cc index ab8d6c9fb4d0..821438ecc28c 100644 --- a/absl/base/internal/exception_safety_testing.cc +++ b/absl/base/internal/exception_safety_testing.cc @@ -23,8 +23,11 @@ namespace exceptions_internal { int countdown = -1; -void MaybeThrow(absl::string_view msg) { - if (countdown-- == 0) throw TestException(msg); +void MaybeThrow(absl::string_view msg, bool throw_bad_alloc) { + if (countdown-- == 0) { + if (throw_bad_alloc) throw TestBadAllocException(msg); + throw TestException(msg); + } } testing::AssertionResult FailureMessage(const TestException& e, diff --git a/absl/base/internal/exception_safety_testing.h b/absl/base/internal/exception_safety_testing.h index a0127a8819fa..8eac2264884f 100644 --- a/absl/base/internal/exception_safety_testing.h +++ b/absl/base/internal/exception_safety_testing.h @@ -35,6 +35,8 @@ #include "absl/types/optional.h" namespace absl { +struct InternalAbslNamespaceFinder {}; + struct AllocInspector; // A configuration enum for Throwing*. Operations whose flags are set will @@ -71,31 +73,45 @@ constexpr bool ThrowingAllowed(NoThrow flags, NoThrow flag) { class TestException { public: explicit TestException(absl::string_view msg) : msg_(msg) {} - absl::string_view what() const { return msg_; } + virtual ~TestException() {} + virtual const char* what() const noexcept { return msg_.c_str(); } private: std::string msg_; }; +// TestBadAllocException exists because allocation functions must throw an +// exception which can be caught by a handler of std::bad_alloc. We use a child +// class of std::bad_alloc so we can customise the error message, and also +// derive from TestException so we don't accidentally end up catching an actual +// bad_alloc exception in TestExceptionSafety. +class TestBadAllocException : public std::bad_alloc, public TestException { + public: + explicit TestBadAllocException(absl::string_view msg) + : TestException(msg) {} + using TestException::what; +}; + extern int countdown; -void MaybeThrow(absl::string_view msg); +void MaybeThrow(absl::string_view msg, bool throw_bad_alloc = false); testing::AssertionResult FailureMessage(const TestException& e, int countdown) noexcept; class TrackedObject { + public: + TrackedObject(const TrackedObject&) = delete; + TrackedObject(TrackedObject&&) = delete; + protected: - explicit TrackedObject(absl::string_view child_ctor) { + explicit TrackedObject(const char* child_ctor) { if (!GetAllocs().emplace(this, child_ctor).second) { ADD_FAILURE() << "Object at address " << static_cast<void*>(this) << " re-constructed in ctor " << child_ctor; } } - TrackedObject(const TrackedObject&) = delete; - TrackedObject(TrackedObject&&) = delete; - static std::unordered_map<TrackedObject*, absl::string_view>& GetAllocs() { static auto* m = new std::unordered_map<TrackedObject*, absl::string_view>(); @@ -120,10 +136,10 @@ using FactoryType = typename absl::result_of_t<Factory()>::element_type; template <typename Factory, typename Op, typename Checker> absl::optional<testing::AssertionResult> TestCheckerAtCountdown( Factory factory, const Op& op, int count, const Checker& check) { - exceptions_internal::countdown = count; auto t_ptr = factory(); absl::optional<testing::AssertionResult> out; try { + exceptions_internal::countdown = count; op(t_ptr.get()); } catch (const exceptions_internal::TestException& e) { out.emplace(check(t_ptr.get())); @@ -141,6 +157,10 @@ int UpdateOut(Factory factory, const Op& op, int count, const Checker& checker, return 0; } +// Declare AbslCheckInvariants so that it can be found eventually via ADL. +// Taking `...` gives it the lowest possible precedence. +void AbslCheckInvariants(...); + // Returns an optional with the result of the check if op fails, or an empty // optional if op passes template <typename Factory, typename Op, typename... Checkers> @@ -148,8 +168,9 @@ absl::optional<testing::AssertionResult> TestAtCountdown( Factory factory, const Op& op, int count, const Checkers&... checkers) { // Don't bother with the checkers if the class invariants are already broken. auto out = TestCheckerAtCountdown( - factory, op, count, - [](FactoryType<Factory>* t_ptr) { return AbslCheckInvariants(t_ptr); }); + factory, op, count, [](FactoryType<Factory>* t_ptr) { + return AbslCheckInvariants(t_ptr, InternalAbslNamespaceFinder()); + }); if (!out.has_value()) return out; // Run each checker, short circuiting after the first failure @@ -483,7 +504,7 @@ class ThrowingValue : private exceptions_internal::TrackedObject { static void* operator new(size_t s, Args&&... args) noexcept( !exceptions_internal::ThrowingAllowed(Flags, NoThrow::kAllocation)) { if (exceptions_internal::ThrowingAllowed(Flags, NoThrow::kAllocation)) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); + exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION, true); } return ::operator new(s, std::forward<Args>(args)...); } @@ -492,7 +513,7 @@ class ThrowingValue : private exceptions_internal::TrackedObject { static void* operator new[](size_t s, Args&&... args) noexcept( !exceptions_internal::ThrowingAllowed(Flags, NoThrow::kAllocation)) { if (exceptions_internal::ThrowingAllowed(Flags, NoThrow::kAllocation)) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); + exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION, true); } return ::operator new[](s, std::forward<Args>(args)...); } @@ -630,10 +651,7 @@ class ThrowingAllocator : private exceptions_internal::TrackedObject { p->~U(); } - size_type max_size() const - noexcept(!exceptions_internal::ThrowingAllowed(Flags, - NoThrow::kNoThrow)) { - ReadStateAndMaybeThrow(ABSL_PRETTY_FUNCTION); + size_type max_size() const noexcept { return std::numeric_limits<difference_type>::max() / sizeof(value_type); } @@ -720,9 +738,12 @@ T TestThrowingCtor(Args&&... args) { // Tests that performing operation Op on a T follows exception safety // guarantees. By default only tests the basic guarantee. There must be a -// function, AbslCheckInvariants(T*) which returns -// anything convertible to bool and which makes sure the invariants of the type -// are upheld. This is called before any of the checkers. +// function, AbslCheckInvariants(T*, absl::InternalAbslNamespaceFinder) which +// returns anything convertible to bool and which makes sure the invariants of +// the type are upheld. This is called before any of the checkers. The +// InternalAbslNamespaceFinder is unused, and just helps find +// AbslCheckInvariants for absl types which become aliases to std::types in +// C++17. // // Parameters: // * TFactory: operator() returns a unique_ptr to the type under test (T). It @@ -740,11 +761,13 @@ template <typename TFactory, typename FunctionFromTPtrToVoid, testing::AssertionResult TestExceptionSafety(TFactory factory, FunctionFromTPtrToVoid&& op, const Checkers&... checkers) { + struct Cleanup { + ~Cleanup() { UnsetCountdown(); } + } c; for (int countdown = 0;; ++countdown) { auto out = exceptions_internal::TestAtCountdown(factory, op, countdown, checkers...); if (!out.has_value()) { - UnsetCountdown(); return testing::AssertionSuccess(); } if (!*out) return *out; diff --git a/absl/base/internal/inline_variable.h b/absl/base/internal/inline_variable.h new file mode 100644 index 000000000000..a65fe89354cb --- /dev/null +++ b/absl/base/internal/inline_variable.h @@ -0,0 +1,127 @@ +// Copyright 2017 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_BASE_INTERNAL_INLINE_VARIABLE_EMULATION_H_ +#define ABSL_BASE_INTERNAL_INLINE_VARIABLE_EMULATION_H_ + +#include <type_traits> + +#include "absl/base/internal/identity.h" + +// File: +// This file define a macro that allows the creation of or emulation of C++17 +// inline variables based on whether or not the feature is supported. + +//////////////////////////////////////////////////////////////////////////////// +// Macro: ABSL_INTERNAL_INLINE_CONSTEXPR(type, name, init) +// +// Description: +// Expands to the equivalent of an inline constexpr instance of the specified +// `type` and `name`, initialized to the value `init`. If the compiler being +// used is detected as supporting actual inline variables as a language +// feature, then the macro expands to an actual inline variable definition. +// +// Requires: +// `type` is a type that is usable in an extern variable declaration. +// +// Requires: `name` is a valid identifier +// +// Requires: +// `init` is an expression that can be used in the following definition: +// constexpr type name = init; +// +// Usage: +// +// // Equivalent to: `inline constexpr size_t variant_npos = -1;` +// ABSL_INTERNAL_INLINE_CONSTEXPR(size_t, variant_npos, -1); +// +// Differences in implementation: +// For a direct, language-level inline variable, decltype(name) will be the +// type that was specified along with const qualification, whereas for +// emulated inline variables, decltype(name) may be different (in practice +// it will likely be a reference type). +//////////////////////////////////////////////////////////////////////////////// + +// ABSL_INTERNAL_HAS_WARNING() +// +// If the compiler supports the `__has_warning` extension for detecting +// warnings, then this macro is defined to be `__has_warning`. +// +// If the compiler does not support `__has_warning`, invocations expand to 0. +// +// For clang's documentation of `__has_warning`, see +// https://clang.llvm.org/docs/LanguageExtensions.html#has-warning +#if defined(__has_warning) +#define ABSL_INTERNAL_HAS_WARNING __has_warning +#else // Otherwise, be optimistic and assume the warning is not enabled. +#define ABSL_INTERNAL_HAS_WARNING(warning) 0 +#endif // defined(__has_warning) + +// If the compiler supports inline variables and does not warn when used... +#if defined(__cpp_inline_variables) && \ + !ABSL_INTERNAL_HAS_WARNING("-Wc++98-c++11-c++14-compat") + +// Clang's -Wmissing-variable-declarations option erroneously warned that +// inline constexpr objects need to be pre-declared. This has now been fixed, +// but we will need to support this workaround for people building with older +// versions of clang. +// +// Bug: https://bugs.llvm.org/show_bug.cgi?id=35862 +// +// Note: +// identity_t is used here so that the const and name are in the +// appropriate place for pointer types, reference types, function pointer +// types, etc.. +#if defined(__clang__) && \ + ABSL_INTERNAL_HAS_WARNING("-Wmissing-variable-declarations") +#define ABSL_INTERNAL_EXTERN_DECL(type, name) \ + extern const ::absl::internal::identity_t<type> name; +#else // Otherwise, just define the macro to do nothing. +#define ABSL_INTERNAL_EXTERN_DECL(type, name) +#endif // defined(__clang__) && + // ABSL_INTERNAL_HAS_WARNING("-Wmissing-variable-declarations") + +// See above comment at top of file for details. +#define ABSL_INTERNAL_INLINE_CONSTEXPR(type, name, init) \ + ABSL_INTERNAL_EXTERN_DECL(type, name) \ + inline constexpr ::absl::internal::identity_t<type> name = init + +#else // Otherwise, we need to emulate inline variables... + +// See above comment at top of file for details. +// +// Note: +// identity_t is used here so that the const and name are in the +// appropriate place for pointer types, reference types, function pointer +// types, etc.. +#define ABSL_INTERNAL_INLINE_CONSTEXPR(var_type, name, init) \ + template <class /*AbslInternalDummy*/ = void> \ + struct AbslInternalInlineVariableHolder##name { \ + static constexpr ::absl::internal::identity_t<var_type> kInstance = init; \ + }; \ + \ + template <class AbslInternalDummy> \ + constexpr ::absl::internal::identity_t<var_type> \ + AbslInternalInlineVariableHolder##name<AbslInternalDummy>::kInstance; \ + \ + static constexpr const ::absl::internal::identity_t<var_type>& \ + name = /* NOLINT */ \ + AbslInternalInlineVariableHolder##name<>::kInstance; \ + static_assert(sizeof(void (*)(decltype(name))) != 0, \ + "Silence unused variable warnings.") + +#endif // defined(__cpp_inline_variables) && + // !ABSL_INTERNAL_HAS_WARNING("-Wc++98-c++11-c++14-compat") + +#endif // ABSL_BASE_INTERNAL_INLINE_VARIABLE_EMULATION_H_ diff --git a/absl/base/internal/inline_variable_testing.h b/absl/base/internal/inline_variable_testing.h new file mode 100644 index 000000000000..a0dd2bb28a40 --- /dev/null +++ b/absl/base/internal/inline_variable_testing.h @@ -0,0 +1,44 @@ +// Copyright 2017 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_BASE_INLINE_VARIABLE_TESTING_H_ +#define ABSL_BASE_INLINE_VARIABLE_TESTING_H_ + +#include "absl/base/internal/inline_variable.h" + +namespace absl { +namespace inline_variable_testing_internal { + +struct Foo { + int value = 5; +}; + +ABSL_INTERNAL_INLINE_CONSTEXPR(Foo, inline_variable_foo, {}); +ABSL_INTERNAL_INLINE_CONSTEXPR(Foo, other_inline_variable_foo, {}); + +ABSL_INTERNAL_INLINE_CONSTEXPR(int, inline_variable_int, 5); +ABSL_INTERNAL_INLINE_CONSTEXPR(int, other_inline_variable_int, 5); + +ABSL_INTERNAL_INLINE_CONSTEXPR(void(*)(), inline_variable_fun_ptr, nullptr); + +const Foo& get_foo_a(); +const Foo& get_foo_b(); + +const int& get_int_a(); +const int& get_int_b(); + +} // namespace inline_variable_testing_internal +} // namespace absl + +#endif // ABSL_BASE_INLINE_VARIABLE_TESTING_H_ diff --git a/absl/base/internal/malloc_extension.cc b/absl/base/internal/malloc_extension.cc index d48ec5bcf548..5b90653360aa 100644 --- a/absl/base/internal/malloc_extension.cc +++ b/absl/base/internal/malloc_extension.cc @@ -20,7 +20,6 @@ #include <string> #include "absl/base/dynamic_annotations.h" -#include "absl/base/internal/malloc_extension_c.h" namespace absl { namespace base_internal { @@ -155,44 +154,6 @@ void MallocExtension::GetFragmentationProfile(MallocExtensionWriter*) {} } // namespace base_internal } // namespace absl -// These are C shims that work on the current instance. - -#define C_SHIM(fn, retval, paramlist, arglist) \ - extern "C" retval MallocExtension_##fn paramlist { \ - return absl::base_internal::MallocExtension::instance()->fn arglist; \ - } - -C_SHIM(VerifyAllMemory, int, (void), ()); -C_SHIM(VerifyNewMemory, int, (const void* p), (p)); -C_SHIM(VerifyArrayNewMemory, int, (const void* p), (p)); -C_SHIM(VerifyMallocMemory, int, (const void* p), (p)); -C_SHIM( - MallocMemoryStats, int, - (int* blocks, size_t* total, - int histogram[absl::base_internal::MallocExtension::kMallocHistogramSize]), - (blocks, total, histogram)); - -C_SHIM(GetStats, void, - (char* buffer, int buffer_length), (buffer, buffer_length)); -C_SHIM(GetNumericProperty, int, - (const char* property, size_t* value), (property, value)); -C_SHIM(SetNumericProperty, int, - (const char* property, size_t value), (property, value)); - -C_SHIM(MarkThreadIdle, void, (void), ()); -C_SHIM(MarkThreadBusy, void, (void), ()); -C_SHIM(ReleaseFreeMemory, void, (void), ()); -C_SHIM(ReleaseToSystem, void, (size_t num_bytes), (num_bytes)); -C_SHIM(GetEstimatedAllocatedSize, size_t, (size_t size), (size)); -C_SHIM(GetAllocatedSize, size_t, (const void* p), (p)); - -// Can't use the shim here because of the need to translate the enums. -extern "C" -MallocExtension_Ownership MallocExtension_GetOwnership(const void* p) { - return static_cast<MallocExtension_Ownership>( - absl::base_internal::MallocExtension::instance()->GetOwnership(p)); -} - // Default implementation just returns size. The expectation is that // the linked-in malloc implementation might provide an override of // this weak function with a better implementation. diff --git a/absl/base/internal/malloc_extension_test.cc b/absl/base/internal/malloc_extension_test.cc index 246875a030ef..76605eb19936 100644 --- a/absl/base/internal/malloc_extension_test.cc +++ b/absl/base/internal/malloc_extension_test.cc @@ -19,7 +19,6 @@ #include "gtest/gtest.h" #include "absl/base/internal/malloc_extension.h" -#include "absl/base/internal/malloc_extension_c.h" namespace absl { namespace base_internal { @@ -35,15 +34,12 @@ TEST(MallocExtension, MallocExtension) { } else { ASSERT_TRUE(MallocExtension::instance()->GetNumericProperty( "generic.current_allocated_bytes", &cxx_bytes_used)); - ASSERT_TRUE(MallocExtension_GetNumericProperty( - "generic.current_allocated_bytes", &c_bytes_used)); #ifndef MEMORY_SANITIZER EXPECT_GT(cxx_bytes_used, 1000); EXPECT_GT(c_bytes_used, 1000); #endif EXPECT_TRUE(MallocExtension::instance()->VerifyAllMemory()); - EXPECT_TRUE(MallocExtension_VerifyAllMemory()); EXPECT_EQ(MallocExtension::kOwned, MallocExtension::instance()->GetOwnership(a)); @@ -65,30 +61,11 @@ TEST(MallocExtension, MallocExtension) { MallocExtension::instance()->GetEstimatedAllocatedSize(i)); free(p); } - - // Check the c-shim version too. - EXPECT_EQ(MallocExtension_kOwned, MallocExtension_GetOwnership(a)); - EXPECT_EQ(MallocExtension_kNotOwned, - MallocExtension_GetOwnership(&cxx_bytes_used)); - EXPECT_EQ(MallocExtension_kNotOwned, MallocExtension_GetOwnership(nullptr)); - EXPECT_GE(MallocExtension_GetAllocatedSize(a), 1000); - EXPECT_LE(MallocExtension_GetAllocatedSize(a), 5000); - EXPECT_GE(MallocExtension_GetEstimatedAllocatedSize(1000), 1000); } free(a); } -// Verify that the .cc file and .h file have the same enum values. -TEST(GetOwnership, EnumValuesEqualForCAndCXX) { - EXPECT_EQ(static_cast<int>(MallocExtension::kUnknownOwnership), - static_cast<int>(MallocExtension_kUnknownOwnership)); - EXPECT_EQ(static_cast<int>(MallocExtension::kOwned), - static_cast<int>(MallocExtension_kOwned)); - EXPECT_EQ(static_cast<int>(MallocExtension::kNotOwned), - static_cast<int>(MallocExtension_kNotOwned)); -} - TEST(nallocx, SaneBehavior) { for (size_t size = 0; size < 64 * 1024; ++size) { size_t alloc_size = nallocx(size, 0); diff --git a/absl/base/internal/malloc_hook.cc b/absl/base/internal/malloc_hook.cc index 52531c680148..780e8fe3296c 100644 --- a/absl/base/internal/malloc_hook.cc +++ b/absl/base/internal/malloc_hook.cc @@ -215,139 +215,101 @@ HookList<MallocHook::MunmapReplacement> munmap_replacement_ = INIT_HOOK_LIST; #undef INIT_HOOK_LIST_WITH_VALUE #undef INIT_HOOK_LIST -} // namespace base_internal -} // namespace absl +bool MallocHook::AddNewHook(NewHook hook) { return new_hooks_.Add(hook); } -// These are available as C bindings as well as C++, hence their -// definition outside the MallocHook class. -extern "C" -int MallocHook_AddNewHook(MallocHook_NewHook hook) { - return absl::base_internal::new_hooks_.Add(hook); -} - -extern "C" -int MallocHook_RemoveNewHook(MallocHook_NewHook hook) { - return absl::base_internal::new_hooks_.Remove(hook); -} +bool MallocHook::RemoveNewHook(NewHook hook) { return new_hooks_.Remove(hook); } -extern "C" -int MallocHook_AddDeleteHook(MallocHook_DeleteHook hook) { - return absl::base_internal::delete_hooks_.Add(hook); +bool MallocHook::AddDeleteHook(DeleteHook hook) { + return delete_hooks_.Add(hook); } -extern "C" -int MallocHook_RemoveDeleteHook(MallocHook_DeleteHook hook) { - return absl::base_internal::delete_hooks_.Remove(hook); +bool MallocHook::RemoveDeleteHook(DeleteHook hook) { + return delete_hooks_.Remove(hook); } -extern "C" int MallocHook_AddSampledNewHook(MallocHook_SampledNewHook hook) { - return absl::base_internal::sampled_new_hooks_.Add(hook); +bool MallocHook::AddSampledNewHook(SampledNewHook hook) { + return sampled_new_hooks_.Add(hook); } -extern "C" int MallocHook_RemoveSampledNewHook(MallocHook_SampledNewHook hook) { - return absl::base_internal::sampled_new_hooks_.Remove(hook); +bool MallocHook::RemoveSampledNewHook(SampledNewHook hook) { + return sampled_new_hooks_.Remove(hook); } -extern "C" int MallocHook_AddSampledDeleteHook( - MallocHook_SampledDeleteHook hook) { - return absl::base_internal::sampled_delete_hooks_.Add(hook); +bool MallocHook::AddSampledDeleteHook(SampledDeleteHook hook) { + return sampled_delete_hooks_.Add(hook); } -extern "C" int MallocHook_RemoveSampledDeleteHook( - MallocHook_SampledDeleteHook hook) { - return absl::base_internal::sampled_delete_hooks_.Remove(hook); +bool MallocHook::RemoveSampledDeleteHook(SampledDeleteHook hook) { + return sampled_delete_hooks_.Remove(hook); } -extern "C" -int MallocHook_AddPreMmapHook(MallocHook_PreMmapHook hook) { - return absl::base_internal::premmap_hooks_.Add(hook); +bool MallocHook::AddPreMmapHook(PreMmapHook hook) { + return premmap_hooks_.Add(hook); } -extern "C" -int MallocHook_RemovePreMmapHook(MallocHook_PreMmapHook hook) { - return absl::base_internal::premmap_hooks_.Remove(hook); +bool MallocHook::RemovePreMmapHook(PreMmapHook hook) { + return premmap_hooks_.Remove(hook); } -extern "C" -int MallocHook_SetMmapReplacement(MallocHook_MmapReplacement hook) { +bool MallocHook::SetMmapReplacement(MmapReplacement hook) { // NOTE this is a best effort CHECK. Concurrent sets could succeed since // this test is outside of the Add spin lock. - ABSL_RAW_CHECK(absl::base_internal::mmap_replacement_.empty(), + ABSL_RAW_CHECK(mmap_replacement_.empty(), "Only one MMapReplacement is allowed."); - return absl::base_internal::mmap_replacement_.Add(hook); -} - -extern "C" -int MallocHook_RemoveMmapReplacement(MallocHook_MmapReplacement hook) { - return absl::base_internal::mmap_replacement_.Remove(hook); -} - -extern "C" -int MallocHook_AddMmapHook(MallocHook_MmapHook hook) { - return absl::base_internal::mmap_hooks_.Add(hook); + return mmap_replacement_.Add(hook); } -extern "C" -int MallocHook_RemoveMmapHook(MallocHook_MmapHook hook) { - return absl::base_internal::mmap_hooks_.Remove(hook); +bool MallocHook::RemoveMmapReplacement(MmapReplacement hook) { + return mmap_replacement_.Remove(hook); } -extern "C" -int MallocHook_AddMunmapHook(MallocHook_MunmapHook hook) { - return absl::base_internal::munmap_hooks_.Add(hook); -} +bool MallocHook::AddMmapHook(MmapHook hook) { return mmap_hooks_.Add(hook); } -extern "C" -int MallocHook_RemoveMunmapHook(MallocHook_MunmapHook hook) { - return absl::base_internal::munmap_hooks_.Remove(hook); +bool MallocHook::RemoveMmapHook(MmapHook hook) { + return mmap_hooks_.Remove(hook); } -extern "C" -int MallocHook_SetMunmapReplacement(MallocHook_MunmapReplacement hook) { +bool MallocHook::SetMunmapReplacement(MunmapReplacement hook) { // NOTE this is a best effort CHECK. Concurrent sets could succeed since // this test is outside of the Add spin lock. - ABSL_RAW_CHECK(absl::base_internal::munmap_replacement_.empty(), + ABSL_RAW_CHECK(munmap_replacement_.empty(), "Only one MunmapReplacement is allowed."); - return absl::base_internal::munmap_replacement_.Add(hook); + return munmap_replacement_.Add(hook); } -extern "C" -int MallocHook_RemoveMunmapReplacement(MallocHook_MunmapReplacement hook) { - return absl::base_internal::munmap_replacement_.Remove(hook); +bool MallocHook::RemoveMunmapReplacement(MunmapReplacement hook) { + return munmap_replacement_.Remove(hook); } -extern "C" -int MallocHook_AddMremapHook(MallocHook_MremapHook hook) { - return absl::base_internal::mremap_hooks_.Add(hook); +bool MallocHook::AddMunmapHook(MunmapHook hook) { + return munmap_hooks_.Add(hook); } -extern "C" -int MallocHook_RemoveMremapHook(MallocHook_MremapHook hook) { - return absl::base_internal::mremap_hooks_.Remove(hook); +bool MallocHook::RemoveMunmapHook(MunmapHook hook) { + return munmap_hooks_.Remove(hook); } -extern "C" -int MallocHook_AddPreSbrkHook(MallocHook_PreSbrkHook hook) { - return absl::base_internal::presbrk_hooks_.Add(hook); +bool MallocHook::AddMremapHook(MremapHook hook) { + return mremap_hooks_.Add(hook); } -extern "C" -int MallocHook_RemovePreSbrkHook(MallocHook_PreSbrkHook hook) { - return absl::base_internal::presbrk_hooks_.Remove(hook); +bool MallocHook::RemoveMremapHook(MremapHook hook) { + return mremap_hooks_.Remove(hook); } -extern "C" -int MallocHook_AddSbrkHook(MallocHook_SbrkHook hook) { - return absl::base_internal::sbrk_hooks_.Add(hook); +bool MallocHook::AddPreSbrkHook(PreSbrkHook hook) { + return presbrk_hooks_.Add(hook); } -extern "C" -int MallocHook_RemoveSbrkHook(MallocHook_SbrkHook hook) { - return absl::base_internal::sbrk_hooks_.Remove(hook); +bool MallocHook::RemovePreSbrkHook(PreSbrkHook hook) { + return presbrk_hooks_.Remove(hook); } -namespace absl { -namespace base_internal { +bool MallocHook::AddSbrkHook(SbrkHook hook) { return sbrk_hooks_.Add(hook); } + +bool MallocHook::RemoveSbrkHook(SbrkHook hook) { + return sbrk_hooks_.Remove(hook); +} // Note: embedding the function calls inside the traversal of HookList would be // very confusing, as it is legal for a hook to remove itself and add other @@ -501,12 +463,11 @@ static void InitializeInHookCaller() { ABSL_INIT_ATTRIBUTE_SECTION_VARS(blink_malloc); } -// We can improve behavior/compactness of this function -// if we pass a generic test function (with a generic arg) -// into the implementations for get_stack_trace_fn instead of the skip_count. -extern "C" int MallocHook_GetCallerStackTrace( - void** result, int max_depth, int skip_count, - MallocHook_GetStackTraceFn get_stack_trace_fn) { +namespace absl { +namespace base_internal { +int MallocHook::GetCallerStackTrace(void** result, int max_depth, + int skip_count, + GetStackTraceFn get_stack_trace_fn) { if (!ABSL_HAVE_ATTRIBUTE_SECTION) { // Fall back to get_stack_trace_fn and good old but fragile frame skip // counts. @@ -524,11 +485,11 @@ extern "C" int MallocHook_GetCallerStackTrace( absl::call_once(in_hook_caller_once, InitializeInHookCaller); // MallocHook caller determination via InHookCaller works, use it: static const int kMaxSkip = 32 + 6 + 3; - // Constant tuned to do just one get_stack_trace_fn call below in practice - // and not get many frames that we don't actually need: - // currently max passed max_depth is 32, - // max passed/needed skip_count is 6 - // and 3 is to account for some hook daisy chaining. + // Constant tuned to do just one get_stack_trace_fn call below in practice + // and not get many frames that we don't actually need: + // currently max passed max_depth is 32, + // max passed/needed skip_count is 6 + // and 3 is to account for some hook daisy chaining. static const int kStackSize = kMaxSkip + 1; void* stack[kStackSize]; int depth = @@ -538,11 +499,11 @@ extern "C" int MallocHook_GetCallerStackTrace( return 0; for (int i = depth - 1; i >= 0; --i) { // stack[0] is our immediate caller if (InHookCaller(stack[i])) { - i += 1; // skip hook caller frame + i += 1; // skip hook caller frame depth -= i; // correct depth if (depth > max_depth) depth = max_depth; std::copy(stack + i, stack + i + depth, result); - if (depth < max_depth && depth + i == kStackSize) { + if (depth < max_depth && depth + i == kStackSize) { // get frames for the missing depth depth += get_stack_trace_fn(result + depth, max_depth - depth, 1 + kStackSize); @@ -558,6 +519,8 @@ extern "C" int MallocHook_GetCallerStackTrace( // all functions in that section must be inside the same library. return 0; } +} // namespace base_internal +} // namespace absl // On systems where we know how, we override mmap/munmap/mremap/sbrk // to provide support for calling the related hooks (in addition, diff --git a/absl/base/internal/malloc_hook.h b/absl/base/internal/malloc_hook.h index ed5cf2e65dd6..6b006edac6d4 100644 --- a/absl/base/internal/malloc_hook.h +++ b/absl/base/internal/malloc_hook.h @@ -74,24 +74,16 @@ class MallocHook { // Object pointer and size are passed in. // It may be passed null pointer if the allocator returned null. typedef MallocHook_NewHook NewHook; - inline static bool AddNewHook(NewHook hook) { - return MallocHook_AddNewHook(hook); - } - inline static bool RemoveNewHook(NewHook hook) { - return MallocHook_RemoveNewHook(hook); - } + static bool AddNewHook(NewHook hook); + static bool RemoveNewHook(NewHook hook); inline static void InvokeNewHook(const void* ptr, size_t size); // The DeleteHook is invoked whenever an object is being deallocated. // Object pointer is passed in. // It may be passed null pointer if the caller is trying to delete null. typedef MallocHook_DeleteHook DeleteHook; - inline static bool AddDeleteHook(DeleteHook hook) { - return MallocHook_AddDeleteHook(hook); - } - inline static bool RemoveDeleteHook(DeleteHook hook) { - return MallocHook_RemoveDeleteHook(hook); - } + static bool AddDeleteHook(DeleteHook hook); + static bool RemoveDeleteHook(DeleteHook hook); inline static void InvokeDeleteHook(const void* ptr); // The SampledNewHook is invoked for some subset of object allocations @@ -99,20 +91,19 @@ class MallocHook { // SampledAlloc has the following fields: // * AllocHandle handle: to be set to an effectively unique value (in this // process) by allocator. - // * size_t allocated_size: space actually used by allocator to host - // the object. + // * size_t allocated_size: space actually used by allocator to host the + // object. Not necessarily equal to the requested size due to alignment + // and other reasons. + // * double weight: the expected number of allocations matching this profile + // that this sample represents. // * int stack_depth and const void* stack: invocation stack for // the allocation. // The allocator invoking the hook should record the handle value and later // call InvokeSampledDeleteHook() with that value. typedef MallocHook_SampledNewHook SampledNewHook; typedef MallocHook_SampledAlloc SampledAlloc; - inline static bool AddSampledNewHook(SampledNewHook hook) { - return MallocHook_AddSampledNewHook(hook); - } - inline static bool RemoveSampledNewHook(SampledNewHook hook) { - return MallocHook_RemoveSampledNewHook(hook); - } + static bool AddSampledNewHook(SampledNewHook hook); + static bool RemoveSampledNewHook(SampledNewHook hook); inline static void InvokeSampledNewHook(const SampledAlloc* sampled_alloc); // The SampledDeleteHook is invoked whenever an object previously chosen @@ -121,12 +112,8 @@ class MallocHook { // InvokeSampledNewHook()-- is passed in. typedef MallocHook_SampledDeleteHook SampledDeleteHook; typedef MallocHook_AllocHandle AllocHandle; - inline static bool AddSampledDeleteHook(SampledDeleteHook hook) { - return MallocHook_AddSampledDeleteHook(hook); - } - inline static bool RemoveSampledDeleteHook(SampledDeleteHook hook) { - return MallocHook_RemoveSampledDeleteHook(hook); - } + static bool AddSampledDeleteHook(SampledDeleteHook hook); + static bool RemoveSampledDeleteHook(SampledDeleteHook hook); inline static void InvokeSampledDeleteHook(AllocHandle handle); // The PreMmapHook is invoked with mmap's or mmap64's arguments just @@ -134,12 +121,8 @@ class MallocHook { // in memory limited contexts, to catch allocations that will exceed // a memory limit, and take outside actions to increase that limit. typedef MallocHook_PreMmapHook PreMmapHook; - inline static bool AddPreMmapHook(PreMmapHook hook) { - return MallocHook_AddPreMmapHook(hook); - } - inline static bool RemovePreMmapHook(PreMmapHook hook) { - return MallocHook_RemovePreMmapHook(hook); - } + static bool AddPreMmapHook(PreMmapHook hook); + static bool RemovePreMmapHook(PreMmapHook hook); inline static void InvokePreMmapHook(const void* start, size_t size, int protection, @@ -159,12 +142,8 @@ class MallocHook { // you must call RemoveMmapReplacement before calling SetMmapReplacement // again. typedef MallocHook_MmapReplacement MmapReplacement; - inline static bool SetMmapReplacement(MmapReplacement hook) { - return MallocHook_SetMmapReplacement(hook); - } - inline static bool RemoveMmapReplacement(MmapReplacement hook) { - return MallocHook_RemoveMmapReplacement(hook); - } + static bool SetMmapReplacement(MmapReplacement hook); + static bool RemoveMmapReplacement(MmapReplacement hook); inline static bool InvokeMmapReplacement(const void* start, size_t size, int protection, @@ -178,12 +157,8 @@ class MallocHook { // a region of memory has been just mapped. // It may be passed MAP_FAILED if the mmap failed. typedef MallocHook_MmapHook MmapHook; - inline static bool AddMmapHook(MmapHook hook) { - return MallocHook_AddMmapHook(hook); - } - inline static bool RemoveMmapHook(MmapHook hook) { - return MallocHook_RemoveMmapHook(hook); - } + static bool AddMmapHook(MmapHook hook); + static bool RemoveMmapHook(MmapHook hook); inline static void InvokeMmapHook(const void* result, const void* start, size_t size, @@ -202,12 +177,8 @@ class MallocHook { // MunmapReplacement you must call RemoveMunmapReplacement before // calling SetMunmapReplacement again. typedef MallocHook_MunmapReplacement MunmapReplacement; - inline static bool SetMunmapReplacement(MunmapReplacement hook) { - return MallocHook_SetMunmapReplacement(hook); - } - inline static bool RemoveMunmapReplacement(MunmapReplacement hook) { - return MallocHook_RemoveMunmapReplacement(hook); - } + static bool SetMunmapReplacement(MunmapReplacement hook); + static bool RemoveMunmapReplacement(MunmapReplacement hook); inline static bool InvokeMunmapReplacement(const void* start, size_t size, int* result); @@ -217,23 +188,15 @@ class MallocHook { // TODO(maxim): Rename this to PreMunmapHook for consistency with PreMmapHook // and PreSbrkHook. typedef MallocHook_MunmapHook MunmapHook; - inline static bool AddMunmapHook(MunmapHook hook) { - return MallocHook_AddMunmapHook(hook); - } - inline static bool RemoveMunmapHook(MunmapHook hook) { - return MallocHook_RemoveMunmapHook(hook); - } + static bool AddMunmapHook(MunmapHook hook); + static bool RemoveMunmapHook(MunmapHook hook); inline static void InvokeMunmapHook(const void* start, size_t size); // The MremapHook is invoked with mremap's return value and arguments // whenever a region of memory has been just remapped. typedef MallocHook_MremapHook MremapHook; - inline static bool AddMremapHook(MremapHook hook) { - return MallocHook_AddMremapHook(hook); - } - inline static bool RemoveMremapHook(MremapHook hook) { - return MallocHook_RemoveMremapHook(hook); - } + static bool AddMremapHook(MremapHook hook); + static bool RemoveMremapHook(MremapHook hook); inline static void InvokeMremapHook(const void* result, const void* old_addr, size_t old_size, @@ -248,12 +211,8 @@ class MallocHook { // to catch allocations that will exceed the limit and take outside // actions to increase such a limit. typedef MallocHook_PreSbrkHook PreSbrkHook; - inline static bool AddPreSbrkHook(PreSbrkHook hook) { - return MallocHook_AddPreSbrkHook(hook); - } - inline static bool RemovePreSbrkHook(PreSbrkHook hook) { - return MallocHook_RemovePreSbrkHook(hook); - } + static bool AddPreSbrkHook(PreSbrkHook hook); + static bool RemovePreSbrkHook(PreSbrkHook hook); inline static void InvokePreSbrkHook(ptrdiff_t increment); // The SbrkHook is invoked with sbrk's result and argument whenever sbrk @@ -261,12 +220,8 @@ class MallocHook { // This is because sbrk(0) is often called to get the top of the memory stack, // and is not actually a memory-allocation call. typedef MallocHook_SbrkHook SbrkHook; - inline static bool AddSbrkHook(SbrkHook hook) { - return MallocHook_AddSbrkHook(hook); - } - inline static bool RemoveSbrkHook(SbrkHook hook) { - return MallocHook_RemoveSbrkHook(hook); - } + static bool AddSbrkHook(SbrkHook hook); + static bool RemoveSbrkHook(SbrkHook hook); inline static void InvokeSbrkHook(const void* result, ptrdiff_t increment); // Pointer to a absl::GetStackTrace implementation, following the API in @@ -280,12 +235,8 @@ class MallocHook { // is not available. // Stack trace is filled into *result up to the size of max_depth. // The actual number of stack frames filled is returned. - inline static int GetCallerStackTrace(void** result, int max_depth, - int skip_count, - GetStackTraceFn get_stack_trace_fn) { - return MallocHook_GetCallerStackTrace(result, max_depth, skip_count, - get_stack_trace_fn); - } + static int GetCallerStackTrace(void** result, int max_depth, int skip_count, + GetStackTraceFn get_stack_trace_fn); #if ABSL_HAVE_MMAP // Unhooked versions of mmap() and munmap(). These should be used diff --git a/absl/base/internal/malloc_hook_c.h b/absl/base/internal/malloc_hook_c.h index 03b84ca627d2..7255ddc22900 100644 --- a/absl/base/internal/malloc_hook_c.h +++ b/absl/base/internal/malloc_hook_c.h @@ -29,100 +29,38 @@ extern "C" { #endif /* __cplusplus */ -/* Get the current stack trace. Try to skip all routines up to and - * including the caller of MallocHook::Invoke*. - * Use "skip_count" (similarly to absl::GetStackTrace from stacktrace.h) - * as a hint about how many routines to skip if better information - * is not available. - */ typedef int (*MallocHook_GetStackTraceFn)(void**, int, int); -int MallocHook_GetCallerStackTrace(void** result, int max_depth, int skip_count, - MallocHook_GetStackTraceFn fn); - -/* All the MallocHook_{Add,Remove}*Hook functions below return 1 on success - * and 0 on failure. - */ - typedef void (*MallocHook_NewHook)(const void* ptr, size_t size); -int MallocHook_AddNewHook(MallocHook_NewHook hook); -int MallocHook_RemoveNewHook(MallocHook_NewHook hook); - typedef void (*MallocHook_DeleteHook)(const void* ptr); -int MallocHook_AddDeleteHook(MallocHook_DeleteHook hook); -int MallocHook_RemoveDeleteHook(MallocHook_DeleteHook hook); - typedef int64_t MallocHook_AllocHandle; typedef struct { /* See malloc_hook.h for documentation for this struct. */ MallocHook_AllocHandle handle; size_t allocated_size; + double weight; int stack_depth; const void* stack; } MallocHook_SampledAlloc; typedef void (*MallocHook_SampledNewHook)( const MallocHook_SampledAlloc* sampled_alloc); -int MallocHook_AddSampledNewHook(MallocHook_SampledNewHook hook); -int MallocHook_RemoveSampledNewHook(MallocHook_SampledNewHook hook); - typedef void (*MallocHook_SampledDeleteHook)(MallocHook_AllocHandle handle); -int MallocHook_AddSampledDeleteHook(MallocHook_SampledDeleteHook hook); -int MallocHook_RemoveSampledDeleteHook(MallocHook_SampledDeleteHook hook); - -typedef void (*MallocHook_PreMmapHook)(const void *start, - size_t size, - int protection, - int flags, - int fd, +typedef void (*MallocHook_PreMmapHook)(const void* start, size_t size, + int protection, int flags, int fd, off_t offset); -int MallocHook_AddPreMmapHook(MallocHook_PreMmapHook hook); -int MallocHook_RemovePreMmapHook(MallocHook_PreMmapHook hook); - -typedef void (*MallocHook_MmapHook)(const void* result, - const void* start, - size_t size, - int protection, - int flags, - int fd, - off_t offset); -int MallocHook_AddMmapHook(MallocHook_MmapHook hook); -int MallocHook_RemoveMmapHook(MallocHook_MmapHook hook); - -typedef int (*MallocHook_MmapReplacement)(const void* start, - size_t size, - int protection, - int flags, - int fd, - off_t offset, - void** result); -int MallocHook_SetMmapReplacement(MallocHook_MmapReplacement hook); -int MallocHook_RemoveMmapReplacement(MallocHook_MmapReplacement hook); - +typedef void (*MallocHook_MmapHook)(const void* result, const void* start, + size_t size, int protection, int flags, + int fd, off_t offset); +typedef int (*MallocHook_MmapReplacement)(const void* start, size_t size, + int protection, int flags, int fd, + off_t offset, void** result); typedef void (*MallocHook_MunmapHook)(const void* start, size_t size); -int MallocHook_AddMunmapHook(MallocHook_MunmapHook hook); -int MallocHook_RemoveMunmapHook(MallocHook_MunmapHook hook); - -typedef int (*MallocHook_MunmapReplacement)(const void* start, - size_t size, +typedef int (*MallocHook_MunmapReplacement)(const void* start, size_t size, int* result); -int MallocHook_SetMunmapReplacement(MallocHook_MunmapReplacement hook); -int MallocHook_RemoveMunmapReplacement(MallocHook_MunmapReplacement hook); - -typedef void (*MallocHook_MremapHook)(const void* result, - const void* old_addr, - size_t old_size, - size_t new_size, - int flags, - const void* new_addr); -int MallocHook_AddMremapHook(MallocHook_MremapHook hook); -int MallocHook_RemoveMremapHook(MallocHook_MremapHook hook); - +typedef void (*MallocHook_MremapHook)(const void* result, const void* old_addr, + size_t old_size, size_t new_size, + int flags, const void* new_addr); typedef void (*MallocHook_PreSbrkHook)(ptrdiff_t increment); -int MallocHook_AddPreSbrkHook(MallocHook_PreSbrkHook hook); -int MallocHook_RemovePreSbrkHook(MallocHook_PreSbrkHook hook); - typedef void (*MallocHook_SbrkHook)(const void* result, ptrdiff_t increment); -int MallocHook_AddSbrkHook(MallocHook_SbrkHook hook); -int MallocHook_RemoveSbrkHook(MallocHook_SbrkHook hook); #ifdef __cplusplus } /* extern "C" */ diff --git a/absl/base/internal/per_thread_tls.h b/absl/base/internal/per_thread_tls.h index 7397451031b9..2428bdc1238e 100644 --- a/absl/base/internal/per_thread_tls.h +++ b/absl/base/internal/per_thread_tls.h @@ -26,7 +26,7 @@ // // Microsoft C supports thread-local storage. // GCC supports it if the appropriate version of glibc is available, -// which the programme can indicate by defining ABSL_HAVE_TLS +// which the programmer can indicate by defining ABSL_HAVE_TLS #include "absl/base/port.h" // For ABSL_HAVE_TLS diff --git a/absl/base/internal/raw_logging.cc b/absl/base/internal/raw_logging.cc index 301b108c07e9..86e34d458f4e 100644 --- a/absl/base/internal/raw_logging.cc +++ b/absl/base/internal/raw_logging.cc @@ -22,7 +22,7 @@ #include "absl/base/config.h" #include "absl/base/internal/atomic_hook.h" -#include "absl/base/internal/log_severity.h" +#include "absl/base/log_severity.h" // We know how to perform low-level writes to stderr in POSIX and Windows. For // these platforms, we define the token ABSL_LOW_LEVEL_WRITE_SUPPORTED. diff --git a/absl/base/internal/raw_logging.h b/absl/base/internal/raw_logging.h index 568d2afce10a..1b2a44b7a7da 100644 --- a/absl/base/internal/raw_logging.h +++ b/absl/base/internal/raw_logging.h @@ -20,7 +20,7 @@ #define ABSL_BASE_INTERNAL_RAW_LOGGING_H_ #include "absl/base/attributes.h" -#include "absl/base/internal/log_severity.h" +#include "absl/base/log_severity.h" #include "absl/base/macros.h" #include "absl/base/port.h" diff --git a/absl/base/internal/spinlock.h b/absl/base/internal/spinlock.h index a9037e3ed05c..212abc669e62 100644 --- a/absl/base/internal/spinlock.h +++ b/absl/base/internal/spinlock.h @@ -227,7 +227,7 @@ inline uint32_t SpinLock::TryLockInternal(uint32_t lock_value, kSpinLockHeld | lock_value | wait_cycles | sched_disabled_bit, std::memory_order_acquire, std::memory_order_relaxed)) { } else { - base_internal::SchedulingGuard::EnableRescheduling(sched_disabled_bit); + base_internal::SchedulingGuard::EnableRescheduling(sched_disabled_bit != 0); } return lock_value; diff --git a/absl/base/internal/thread_identity.h b/absl/base/internal/thread_identity.h index 914d5da7ef40..a51722f9d828 100644 --- a/absl/base/internal/thread_identity.h +++ b/absl/base/internal/thread_identity.h @@ -61,7 +61,7 @@ struct PerThreadSynch { PerThreadSynch *next; // Circular waiter queue; initialized to 0. PerThreadSynch *skip; // If non-zero, all entries in Mutex queue - // upto and including "skip" have same + // up to and including "skip" have same // condition as this, and will be woken later bool may_skip; // if false while on mutex queue, a mutex unlocker // is using this PerThreadSynch as a terminator. Its diff --git a/absl/base/internal/log_severity.h b/absl/base/log_severity.h index deaf6a578925..deaf6a578925 100644 --- a/absl/base/internal/log_severity.h +++ b/absl/base/log_severity.h diff --git a/absl/base/macros.h b/absl/base/macros.h index d41408727731..5ae0f05bf8c1 100644 --- a/absl/base/macros.h +++ b/absl/base/macros.h @@ -146,7 +146,7 @@ enum LinkerInitialized { // Every usage of a deprecated entity will trigger a warning when compiled with // clang's `-Wdeprecated-declarations` option. This option is turned off by // default, but the warnings will be reported by clang-tidy. -#if defined(__clang__) && __cplusplus >= 201103L && defined(__has_warning) +#if defined(__clang__) && __cplusplus >= 201103L #define ABSL_DEPRECATED(message) __attribute__((deprecated(message))) #endif |