This is an archive of the discontinued LLVM Phabricator instance.

[LLVM][Support] Delete non-const lvalue ref "copy" constructor of BumpPtrAllocatorImpl
Needs ReviewPublic

Authored by zixuw on Feb 11 2022, 1:02 PM.

Details

Summary

Though the implicit copy constructor of BumpPtrAllocatorImpl is deleted
because of the presence of a user-defined move constructor, the
perfect-forwarding constructor will still match for lvalue reference of
BumpPtrAllocatorImpl, silently "copying" a BumpPtrAllocatorImpl
(actually just copy-constructing an underlying AllocatorT and
blank-constructing a BumpPtrAllocatorImpl).
This patch explicitly deletes the problematic specialization of the
forwarding constructor.

Diff Detail

Event Timeline

zixuw created this revision.Feb 11 2022, 1:02 PM
zixuw requested review of this revision.Feb 11 2022, 1:02 PM
Herald added a project: Restricted Project. · View Herald TranscriptFeb 11 2022, 1:03 PM
zixuw added a comment.Feb 11 2022, 1:27 PM

I'm having trouble to find an appropriate place and approach to test this. Any ideas?

I'm having trouble to find an appropriate place and approach to test this. Any ideas?

Maybe you can use the std::is_copy_constructible trait in a unit test?

zixuw updated this revision to Diff 408057.Feb 11 2022, 2:28 PM

Add unit test case with std::is_[copy]_constructible

zixuw retitled this revision from [LLVM][Support] Delete "copy" constructor of BumpPtrAllocatorImpl to [LLVM][Support] Delete non-const lvalue ref "copy" constructor of BumpPtrAllocatorImpl.Feb 11 2022, 2:28 PM
efriedma added inline comments.
llvm/include/llvm/Support/Allocator.h
85

This isn't using the right template parameters. I'd suggest just BumpPtrAllocatorImpl(const BumpPtrAllocatorImpl &) = delete;. Or I guess you could do something like template <typename AllocatorT, size_t SlabSize, size_t SizeThreshold, size_t GrowthDelay> BumpPtrAllocatorImpl(const BumpPtrAllocatorImpl<AllocatorT, SlabSize, SizeThreshold, GrowthDelay> &) = delete;.

JDevlieghere added a comment.EditedFeb 11 2022, 2:48 PM

I was curious if the standard specified anything about allocators being copy-constructable. I didn't actually check the standard itself, but cppreference seems to say so: https://en.cppreference.com/w/cpp/named_req/Allocator

Every Allocator also satisfies CopyConstructible.

zixuw added inline comments.Feb 11 2022, 2:49 PM
llvm/include/llvm/Support/Allocator.h
85

Ahh makes sense.

just BumpPtrAllocatorImpl(const BumpPtrAllocatorImpl &) = delete;

IIUC this would just delete the case where BumpPtrAllocatorImpl with the same template arguments right? I guess I should go with the full thing.

Also I need to drop the const apparently because otherwise the perfect-forwarding will always be a better match.

zixuw added a comment.EditedFeb 11 2022, 2:54 PM

I was curious if the standard specified anything about allocators being copy-constructable. I didn't actually check the standard itself, but cppreference seems to say so: https://en.cppreference.com/w/cpp/named_req/Allocator

Every Allocator also satisfies CopyConstructible.

Huh. Then I guess the "fix" would be to actually provide correct copy-constructing behaviors? Currently in this case, the implicit copy-constructor (BumpAllocatorImpl(const BumpAllocatorImpl &)) is deleted, and the forwarding constructor provides a match for BumpAllocatorImpl(BumpAllocatorImpl &) but does nothing.

zixuw updated this revision to Diff 408073.Feb 11 2022, 3:05 PM

Fix template parameters.

zixuw marked an inline comment as done.Feb 11 2022, 3:06 PM
dblaikie added inline comments.
llvm/unittests/Support/AllocatorTest.cpp
49–58

Perhaps this could be done with a static_assert in the header - no need for a test case/runtime expect of the value?