Date: Thu, 5 May 2022 09:01:47 -0400
Consider the following code which came to me via a user bug report:
struct foo {
const struct {
int bar;
};
} my_foo;
void baz(void) {
my_foo.bar = 42; // ???
}
Is the line of code marked ??? conforming or not? My claim is that it
is. However, compilers currently disagree, and the behavior that the
standard specifies seems rather surprising to me, so I'm wondering if
it's intentional or not.
6.7.2.1p15: An unnamed member whose type specifier is a structure
specifier with no tag is called an anonymous structure; an unnamed
member whose type specifier is a union specifier with no tag is called
an anonymous union. The members of an anonymous structure or union are
considered to be members of the containing structure or union, keeping
their structure or union layout. This applies recursively if the
containing structure or union is also anonymous.
6.5.2.3p3: 3 A postfix expression followed by the . operator and an
identifier designates a member of a structure or union object. The
value is that of the named member, and is an lvalue if the first
expression is an lvalue. If the first expression has qualified type,
the result has the so-qualified version of the type of the designated
member.
6.3.2.1p1: ... A modifiable lvalue is an lvalue that does not have
array type, does not have an incomplete type, does not have a
const-qualified type, and if it is a structure or union, does not have
any member (including, recursively, any member or element of all
contained aggregates or unions) with a const-qualified type.
6.5.16p2: An assignment operator shall have a modifiable lvalue as its
left operand.
I *think* what may have been intended is for 6.7.2.1p15 to instead say
something along the lines of: ... The members of an anonymous
structure or union are considered to be members of the containing
structure or union, keeping their structure or union layout <ins>and
the qualifiers specified for the unnamed member</ins>. ...
~Aaron
struct foo {
const struct {
int bar;
};
} my_foo;
void baz(void) {
my_foo.bar = 42; // ???
}
Is the line of code marked ??? conforming or not? My claim is that it
is. However, compilers currently disagree, and the behavior that the
standard specifies seems rather surprising to me, so I'm wondering if
it's intentional or not.
6.7.2.1p15: An unnamed member whose type specifier is a structure
specifier with no tag is called an anonymous structure; an unnamed
member whose type specifier is a union specifier with no tag is called
an anonymous union. The members of an anonymous structure or union are
considered to be members of the containing structure or union, keeping
their structure or union layout. This applies recursively if the
containing structure or union is also anonymous.
6.5.2.3p3: 3 A postfix expression followed by the . operator and an
identifier designates a member of a structure or union object. The
value is that of the named member, and is an lvalue if the first
expression is an lvalue. If the first expression has qualified type,
the result has the so-qualified version of the type of the designated
member.
6.3.2.1p1: ... A modifiable lvalue is an lvalue that does not have
array type, does not have an incomplete type, does not have a
const-qualified type, and if it is a structure or union, does not have
any member (including, recursively, any member or element of all
contained aggregates or unions) with a const-qualified type.
6.5.16p2: An assignment operator shall have a modifiable lvalue as its
left operand.
I *think* what may have been intended is for 6.7.2.1p15 to instead say
something along the lines of: ... The members of an anonymous
structure or union are considered to be members of the containing
structure or union, keeping their structure or union layout <ins>and
the qualifiers specified for the unnamed member</ins>. ...
~Aaron
Received on 2022-05-05 13:02:01