Date: Fri, 16 Oct 2026 11:39:25 +0200
pt., 16 paź 2026 o 11:17 jim x via Std-Discussion
<std-discussion_at_[hidden]> napisał(a):
>
> 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?
>
`(sizeof(int) - X)` is implementation defined
`1024 / ???` is UB when you divide by zero
We can combine both to have UBID: implementation effectively decides
if a given operation is Undefined behavior and this is different to
Defined behavior by the same implementation.
This is similar to how big the call stack can be. Same program can run
fine one one implementation but on the other it will make stack
overflow and crash the whole system (as there is no memory
protection).
As I previously said your job is to check for zero there to have a
portable program to any implementation as `sizeof` has a specific
range of allowed values and YOU need to handle all of them.
> 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
>
> --
> Std-Discussion mailing list
> Std-Discussion_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
<std-discussion_at_[hidden]> napisał(a):
>
> 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?
>
`(sizeof(int) - X)` is implementation defined
`1024 / ???` is UB when you divide by zero
We can combine both to have UBID: implementation effectively decides
if a given operation is Undefined behavior and this is different to
Defined behavior by the same implementation.
This is similar to how big the call stack can be. Same program can run
fine one one implementation but on the other it will make stack
overflow and crash the whole system (as there is no memory
protection).
As I previously said your job is to check for zero there to have a
portable program to any implementation as `sizeof` has a specific
range of allowed values and YOU need to handle all of them.
> 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
>
> --
> Std-Discussion mailing list
> Std-Discussion_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
Received on 2026-10-16 09:39:41
