Date: Sat, 26 Apr 2025 21:44:00 +0100
>But I am not able to find what "the same function" actually means.
It isn't explicitly defined in the standard, it's normative.
>For example:
>
>extern "C"{
>void foo();
>void bar();
>}
>
>// in cpp file
>void foo() __attribute__((alias("bar")));
You're using a non-standard attribute, so you won't find anything that can help you in the standard. As far as the standard is concerned it's not possible to create an alias. The semantics of what alias means is up to the implementation that is providing the attribute.
As far as the standard is concerned there's also no other languages, or optimising linkers, or compiler options. As soon as you are talking about how C++ interacts with things that are not defined in the standard you're off the edge of the standardisation map.
On 26 April 2025 19:24:27 BST, Federico Kircheis via Std-Discussion <std-discussion_at_[hidden]> wrote:
>On 26/04/2025 7:34 pm, Andrey Semashev via Std-Discussion wrote:
>> On 26 Apr 2025 20:17, Nate Eldredge via Std-Discussion wrote:
>>>
>>>
>>>> On Apr 26, 2025, at 10:22, Federico Kircheis via Std-Discussion <std-
>>>> discussion_at_[hidden]> wrote:
>>>>
>>>> On 26/04/2025 4:05 pm, mauro russo wrote:
>>>>>
>>>>
>>>>>> * if different function can have the same address, the class if
>>>>>> broken, (the lifetime of the previous object did not end correctly)
>>>>> This should be something never happening. It cannot make sense
>>>>> to have different functions at the same address.
>>>>
>>>> IMHO it makes sense that
>>>>
>>>> void foo(){}
>>>> void bar(){}
>>>>
>>>> can have the same address, similarly to how identical string literals
>>>> can have the same address; I was not sure if such optimization was
>>>> allowed.
>>>
>>> I think it's forbidden by expr.eq p3.2-3.3 (https://eel.is/c++draft/
>>> expr.eq#3.2 <https://eel.is/c++draft/expr.eq#3.2>). Two function
>>> pointers compare equal if and only if they "point to the same function".
>>> I think it's clear that foo() and bar() are not "the same function",
>>> even if they perform the same behavior.
>
>
>I guess its clear if being "the same function" means having the same function signature, in the same namespace, and name.
>But I am not able to find what "the same function" actually means.
>Maybe I'm too pedantic?
>What about functions that are declared in C++ and implemented in another language? For example, with the linker it is possible to create aliases:
>
>For example:
>
>extern "C"{
>void foo();
>void bar();
>}
>
>// in cpp file
>void foo() __attribute__((alias("bar")));
>
>I would expect those to have the same address, even if the names or even namespaces are different.
>
>>> String literals have an explicit exemption from this rule per
>>> intro.object p9 (https://eel.is/c++draft/intro.object#9 <https://eel.is/
>>> c++draft/intro.object#9>).
>>>
>>> Somewhat related, clang does a "controversial" optimization where, if a
>>> function would unconditionally cause UB if called, the compiler emits a
>>> label for it but no code, not even a return instruction. As such, the
>>> next function compiled can end up at the same address. See https://
>>> godbolt.org/z/775s6e4vv for an example.
>>> This does seem like a clear violation of expr.eq p3, but it's
>>> been unfixed for a long time.
>
>Oh, that's bad since the function with UB is never called...
>Strangely removing volatile helps.
>
>>> So if the situation for lambdas is different, it must be something specific to them.
>
>
>Ignoring what I wrote about function and the meaning of "the same function", I guess a lambda with static operator() could be implemented by the compiler as a wrapper to a function pointer, and multiple lambda (if the body is the same) would point to the same function.
>At least I currently see nothing that prohibits such implementation/behavior.
>
>> While the standard is pretty clear that two pointers to a function shall
>> only compare equal if they point to the same function, the rule has been
>> violated by compilers rather often. In both ways. For example, two
>> pointers to the same function may compare unequal if the function ends
>> up compiled in different shared objects with local visibility (e.g. if
>> the function is defined in a header that gets included in both shared
>> objects during compilation). And some compilers (MSVC, possibly others)
>> also implement an optimization to merge equivalent bodies of different
>> functions in the compiled binary, thus reducing the binary size. This
>> would result in addresses of foo and bar defined above to compare equal.
>
>I could remember something with msvc, but was not sure anymore and since I was not able to create an example, I thought I misremembered.
>Since from the standard I could not find a clear answer, here I am.
>
>I think it cannot be avoided that a function has multiple addresses when using shared libraries.
>Since those are not specified, it is obviously a grey area.
>
>I was more concerned about different functions having the same address, especially if there is no way to opt-out from this behavior (which would be compiler specific).
>
>> The point is, even if the standard guarantees this, it's probably not a
>> good idea to rely on this in practice.
>
>So it seems my concerns are not too far-fetched, even without talking about function pointer created by lambdas:
>
> * function bodies are not identical
> * intermediate (and valid) compiler optimization makes function body identical (removes dependency on T)
> * linker optimization (valid or not, happens in practice) merges two functions with the same behavior together
> * code that relies on equality/inequality misbehaves
>
>Damn.
It isn't explicitly defined in the standard, it's normative.
>For example:
>
>extern "C"{
>void foo();
>void bar();
>}
>
>// in cpp file
>void foo() __attribute__((alias("bar")));
You're using a non-standard attribute, so you won't find anything that can help you in the standard. As far as the standard is concerned it's not possible to create an alias. The semantics of what alias means is up to the implementation that is providing the attribute.
As far as the standard is concerned there's also no other languages, or optimising linkers, or compiler options. As soon as you are talking about how C++ interacts with things that are not defined in the standard you're off the edge of the standardisation map.
On 26 April 2025 19:24:27 BST, Federico Kircheis via Std-Discussion <std-discussion_at_[hidden]> wrote:
>On 26/04/2025 7:34 pm, Andrey Semashev via Std-Discussion wrote:
>> On 26 Apr 2025 20:17, Nate Eldredge via Std-Discussion wrote:
>>>
>>>
>>>> On Apr 26, 2025, at 10:22, Federico Kircheis via Std-Discussion <std-
>>>> discussion_at_[hidden]> wrote:
>>>>
>>>> On 26/04/2025 4:05 pm, mauro russo wrote:
>>>>>
>>>>
>>>>>> * if different function can have the same address, the class if
>>>>>> broken, (the lifetime of the previous object did not end correctly)
>>>>> This should be something never happening. It cannot make sense
>>>>> to have different functions at the same address.
>>>>
>>>> IMHO it makes sense that
>>>>
>>>> void foo(){}
>>>> void bar(){}
>>>>
>>>> can have the same address, similarly to how identical string literals
>>>> can have the same address; I was not sure if such optimization was
>>>> allowed.
>>>
>>> I think it's forbidden by expr.eq p3.2-3.3 (https://eel.is/c++draft/
>>> expr.eq#3.2 <https://eel.is/c++draft/expr.eq#3.2>). Two function
>>> pointers compare equal if and only if they "point to the same function".
>>> I think it's clear that foo() and bar() are not "the same function",
>>> even if they perform the same behavior.
>
>
>I guess its clear if being "the same function" means having the same function signature, in the same namespace, and name.
>But I am not able to find what "the same function" actually means.
>Maybe I'm too pedantic?
>What about functions that are declared in C++ and implemented in another language? For example, with the linker it is possible to create aliases:
>
>For example:
>
>extern "C"{
>void foo();
>void bar();
>}
>
>// in cpp file
>void foo() __attribute__((alias("bar")));
>
>I would expect those to have the same address, even if the names or even namespaces are different.
>
>>> String literals have an explicit exemption from this rule per
>>> intro.object p9 (https://eel.is/c++draft/intro.object#9 <https://eel.is/
>>> c++draft/intro.object#9>).
>>>
>>> Somewhat related, clang does a "controversial" optimization where, if a
>>> function would unconditionally cause UB if called, the compiler emits a
>>> label for it but no code, not even a return instruction. As such, the
>>> next function compiled can end up at the same address. See https://
>>> godbolt.org/z/775s6e4vv for an example.
>>> This does seem like a clear violation of expr.eq p3, but it's
>>> been unfixed for a long time.
>
>Oh, that's bad since the function with UB is never called...
>Strangely removing volatile helps.
>
>>> So if the situation for lambdas is different, it must be something specific to them.
>
>
>Ignoring what I wrote about function and the meaning of "the same function", I guess a lambda with static operator() could be implemented by the compiler as a wrapper to a function pointer, and multiple lambda (if the body is the same) would point to the same function.
>At least I currently see nothing that prohibits such implementation/behavior.
>
>> While the standard is pretty clear that two pointers to a function shall
>> only compare equal if they point to the same function, the rule has been
>> violated by compilers rather often. In both ways. For example, two
>> pointers to the same function may compare unequal if the function ends
>> up compiled in different shared objects with local visibility (e.g. if
>> the function is defined in a header that gets included in both shared
>> objects during compilation). And some compilers (MSVC, possibly others)
>> also implement an optimization to merge equivalent bodies of different
>> functions in the compiled binary, thus reducing the binary size. This
>> would result in addresses of foo and bar defined above to compare equal.
>
>I could remember something with msvc, but was not sure anymore and since I was not able to create an example, I thought I misremembered.
>Since from the standard I could not find a clear answer, here I am.
>
>I think it cannot be avoided that a function has multiple addresses when using shared libraries.
>Since those are not specified, it is obviously a grey area.
>
>I was more concerned about different functions having the same address, especially if there is no way to opt-out from this behavior (which would be compiler specific).
>
>> The point is, even if the standard guarantees this, it's probably not a
>> good idea to rely on this in practice.
>
>So it seems my concerns are not too far-fetched, even without talking about function pointer created by lambdas:
>
> * function bodies are not identical
> * intermediate (and valid) compiler optimization makes function body identical (removes dependency on T)
> * linker optimization (valid or not, happens in practice) merges two functions with the same behavior together
> * code that relies on equality/inequality misbehaves
>
>Damn.
Received on 2025-04-26 20:44:07