https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121376

--- Comment #3 from Halalaluyafail3 <luigighiron at gmail dot com> ---
(In reply to Joseph S. Myers from comment #2)
> C23 says "Any attempt to modify an object with temporary lifetime results in
> undefined behavior.", so this test does not demonstrate a bug. It also says
> "Such an object may not have a unique address.", and the Proposed Committee
> Response in issue 0452, as linked from that LLVM issue, says 'To the
> question "Should the expression (O, o2).ca == o2.ca yield zero, non-zero, or
> should it be implementation defined?" the answer is "implementation
> defined".', which appears to indicate an intent that it's not unique with
> respect to objects with non-temporary lifetime, not just with respect to
> other objects with temporary lifetime (although it looks "unspecified" not
> "implementation-defined" to me). So even if there were a test based on
> comparing addresses rather than modifying an object with temporary lifetime,
> I don't think it would demonstrate a bug,
If this interpretation is correct, then can't the temporary object share
addresses with any object? For example:

#include<errno.h>
int main(){
    struct{int x[1];}x={};
    int*p;
    return p=(0,x).x,errno=1,*p;
}

Could this be UB because errno=1 modifies the temporary object? Here is another
example:

#include<string.h>
int main(){
    int a=0;
    struct{int x[1];}x={};
    int*p;
    return p=(0,x).x,memcpy(&a,p,sizeof(int)),*p;
}

Could this be UB because the temporary object and a share the same address
violating the aliasing restriction of memcpy? Furthermore, what if the
temporary object isn't even read from:

int main(){
    struct{int x[1];}x={};
    int*p;
    return p=(0,x).x,*x.x=1,0;
}

Further reduced:

int main(){
    struct{int x[1];}x={};
    return(0,x).x,*x.x=1,0;
}

Does the mere existence of a temporary object create undefined behavior if
another object exists with sufficient alignment and the same bit pattern (so
the addresses can be shared) and gets modified during the existence of the
temporary object? Here is another example:

struct foo{char str[4];};
struct foo bar(){
    return(struct foo){"abc"};
}
int baz(const char*p){
    int x=0;
    return x;
}
int main(){
    return baz(bar().str);
}

bar().str doesn't have a unique address, and at the start of the call of baz x
has an indeterminate value. So if the implementation chooses the correct bit
pattern of x and the alignment of the temporary object is sufficient for int
then p and &x can share the same address. If that happens, then the
initialization of x will modify the temporary object causing undefined
behavior.

As far as a I understand, if the interpretation in DR452 is correct then even
simple uses such as:

#include<stdio.h>
struct X{char x[32];};
struct X get(){
    return(struct X){"a string"};
}
int main(){
    puts(get().x);
}

Would be undefined behavior.

Reply via email to