Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does reading to another variant member of a union that has the same type as the active variant cause UB?

union A{
  int a;
  int b;
};
int main(){
  A u = {.a = 0};
  int r = u.b; // #1 Is this UB?
}

[class.union] says

In a union, a non-static data member is active if its name refers to an object whose lifetime has begun and has not ended ([basic.life]). At most one of the non-static data members of an object of union type can be active at any time, that is, the value of at most one of the non-static data members can be stored in a union at any time.

In this example, only A::a is active, then [basic.life] p7 says

The program has undefined behavior if:

  • the glvalue is used to access the object, or

#1 tries to access the object whose lifetime has not begun. Does this access cause UB, if it is, is this requirement too restrictive?

BTW, Does the C standard impose the same requirement in this example? Or, Does C have a looser requirement in this case?

Update

In C standard, I find a note, which says

If the member used to read the contents of a union object is not the same as the member last used to store a value in the object the appropriate part of the object representation of the value is reinterpreted as an object representation in the new type as described in 6.2.6 (a process sometimes called type punning). This might be a non-value representation.

This means it is permitted in C. However, https://eel.is/c++draft/diff.iso

Subclause [diff.iso] lists the differences between C++ and ISO C, in addition to those listed above, by the chapters of this document.

does not point out the difference.

like image 334
xmh0511 Avatar asked Nov 23 '25 08:11

xmh0511


1 Answers

I think in C++ this is undefined behavior per the first standard quotation in the question itself: there is no exception there for the case of same types of data members.

And major compilers seem to agree with this reading, disallowing such code in constant expressions:

union A{
  int a;
  int b;
};

constexpr int f() {
  A u = {.a = 0};
  return u.b;
}

constexpr int x = f();

Online demo: https://gcc.godbolt.org/z/We4zYzdaa

Clang's error:

read of member 'b' of union with active member 'a' is not allowed in a constant expression

GCC's error:

accessing 'A::b' member instead of initialized 'A::a' member in constant expression

MSVC's error:

failure was caused by accessing a non-active member of a union
like image 116
Fedor Avatar answered Nov 25 '25 20:11

Fedor



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!