Skip to content

Commit

Permalink
Export of internal Abseil changes
Browse files Browse the repository at this point in the history
--
0f6565955231dc74ebad62ef32a18c457afa2dc7 by Abseil Team <absl-team@google.com>:

Document guarantee that we do not move from rvalue arguments if no insertion happens with absl::raw_hash_map::try_emplace, as done with std::unordered_map::try_emplace.

PiperOrigin-RevId: 264430409

--
292e6b9e08fa689e8400d7f2db94cbcab29d5889 by CJ Johnson <johnsoncj@google.com>:

Removes use of aligned_storage in FixedArray and InlinedVector in favor of aligned char buffers.

PiperOrigin-RevId: 264385559

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

Make the unit tests for absl::any, absl::optional, and absl::variant
no-ops when these types are just aliases for the corresponding std::
types. We have no way to fix standard library implementation bugs, so
don't bother working around them.

Also disable the corresponding exception-safety tests as well when
exceptions are not enabled.

Fixes #360

PiperOrigin-RevId: 264382050

--
65896a911f36481b89b4712c83b91c90a76b64e8 by Abseil Team <absl-team@google.com>:

Improve documentation on erase

PiperOrigin-RevId: 264381266
GitOrigin-RevId: 0f6565955231dc74ebad62ef32a18c457afa2dc7
Change-Id: I74b9bd2ddf84526014104f17e87de70bd3fe65fa
  • Loading branch information
