Date: Fri, 16 Oct 2026 17:16:48 +0800
Of course, an implementation need not specify the semantics as if they were
atomic. However, since the semantics are implementation-defined, a
hypothetical implementation are free to do that. Now, consider a simpler
similar example:
````cpp
constexpr size_t X = 32;
int n = 1024 / (sizeof(int) - X); // A
````
Now, what is the behavior of the program? Since sizeof(int) is
implementation-defined, you cannot say the operation at `A` is definitely
undefined behavior. From the perspective of the C++ standard, is this
program implementation-defined behavior or undefined behavior?
On Fri, Oct 16, 2026 at 11:49 AM Julien Villemure-Fréchette via
Std-Discussion <std-discussion_at_[hidden]> wrote:
> > I think the wording should be rephrased to embody the meaning that the
> operations at `#1` and `#2` are non-atomic regardless of how the
> implementations give the semantics; for example, these operations are
> deemed non-atomic even though the implementation specifies them as
> std::atomic_ref::load() / store() for their semantics.
>
> An important point that needs to be said to make sure we are on the same
> page, is that nowhere the standard states the semantics of volatile access
> is to be defined in terms of atomic load/store.
>
> The main clause describing volatile access doesn't imply any behavior
> related to antomics.
>
> The clause 4.1.2.8 <https://eel.is/c++draft/intro.abstract#8.1>
>
> Accesses through volatile glvalues are
> evaluated strictly according to the rules
> of the abstract machine.
>
> This doesn't mean volatile access must be implemented with atomic
> operations or somewhat emulate such.
>
>
> ------------------------------
> *From:* jim x via Std-Discussion <std-discussion_at_[hidden]>
> *Sent:* October 15, 2026 5:50:09 a.m. EDT
> *To:* Tiago Freire <tmiguelf_at_[hidden]>
> *Cc:* jim x <xmh970252187_at_[hidden]>, "std-discussion_at_[hidden]" <
> std-discussion_at_[hidden]>
> *Subject:* Re: [std-discussion] Is this program undefined-behavior or
> implementation-defined behavior?
>
> If yes, then I think we already explained why we can’t make data-races
>> with volatile to be implementation-defined, because that would force the
>> implementation to pick a behavior with quite negative consequences, and we
>> don’t want that.
>
>
> I agree that the behavior of the program in my question should be intended
> to be undefined behavior. What I don't agree with is that the wording in
> the current standard is clear enough to help us infer that the program
> contains a data race, especially since the standard doesn't formally define
> the term "atomic" appearing in [intro.race] p17.
>
> I think the wording should be rephrased to embody the meaning that the
> operations at `#1` and `#2` are *non-atomic* regardless of how the
> implementations give the semantics; for example, these operations are
> deemed non-atomic even though the implementation specifies them as
> std::atomic_ref::load() / store() for their semantics.
>
>
>
> On Thu, Oct 15, 2026 at 3:26 PM Tiago Freire <tmiguelf_at_[hidden]> wrote:
>
>> If an implementation makes volatile to have the same semantics as an
>> atomic, then I would expect that in that implementation volatile would have
>> the same properties as an atomic.
>>
>> Not that this helps anyone in any way, as if I was to write code that
>> needed to rely on the specific implementation of volatile = atomic, I would
>> have just used atomic in the first place.
>>
>>
>>
>> Also note that the consequences are irrelevant to the original example
>> (source code) you provided would still have an undetermined result even
>> with atomics.
>>
>>
>>
>> What is the point of all of this anyways? Are you trying to change the
>> text?
>>
>>
>>
>> If yes, then I think we already explained why we can’t make data-races
>> with volatile to be implementation-defined, because that would force the
>> implementation to pick a behavior with quite negative consequences, and we
>> don’t want that. And if you think this observation is not quite correct,
>> then I think you need to properly formalize a proposal, because nobody
>> seems to agree with you in this informal email exchange format. Maybe we
>> don’t get it, and the devil is in the details, and you need to be very
>> specific about it.
>>
>>
>>
>> If no, then what is the point of this conversation?
>>
>>
>>
>>
>>
>> *From:* Std-Discussion <std-discussion-bounces_at_[hidden]> *On
>> Behalf Of *jim x via Std-Discussion
>> *Sent:* Thursday, October 15, 2026 07:40
>> *To:* Thiago Macieira <thiago_at_[hidden]>
>> *Cc:* jim x <xmh970252187_at_[hidden]>; std-discussion_at_[hidden]
>> *Subject:* Re: [std-discussion] Is this program undefined-behavior or
>> implementation-defined behavior?
>>
>>
>>
>> I don't think that there's anywhere that an IB choice can make what is
>> otherwise UB not so.
>>
>>
>>
>> If the standard deems a program to have undefined behavior, then
>> regardless of how an implementation guarantees its specific behavior, the
>> program is undefined from the perspective of the standard—there is no
>> dispute about this. However, the crux of the problem is that ambiguity
>> arises in the very process of applying the standard's rules to determine
>> whether the program is undefined in the first place.
>>
>> The premise of your claim that the program in my question is undefined is
>> that it contains a data race, and whether a program contains a data race is
>> determined by the rules in *[intro.race] p17*. One of the conditions in
>> paragraph 17 is *"at least one of which is not atomic"*—if both
>> operations are atomic, then no data race exists. Meanwhile, another rule in
>> the standard states: *"The semantics of an access through a volatile
>> glvalue are implementation-defined"*, which means the semantics of the
>> access depend on the specific implementation and serve as an open parameter
>> within the abstract machine.
>>
>> The question, then, is this: if an implementation defines these
>> operations to be identical to std::atomic_ref::load() / store(), does
>> the condition *"at least one of which is not atomic"* in [intro.race]
>> p17 evaluate to false? In that case, is the program still undefined? This
>> is the core issue, whereas your initial claim that the program is simply
>> undefined completely skipped the process of determining whether a data race
>> actually exists.
>>
>>
>>
>>
>>
>> On Thu, Oct 15, 2026 at 1:24 PM Thiago Macieira <thiago_at_[hidden]>
>> wrote:
>>
>> On Wednesday, 14 October 2026 22:15:52 Pacific Daylight Time jim x wrote:
>> > But my question isn't about implementation conformance; that is, I
>> didn't
>> > ask whether a conforming implementation can specify a concrete behavior
>> for
>> > the undefined behavior program; of course, it can. I'm asking what the
>> > program's behavior should be, given the current wording, within the
>> scope
>> > the standard leaves to implementations to define the semantics of
>> access.
>>
>> The problem here is what you're assuming can be implementation-defined.
>> There
>> are a few things the Standard requires implementations make a choice,
>> document, and stick to it, which we call "implementation-defined
>> behaviour". IB
>> is never UB. I don't think that there's anywhere that an IB choice can
>> make
>> what is otherwise UB not so.
>>
>> And then there's UB, which an implementation can, if it wants to, make
>> defined.
>> It does not need to document it, but it can too. But making such choices
>> does
>> not change the Standard. From its point of view, it's still UB.
>>
>> > In other words, since the premise based on which we say the program is
>> > undefined is that the program contains a data race as per [intro.race]
>> p17,
>> > which depends on whether the condition "at least one of which is not
>> > atomic" is true, the current wording is unclear about whether the
>> > operations at `#1` and `#2` are non-atomic even if the implementations
>> > define the semantics as being equivalent to
>> > `std::atomic_ref::load()/store()`.
>>
>> There is a data race from the Standard's point of view.
>>
>> If this implementation chose to implement the particular access in
>> question
>> atomically, then in this implementation there would be no data race. But
>> it
>> does not change the Standard: it's still UB from its point of view.
>>
>> --
>> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
>> Principal Engineer - Intel Data Center - Platform & Sys. Eng.
>>
>> -- Julien Villemure
> Sent from my Android device with K-9 Mail.
> --
> Std-Discussion mailing list
> Std-Discussion_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>
atomic. However, since the semantics are implementation-defined, a
hypothetical implementation are free to do that. Now, consider a simpler
similar example:
````cpp
constexpr size_t X = 32;
int n = 1024 / (sizeof(int) - X); // A
````
Now, what is the behavior of the program? Since sizeof(int) is
implementation-defined, you cannot say the operation at `A` is definitely
undefined behavior. From the perspective of the C++ standard, is this
program implementation-defined behavior or undefined behavior?
On Fri, Oct 16, 2026 at 11:49 AM Julien Villemure-Fréchette via
Std-Discussion <std-discussion_at_[hidden]> wrote:
> > I think the wording should be rephrased to embody the meaning that the
> operations at `#1` and `#2` are non-atomic regardless of how the
> implementations give the semantics; for example, these operations are
> deemed non-atomic even though the implementation specifies them as
> std::atomic_ref::load() / store() for their semantics.
>
> An important point that needs to be said to make sure we are on the same
> page, is that nowhere the standard states the semantics of volatile access
> is to be defined in terms of atomic load/store.
>
> The main clause describing volatile access doesn't imply any behavior
> related to antomics.
>
> The clause 4.1.2.8 <https://eel.is/c++draft/intro.abstract#8.1>
>
> Accesses through volatile glvalues are
> evaluated strictly according to the rules
> of the abstract machine.
>
> This doesn't mean volatile access must be implemented with atomic
> operations or somewhat emulate such.
>
>
> ------------------------------
> *From:* jim x via Std-Discussion <std-discussion_at_[hidden]>
> *Sent:* October 15, 2026 5:50:09 a.m. EDT
> *To:* Tiago Freire <tmiguelf_at_[hidden]>
> *Cc:* jim x <xmh970252187_at_[hidden]>, "std-discussion_at_[hidden]" <
> std-discussion_at_[hidden]>
> *Subject:* Re: [std-discussion] Is this program undefined-behavior or
> implementation-defined behavior?
>
> If yes, then I think we already explained why we can’t make data-races
>> with volatile to be implementation-defined, because that would force the
>> implementation to pick a behavior with quite negative consequences, and we
>> don’t want that.
>
>
> I agree that the behavior of the program in my question should be intended
> to be undefined behavior. What I don't agree with is that the wording in
> the current standard is clear enough to help us infer that the program
> contains a data race, especially since the standard doesn't formally define
> the term "atomic" appearing in [intro.race] p17.
>
> I think the wording should be rephrased to embody the meaning that the
> operations at `#1` and `#2` are *non-atomic* regardless of how the
> implementations give the semantics; for example, these operations are
> deemed non-atomic even though the implementation specifies them as
> std::atomic_ref::load() / store() for their semantics.
>
>
>
> On Thu, Oct 15, 2026 at 3:26 PM Tiago Freire <tmiguelf_at_[hidden]> wrote:
>
>> If an implementation makes volatile to have the same semantics as an
>> atomic, then I would expect that in that implementation volatile would have
>> the same properties as an atomic.
>>
>> Not that this helps anyone in any way, as if I was to write code that
>> needed to rely on the specific implementation of volatile = atomic, I would
>> have just used atomic in the first place.
>>
>>
>>
>> Also note that the consequences are irrelevant to the original example
>> (source code) you provided would still have an undetermined result even
>> with atomics.
>>
>>
>>
>> What is the point of all of this anyways? Are you trying to change the
>> text?
>>
>>
>>
>> If yes, then I think we already explained why we can’t make data-races
>> with volatile to be implementation-defined, because that would force the
>> implementation to pick a behavior with quite negative consequences, and we
>> don’t want that. And if you think this observation is not quite correct,
>> then I think you need to properly formalize a proposal, because nobody
>> seems to agree with you in this informal email exchange format. Maybe we
>> don’t get it, and the devil is in the details, and you need to be very
>> specific about it.
>>
>>
>>
>> If no, then what is the point of this conversation?
>>
>>
>>
>>
>>
>> *From:* Std-Discussion <std-discussion-bounces_at_[hidden]> *On
>> Behalf Of *jim x via Std-Discussion
>> *Sent:* Thursday, October 15, 2026 07:40
>> *To:* Thiago Macieira <thiago_at_[hidden]>
>> *Cc:* jim x <xmh970252187_at_[hidden]>; std-discussion_at_[hidden]
>> *Subject:* Re: [std-discussion] Is this program undefined-behavior or
>> implementation-defined behavior?
>>
>>
>>
>> I don't think that there's anywhere that an IB choice can make what is
>> otherwise UB not so.
>>
>>
>>
>> If the standard deems a program to have undefined behavior, then
>> regardless of how an implementation guarantees its specific behavior, the
>> program is undefined from the perspective of the standard—there is no
>> dispute about this. However, the crux of the problem is that ambiguity
>> arises in the very process of applying the standard's rules to determine
>> whether the program is undefined in the first place.
>>
>> The premise of your claim that the program in my question is undefined is
>> that it contains a data race, and whether a program contains a data race is
>> determined by the rules in *[intro.race] p17*. One of the conditions in
>> paragraph 17 is *"at least one of which is not atomic"*—if both
>> operations are atomic, then no data race exists. Meanwhile, another rule in
>> the standard states: *"The semantics of an access through a volatile
>> glvalue are implementation-defined"*, which means the semantics of the
>> access depend on the specific implementation and serve as an open parameter
>> within the abstract machine.
>>
>> The question, then, is this: if an implementation defines these
>> operations to be identical to std::atomic_ref::load() / store(), does
>> the condition *"at least one of which is not atomic"* in [intro.race]
>> p17 evaluate to false? In that case, is the program still undefined? This
>> is the core issue, whereas your initial claim that the program is simply
>> undefined completely skipped the process of determining whether a data race
>> actually exists.
>>
>>
>>
>>
>>
>> On Thu, Oct 15, 2026 at 1:24 PM Thiago Macieira <thiago_at_[hidden]>
>> wrote:
>>
>> On Wednesday, 14 October 2026 22:15:52 Pacific Daylight Time jim x wrote:
>> > But my question isn't about implementation conformance; that is, I
>> didn't
>> > ask whether a conforming implementation can specify a concrete behavior
>> for
>> > the undefined behavior program; of course, it can. I'm asking what the
>> > program's behavior should be, given the current wording, within the
>> scope
>> > the standard leaves to implementations to define the semantics of
>> access.
>>
>> The problem here is what you're assuming can be implementation-defined.
>> There
>> are a few things the Standard requires implementations make a choice,
>> document, and stick to it, which we call "implementation-defined
>> behaviour". IB
>> is never UB. I don't think that there's anywhere that an IB choice can
>> make
>> what is otherwise UB not so.
>>
>> And then there's UB, which an implementation can, if it wants to, make
>> defined.
>> It does not need to document it, but it can too. But making such choices
>> does
>> not change the Standard. From its point of view, it's still UB.
>>
>> > In other words, since the premise based on which we say the program is
>> > undefined is that the program contains a data race as per [intro.race]
>> p17,
>> > which depends on whether the condition "at least one of which is not
>> > atomic" is true, the current wording is unclear about whether the
>> > operations at `#1` and `#2` are non-atomic even if the implementations
>> > define the semantics as being equivalent to
>> > `std::atomic_ref::load()/store()`.
>>
>> There is a data race from the Standard's point of view.
>>
>> If this implementation chose to implement the particular access in
>> question
>> atomically, then in this implementation there would be no data race. But
>> it
>> does not change the Standard: it's still UB from its point of view.
>>
>> --
>> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
>> Principal Engineer - Intel Data Center - Platform & Sys. Eng.
>>
>> -- Julien Villemure
> Sent from my Android device with K-9 Mail.
> --
> Std-Discussion mailing list
> Std-Discussion_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>
Received on 2026-10-16 09:17:04
