This is an archive of the discontinued LLVM Phabricator instance.

[libcxx] [test] Fix incorrect allocator::construct assertions in associative container tests
AbandonedPublic

Authored by EricWF on Apr 30 2019, 11:59 PM.

Details

Summary

In $:\Dev\msvc\src\qa\VC\Libs\libcxx\upstream\test\std\containers\map_allocator_requirement_test_templates.h and $\test\std\containers\set_allocator_requirement_test_templates.h, libcxx tests are asserting that the container's insert operation passes an incorrect type down to allocator::construct. Specifically, given something like:

{
  CHECKPOINT("Testing C::insert(value_type&)");
  Container c;
  ValueTp v(42, 1);
  cc->expect<const ValueTp&>(); // <-- !!!!!
  assert(c.insert(v).second);
  assert(!cc->unchecked());
  {
    DisableAllocationGuard g;
    ValueTp v2(42, 1);
    assert(c.insert(v2).second == false);
  }
}

This call to ::insert ends up calling the insert(P&&), not insert(const value_type&), because P is deduced to value_type&, meaning the insert(P&&) overload is an exact match, while insert(const value_type&) requires adding const. See http://eel.is/c++draft/associative#map.modifiers

When the insert(P&&) is called, it delegates to emplace, which only gets Cpp17EmplaceConstructible from the supplied parameters, not Cpp17EmplaceConstructible from add_const_t of the parameters. Thus, libcxx's test is asserting a condition the standard explicitly does not allow at this time. (Though it may be reasonable to fix the standard to make what libcxx is doing okay....)

Unfortunately with the tests fixed to assert the correct allocator::construct call, libc++ will fail these tests. I'm looking for guidance on how libc++ maintainers would like to handle this.

Diff Detail

Event Timeline

BillyONeal created this revision.Apr 30 2019, 11:59 PM
BillyONeal edited the summary of this revision. (Show Details)May 1 2019, 12:05 AM

When the insert(P&&) is called, it delegates to emplace, which only gets Cpp17EmplaceConstructible from the supplied parameters, not Cpp17EmplaceConstructible from add_const_t of the parameters. Thus, libcxx's test is asserting a condition the standard explicitly does not allow at this time. [...]

Agreed.

Unfortunately with the tests fixed to assert the correct allocator::construct call, libc++ will fail these tests. I'm looking for guidance on how libc++ maintainers would like to handle this.

Do you know *why* the tests are failing with libc++? I see this overload for insert and it seems like it should be a better match?

template <class _Pp,
          class = typename enable_if<is_constructible<value_type, _Pp>::value>::type>
    _LIBCPP_INLINE_VISIBILITY
    pair<iterator, bool> insert(_Pp&& __p);

I think we should just fix libc++ to do the right thing (according to the standard).

Separately, I'm not sure it's worth changing the Standard to ensure that the T const& overload is selected -- I don't see a huge benefit here.

Do you know *why* the tests are failing with libc++? I see this overload for insert and it seems like it should be a better match?

No, I haven't investigated. I avoid looking at libc++ product code too much for now because I want to avoid any appearance or reality of licensing conflicts... for now ;) .

I think we should just fix libc++ to do the right thing (according to the standard).

That's what I'd recommend :)

Separately, I'm not sure it's worth changing the Standard to ensure that the T const& overload is selected -- I don't see a huge benefit here.

Would be a code size win if both overloads are called in the same program.

From Billy and my last discussion, I think we came to the agreement that it's not clear exactly what the "standard behavior" is.

EricWF added inline comments.May 14 2019, 3:55 PM
test/std/containers/map_allocator_requirement_test_templates.h
236

I really think the current behavior libc++ has here is correct.

From Billy and my last discussion, I think we came to the agreement that it's not clear exactly what the "standard behavior" is.

No, I don't think so. I think there was agreement that the behavior in the standard may not have been what was intended by the original move semantics proposals, but I don't think there's any doubt about what the standard currently requires.

BillyONeal marked an inline comment as done.May 14 2019, 3:58 PM
BillyONeal added inline comments.
test/std/containers/map_allocator_requirement_test_templates.h
236

File a DR to retroactively make libc++'s behavior standard then? :)

EricWF commandeered this revision.Sep 14 2023, 1:35 PM
EricWF edited reviewers, added: BillyONeal; removed: EricWF.

Fixing this requires a bunch of container overall in the containers that I don't have the time for right now.
So I'm going to go ahead and close this for being inactive.

Herald added a project: Restricted Project. · View Herald TranscriptSep 14 2023, 1:35 PM
EricWF abandoned this revision.Sep 14 2023, 1:35 PM