[cfe-dev] operator new alignment assumptions
Richard Smith via cfe-dev
cfe-dev at lists.llvm.org
Wed Feb 15 17:34:36 PST 2017
On 13 February 2017 at 06:55, Stephan Bergmann <sbergman at redhat.com> wrote:
> Since r283789 (re-commit of r283722, "P0035R4: Semantic analysis and code
> generation for C++17 overaligned allocation"),
> CodeGenFunction::EmitCXXNewExpr (lib/CodeGen/CGExprCXX.cpp) contains
>
> // If this was a call to a global replaceable allocation function that
>> does
>> // not take an alignment argument, the allocator is known to produce
>> // storage that's suitably aligned for any object that fits, up to a
>> known
>> // threshold. Otherwise assume it's suitably aligned for the
>> allocated type.
>> CharUnits allocationAlign = allocAlign;
>> if (!E->passAlignment() &&
>> allocator->isReplaceableGlobalAllocationFunction()) {
>> unsigned AllocatorAlign = llvm::PowerOf2Floor(std::min<uint64_t>(
>> Target.getNewAlign(), getContext().getTypeSize(allocType)));
>> allocationAlign = std::max(
>> allocationAlign, getContext().toCharUnitsFromBi
>> ts(AllocatorAlign));
>> }
>>
>
> which I have two questions about:
>
> * Why restrict this to global replaceable allocation functions? My
> interpretation of the standard up to C++14 is that all allocation functions
> consistently have the same requirements wrt alignment ("The pointer
> returned shall be suitably aligned so that it can be converted
> to a pointer of any complete object type with a fundamental alignment
> requirement", [basic.stc.dynamic.allocation]), and that P0035R4
> (presumably unintentionally) makes it confusing that this consistency still
> holds (cf. my question at <https://groups.google.com/a/i
> socpp.org/forum/?fromgroups#!topic/std-discussion/mTZ4sB5P1Sg> "Confusing
> wording in P0035R4, 'any suitable complete object type'").
>
There is no reasonable assumption you can make about the alignment provided
by any other 'operator new' function, other than assuming that the user got
it right: that it produces a pointer that is suitably aligned for the
allocated object. For instance, a class-specific allocator for a class with
1-byte alignment might reasonably produce 1-byte-aligned pointers
regardless of the allocation size. Breaking such code merely because poor
wording in the C++ standard may have allowed us to do so seems unlikely to
make anyone happier.
* At least with the wording from P0035R4, it is unclear to me what the
> alignment requirements in
>
> struct S { char a[25]; };
>> S * func() { return new S(); }
>>
>
> are. When compiled at -O for x86_64-unknown-linux-gnu, Clang trunk
> apparently assumes that the pointer returned from operator new is 16-byte
> aligned (writing to it with movaps). But the requirements for that
> operator new in [new.delete.single] merely states that it "allocates
> storage suitably aligned to represent any object of that size", and I don't
> think there is a type of size 25 with a stricter alignment requirement than
> 1 for that target.
Yes, you're right that this is at best unclear and at worst says that our
assumption is not valid for allocations that are not a multiple of the
allocator alignment. This is the subject of C++ core issue 2207 (
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2207, but
there's no information on the public version of the issues list yet); there
generally seemed to be consensus in committee discussion that global
non-array non-aligned operator new should provide sufficient storage for
any object with a fundamental alignment that fits in the storage, not just
for fundamental alignments that divide the allocated size.
For instance, we want to guarantee that this sort of thing works:
S *p = func();
static_assert(sizeof(long double) <= 25);
new (p->a) long double; // ok, 'a' is suitably aligned for 'long double'
Is this assumption causing problems in practice?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20170215/a9640bf5/attachment.html>
More information about the cfe-dev
mailing list