Abseil Team authored and Xiaoyi Zhang committed Aug 20, 2019
1 parent 0e7afdc commit f0afae0
Show file tree
Hide file tree
Showing 20 changed files with 140 additions and 30 deletions.
1 change: 1 addition & 0 deletions absl/container/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,7 @@ cc_library(
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":hash_policy_testing",
"//absl/memory",
"//absl/meta:type_traits",
"//absl/strings",
],
Expand Down
1 change: 1 addition & 0 deletions absl/container/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,7 @@ absl_cc_library(
${ABSL_TEST_COPTS}
DEPS
absl::hash_policy_testing
absl::memory
absl::meta
absl::strings
TESTONLY
Expand Down
28 changes: 11 additions & 17 deletions absl/container/fixed_array.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
#define ABSL_CONTAINER_FIXED_ARRAY_H_

#include <algorithm>
#include <array>
#include <cassert>
#include <cstddef>
#include <initializer_list>
Expand Down Expand Up @@ -386,8 +385,7 @@ class FixedArray {
// error: call to int __builtin___sprintf_chk(etc...)
// will always overflow destination buffer [-Werror]
//
template <typename OuterT = value_type,
typename InnerT = absl::remove_extent_t<OuterT>,
template <typename OuterT, typename InnerT = absl::remove_extent_t<OuterT>,
size_t InnerN = std::extent<OuterT>::value>
struct StorageElementWrapper {
InnerT array[InnerN];
Expand All @@ -396,8 +394,6 @@ class FixedArray {
using StorageElement =
absl::conditional_t<std::is_array<value_type>::value,
StorageElementWrapper<value_type>, value_type>;
using StorageElementBuffer =
absl::aligned_storage_t<sizeof(StorageElement), alignof(StorageElement)>;

static pointer AsValueType(pointer ptr) { return ptr; }
static pointer AsValueType(StorageElementWrapper<value_type>* ptr) {
Expand All @@ -407,25 +403,25 @@ class FixedArray {
static_assert(sizeof(StorageElement) == sizeof(value_type), "");
static_assert(alignof(StorageElement) == alignof(value_type), "");

struct NonEmptyInlinedStorage {
StorageElement* data() {
return reinterpret_cast<StorageElement*>(inlined_storage_.data());
}
class NonEmptyInlinedStorage {
public:
StorageElement* data() { return reinterpret_cast<StorageElement*>(buff_); }
void AnnotateConstruct(size_type n);
void AnnotateDestruct(size_type n);

#ifdef ADDRESS_SANITIZER
void* RedzoneBegin() { return &redzone_begin_; }
void* RedzoneEnd() { return &redzone_end_ + 1; }
#endif // ADDRESS_SANITIZER

void AnnotateConstruct(size_type);
void AnnotateDestruct(size_type);

private:
ADDRESS_SANITIZER_REDZONE(redzone_begin_);
std::array<StorageElementBuffer, inline_elements> inlined_storage_;
alignas(StorageElement) char buff_[sizeof(StorageElement[inline_elements])];
ADDRESS_SANITIZER_REDZONE(redzone_end_);
};

struct EmptyInlinedStorage {
class EmptyInlinedStorage {
public:
StorageElement* data() { return nullptr; }
void AnnotateConstruct(size_type) {}
void AnnotateDestruct(size_type) {}
Expand Down Expand Up @@ -459,9 +455,7 @@ class FixedArray {
size_type size() const { return size_alloc_.template get<0>(); }
StorageElement* begin() const { return data_; }
StorageElement* end() const { return begin() + size(); }
allocator_type& alloc() {
return size_alloc_.template get<1>();
}
allocator_type& alloc() { return size_alloc_.template get<1>(); }

private:
static bool UsingInlinedStorage(size_type n) {
Expand Down
4 changes: 4 additions & 0 deletions absl/container/flat_hash_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,10 @@ class flat_hash_map : public absl::container_internal::raw_hash_map<
// Inserts (via copy or move) the element of the specified key into the
// `flat_hash_map` using the position of `hint` as a non-binding suggestion
// for where to begin the insertion search.
//
// All `try_emplace()` overloads make the same guarantees regarding rvalue
// arguments as `std::unordered_map::try_emplace()`, namely that these
// functions will not move from rvalue arguments if insertions do not happen.
using Base::try_emplace;

// flat_hash_map::extract()
Expand Down
7 changes: 7 additions & 0 deletions absl/container/flat_hash_map_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

#include "absl/container/flat_hash_map.h"

#include <memory>

#include "absl/container/internal/hash_generator_testing.h"
#include "absl/container/internal/unordered_map_constructor_test.h"
#include "absl/container/internal/unordered_map_lookup_test.h"
Expand Down Expand Up @@ -46,6 +48,11 @@ INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashMap, LookupTest, MapTypes);
INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashMap, MembersTest, MapTypes);
INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashMap, ModifiersTest, MapTypes);

using UniquePtrMapTypes = ::testing::Types<Map<int, std::unique_ptr<int>>>;

INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashMap, UniquePtrModifiersTest,
UniquePtrMapTypes);

TEST(FlatHashMap, StandardLayout) {
struct Int {
explicit Int(size_t value) : value(value) {}
Expand Down
9 changes: 9 additions & 0 deletions absl/container/internal/hash_generator_testing.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#define ABSL_CONTAINER_INTERNAL_HASH_GENERATOR_TESTING_H_

#include <stdint.h>

#include <algorithm>
#include <iosfwd>
#include <random>
Expand All @@ -27,6 +28,7 @@
#include <utility>

#include "absl/container/internal/hash_policy_testing.h"
#include "absl/memory/memory.h"
#include "absl/meta/type_traits.h"
#include "absl/strings/string_view.h"

Expand Down Expand Up @@ -129,6 +131,13 @@ struct Generator<std::tuple<Ts...>> {
}
};

template <class T>
struct Generator<std::unique_ptr<T>> {
std::unique_ptr<T> operator()() const {
return absl::make_unique<T>(Generator<T>()());
}
};

template <class U>
struct Generator<U, absl::void_t<decltype(std::declval<U&>().key()),
decltype(std::declval<U&>().value())>>
Expand Down
4 changes: 1 addition & 3 deletions absl/container/internal/inlined_vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -445,9 +445,7 @@ class Storage {
};

struct Inlined {
using InlinedDataElement =
absl::aligned_storage_t<sizeof(value_type), alignof(value_type)>;
InlinedDataElement inlined_data[N];
alignas(value_type) char inlined_data[sizeof(value_type[N])];
};

union Data {
Expand Down
3 changes: 3 additions & 0 deletions absl/container/internal/raw_hash_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ class raw_hash_map : public raw_hash_set<Policy, Hash, Eq, Alloc> {
return insert_or_assign(k, v).first;
}

// All `try_emplace()` overloads make the same guarantees regarding rvalue
// arguments as `std::unordered_map::try_emplace()`, namely that these
// functions will not move from rvalue arguments if insertions do not happen.
template <class K = key_type, class... Args,
typename std::enable_if<
!std::is_convertible<K, const_iterator>::value, int>::type = 0,
Expand Down
13 changes: 7 additions & 6 deletions absl/container/internal/raw_hash_set.h
Original file line number Diff line number Diff line change
Expand Up @@ -1133,15 +1133,16 @@ class raw_hash_set {
}

// Erases the element pointed to by `it`. Unlike `std::unordered_set::erase`,
// this method returns void to reduce algorithmic complexity to O(1). In
// order to erase while iterating across a map, use the following idiom (which
// also works for standard containers):
// this method returns void to reduce algorithmic complexity to O(1). The
// iterator is invalidated, so any increment should be done before calling
// erase. In order to erase while iterating across a map, use the following
// idiom (which also works for standard containers):
//
// for (auto it = m.begin(), end = m.end(); it != end;) {
// // `erase()` will invalidate `it`, so advance `it` first.
// auto copy_it = it++;
// if (<pred>) {
// m.erase(it++);
// } else {
// ++it;
// m.erase(copy_it);
// }
// }
void erase(const_iterator cit) { erase(cit.inner_); }
Expand Down
41 changes: 41 additions & 0 deletions absl/container/internal/unordered_map_modifiers_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#ifndef ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MODIFIERS_TEST_H_
#define ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MODIFIERS_TEST_H_

#include <memory>

#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/container/internal/hash_generator_testing.h"
Expand Down Expand Up @@ -267,6 +269,45 @@ REGISTER_TYPED_TEST_CASE_P(ModifiersTest, Clear, Insert, InsertHint,
Emplace, EmplaceHint, TryEmplace, TryEmplaceHint,
Erase, EraseRange, EraseKey, Swap);

template <typename Type>
struct is_unique_ptr : std::false_type {};

template <typename Type>
struct is_unique_ptr<std::unique_ptr<Type>> : std::true_type {};

template <class UnordMap>
class UniquePtrModifiersTest : public ::testing::Test {
protected:
UniquePtrModifiersTest() {
static_assert(is_unique_ptr<typename UnordMap::mapped_type>::value,
"UniquePtrModifiersTyest may only be called with a "
"std::unique_ptr value type.");
}
};

TYPED_TEST_SUITE_P(UniquePtrModifiersTest);

// Test that we do not move from rvalue arguments if an insertion does not
// happen.
TYPED_TEST_P(UniquePtrModifiersTest, TryEmplace) {
#ifdef UNORDERED_MAP_CXX17
using T = hash_internal::GeneratedType<TypeParam>;
using V = typename TypeParam::mapped_type;
T val = hash_internal::Generator<T>()();
TypeParam m;
auto p = m.try_emplace(val.first, std::move(val.second));
EXPECT_TRUE(p.second);
// A moved from std::unique_ptr is guaranteed to be nullptr.
EXPECT_EQ(val.second, nullptr);
T val2 = {val.first, hash_internal::Generator<V>()()};
p = m.try_emplace(val2.first, std::move(val2.second));
EXPECT_FALSE(p.second);
EXPECT_NE(val2.second, nullptr);
#endif
}

REGISTER_TYPED_TEST_SUITE_P(UniquePtrModifiersTest, TryEmplace);

} // namespace container_internal
} // namespace absl

Expand Down
8 changes: 8 additions & 0 deletions absl/container/internal/unordered_map_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#include <memory>
#include <unordered_map>

#include "absl/container/internal/unordered_map_constructor_test.h"
Expand All @@ -35,6 +36,13 @@ INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, LookupTest, MapTypes);
INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, MembersTest, MapTypes);
INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, ModifiersTest, MapTypes);

using UniquePtrMapTypes = ::testing::Types<std::unordered_map<
int, std::unique_ptr<int>, StatefulTestingHash, StatefulTestingEqual,
Alloc<std::pair<const int, std::unique_ptr<int>>>>>;

INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, UniquePtrModifiersTest,
UniquePtrMapTypes);

} // namespace
} // namespace container_internal
} // namespace absl
4 changes: 4 additions & 0 deletions absl/container/node_hash_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,10 @@ class node_hash_map
// Inserts (via copy or move) the element of the specified key into the
// `node_hash_map` using the position of `hint` as a non-binding suggestion
// for where to begin the insertion search.
//
// All `try_emplace()` overloads make the same guarantees regarding rvalue
// arguments as `std::unordered_map::try_emplace()`, namely that these
// functions will not move from rvalue arguments if insertions do not happen.
using Base::try_emplace;

