Discussion:
Anonymous union object lifetime
(too old to reply)
Language Lawyer
2018-08-31 05:37:33 UTC
Permalink
[class.union.anon]/1: For the purpose of name lookup, after the anonymous union definition, the members of the anonymous union are considered to have been defined in the scope in which the anonymous union is declared.


But it is unclear if the "name" of an unnamed object is used to access its members, at least conceptually.

The question comes from the following example:

void f() {
union { int i; double d; };
new (&i) float; // 1
i = 1; // 2
}

Is line 2 defined after line 1?
There is no float member subobject in the union, so the lifetime of the unnamed union object ends because its storage is reused by an object not nested within it.
Is it allowed to access its members after? For named objects, after its lifetime is ended, using the name to access data members results in UB. But for unnamed object it is not clear.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Nathan Ernst
2018-08-31 16:47:27 UTC
Permalink
I don't think this is well defined. As you said, there is no float member
defined. Further, you're trying to do a placement new on a int with a float
- also not allowed. Certainly doesn't work on my compiler:

g++ --version
g++ (Ubuntu 4.8.4-2ubuntu1~14.04.4) 4.8.4

g++ -std=c++1y test.cpp
test.cpp: In function ‘void f()’:
test.cpp:3:11: error: no matching function for call to ‘operator
new(sizetype, int*)’
new (&i) float; // 1
^
test.cpp:3:11: note: candidate is:
<built-in>:0:0: note: void* operator new(long unsigned int)
<built-in>:0:0: note: candidate expects 1 argument, 2 provided

I get the same error if I eliminate the union and just have:

void f() {
int i;
new (&i) float; // 1
i = 1; // 2
}

test.cpp: In function ‘void f()’:
test.cpp:3:11: error: no matching function for call to ‘operator
new(sizetype, int*)’
new (&i) float; // 1
^
test.cpp:3:11: note: candidate is:
<built-in>:0:0: note: void* operator new(long unsigned int)
<built-in>:0:0: note: candidate expects 1 argument, 2 provided
Post by Language Lawyer
[class.union.anon]/1: For the purpose of name lookup, after the anonymous
union definition, the members of the anonymous union are considered to have
been defined in the scope in which the anonymous union is declared.
But it is unclear if the "name" of an unnamed object is used to access its
members, at least conceptually.
void f() {
union { int i; double d; };
new (&i) float; // 1
i = 1; // 2
}
Is line 2 defined after line 1?
There is no float member subobject in the union, so the lifetime of the
unnamed union object ends because its storage is reused by an object not
nested within it.
Is it allowed to access its members after? For named objects, after its
lifetime is ended, using the name to access data members results in UB. But
for unnamed object it is not clear.
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
https://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Language Lawyer
2018-08-31 16:54:05 UTC
Permalink
You just forgot to #include <new>
Post by Nathan Ernst
I don't think this is well defined. As you said, there is no float member
defined. Further, you're trying to do a placement new on a int with a float
g++ --version
g++ (Ubuntu 4.8.4-2ubuntu1~14.04.4) 4.8.4
g++ -std=c++1y test.cpp
test.cpp:3:11: error: no matching function for call to ‘operator
new(sizetype, int*)’
new (&i) float; // 1
^
<built-in>:0:0: note: void* operator new(long unsigned int)
<built-in>:0:0: note: candidate expects 1 argument, 2 provided
void f() {
int i;
new (&i) float; // 1
i = 1; // 2
}
test.cpp:3:11: error: no matching function for call to ‘operator
new(sizetype, int*)’
new (&i) float; // 1
^
<built-in>:0:0: note: void* operator new(long unsigned int)
<built-in>:0:0: note: candidate expects 1 argument, 2 provided
Post by Language Lawyer
[class.union.anon]/1: For the purpose of name lookup, after the anonymous
union definition, the members of the anonymous union are considered to have
been defined in the scope in which the anonymous union is declared.
But it is unclear if the "name" of an unnamed object is used to access its
members, at least conceptually.
void f() {
union { int i; double d; };
new (&i) float; // 1
i = 1; // 2
}
Is line 2 defined after line 1?
There is no float member subobject in the union, so the lifetime of the
unnamed union object ends because its storage is reused by an object not
nested within it.
Is it allowed to access its members after? For named objects, after its
lifetime is ended, using the name to access data members results in UB. But
for unnamed object it is not clear.
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
https://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Language Lawyer
2018-09-02 09:33:35 UTC
Permalink
Post by Language Lawyer
[class.union.anon]/1: For the purpose of name lookup, after the anonymous union definition, the members of the anonymous union are considered to have been defined in the scope in which the anonymous union is declared.
But it is unclear if the "name" of an unnamed object is used to access its members, at least conceptually.
I think the intent is that it is used, because otherwise the lifetime of an anonymous union members won't start implicitly, as described below.

[class.union]/5: When the left operand of an assignment operator involves a member access expression ([expr.ref]) that nominates a union member, it may begin the lifetime of that union member, as described below. For an expression E, define the set S(E) of subexpressions of E as follows:
— If E is of the form A.B, S(E) contains the elements of S(A), and also contains A.B if B names a union member of a non-class, non-array type, or of a class type with a trivial default constructor that is not deleted, or an array of such types.
— If E is of the form A[B] and is interpreted as a built-in array subscripting operator, S(E) is S(A) if A is of array type, S(B) if B is of array type, and empty otherwise.
— Otherwise, S(E) is empty.
In an assignment expression of the form E1 = E2 that uses either the built-in assignment operator ([expr.ass]) or a trivial assignment operator ([class.copy.assign]), for each element X of S(E1), if modification of X would have undefined behavior under [basic.life], an object of the type of X is implicitly created in the nominated storage;

[class.union.anon]/1 has an example:
void f() {
union { int a; const char* p; };
a = 1;
p = "Jennifer";
}

In `p = "Jennifer"`, E1 is `p`. It should count as an expression of the form A.B to implicitly start the lifetime of `p`!
Post by Language Lawyer
void f() {
    union { int i; double d; };
    new (&i) float; // 1
    i = 1;          // 2
}
Is line 2 defined after line 1?
There is no float member subobject in the union, so the lifetime of the unnamed union object ends because its storage is reused by an object not nested within it.
Is it allowed to access its members after? For named objects, after its lifetime is ended, using the name to access data members results in UB. But for unnamed object it is not clear.
Let's eat the elephant one bite at a time.
Post by Language Lawyer
For named objects, after its lifetime is ended, using the name to access data members results in UB.
[class.cdtor]/1 says that it is true only for objects with non-trivial destructor. Strictly speaking, I was wrong.

As for `i = 1;`, [class.union]/5 says that "an object of the type of X is implicitly created in the nominated storage".
Sounds like it is not necessary for a union object (named or unnamed) to be alive, only the storage it occupies (used to occupy) has not to be released.

Dunno how to feel about such a sloppiness.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Language Lawyer
2018-09-02 10:55:55 UTC
Permalink
Post by Language Lawyer
[class.union.anon]/1: For the purpose of name lookup, after the anonymous union definition, the members of the anonymous union are considered to have been defined in the scope in which the anonymous union is declared.
But it is unclear if the "name" of an unnamed object is used to access its members, at least conceptually.
Ah, there is http://wg21.link/cwg1801 which asks this question about a global anonymous union.
I think it is applicable to non-class scoped anonymous unions.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Continue reading on narkive:
Loading...