This is an archive of the discontinued LLVM Phabricator instance.

Move internal usages of `alignof`/`__alignof` to use `_LIBCPP_ALIGNOF`.
ClosedPublic

Authored by EricWF on Nov 21 2018, 2:39 PM.

Details

Summary

Starting in Clang 8.0 and GCC 8.0, alignof and __alignof return different values in same cases. Specifically alignof and _Alignof return the minimum alignment for a type, where as __alignof returns the preferred alignment. libc++ currently uses __alignof but means to use alignof. See llvm.org/PR39713

This patch introduces the macro _LIBCPP_ALIGNOF so we can control which spelling gets used.

This patch does not introduce any ABI guard to provide the old behavior with newer compilers. However, if we decide that is needed, this patch makes it trivial to implement.

I think we should commit this change immediately, and decide what we want to do about the ABI afterwards.

Diff Detail

Event Timeline

EricWF created this revision.Nov 21 2018, 2:39 PM

Please hold off with committing this until we've agreed on the ABI part. That'll take at least until next week when people are back from Thanksgiving.

include/__config
1285

Can you indent nested #defines? I find it very difficult to read our PP code because it often lacks indentation.

test/libcxx/libcpp_alignof.pass.cpp
30

Why is this test useful? Isn't the previous one (for C++11) sufficient?

test/support/test_macros.h
118–122

Why not always just alignof? Shouldn't we only use that macro in C++11 and above anyway?

I like this, though. It's a nice cleanup.

EricWF accepted this revision.Nov 28 2018, 10:16 AM
EricWF marked 6 inline comments as done.

Please hold off with committing this until we've agreed on the ABI part. That'll take at least until next week when people are back from Thanksgiving.

I don't know if there is an ABI part to agree on. Libc++ should have always been using alignof. The fact we were using __alignof was unobservable until Clang 8. If we release this in libc++ 8, it will continue to appear as if we have always been using alignof.
If users want the old behavior, the use the Clang flag.

Accepting. Further review can be post-commit review.

include/__config
1285

OK, but generally I'm pretty hostile to manually formatting anything. If clang-format doesn't do it, then I don't normally care.

test/libcxx/libcpp_alignof.pass.cpp
30

It checks that _Alignof acts like alignof which acts like _LIBCPP_ALIGNOF. The test is useful in that it would have caught the Clang bug related to this change.

And additional tests never hurt. This was certainly doesn't.

test/support/test_macros.h
118–122

We provide almost all of the C++11 library in C++03, C++03 is really just a thing we tolerate. For example, we provide alignment_of in C++03. Our allocators pass around the alignment in case we can use aligned new, etc.

This revision is now accepted and ready to land.Nov 28 2018, 10:16 AM
This revision was automatically updated to reflect the committed changes.
EricWF marked 3 inline comments as done.

Please hold off with committing this until we've agreed on the ABI part. That'll take at least until next week when people are back from Thanksgiving.

I don't know if there is an ABI part to agree on. Libc++ should have always been using alignof. The fact we were using __alignof was unobservable until Clang 8. If we release this in libc++ 8, it will continue to appear as if we have always been using alignof.
If users want the old behavior, the use the Clang flag.

Accepting. Further review can be post-commit review.

FWIW, I agree with the argument that people should use Clang's ABI compat flag if they want to retain ABI compatibility, and that the libc++ change (this one) is largely orthogonal to ABI implications (but the Clang change is a different story). I would have given you a ship-it with that comment even though I'm still considering the ABI implications of the Clang change.

However, I would have appreciated that you held off until I gave you a thumbs up since I did mention explicitly this was a sticky issue. I understand LLVM has a revert-friendly culture, but I feel like discussing reviewers' concerns is a better way of building trust. I just want to make sure we collaborate effectively.

I'm fine with this change, and thanks for the cleanup!

I'd note that most of this diff was not actually required to fix the issue. E.g, in the locations where an alignment is passed to allocation/deallocation functions directly, it is perfectly fine to use the __alignof value instead of the alignof value.

We could also ameliorate some ABI breakage by continuing to use alignof within libc++, where changing to alignof would break the ABI of a standard library type. E.g., we could switch the use of std::alignment_of in any_imp to instead call __alignof, preserving behavior.

That appears to be the strategy GCC went with -- making the minimal ABI change necessary to be compliant.

I'd note that most of this diff was not actually required to fix the issue. E.g, in the locations where an alignment is passed to allocation/deallocation functions directly, it is perfectly fine to use the __alignof value instead of the alignof value.

We could also ameliorate some ABI breakage by continuing to use alignof within libc++, where changing to alignof would break the ABI of a standard library type. E.g., we could switch the use of std::alignment_of in any_imp to instead call __alignof, preserving behavior.

That appears to be the strategy GCC went with -- making the minimal ABI change necessary to be compliant.

I think it's better to fix it everywhere. If they want to truly be safe, people who actually care about ABI (and not breaking their customer's ABIs) will have to use -fclang-abi-compat=7.

After further thought I don't think this approach is strictly correct.

I'd note that most of this diff was not actually required to fix the issue. E.g, in the locations where an alignment is passed to allocation/deallocation functions directly, it is perfectly fine to use the __alignof value instead of the alignof value.

We could also ameliorate some ABI breakage by continuing to use alignof within libc++, where changing to alignof would break the ABI of a standard library type. E.g., we could switch the use of std::alignment_of in any_imp to instead call __alignof, preserving behavior.

I see a couple different classes of use cases:

  1. std::alignment_of which should obviously use alignof.
  2. Allocation functions and friends (such as __libcpp_allocate and __is_over_aligned_for_new). These should use alignof so they dispatch to aligned operator new in the same cases where Clang would implicitly call it.
  3. aligned_storage and aligned_union: I think it's better to keep these using the preferred alignment, especially considering that aligned_storage_t<sizeof(max_align_t)> would be under aligned if we didn't (Thanks to how GCC and Clang define max_align_t).
  4. Manually aligned STL internals (such as in std::array or std::any). These should switch to use alignof (as if we had been using it all along). If this breaks users ABI's, they should use the Clang flag.

I think I'll iterate by introducing _LIBCPP_PREFERRED_ALIGNOF to service instances of (3) while using _LIBCPP_ALIGNOF for cases (1), (2), and (4).

EricWF reopened this revision.Dec 11 2018, 2:38 PM

Reopening with new approach.

This is all awful, but it seems to work.

This revision is now accepted and ready to land.Dec 11 2018, 2:38 PM
EricWF updated this revision to Diff 177788.Dec 11 2018, 2:39 PM

Introduce _LIBCPP_PREFERRED_ALIGNOF for cases where preferred alignment is needed.

ldionne accepted this revision.Dec 12 2018, 8:38 AM
This revision was automatically updated to reflect the committed changes.