LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 40977 - Wrong static_assert on type of underlying_type<memory_order>
Summary: Wrong static_assert on type of underlying_type<memory_order>
Status: RESOLVED FIXED
Alias: None
Product: libc++
Classification: Unclassified
Component: All Bugs (show other bugs)
Version: unspecified
Hardware: PC Linux
: P release blocker
Assignee: Louis Dionne
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-03-06 07:14 PST by Diogo Sampaio
Modified: 2019-03-06 09:08 PST (History)
3 users (show)

See Also:
Fixed By Commit(s): r355521


Attachments
Small reproducer (926 bytes, text/plain)
2019-03-06 07:14 PST, Diogo Sampaio
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Diogo Sampaio 2019-03-06 07:14:41 PST
Created attachment 21570 [details]
Small reproducer

In the file include/atomic

typedef enum memory_order {
  memory_order_relaxed, memory_order_consume, memory_order_acquire,
  memory_order_release, memory_order_acq_rel, memory_order_seq_cst
} memory_order;

static_assert((is_same<underlying_type<memory_order>::type,
unsigned>::value), "Underlying type differs from unsigned unexpectedly");

when compiling with "g++ -std=c++11 -fshort-enums"
the underlying type reduces to unsigned char, and the assert fails.

--
A quick fix would be set the last value to something that won't fit in a uchar...

memory_order_seq_cst = 0xFFFFFFFF
Comment 1 Marshall Clow (home) 2019-03-06 08:30:33 PST
We just changed this for C++20 - changed to an enum class with an underlying type.
Still a problem for C++17 and before.

I think the question that needs answering is:
Should the size of a memory_order change when `-fshort-enums` is specified?

It's clearly NOT going to change when compiling for C++20.
Comment 2 Louis Dionne 2019-03-06 08:38:34 PST
IOW, we used not to specify an underlying type for this enumeration. Hence, the underlying type of the enumeration was `unsigned int` normally, and `unsigned char` when `-fshort-enums` was used.

By specifying an underlying type in C++20, we are forcing the underlying type to be `unsigned int` regardless of `-fshort-enums`. This is technically an ABI break for users of `-fshort-enums`.

I'm not sure we care about that specific ABI break because I don't think anyone that is using -fshort-enums is realistically relying on the size of the memory_order enumeration. However, I would still be tempted to remove the underlying type since it does not really buy us much. It creates a discrepancy between the C++20 and the non-C++20 versions, and it doesn't actually allow us to know what size the enum is since we're using `unsigned int` as opposed to a fixed-width type.

Furthermore, http://wg21.link/p0439 (the paper that made memory_order a scoped enumeration) said:

> In order to maintain binary compatibility the underlying type of the scoped enumeration type should be left unspecified, so that implementations can set it to match the underlying type that was previously chosen (either implicitly or explicitly) for the unscoped enumeration type.

I think we should just leave it unspecified.
Comment 3 Louis Dionne 2019-03-06 08:54:29 PST
I implemented my proposed fix here: https://reviews.llvm.org/D59029
Comment 4 Louis Dionne 2019-03-06 09:08:02 PST
Should be fixed in r355521.