diff options
-rw-r--r-- | absl/base/BUILD.bazel | 14 | ||||
-rw-r--r-- | absl/base/CMakeLists.txt | 13 | ||||
-rw-r--r-- | absl/base/casts.h | 22 | ||||
-rw-r--r-- | absl/base/dynamic_annotations.h | 2 | ||||
-rw-r--r-- | absl/base/log_severity.cc | 25 | ||||
-rw-r--r-- | absl/base/log_severity.h | 5 | ||||
-rw-r--r-- | absl/base/log_severity_test.cc | 43 | ||||
-rw-r--r-- | absl/meta/BUILD.bazel | 1 | ||||
-rw-r--r-- | absl/meta/CMakeLists.txt | 2 | ||||
-rw-r--r-- | absl/meta/type_traits.h | 43 | ||||
-rw-r--r-- | absl/meta/type_traits_test.cc | 135 | ||||
-rw-r--r-- | absl/strings/BUILD.bazel | 2 |
12 files changed, 281 insertions, 26 deletions
diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel index 8133a462..9fb1d8cd 100644 --- a/absl/base/BUILD.bazel +++ b/absl/base/BUILD.bazel @@ -135,6 +135,7 @@ cc_library( "internal/sysinfo.cc", "internal/thread_identity.cc", "internal/unscaledcycleclock.cc", + "log_severity.cc", ], hdrs = [ "call_once.h", @@ -162,6 +163,7 @@ cc_library( ":core_headers", ":dynamic_annotations", ":spinlock_wait", + "//absl/meta:type_traits", ], ) @@ -523,3 +525,15 @@ cc_test( "@com_google_googletest//:gtest_main", ], ) + +cc_test( + name = "log_severity_test", + size = "small", + srcs = ["log_severity_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":base", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt index cd1ec412..5042f156 100644 --- a/absl/base/CMakeLists.txt +++ b/absl/base/CMakeLists.txt @@ -127,6 +127,7 @@ absl_cc_library( "internal/sysinfo.cc" "internal/thread_identity.cc" "internal/unscaledcycleclock.cc" + "log_severity.cc" COPTS ${ABSL_DEFAULT_COPTS} DEPS @@ -135,6 +136,7 @@ absl_cc_library( absl::core_headers absl::dynamic_annotations absl::spinlock_wait + absl::type_traits Threads::Threads PUBLIC ) @@ -449,3 +451,14 @@ absl_cc_test( DEPS absl::base ) + +absl_cc_test( + NAME + log_severity_test + SRCS + "log_severity_test.cc" + DEPS + absl::base + gmock + gtest_main +) diff --git a/absl/base/casts.h b/absl/base/casts.h index 00196d20..a381c427 100644 --- a/absl/base/casts.h +++ b/absl/base/casts.h @@ -30,28 +30,20 @@ #include "absl/base/internal/identity.h" #include "absl/base/macros.h" +#include "absl/meta/type_traits.h" namespace absl { namespace internal_casts { -// NOTE: Not a fully compliant implementation of `std::is_trivially_copyable`. -// TODO(calabrese) Branch on implementations that directly provide -// `std::is_trivially_copyable`, create a more rigorous workaround, and publicly -// expose in meta/type_traits. -template <class T> -struct is_trivially_copyable - : std::integral_constant< - bool, std::is_destructible<T>::value&& __has_trivial_destructor(T) && - __has_trivial_copy(T) && __has_trivial_assign(T)> {}; - template <class Dest, class Source> struct is_bitcastable - : std::integral_constant<bool, - sizeof(Dest) == sizeof(Source) && - is_trivially_copyable<Source>::value && - is_trivially_copyable<Dest>::value && - std::is_default_constructible<Dest>::value> {}; + : std::integral_constant< + bool, + sizeof(Dest) == sizeof(Source) && + type_traits_internal::is_trivially_copyable<Source>::value && + type_traits_internal::is_trivially_copyable<Dest>::value && + std::is_default_constructible<Dest>::value> {}; } // namespace internal_casts diff --git a/absl/base/dynamic_annotations.h b/absl/base/dynamic_annotations.h index ac33df9e..65a54b44 100644 --- a/absl/base/dynamic_annotations.h +++ b/absl/base/dynamic_annotations.h @@ -377,7 +377,7 @@ inline T ANNOTATE_UNPROTECTED_READ(const volatile T &x) { /* NOLINT */ struct { char x[8] __attribute__ ((aligned (8))); } name #else #define ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid) -#define ADDRESS_SANITIZER_REDZONE(name) +#define ADDRESS_SANITIZER_REDZONE(name) static_assert(true, "") #endif // ADDRESS_SANITIZER /* Undefine the macros intended only in this file. */ diff --git a/absl/base/log_severity.cc b/absl/base/log_severity.cc new file mode 100644 index 00000000..02a2a485 --- /dev/null +++ b/absl/base/log_severity.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 +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "absl/base/log_severity.h" + +#include <ostream> + +namespace absl { + +std::ostream& operator<<(std::ostream& os, absl::LogSeverity s) { + if (s == absl::NormalizeLogSeverity(s)) return os << absl::LogSeverityName(s); + return os << "absl::LogSeverity(" << static_cast<int>(s) << ")"; +} +} // namespace absl diff --git a/absl/base/log_severity.h b/absl/base/log_severity.h index b19a7ffa..5a1d5576 100644 --- a/absl/base/log_severity.h +++ b/absl/base/log_severity.h @@ -16,6 +16,7 @@ #define ABSL_BASE_INTERNAL_LOG_SEVERITY_H_ #include <array> +#include <ostream> #include "absl/base/attributes.h" @@ -61,6 +62,10 @@ constexpr absl::LogSeverity NormalizeLogSeverity(int s) { return NormalizeLogSeverity(static_cast<absl::LogSeverity>(s)); } +// The exact representation of a streamed `absl::LogSeverity` is deliberately +// unspecified; do not rely on it. +std::ostream& operator<<(std::ostream& os, absl::LogSeverity s); + } // namespace absl #endif // ABSL_BASE_INTERNAL_LOG_SEVERITY_H_ diff --git a/absl/base/log_severity_test.cc b/absl/base/log_severity_test.cc new file mode 100644 index 00000000..1de2d101 --- /dev/null +++ b/absl/base/log_severity_test.cc @@ -0,0 +1,43 @@ +// 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 +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "absl/base/log_severity.h" + +#include <sstream> +#include <string> + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace { +using testing::Eq; + +std::string StreamHelper(absl::LogSeverity value) { + std::ostringstream stream; + stream << value; + return stream.str(); +} + +TEST(StreamTest, Works) { + EXPECT_THAT(StreamHelper(static_cast<absl::LogSeverity>(-100)), + Eq("absl::LogSeverity(-100)")); + EXPECT_THAT(StreamHelper(absl::LogSeverity::kInfo), Eq("INFO")); + EXPECT_THAT(StreamHelper(absl::LogSeverity::kWarning), Eq("WARNING")); + EXPECT_THAT(StreamHelper(absl::LogSeverity::kError), Eq("ERROR")); + EXPECT_THAT(StreamHelper(absl::LogSeverity::kFatal), Eq("FATAL")); + EXPECT_THAT(StreamHelper(static_cast<absl::LogSeverity>(4)), + Eq("absl::LogSeverity(4)")); +} + +} // namespace diff --git a/absl/meta/BUILD.bazel b/absl/meta/BUILD.bazel index c2435f4f..e004b509 100644 --- a/absl/meta/BUILD.bazel +++ b/absl/meta/BUILD.bazel @@ -26,7 +26,6 @@ cc_test( linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":type_traits", - "//absl/base:core_headers", "@com_google_googletest//:gtest_main", ], ) diff --git a/absl/meta/CMakeLists.txt b/absl/meta/CMakeLists.txt index 74d4a543..f866e54e 100644 --- a/absl/meta/CMakeLists.txt +++ b/absl/meta/CMakeLists.txt @@ -35,8 +35,6 @@ absl_cc_test( ${ABSL_TEST_COPTS} DEPS absl::type_traits - absl::base - absl::core_headers gmock_main ) diff --git a/absl/meta/type_traits.h b/absl/meta/type_traits.h index fbdc921f..a8068e31 100644 --- a/absl/meta/type_traits.h +++ b/absl/meta/type_traits.h @@ -341,6 +341,49 @@ struct is_trivially_copy_assignable #endif // ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE }; +namespace type_traits_internal { +// is_trivially_copyable() +// +// Determines whether the passed type `T` is trivially copyable. +// +// This metafunction is designed to be a drop-in replacement for the C++11 +// `std::is_trivially_copyable()` metafunction for platforms that have +// incomplete C++11 support (such as libstdc++ 4.x). We use the C++17 definition +// of TriviallyCopyable. +// +// NOTE: `is_trivially_copyable<T>::value` is `true` if all of T's copy/move +// constructors/assignment operators are trivial or deleted, T has at least +// one non-deleted copy/move constructor/assignment operator, and T is trivially +// destructible. Arrays of trivially copyable types are trivially copyable. +// +// We expose this metafunction only for internal use within absl. +template <typename T> +class is_trivially_copyable_impl { + using ExtentsRemoved = typename std::remove_all_extents<T>::type; + static constexpr bool kIsCopyOrMoveConstructible = + std::is_copy_constructible<ExtentsRemoved>::value || + std::is_move_constructible<ExtentsRemoved>::value; + static constexpr bool kIsCopyOrMoveAssignable = + absl::is_copy_assignable<ExtentsRemoved>::value || + absl::is_move_assignable<ExtentsRemoved>::value; + + public: + static constexpr bool kValue = + (__has_trivial_copy(ExtentsRemoved) || !kIsCopyOrMoveConstructible) && + (__has_trivial_assign(ExtentsRemoved) || !kIsCopyOrMoveAssignable) && + (kIsCopyOrMoveConstructible || kIsCopyOrMoveAssignable) && + is_trivially_destructible<ExtentsRemoved>::value && + // We need to check for this explicitly because otherwise we'll say + // references are trivial copyable when compiled by MSVC. + !std::is_reference<ExtentsRemoved>::value; +}; + +template <typename T> +struct is_trivially_copyable + : std::integral_constant< + bool, type_traits_internal::is_trivially_copyable_impl<T>::kValue> {}; +} // namespace type_traits_internal + // ----------------------------------------------------------------------------- // C++14 "_t" trait aliases // ----------------------------------------------------------------------------- diff --git a/absl/meta/type_traits_test.cc b/absl/meta/type_traits_test.cc index 912336e9..d3ead6d0 100644 --- a/absl/meta/type_traits_test.cc +++ b/absl/meta/type_traits_test.cc @@ -280,10 +280,20 @@ class DeletedCopyAssign { int n_; }; -struct NonCopyable { - NonCopyable() = default; - NonCopyable(const NonCopyable&) = delete; - NonCopyable& operator=(const NonCopyable&) = delete; +struct MovableNonCopyable { + MovableNonCopyable() = default; + MovableNonCopyable(const MovableNonCopyable&) = delete; + MovableNonCopyable(MovableNonCopyable&&) = default; + MovableNonCopyable& operator=(const MovableNonCopyable&) = delete; + MovableNonCopyable& operator=(MovableNonCopyable&&) = default; +}; + +struct NonCopyableOrMovable { + NonCopyableOrMovable() = default; + NonCopyableOrMovable(const NonCopyableOrMovable&) = delete; + NonCopyableOrMovable(NonCopyableOrMovable&&) = delete; + NonCopyableOrMovable& operator=(const NonCopyableOrMovable&) = delete; + NonCopyableOrMovable& operator=(NonCopyableOrMovable&&) = delete; }; class Base { @@ -507,7 +517,9 @@ TEST(TypeTraitsTest, TestTrivialCopyCtor) { absl::is_trivially_copy_constructible<NontrivialCopyCtor>::value); EXPECT_FALSE(absl::is_trivially_copy_constructible<DeletedCopyCtor>::value); EXPECT_FALSE( - absl::is_trivially_copy_constructible<NonCopyable>::value); + absl::is_trivially_copy_constructible<MovableNonCopyable>::value); + EXPECT_FALSE( + absl::is_trivially_copy_constructible<NonCopyableOrMovable>::value); #ifdef ABSL_TRIVIALLY_CONSTRUCTIBLE_VERIFY_TRIVIALLY_DESTRUCTIBLE // type with nontrivial destructor are nontrivial copy construbtible @@ -577,7 +589,8 @@ TEST(TypeTraitsTest, TestTrivialCopyAssign) { // Verify that types without them (i.e. nontrivial or deleted) are not. EXPECT_FALSE(absl::is_trivially_copy_assignable<NontrivialCopyAssign>::value); EXPECT_FALSE(absl::is_trivially_copy_assignable<DeletedCopyAssign>::value); - EXPECT_FALSE(absl::is_trivially_copy_assignable<NonCopyable>::value); + EXPECT_FALSE(absl::is_trivially_copy_assignable<MovableNonCopyable>::value); + EXPECT_FALSE(absl::is_trivially_copy_assignable<NonCopyableOrMovable>::value); // types with vtables EXPECT_FALSE(absl::is_trivially_copy_assignable<Base>::value); @@ -611,6 +624,116 @@ TEST(TypeTraitsTest, TestTrivialCopyAssign) { EXPECT_TRUE(absl::is_trivially_copy_assignable<Trivial&>::value); } +TEST(TypeTraitsTest, TestTriviallyCopyable) { + // Verify that arithmetic types and pointers are trivially copyable. + EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<bool>::value); + EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<char>::value); + EXPECT_TRUE( + absl::type_traits_internal::is_trivially_copyable<unsigned char>::value); + EXPECT_TRUE( + absl::type_traits_internal::is_trivially_copyable<signed char>::value); + EXPECT_TRUE( + absl::type_traits_internal::is_trivially_copyable<wchar_t>::value); + EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<int>::value); + EXPECT_TRUE( + absl::type_traits_internal::is_trivially_copyable<unsigned int>::value); + EXPECT_TRUE( + absl::type_traits_internal::is_trivially_copyable<int16_t>::value); + EXPECT_TRUE( + absl::type_traits_internal::is_trivially_copyable<uint16_t>::value); + EXPECT_TRUE( + absl::type_traits_internal::is_trivially_copyable<int64_t>::value); + EXPECT_TRUE( + absl::type_traits_internal::is_trivially_copyable<uint64_t>::value); + EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<float>::value); + EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<double>::value); + EXPECT_TRUE( + absl::type_traits_internal::is_trivially_copyable<long double>::value); + EXPECT_TRUE( + absl::type_traits_internal::is_trivially_copyable<std::string*>::value); + EXPECT_TRUE( + absl::type_traits_internal::is_trivially_copyable<Trivial*>::value); + EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable< + const std::string*>::value); + EXPECT_TRUE( + absl::type_traits_internal::is_trivially_copyable<const Trivial*>::value); + EXPECT_TRUE( + absl::type_traits_internal::is_trivially_copyable<std::string**>::value); + EXPECT_TRUE( + absl::type_traits_internal::is_trivially_copyable<Trivial**>::value); + + // const qualified types are not assignable but are constructible + EXPECT_TRUE( + absl::type_traits_internal::is_trivially_copyable<const int>::value); + + // Trivial copy constructor/assignment and destructor. + EXPECT_TRUE( + absl::type_traits_internal::is_trivially_copyable<Trivial>::value); + // Trivial copy assignment, but non-trivial copy constructor/destructor. + EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable< + TrivialCopyAssign>::value); + // Trivial copy constructor, but non-trivial assignment. + EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable< + TrivialCopyCtor>::value); + + // Types with a non-trivial copy constructor/assignment + EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable< + NontrivialCopyCtor>::value); + EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable< + NontrivialCopyAssign>::value); + + // Types without copy constructor/assignment, but with move + // MSVC disagrees with other compilers about this: + // EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable< + // MovableNonCopyable>::value); + + // Types without copy/move constructor/assignment + EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable< + NonCopyableOrMovable>::value); + + // No copy assign, but has trivial copy constructor. + EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable< + DeletedCopyAssign>::value); + + // types with vtables + EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable<Base>::value); + + // Verify that simple_pair is trivially copyable if members are + EXPECT_TRUE((absl::type_traits_internal::is_trivially_copyable< + simple_pair<int, char*>>::value)); + EXPECT_TRUE((absl::type_traits_internal::is_trivially_copyable< + simple_pair<int, Trivial>>::value)); + + // Verify that types not trivially copyable are + // correctly marked as such. + EXPECT_FALSE( + absl::type_traits_internal::is_trivially_copyable<std::string>::value); + EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable< + std::vector<int>>::value); + + // Verify that simple_pairs of types not trivially copyable + // are not marked as trivial. + EXPECT_FALSE((absl::type_traits_internal::is_trivially_copyable< + simple_pair<int, std::string>>::value)); + EXPECT_FALSE((absl::type_traits_internal::is_trivially_copyable< + simple_pair<std::string, int>>::value)); + EXPECT_FALSE((absl::type_traits_internal::is_trivially_copyable< + simple_pair<int, TrivialCopyAssign>>::value)); + + // Verify that arrays of trivially copyable types are trivially copyable + using int10 = int[10]; + EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<int10>::value); + using int10x10 = int[10][10]; + EXPECT_TRUE( + absl::type_traits_internal::is_trivially_copyable<int10x10>::value); + + // Verify that references are handled correctly + EXPECT_FALSE( + absl::type_traits_internal::is_trivially_copyable<Trivial&&>::value); + EXPECT_FALSE( + absl::type_traits_internal::is_trivially_copyable<Trivial&>::value); +} + #define ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(trait_name, ...) \ EXPECT_TRUE((std::is_same<typename std::trait_name<__VA_ARGS__>::type, \ absl::trait_name##_t<__VA_ARGS__>>::value)) diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel index 9640ff46..2b194737 100644 --- a/absl/strings/BUILD.bazel +++ b/absl/strings/BUILD.bazel @@ -16,9 +16,9 @@ load( "//absl:copts/configure_copts.bzl", "ABSL_DEFAULT_COPTS", - "ABSL_TEST_COPTS", "ABSL_EXCEPTIONS_FLAG", "ABSL_EXCEPTIONS_FLAG_LINKOPTS", + "ABSL_TEST_COPTS", ) package( |