// node_hash_map::extract()
Expand Down
2 changes: 2 additions & 0 deletions absl/types/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ cc_test(
linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS + ABSL_DEFAULT_LINKOPTS,
deps = [
":any",
"//absl/base:config",
"//absl/base:exception_safety_testing",
"@com_google_googletest//:gtest_main",
],
Expand Down Expand Up @@ -240,6 +241,7 @@ cc_test(
linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS + ABSL_DEFAULT_LINKOPTS,
deps = [
":optional",
"//absl/base:config",
"//absl/base:exception_safety_testing",
"@com_google_googletest//:gtest_main",
],
Expand Down
2 changes: 2 additions & 0 deletions absl/types/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ absl_cc_test(
${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
DEPS
absl::any
absl::config
absl::exception_safety_testing
gmock_main
)
Expand Down Expand Up @@ -256,6 +257,7 @@ absl_cc_test(
${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
DEPS
absl::optional
absl::config
absl::exception_safety_testing
gmock_main
)
Expand Down
11 changes: 8 additions & 3 deletions absl/types/any_exception_safety_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@

#include "absl/types/any.h"

#include "absl/base/config.h"

// This test is a no-op when absl::any is an alias for std::any and when
// exceptions are not enabled.
#if !defined(ABSL_HAVE_STD_ANY) && defined(ABSL_HAVE_EXCEPTIONS)

#include <typeinfo>
#include <vector>

Expand Down Expand Up @@ -136,8 +142,6 @@ TEST(AnyExceptionSafety, Assignment) {
EXPECT_TRUE(strong_empty_any_tester.Test(move));
}

// libstdc++ std::any fails this test
#if !defined(ABSL_HAVE_STD_ANY)
TEST(AnyExceptionSafety, Emplace) {
auto initial_val =
absl::any{absl::in_place_type_t<Thrower>(), 1, testing::nothrow_ctor};
Expand All @@ -163,6 +167,7 @@ TEST(AnyExceptionSafety, Emplace) {
EXPECT_TRUE(empty_tester.Test(emp_thrower));
EXPECT_TRUE(empty_tester.Test(emp_throwervec));
}
#endif // ABSL_HAVE_STD_ANY

} // namespace

#endif // #if !defined(ABSL_HAVE_STD_ANY) && defined(ABSL_HAVE_EXCEPTIONS)
5 changes: 5 additions & 0 deletions absl/types/any_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@

#include "absl/types/any.h"

// This test is a no-op when absl::any is an alias for std::any.
#if !defined(ABSL_HAVE_STD_ANY)

#include <initializer_list>
#include <type_traits>
#include <utility>
Expand Down Expand Up @@ -774,3 +777,5 @@ TEST(AnyTest, FailedEmplace) {
}

} // namespace

#endif // #if !defined(ABSL_HAVE_STD_ANY)
8 changes: 8 additions & 0 deletions absl/types/optional_exception_safety_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@

#include "absl/types/optional.h"

#include "absl/base/config.h"

// This test is a no-op when absl::optional is an alias for std::optional and
// when exceptions are not enabled.
#if !defined(ABSL_HAVE_STD_OPTIONAL) && defined(ABSL_HAVE_EXCEPTIONS)

#include "gtest/gtest.h"
#include "absl/base/internal/exception_safety_testing.h"

Expand Down Expand Up @@ -280,3 +286,5 @@ TEST(OptionalExceptionSafety, NothrowMoveAssign) {
} // namespace

} // namespace absl

#endif // #if !defined(ABSL_HAVE_STD_OPTIONAL) && defined(ABSL_HAVE_EXCEPTIONS)
5 changes: 5 additions & 0 deletions absl/types/optional_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@

#include "absl/types/optional.h"

// This test is a no-op when absl::optional is an alias for std::optional.
#if !defined(ABSL_HAVE_STD_OPTIONAL)

#include <string>
#include <type_traits>
#include <utility>
Expand Down Expand Up @@ -1654,3 +1657,5 @@ TEST(optionalTest, InPlaceTSFINAEBug) {
#endif // !defined(__EMSCRIPTEN__)

} // namespace

#endif // #if !defined(ABSL_HAVE_STD_OPTIONAL)
Loading

0 comments on commit f0afae0

Please sign in to comment.