C++ Logo

liaison

Advanced search

Re: [wg14/wg21 liaison] cv-qualified anonymous types and member access expressions

From: Aaron Ballman <aaron_at_[hidden]>
Date: Sat, 7 May 2022 11:36:53 -0400
On Thu, May 5, 2022 at 1:49 PM Joseph Myers via Liaison
<liaison_at_[hidden]> wrote:
>
> On Thu, 5 May 2022, Jā‚‘ā‚™ā‚› Gustedt via Liaison wrote:
>
> > This would have made that clearer, but I think that this already
> > follows, anyhow. The type of `bar` is indeed `int const` and not
> > `int`. The `const` of the surrounding structure comes from the part in
> > 6.3.2.1p1 that you cited
> >
> > ... 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.
> >
> > This specification doesn't exclude unnamed members, and so
> > `<anonymous>.bar` is not a modifiable lvalue.
>
> I think what this wording about modifiable lvalues actually says is that
> my_foo is not a modifiable lvalue (because it has a const-qualified
> (anonymous) member) - not anything about whether my_foo.bar is a
> modifiable lvalue. That is, it's about carrying the "not a modifiable
> lvalue because const" property up from members to the containing structure
> or union (even when that containing structure or union is not itself
> const-qualified) - not down from that structure or union to members.
>
> I agree that my_foo.bar *should* have type const int (and so not be a
> modifiable lvalue), because anonymous structs and unions should simply
> provide shorter syntax for corresponding code where names are added for
> those members, without any semantic differences. If the contained struct
> weren't anonymous, the const int type would be achieved by 6.5.2.3#3:
> my_foo.<anonymous> has const-qualified type and so my_foo.<anonymous>.bar
> does. The question is how to make that clear in the specification when
> the only explicit '.' operator is applied to a non-const-qualified
> structure or union but there is a const-qualified anonymous structure or
> union in the middle.

I think we're mostly on the same page, but I want to be sure I'm
clear: the members of the anonymous union don't change type, it's the
member access expression that starts to consider the anonymous field's
qualifiers. e.g.,

struct S {
  const struct {
    int i;
  };
} s;

void foo(void) {
  _Static_assert(_Generic(s.i, int : 1, default : 0), "type of s.i is
not int?"); // Ok
  s.i = 12; // Error, access path involves an intermediate const
(implicit) object
}

I think this could explain the GCC behavior, but it's worth pointing
out that C is then different from C++ in terms of how anonymous unions
are handled (they don't have anonymous structures):
https://godbolt.org/z/98xb83nxv

Given that there's currently only one C compiler I can find which
behaves the way we've been discussing (GCC), and given how deeply
*weird* it is to have qualifiers on an anonymous object, and the C++
compatibility story, I wonder if we want to use this as a chance to
clarify that qualifiers are dropped instead of retained.
https://godbolt.org/z/hTqY8zMb5

~Aaron

>
> --
> Joseph S. Myers
> joseph_at_[hidden]_______________________________________________
> Liaison mailing list
> Liaison_at_[hidden]
> Subscription: https://lists.isocpp.org/mailman/listinfo.cgi/liaison
> Link to this post: http://lists.isocpp.org/liaison/2022/05/1064.php

Received on 2022-05-07 15:37:18