3047. atomic compound assignment operators can cause undefined behavior when corresponding fetch_meow members don't

Section: 32.6.2 [atomics.types.int], 32.6.4 [atomics.types.pointer], 32.6.5 [atomics.types.memop] Status: New Submitter: Tim Song Opened: 2017-12-15 Last modified: 2017-12-16

Priority: Not Prioritized

View all issues with New status.

Discussion:

Given atomic<int> meow{INT_MAX};, meow.fetch_add(1) has well-defined behavior because 32.6.2 [atomics.types.int] p7 says that

Remarks: For signed integer types, arithmetic is defined to use two's complement representation. There are no undefined results.

but meow += 1 and ++meow have undefined behavior, because these operator functions are defined (by, respectively, 32.6.2 [atomics.types.int] p8 and 32.6.5 [atomics.types.memop]) to be equivalent to return fetch_add(1) + 1;, and so the addition of 1 to the result of fetch_add — which causes an integer overflow in this case — occurs outside the protection of fetch_add magic. Additionally, the return value might differ from what fetch_add actually wrote since that addition isn't required to use two's complement. This seems like a trap for the unwary. Is it intended?

A similar issue affects the atomic<T*> partial specialization for pointers.

Proposed resolution: