Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #76449 > unrolled thread

Understanding C89/C99 aliasing

Started bysupercat@casperkitty.com
First post2015-11-18 11:25 -0800
Last post2015-11-19 23:07 +0000
Articles 20 on this page of 158 — 18 participants

Back to article view | Back to comp.lang.c


Contents

  Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-11-18 11:25 -0800
    Re: Understanding C89/C99 aliasing Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-11-19 01:39 +0000
      Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-11-18 19:55 -0800
        Re: Understanding C89/C99 aliasing Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-11-19 14:37 +0000
          Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-11-19 07:07 -0800
            Re: Understanding C89/C99 aliasing Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-11-19 22:58 +0000
      Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-11-18 20:00 -0800
    Re: Understanding C89/C99 aliasing Nick Bowler <nbowler@draconx.ca> - 2015-11-19 15:44 +0000
      Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-11-19 09:46 -0800
        Re: Understanding C89/C99 aliasing Martin Shobe <martin.shobe@yahoo.com> - 2015-11-19 13:28 -0600
          Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-11-19 11:54 -0800
            Re: Understanding C89/C99 aliasing Martin Shobe <martin.shobe@yahoo.com> - 2015-11-19 14:41 -0600
              Re: Understanding C89/C99 aliasing Martin Shobe <martin.shobe@yahoo.com> - 2015-11-19 14:46 -0600
                Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-11-19 13:16 -0800
            Re: Understanding C89/C99 aliasing Nick Bowler <nbowler@draconx.ca> - 2015-11-19 21:11 +0000
              Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-11-19 13:34 -0800
                Re: Understanding C89/C99 aliasing Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-11-19 23:12 +0000
                  Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-11-19 15:18 -0800
                    Re: Understanding C89/C99 aliasing Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-11-20 02:21 +0000
                      Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-11-19 18:40 -0800
                        Re: Understanding C89/C99 aliasing Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-11-21 00:32 +0000
                          Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-11-20 16:47 -0800
                            Re: Understanding C89/C99 aliasing Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-11-21 01:14 +0000
                              Re: Understanding C89/C99 aliasing Stephen Sprunk <stephen@sprunk.org> - 2015-11-20 20:25 -0600
                                Re: Understanding C89/C99 aliasing Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-11-21 10:17 +0000
                                  Re: Understanding C89/C99 aliasing Stephen Sprunk <stephen@sprunk.org> - 2015-11-21 18:11 -0600
                                    Re: Understanding C89/C99 aliasing Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-11-22 00:58 +0000
                                      Re: Understanding C89/C99 aliasing Stephen Sprunk <stephen@sprunk.org> - 2015-11-22 14:41 -0600
                                        Re: Understanding C89/C99 aliasing Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-11-23 00:58 +0000
                                          Re: Understanding C89/C99 aliasing Stephen Sprunk <stephen@sprunk.org> - 2015-11-22 19:33 -0600
                                            Re: Understanding C89/C99 aliasing Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-11-26 01:16 +0000
                                              Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-11-25 21:57 -0800
                                              Re: Understanding C89/C99 aliasing Stephen Sprunk <stephen@sprunk.org> - 2015-11-26 18:01 -0600
                                                Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-11-27 10:17 -0800
                                                Re: Understanding C89/C99 aliasing Tim Rentsch <txr@alumni.caltech.edu> - 2015-11-27 23:38 -0800
                                                  Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-11-28 07:22 -0800
                                                    Re: Understanding C89/C99 aliasing Tim Rentsch <txr@alumni.caltech.edu> - 2015-12-08 08:51 -0800
                                          Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-11-22 18:34 -0800
                                          Re: Understanding C89/C99 aliasing James Kuyper <jameskuyper@verizon.net> - 2015-11-23 06:48 -0500
                                            Re: Understanding C89/C99 aliasing Keith Thompson <kst-u@mib.org> - 2015-11-23 08:28 -0800
                                              Re: Understanding C89/C99 aliasing Tim Rentsch <txr@alumni.caltech.edu> - 2015-11-27 09:21 -0800
                                                Re: Understanding C89/C99 aliasing raltbos@xs4all.nl (Richard Bos) - 2015-11-27 17:45 +0000
                                                  Re: Understanding C89/C99 aliasing Tim Rentsch <txr@alumni.caltech.edu> - 2015-11-27 10:13 -0800
                                                  Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-11-27 10:50 -0800
                                                Re: Understanding C89/C99 aliasing Keith Thompson <kst-u@mib.org> - 2015-11-27 13:46 -0800
                                                  Re: Understanding C89/C99 aliasing Tim Rentsch <txr@alumni.caltech.edu> - 2015-11-28 08:57 -0800
                                                    Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-11-28 11:00 -0800
                                                      Re: Understanding C89/C99 aliasing Tim Rentsch <txr@alumni.caltech.edu> - 2015-12-08 09:04 -0800
                                                        Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-12-08 10:42 -0800
                                                          Re: Understanding C89/C99 aliasing Keith Thompson <kst-u@mib.org> - 2015-12-08 10:54 -0800
                                                            Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-12-08 11:44 -0800
                                                            Re: Understanding C89/C99 aliasing glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-12-09 00:11 +0000
                                                              Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-12-08 16:39 -0800
                                                              Re: Understanding C89/C99 aliasing Keith Thompson <kst-u@mib.org> - 2015-12-08 19:15 -0800
                                                                Re: Understanding C89/C99 aliasing glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-12-09 04:21 +0000
                                                                  Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-12-09 09:04 -0800
                                                          Re: Understanding C89/C99 aliasing Stephen Sprunk <stephen@sprunk.org> - 2015-12-08 22:15 -0600
                                                            Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-12-09 07:04 -0800
                                                              Re: Understanding C89/C99 aliasing Stephen Sprunk <stephen@sprunk.org> - 2015-12-09 14:29 -0600
                                                                Re: Understanding C89/C99 aliasing Keith Thompson <kst-u@mib.org> - 2015-12-09 13:06 -0800
                                                                  Re: Understanding C89/C99 aliasing glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-12-09 22:58 +0000
                                                                  Re: Understanding C89/C99 aliasing Stephen Sprunk <stephen@sprunk.org> - 2015-12-10 11:35 -0600
                                                                    Re: Understanding C89/C99 aliasing James Kuyper <jameskuyper@verizon.net> - 2015-12-10 12:58 -0500
                                                                      Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-12-10 10:12 -0800
                                                                        Re: Understanding C89/C99 aliasing Stephen Sprunk <stephen@sprunk.org> - 2015-12-10 13:39 -0600
                                                                          Re: Understanding C89/C99 aliasing raltbos@xs4all.nl (Richard Bos) - 2015-12-10 22:45 +0000
                                                                            Re: Understanding C89/C99 aliasing Stephen Sprunk <stephen@sprunk.org> - 2015-12-11 12:27 -0600
                                                                          Re: Understanding C89/C99 aliasing James Kuyper <jameskuyper@verizon.net> - 2015-12-10 20:30 -0500
                                                                      Re: Understanding C89/C99 aliasing Stephen Sprunk <stephen@sprunk.org> - 2015-12-10 13:54 -0600
                                                                        Re: Understanding C89/C99 aliasing James Kuyper <jameskuyper@verizon.net> - 2015-12-10 20:57 -0500
                                                                          Re: Understanding C89/C99 aliasing glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-12-11 03:44 +0000
                                                                            Re: Understanding C89/C99 aliasing James Kuyper <jameskuyper@verizon.net> - 2015-12-11 07:26 -0500
                                                                              Re: Understanding C89/C99 aliasing Stephen Sprunk <stephen@sprunk.org> - 2015-12-11 11:58 -0600
                                                                                Re: Understanding C89/C99 aliasing Richard Damon <Richard@Damon-Family.org> - 2015-12-11 23:17 -0500
                                                                              Re: Understanding C89/C99 aliasing James Kuyper <jameskuyper@verizon.net> - 2015-12-11 14:00 -0500
                                                                Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-12-09 13:17 -0800
                                                                  Re: Understanding C89/C99 aliasing Keith Thompson <kst-u@mib.org> - 2015-12-09 14:22 -0800
                                                                    Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-12-09 15:06 -0800
                                                                  Re: Understanding C89/C99 aliasing glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-12-09 23:18 +0000
                                                                    Re: Understanding C89/C99 aliasing James Kuyper <jameskuyper@verizon.net> - 2015-12-09 18:48 -0500
                                                                    Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-12-09 15:49 -0800
                                                                  Re: Understanding C89/C99 aliasing Stephen Sprunk <stephen@sprunk.org> - 2015-12-10 12:44 -0600
                                                                    Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-12-10 11:12 -0800
                                                                Re: Understanding C89/C99 aliasing raltbos@xs4all.nl (Richard Bos) - 2015-12-10 20:18 +0000
                                                                  Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-12-10 12:29 -0800
                                                                  Re: Understanding C89/C99 aliasing Stephen Sprunk <stephen@sprunk.org> - 2015-12-10 16:19 -0600
                                                                    Re: Understanding C89/C99 aliasing raltbos@xs4all.nl (Richard Bos) - 2015-12-10 22:49 +0000
                                                                      Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-12-10 14:58 -0800
                                                                        Re: Understanding C89/C99 aliasing raltbos@xs4all.nl (Richard Bos) - 2015-12-15 18:25 +0000
                                                                          Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-12-15 10:50 -0800
                                                                            Re: Understanding C89/C99 aliasing Keith Thompson <kst-u@mib.org> - 2015-12-15 11:32 -0800
                                                                              Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-12-15 12:20 -0800
                                                                                Re: Understanding C89/C99 aliasing Keith Thompson <kst-u@mib.org> - 2015-12-15 13:08 -0800
                                                                                  Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-12-15 13:24 -0800
                                                                                    Re: Understanding C89/C99 aliasing Keith Thompson <kst-u@mib.org> - 2015-12-15 14:35 -0800
                                                                                      Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-12-15 15:34 -0800
                                                                                    Re: Understanding C89/C99 aliasing David Brown <david.brown@hesbynett.no> - 2015-12-16 00:00 +0100
                                                                                      Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-12-15 15:47 -0800
                                                                                        Re: Understanding C89/C99 aliasing David Brown <david.brown@hesbynett.no> - 2015-12-16 11:08 +0100
                                                                                          Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-12-16 09:45 -0800
                                                                                            Re: Understanding C89/C99 aliasing David Brown <david.brown@hesbynett.no> - 2015-12-17 13:51 +0100
                                                                                              Re: Understanding C89/C99 aliasing Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-12-17 05:10 -0800
                                                                                                Re: Understanding C89/C99 aliasing Richard Heathfield <rjh@cpax.org.uk> - 2015-12-17 13:46 +0000
                                                                                                Re: Understanding C89/C99 aliasing David Brown <david.brown@hesbynett.no> - 2015-12-17 15:24 +0100
                                                                                                  Re: Understanding C89/C99 aliasing Jerry Stuckle <jstucklex@attglobal.net> - 2015-12-17 09:57 -0500
                                                                                                    Re: Understanding C89/C99 aliasing Les Cargill <lcargill99@comcast.com> - 2015-12-17 09:39 -0600
                                                                                                      Re: Understanding C89/C99 aliasing Jerry Stuckle <jstucklex@attglobal.net> - 2015-12-17 12:12 -0500
                                                                                                        Re: Understanding C89/C99 aliasing Les Cargill <lcargill99@comcast.com> - 2015-12-17 12:27 -0600
                                                                                                          Re: Understanding C89/C99 aliasing Jerry Stuckle <jstucklex@attglobal.net> - 2015-12-17 14:22 -0500
                                                                                                            Re: Understanding C89/C99 aliasing Les Cargill <lcargill99@comcast.com> - 2015-12-17 17:58 -0600
                                                                                                              Re: Understanding C89/C99 aliasing Jerry Stuckle <jstucklex@attglobal.net> - 2015-12-17 20:26 -0500
                                                                                                                Re: Understanding C89/C99 aliasing Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2015-12-17 20:35 -0500
                                                                                                                  Re: Understanding C89/C99 aliasing Jerry Stuckle <jstucklex@attglobal.net> - 2015-12-17 21:49 -0500
                                                                                                                Re: Understanding C89/C99 aliasing Les Cargill <lcargill99@comcast.com> - 2015-12-17 20:52 -0600
                                                                                                                  Re: Understanding C89/C99 aliasing Jerry Stuckle <jstucklex@attglobal.net> - 2015-12-17 22:01 -0500
                                                                                                                    Re: Understanding C89/C99 aliasing Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-12-17 20:55 -0800
                                                                                                                      Re: Understanding C89/C99 aliasing Jerry Stuckle <jstucklex@attglobal.net> - 2015-12-18 08:40 -0500
                                                                                              Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-12-17 09:10 -0800
                                                                                  Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-12-15 14:27 -0800
                                                                                    Re: Understanding C89/C99 aliasing Keith Thompson <kst-u@mib.org> - 2015-12-15 16:30 -0800
                                                                                      Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-12-16 12:47 -0800
                                                                                  Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-12-15 14:32 -0800
                                                            Re: Understanding C89/C99 aliasing Öö Tiib <ootiib@hot.ee> - 2015-12-09 08:09 -0800
                                                              Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-12-09 09:10 -0800
                                                                Re: Understanding C89/C99 aliasing Öö Tiib <ootiib@hot.ee> - 2015-12-09 10:38 -0800
                                                                  Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-12-09 11:18 -0800
                                                              Re: Understanding C89/C99 aliasing glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-12-09 19:14 +0000
                                                                Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-12-09 11:27 -0800
                                                              Re: Understanding C89/C99 aliasing Stephen Sprunk <stephen@sprunk.org> - 2015-12-09 15:03 -0600
                                                                Re: Understanding C89/C99 aliasing Öö Tiib <ootiib@hot.ee> - 2015-12-10 01:23 -0800
                                                              Re: Understanding C89/C99 aliasing raltbos@xs4all.nl (Richard Bos) - 2015-12-10 20:21 +0000
                                                          Re: Understanding C89/C99 aliasing Tim Rentsch <txr@alumni.caltech.edu> - 2015-12-09 13:06 -0800
                                                        Re: Understanding C89/C99 aliasing glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-12-09 00:00 +0000
                                                          Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-12-08 16:27 -0800
                                                            Re: Understanding C89/C99 aliasing Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-12-09 01:18 +0000
                                                            Re: Understanding C89/C99 aliasing Keith Thompson <kst-u@mib.org> - 2015-12-08 19:13 -0800
                                                          Re: Understanding C89/C99 aliasing Tim Rentsch <txr@alumni.caltech.edu> - 2015-12-09 13:04 -0800
                                                Re: Understanding C89/C99 aliasing raltbos@xs4all.nl (Richard Bos) - 2015-12-10 20:07 +0000
                                            Re: Understanding C89/C99 aliasing Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-11-23 17:03 +0000
                                              Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-11-23 15:39 -0800
                                                Re: Understanding C89/C99 aliasing Stephen Sprunk <stephen@sprunk.org> - 2015-11-23 18:11 -0600
                                                  Re: Understanding C89/C99 aliasing Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-11-24 01:13 +0000
                                                  Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-11-24 09:29 -0800
                Re: Understanding C89/C99 aliasing Stephen Sprunk <stephen@sprunk.org> - 2015-11-20 09:10 -0600
                  Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-11-20 10:08 -0800
                    Re: Understanding C89/C99 aliasing Stephen Sprunk <stephen@sprunk.org> - 2015-11-21 19:02 -0600
                      Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-11-21 18:17 -0800
                        Re: Understanding C89/C99 aliasing Stephen Sprunk <stephen@sprunk.org> - 2015-11-21 20:52 -0600
                          Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-11-21 19:28 -0800
                            Re: Understanding C89/C99 aliasing Stephen Sprunk <stephen@sprunk.org> - 2015-11-22 20:00 -0600
                  Re: Understanding C89/C99 aliasing Keith Thompson <kst-u@mib.org> - 2015-11-20 19:12 -0800
                    Re: Understanding C89/C99 aliasing Stephen Sprunk <stephen@sprunk.org> - 2015-11-20 23:10 -0600
                      Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-11-20 23:07 -0800
                        Re: Understanding C89/C99 aliasing Stephen Sprunk <stephen@sprunk.org> - 2015-11-21 18:37 -0600
                    Re: Understanding C89/C99 aliasing Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-11-21 10:29 +0000
                      Re: Understanding C89/C99 aliasing supercat@casperkitty.com - 2015-11-21 10:04 -0800
                        Re: Understanding C89/C99 aliasing Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-11-21 19:35 +0000
            Re: Understanding C89/C99 aliasing Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-11-19 23:07 +0000

Page 2 of 8 — ← Prev page 1 [2] 3 4 5 6 7 8  Next page →


#76702

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2015-11-21 00:32 +0000
Message-ID<87si40p4yy.fsf@bsb.me.uk>
In reply to#76593
supercat@casperkitty.com writes:

> On Thursday, November 19, 2015 at 8:21:48 PM UTC-6, Ben Bacarisse wrote:
>> How much further from the bottom-level expression up can one go when
>> applying this rule?  For example, if a union has a pointer member, can
>> "*u.ptr = ...;" access any type that is included as a member of the
>> union?
>
> When an lvalue access is performed via a pointer, the type of the lvalue is
> that of the thing to which the pointer points, and has no relation to the
> type of the thing that contains the pointer.

But, according to you, when an lvalue access is via a union the type of
the lvalue disregards the . operator and remains that of the union.
Where does the support for that point of view come from?

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#76703

Fromsupercat@casperkitty.com
Date2015-11-20 16:47 -0800
Message-ID<8c236df3-a9ad-46c2-aeeb-da2746255871@googlegroups.com>
In reply to#76702
On Friday, November 20, 2015 at 6:32:29 PM UTC-6, Ben Bacarisse wrote:
> But, according to you, when an lvalue access is via a union the type of
> the lvalue disregards the . operator and remains that of the union.
> Where does the support for that point of view come from?

If u is a union with a member f, I would suggest that "u.f=23;" clearly
accesses u.  Would you disagree?  The only way that can work is if that
statement is regarded as using the union type.

The fundamental point is that given:

    void blah(float *fp, int *ip) { *fp = 1.2f; *ip=3; }

a compiler is allowed to regard as Undefined Behavior any situation where
fp and ip alias, *regardless of where they came from*.

Thus, calling the function

    void boom1(void)
    {
      union { float f; int i; } flint;
      blah(&flint.f, &flint.i);
    }

would invoke Undefined Behavior.

Do you see anything in the Standard which make that any different from:

    void blah1(float *fp) { *fp = 1.2f; }
    void blah2(int *ip) { *ip=3; }

    void boom2(void)
    {
      union { float f; int i; } flint;
      blah1(&flint.f);
      blah2(&flint.i);
    }

or even

    void boom3(void)
    {
      union { float f; int i; } flint;
      blah1(&flint.f);
    }

The first example clearly invoked Undefined Behavior, and I see no way to
interpret the Standard such that the first does so but the others do not.

[toc] | [prev] | [next] | [standalone]


#76704

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2015-11-21 01:14 +0000
Message-ID<87io4wp30c.fsf@bsb.me.uk>
In reply to#76703
supercat@casperkitty.com writes:

> On Friday, November 20, 2015 at 6:32:29 PM UTC-6, Ben Bacarisse wrote:
>> But, according to you, when an lvalue access is via a union the type of
>> the lvalue disregards the . operator and remains that of the union.
>> Where does the support for that point of view come from?
>
> If u is a union with a member f, I would suggest that "u.f=23;" clearly
> accesses u.  Would you disagree?

Yes I do, but that's not my main objection.  My point was why you
consider the access to the float object as being by an lvalue expression
of union type (u) rather than by the more obvious lvalue expression of
float type (u.f).  Whether u.f=23; does or does not access u does not
answer that question.

<snip>
> The fundamental point is that given:
>
>     void blah(float *fp, int *ip) { *fp = 1.2f; *ip=3; }
>
> a compiler is allowed to regard as Undefined Behavior any situation where
> fp and ip alias, *regardless of where they came from*.

Eh?  The compiler can assume that fp and ip don't alias, but it most
certainly matters where they come from.  If they both point to a single
area of allocated storage no rules have been broken.

You keep changing the examples which makes discussion hard.  For
example, in the older case where there is a write and read the
destination of the pointers did not matter because the effective type
done through a write "sticks" when the target is allocated.

<snip>
-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#76707

FromStephen Sprunk <stephen@sprunk.org>
Date2015-11-20 20:25 -0600
Message-ID<n2okii$nn9$1@dont-email.me>
In reply to#76704
On 20-Nov-15 19:14, Ben Bacarisse wrote:
> You keep changing the examples which makes discussion hard.  For 
> example, in the older case where there is a write and read the 
> destination of the pointers did not matter because the effective
> type done through a write "sticks" when the target is allocated.

Since the compiler is allowed to assume incompatible pointers do not
alias, doesn't that mean it is free to reorder writes and indirectly
change the effective type of the storage they point to?

Or is there some other rule I'm missing that would prevent that?

S

-- 
Stephen Sprunk         "God does not play dice."  --Albert Einstein
CCIE #3723         "God is an inveterate gambler, and He throws the
K5SSS        dice at every possible opportunity." --Stephen Hawking

[toc] | [prev] | [next] | [standalone]


#76742

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2015-11-21 10:17 +0000
Message-ID<87d1v3psfq.fsf@bsb.me.uk>
In reply to#76707
Stephen Sprunk <stephen@sprunk.org> writes:

> On 20-Nov-15 19:14, Ben Bacarisse wrote:
>> You keep changing the examples which makes discussion hard.  For 
>> example, in the older case where there is a write and read the 
>> destination of the pointers did not matter because the effective
>> type done through a write "sticks" when the target is allocated.
>
> Since the compiler is allowed to assume incompatible pointers do not
> alias, doesn't that mean it is free to reorder writes and indirectly
> change the effective type of the storage they point to?
>
> Or is there some other rule I'm missing that would prevent that?

It may well be able to re-order the writes but that does not make the
code shown undefined.  It might break something else in the program, but
the example is too brief to know.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#76815

FromStephen Sprunk <stephen@sprunk.org>
Date2015-11-21 18:11 -0600
Message-ID<n2r135$luc$1@dont-email.me>
In reply to#76742
On 21-Nov-15 04:17, Ben Bacarisse wrote:
> Stephen Sprunk <stephen@sprunk.org> writes:
>> On 20-Nov-15 19:14, Ben Bacarisse wrote:
>>> You keep changing the examples which makes discussion hard.  For
>>> example, in the older case where there is a write and read the 
>>> destination of the pointers did not matter because the effective 
>>> type done through a write "sticks" when the target is allocated.
>> 
>> Since the compiler is allowed to assume incompatible pointers do
>> not alias, doesn't that mean it is free to reorder writes and
>> indirectly change the effective type of the storage they point to?
>> 
>> Or is there some other rule I'm missing that would prevent that?
> 
> It may well be able to re-order the writes but that does not make
> the code shown undefined.  It might break something else in the
> program, but the example is too brief to know.

Okay, here's a very simple example:

void foo(float *fp, int *ip) {
  *fp = 42.0;
  *ip = 42;
  printf("%d\n", *ip);
}

If the compiler doesn't reorder the assignments, then the read is
well-defined.  However, it is allowed to assume fp and ip are not
aliases and thus reorder the assignments, but if they actually are
aliases, then the read would become undefined.  Correct?

I don't understand previous responses that indicate some answers may
depend on where fp and ip came from; I have been assuming that origin
doesn't matter, but if it actually does, please explain.

Also, I've deliberately not used unions from this example because I'm
assuming that a pointer to a member of a union does not benefit from the
special rules that apply to directly accessing a member of a (pointed
to) union; if that is incorrect, please explain.

S

-- 
Stephen Sprunk         "God does not play dice."  --Albert Einstein
CCIE #3723         "God is an inveterate gambler, and He throws the
K5SSS        dice at every possible opportunity." --Stephen Hawking

[toc] | [prev] | [next] | [standalone]


#76818

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2015-11-22 00:58 +0000
Message-ID<87wptalujc.fsf@bsb.me.uk>
In reply to#76815
Stephen Sprunk <stephen@sprunk.org> writes:

> On 21-Nov-15 04:17, Ben Bacarisse wrote:
>> Stephen Sprunk <stephen@sprunk.org> writes:
>>> On 20-Nov-15 19:14, Ben Bacarisse wrote:
>>>> You keep changing the examples which makes discussion hard.  For
>>>> example, in the older case where there is a write and read the 
>>>> destination of the pointers did not matter because the effective 
>>>> type done through a write "sticks" when the target is allocated.
>>> 
>>> Since the compiler is allowed to assume incompatible pointers do
>>> not alias, doesn't that mean it is free to reorder writes and
>>> indirectly change the effective type of the storage they point to?
>>> 
>>> Or is there some other rule I'm missing that would prevent that?
>> 
>> It may well be able to re-order the writes but that does not make
>> the code shown undefined.  It might break something else in the
>> program, but the example is too brief to know.
>
> Okay, here's a very simple example:
>
> void foo(float *fp, int *ip) {
>   *fp = 42.0;
>   *ip = 42;
>   printf("%d\n", *ip);
> }
>
> If the compiler doesn't reorder the assignments, then the read is
> well-defined.  However, it is allowed to assume fp and ip are not
> aliases and thus reorder the assignments, but if they actually are
> aliases, then the read would become undefined.  Correct?

I don't think so.  If ip and fp alias then they refer to some common
object.  If that has a declared type of int, then the assignment through
*fp is undefined because it violates a "shall" in the standard.
Similarly if it's an object declared to be float.  The read of *ip is
not involved in any of that -- the code is already undefined before it
gets there.

But there is an other case.  If ip and fp both point to the same
properly sized and aligned allocated storage, then there is nothing
wrong with the above code.  The effective type rules mean that allocated
storage gets it's effective type from the type of the lvalue expression
last used to write it.  The result is that the code is valid even if ip
and fp alias, so the compile can not do anything to disturb the clear
intent of the code.  Of course, if it can prove that ip and fp are not
pointers to allocated storage (or point to allocated storage with some
other effective type), then all bets are off.

> I don't understand previous responses that indicate some answers may
> depend on where fp and ip came from; I have been assuming that origin
> doesn't matter, but if it actually does, please explain.

There was a previous example that was a bit different:

  void foo(float *fp, int *ip) {
    *ip = 42;
    *fp = 42.0;
    printf("%d\n", *ip);
  }

Note the change in order.  In this case the compiler *can* assume that
ip and fp don't alias.  It can do the writes in either order and it can
avoid re-reading *ip for the printf call.  This is because there is no
situation where the code won't break the effective type rules if ip and
fp do alias.  Even if they point to allocated storage, the effective
type from the write through fp "sticks", so the read of *ip breaks a
"shall" in the standard.

Many of the examples have been slightly different line this.
Unfortunately this is an area where small differences can matter a lot.
By the way, I'm also pretty sure that I've made mistakes in describing
how these rules are supposed to work, so looking at old posts won't
necessarily be a good guide to how I now see things.  I've been working
some of this out as I go.

> Also, I've deliberately not used unions from this example because I'm
> assuming that a pointer to a member of a union does not benefit from the
> special rules that apply to directly accessing a member of a (pointed
> to) union; if that is incorrect, please explain.

I'm not sure I understand, but I think it's good to get rid of unions
for a while.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#76909

FromStephen Sprunk <stephen@sprunk.org>
Date2015-11-22 14:41 -0600
Message-ID<n2t94q$tsd$1@dont-email.me>
In reply to#76818
On 21-Nov-15 18:58, Ben Bacarisse wrote:
> Stephen Sprunk <stephen@sprunk.org> writes:
>> On 21-Nov-15 04:17, Ben Bacarisse wrote:
>>> It may well be able to re-order the writes but that does not make
>>> the code shown undefined.  It might break something else in the
>>> program, but the example is too brief to know.
>>
>> Okay, here's a very simple example:
>>
>> void foo(float *fp, int *ip) {
>>   *fp = 42.0;
>>   *ip = 42;
>>   printf("%d\n", *ip);
>> }
>>
>> If the compiler doesn't reorder the assignments, then the read is 
>> well-defined.  However, it is allowed to assume fp and ip are not 
>> aliases and thus reorder the assignments, but if they actually are 
>> aliases, then the read would become undefined.  Correct?
> 
> I don't think so.  If ip and fp alias then they refer to some common 
> object.  If that has a declared type of int, then the assignment
> through *fp is undefined because it violates a "shall" in the
> standard. Similarly if it's an object declared to be float.  The read
> of *ip is not involved in any of that -- the code is already
> undefined before it gets there.

Thanks; that explains why the pointers' origin matters.

> But there is an other case.  If ip and fp both point to the same 
> properly sized and aligned allocated storage, then there is nothing 
> wrong with the above code.  The effective type rules mean that
> allocated storage gets it's effective type from the type of the
> lvalue expression last used to write it.

That's where I keep getting hung up, so please excuse what probably
looks like a stupid question: does "last" really mean in source code
order, or could it mean "last" after the compiler reorders things?

If the former, I think that solves supercat's problem, at least if he
_has_ allocated storage available.

> The result is that the code is valid even if ip and fp alias, so
> the compile can not do anything to disturb the clear intent of the
> code.  Of course, if it can prove that ip and fp are not pointers to
> allocated storage (or point to allocated storage with some other
> effective type), then all bets are off.

Assuming the target _has_ allocated storage, it seems impossible for a
compiler to prove (in all cases) that the storage was _not_ allocated;
it would generally have to assume that it _might_ be allocated and
therefore treat all pointers as if such rules applied.

>> I don't understand previous responses that indicate some answers may
>> depend on where fp and ip came from; I have been assuming that origin
>> doesn't matter, but if it actually does, please explain.
> 
> There was a previous example that was a bit different:
> 
>   void foo(float *fp, int *ip) {
>     *ip = 42;
>     *fp = 42.0;
>     printf("%d\n", *ip);
>   }
> 
> Note the change in order.  In this case the compiler *can* assume that
> ip and fp don't alias.  It can do the writes in either order and it can
> avoid re-reading *ip for the printf call.  This is because there is no
> situation where the code won't break the effective type rules if ip and
> fp do alias.  Even if they point to allocated storage, the effective
> type from the write through fp "sticks", so the read of *ip breaks a
> "shall" in the standard.

That makes sense; thanks.

> Many of the examples have been slightly different line this.
> Unfortunately this is an area where small differences can matter a lot.

Indeed; that is partly why the examples keep changing.  We try it one
way, get an unfavorable answer, and try again in a slightly different
way that hopefully has a different answer :)

> By the way, I'm also pretty sure that I've made mistakes in
> describing how these rules are supposed to work, so looking at old
> posts won't necessarily be a good guide to how I now see things.
> I've been working some of this out as I go.

Ditto.  I've always gone out of my way to avoid aliasing since I know
that I don't understand exactly what the rules are.  It's like the old
maps with "here be dragons" on them; if you simply don't go to such
places, there's no need to worry about dragons eating you.

>> Also, I've deliberately not used unions from this example because
>> I'm assuming that a pointer to a member of a union does not benefit
>> from the special rules that apply to directly accessing a member of
>> a (pointed to) union; if that is incorrect, please explain.
> 
> I'm not sure I understand, ...

What I meant is that if you have this:

union { float f; int i; } u, *up = &u;
float *fp = &u.f; // or &up->f
int *ip = &u.i; // or &up->i

Accessing u.f and u.i or up->f and up->i is obviously governed by the
union rules, but AFAICT accessing fp and ip is governed by the alias
rules as if no union were involved.  Correct?

> but I think it's good to get rid of unions for a while.

If you can settle the one reordering question above, I think that gets
me to a point where we can reintroduce unions to the examples.

S

-- 
Stephen Sprunk         "God does not play dice."  --Albert Einstein
CCIE #3723         "God is an inveterate gambler, and He throws the
K5SSS        dice at every possible opportunity." --Stephen Hawking

[toc] | [prev] | [next] | [standalone]


#76952

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2015-11-23 00:58 +0000
Message-ID<874mgdlef2.fsf@bsb.me.uk>
In reply to#76909
Stephen Sprunk <stephen@sprunk.org> writes:

> On 21-Nov-15 18:58, Ben Bacarisse wrote:
>> Stephen Sprunk <stephen@sprunk.org> writes:
>>> On 21-Nov-15 04:17, Ben Bacarisse wrote:
>>>> It may well be able to re-order the writes but that does not make
>>>> the code shown undefined.  It might break something else in the
>>>> program, but the example is too brief to know.
>>>
>>> Okay, here's a very simple example:
>>>
>>> void foo(float *fp, int *ip) {
>>>   *fp = 42.0;
>>>   *ip = 42;
>>>   printf("%d\n", *ip);
>>> }
>>>
>>> If the compiler doesn't reorder the assignments, then the read is 
>>> well-defined.  However, it is allowed to assume fp and ip are not 
>>> aliases and thus reorder the assignments, but if they actually are 
>>> aliases, then the read would become undefined.  Correct?
>> 
>> I don't think so.  If ip and fp alias then they refer to some common 
>> object.  If that has a declared type of int, then the assignment
>> through *fp is undefined because it violates a "shall" in the
>> standard. Similarly if it's an object declared to be float.  The read
>> of *ip is not involved in any of that -- the code is already
>> undefined before it gets there.
>
> Thanks; that explains why the pointers' origin matters.
>
>> But there is an other case.  If ip and fp both point to the same 
>> properly sized and aligned allocated storage, then there is nothing 
>> wrong with the above code.  The effective type rules mean that
>> allocated storage gets it's effective type from the type of the
>> lvalue expression last used to write it.
>
> That's where I keep getting hung up, so please excuse what probably
> looks like a stupid question: does "last" really mean in source code
> order, or could it mean "last" after the compiler reorders things?

The analysis must be done from the point of view of the C virtual
machine, so *fp = 42; would make the effective type float first, and
then *ip = 42; would make it int.  That is the last write before the
valid access to *ip.  An implementation can re-order things in valid
code only in so far as the result is undetectable.

> If the former, I think that solves supercat's problem, at least if he
> _has_ allocated storage available.

Yes, but some of his other examples use static buffers that get re-used.
The trouble is that there have been loads of ever so slightly different
examples, often with subtly different issues or, in some cases, none at
all.

With a non-allocated buffer even the first write though an lvalue
expression that is not of the buffer's type will be undefined behaviour
because of the "shall" it violates.  This is true even with no other
pointers in sight.  I think of this as a "technical shall" since the
purpose of the effective type rules are to permit aliasing assumptions.
In most cases the implementation simply can't know enough to take any
action that could disrupt the code, but one can imagine a simple inlined
allocator where it might, or even whole-program optimisations that could
detect it.

>> The result is that the code is valid even if ip and fp alias, so
>> the compile can not do anything to disturb the clear intent of the
>> code.  Of course, if it can prove that ip and fp are not pointers to
>> allocated storage (or point to allocated storage with some other
>> effective type), then all bets are off.
>
> Assuming the target _has_ allocated storage, it seems impossible for a
> compiler to prove (in all cases) that the storage was _not_ allocated;
> it would generally have to assume that it _might_ be allocated and
> therefore treat all pointers as if such rules applied.

Well, see above.

<snip>
-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#76954

FromStephen Sprunk <stephen@sprunk.org>
Date2015-11-22 19:33 -0600
Message-ID<n2tq8p$tj6$1@dont-email.me>
In reply to#76952
On 22-Nov-15 18:58, Ben Bacarisse wrote:
> Stephen Sprunk <stephen@sprunk.org> writes:
>> On 21-Nov-15 18:58, Ben Bacarisse wrote:
>>> But there is an other case.  If ip and fp both point to the same
>>> properly sized and aligned allocated storage, then there is
>>> nothing wrong with the above code.  The effective type rules mean
>>> that allocated storage gets it's effective type from the type of
>>> the lvalue expression last used to write it.
>> 
>> That's where I keep getting hung up, so please excuse what
>> probably looks like a stupid question: does "last" really mean in
>> source code order, or could it mean "last" after the compiler
>> reorders things?
> 
> The analysis must be done from the point of view of the C virtual 
> machine, so *fp = 42; would make the effective type float first, and 
> then *ip = 42; would make it int.  That is the last write before the 
> valid access to *ip.  An implementation can re-order things in valid 
> code only in so far as the result is undetectable.

That's what I was looking for; thanks.

>> If the former, I think that solves supercat's problem, at least if
>> he _has_ allocated storage available.
> 
> Yes, but some of his other examples use static buffers that get
> re-used.

Indeed.  Even assuming a good reason to avoid using malloc()/free()
throughout a program, though, it seems harmless for a custom allocator
to get its pool from a single call to malloc() at startup.

That just leaves platforms that don't have malloc() at all.

> With a non-allocated buffer even the first write though an lvalue 
> expression that is not of the buffer's type will be undefined
> behaviour because of the "shall" it violates.  This is true even with
> no other pointers in sight.  I think of this as a "technical shall"
> since the purpose of the effective type rules are to permit aliasing
> assumptions. In most cases the implementation simply can't know
> enough to take any action that could disrupt the code, but one can
> imagine a simple inlined allocator where it might, or even
> whole-program optimisations that could detect it.

Indeed.

This is where I think we need to reintroduce unions.  Does a union in
static and/or auto storage benefit from the same guarantees as the
allocated storage case above, as long as the compiler _knows_ it's
dealing with a union?

(Cases where you hide the union's nature are the next step, but let's
not go there quite yet.)

S

-- 
Stephen Sprunk         "God does not play dice."  --Albert Einstein
CCIE #3723         "God is an inveterate gambler, and He throws the
K5SSS        dice at every possible opportunity." --Stephen Hawking

[toc] | [prev] | [next] | [standalone]


#77200

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2015-11-26 01:16 +0000
Message-ID<87d1uxh86b.fsf@bsb.me.uk>
In reply to#76954
Stephen Sprunk <stephen@sprunk.org> writes:

> On 22-Nov-15 18:58, Ben Bacarisse wrote:
<snip>
>> With a non-allocated buffer even the first write though an lvalue 
>> expression that is not of the buffer's type will be undefined
>> behaviour because of the "shall" it violates.  This is true even with
>> no other pointers in sight.  I think of this as a "technical shall"
>> since the purpose of the effective type rules are to permit aliasing
>> assumptions. In most cases the implementation simply can't know
>> enough to take any action that could disrupt the code, but one can
>> imagine a simple inlined allocator where it might, or even
>> whole-program optimisations that could detect it.
>
> Indeed.
>
> This is where I think we need to reintroduce unions.  Does a union in
> static and/or auto storage benefit from the same guarantees as the
> allocated storage case above, as long as the compiler _knows_ it's
> dealing with a union?

Sorry it's taken a while to get back to this.  I was not sure I had the
enthusiasm for more!

I don't think simply giving a static buffer a union type helps.  Of
course it's fine if everything knows about the union -- that's what they
are for -- but I don't think this:

  void *alloc(void)
  {
      union types { int i; float f; };
      static union types storage[4];
      static int n;
      return &storage[n++ & 3];
  }

  int *ip = alloc();
  *ip = 42;

avoids the problem.  The effective type of storage[0] is the union (its
declared type) and it is accessed by a lvalue expression of a type (int)
not on the permitted list.  Whether any implementation would take
advantage of this undefined behaviour is something I can't give an
informed answer to.

The solution (which would not always be available) is to know the type
used by the allocator and then to use a union where the storage is
needed:

  void *alloc(void)
  {
      static float storage[4];
      static int n;
      return &storage[n++ & 3];
  }

  union types { int i; float f; } *up = alloc();
  *up = (union types){42};

Here, the object (a float) is accessed by an lvalue expression (*up) of
a union type that includes a member compatible with that of the object.

A more likely scenario would be for the allocator to use a character
buffer, and then the union must include a char member.

I think it's been suggested that the presence of a suitable union in the
accessing expression is enough.  I.e. that

  up->i = 42;

would suffice, but I don't think so because the lvalue expression used
to access the float object is, in my opinion, of type int.  Sure, there
*is* an lvalue expression of a suitable type as part of the whole
expression, but I would not say that it's the one used to access the
stored value.

> (Cases where you hide the union's nature are the next step, but let's
> not go there quite yet.)

Is this such a case?  I was not sure what you meant by hiding here.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#77203

Fromsupercat@casperkitty.com
Date2015-11-25 21:57 -0800
Message-ID<2659d548-6795-4dd8-affd-e90764ca91f1@googlegroups.com>
In reply to#77200
On Wednesday, November 25, 2015 at 7:16:20 PM UTC-6, Ben Bacarisse wrote:
>                       The effective type of storage[0] is the union (its
> declared type) and it is accessed by a lvalue expression of a type (int)
> not on the permitted list.  Whether any implementation would take
> advantage of this undefined behaviour is something I can't give an
> informed answer to.

I agree with that wording of the Standard, though I consider it a pretty
major defect.

> The solution (which would not always be available) is to know the type
> used by the allocator and then to use a union where the storage is
> needed:
> 
>   void *alloc(void)
>   {
>       static float storage[4];
>       static int n;
>       return &storage[n++ & 3];
>   }
> 
>   union types { int i; float f; } *up = alloc();
>   *up = (union types){42};
> 
> Here, the object (a float) is accessed by an lvalue expression (*up) of
> a union type that includes a member compatible with that of the object.

The Standard seems to have a lot of language which regards unions and
structures interchangeably, although they are fundamentally different.
Even if one can use purely-defined means to construct pointers to two
potential instances of the same structure type such that s1->i1 and
s2->i2 have the same defined address, code which writes to one and reads
the other will fail in a number of compilers even though creating and
using either structure in isolation would be fully defined.  I think
it's necessary not only that types match, but also that they be accessed
in the same way.

> A more likely scenario would be for the allocator to use a character
> buffer, and then the union must include a char member.

Using a character buffer would make it necessary to over-allocate the size
of the buffer slightly and then be prepared to adjust the returned pointer
to accommodate alignment issues.  Further, it would require that everyplace
that uses any type returned by the allocator must use a union containing all
the types, and not pass pointers to interior members.

> I think it's been suggested that the presence of a suitable union in the
> accessing expression is enough.  I.e. that
> 
>   up->i = 42;
> 
> would suffice, but I don't think so because the lvalue expression used
> to access the float object is, in my opinion, of type int.  Sure, there
> *is* an lvalue expression of a suitable type as part of the whole
> expression, but I would not say that it's the one used to access the
> stored value.

When C99 added restrict pointers, it could have used those to apply sensible
semantics to union-member and struct-member pointers by saying that the
pointer obtained by applying the address-of operator to a structure or union
member must either be assigned to a restrict-qualified variable or used as a
temporary which will behave as a restrict-qualified variable that dies at the
next sequence point.

Under such semantics, given:

   union { float f; int i; } flint;
   flint.f = 1.0;
   do_something(&flint.f, &flint.i);

would be perfectly legitimate if and only if at least one of the following
conditions holds throughout the execution of do_something:

1. Nothing writes to either pointer, nor to flint.
2. There are no accesses to the union except via flint.f.
3. There are no accesses to the union except via flint.i.

That would be a perfect fit for "restrict" semantics, which are miles better
than type-based aliasing.

[toc] | [prev] | [next] | [standalone]


#77234

FromStephen Sprunk <stephen@sprunk.org>
Date2015-11-26 18:01 -0600
Message-ID<n386c2$1k1$1@dont-email.me>
In reply to#77200
On 25-Nov-15 19:16, Ben Bacarisse wrote:
> Stephen Sprunk <stephen@sprunk.org> writes:
>> This is where I think we need to reintroduce unions.  Does a union
>> in static and/or auto storage benefit from the same guarantees as
>> the allocated storage case above, as long as the compiler _knows_
>> it's dealing with a union?
> 
> Sorry it's taken a while to get back to this.  I was not sure I had
> the enthusiasm for more!
> 
> I don't think simply giving a static buffer a union type helps.  Of 
> course it's fine if everything knows about the union -- that's what
> they are for -- but I don't think this:
> 
>   void *alloc(void)
>   {
>       union types { int i; float f; };
>       static union types storage[4];
>       static int n;
>       return &storage[n++ & 3];
>   }
> 
>   int *ip = alloc();
>   *ip = 42;
> ...

I'll stop you right there and jump to the end:

>> (Cases where you hide the union's nature are the next step, but
>> let's not go there quite yet.)
> 
> Is this such a case?  I was not sure what you meant by hiding here.

Yes.  Consider:

union { float f; int i; } u, *up = &u;
float *fp = &u.f; // or &up->f
int *ip = &u.i; // or &up->i

If you access u.f and u.i, or up->f and up->i, then the compiler knows
it's dealing with a union and must act accordingly.  If you access *fp
and *ip, however, the union's nature may become hidden--especially if
passed to or returned from a function.

A compiler _may_ be able to figure out that *fp and *ip point into the
same union, but depending on how tricky your code is (or how dumb the
compiler is), that may not be possible in all cases.

OTOH, as long as you only access one of them (including after passing to
or returning from a function), that seems perfectly fine since the
union's nature is irrelevant in that case.

Perhaps my mental model is backward (or just plain wrong), but it seems
as if the effective type rules for allocated storage are simply treating
such as unions of all possible types.

S

-- 
Stephen Sprunk         "God does not play dice."  --Albert Einstein
CCIE #3723         "God is an inveterate gambler, and He throws the
K5SSS        dice at every possible opportunity." --Stephen Hawking

[toc] | [prev] | [next] | [standalone]


#77265

Fromsupercat@casperkitty.com
Date2015-11-27 10:17 -0800
Message-ID<2b093515-2f15-4c0a-8244-da464d6f80b7@googlegroups.com>
In reply to#77234
On Thursday, November 26, 2015 at 6:01:30 PM UTC-6, Stephen Sprunk wrote:
> OTOH, as long as you only access one of them (including after passing to
> or returning from a function), that seems perfectly fine since the
> union's nature is irrelevant in that case.

If code never accesses the union using a union-type lvalue, there's no reason
that a compiler should have any trouble.  On the other hand, there's no
reason why any compilers should ever have had any trouble with the "classic"
rotate-bits formula:

    unsigned int rol32(uint32_t x, uint32_t n) 
    { return (x<<n) | (x>>(32-n)); }

but some may nonetheless behave in arbitrary fashion when 'n' is zero even
when targeting processors whose shift-right instruction would either yield x
or 0 when shifting right by 32 bits, so the lack of any clear reason for code
to behave oddly (beyond "because the standard says it can") means nothing.

What do you think of the idea that most of the aliasing rules would be more
helpful for programmers and compilers alike if the were written in terms of
sequencing?  Given "void foo(int * restrict p1)", accesses made with pointers
based on p1 would be sequenced after the function is called, and before it
returns, but would be unsequenced relative to anything else that happens in
the universe.  If pointers to allocated storage are given to a function with
a signature like

    void foo(int *ip[static 100], float *fp[static 100]);

the present rules would seem to be roughly equivalent to saying that reads
via ip may be moved ahead of writes via fp, and reads of fp may be moved
ahead of writes via ip, but writes cannot be moved across other writes,
and reads cannot be moved behind writes.  Most accesses to character
pointers could not be moved at all relative to accesses using anything else,
though I've read that gcc doesn't think it necessary to keep writes to
character pointers sequenced with regard to other types.

Expressing rules in such a fashion would make it possible to better clarify
how pointers unions and structure members work, and would also make it
practical to have code specify that it could tolerate looser-than-normal
rules in places that don't specify explicit ordering requirements (e.g.
indicate that it won't rely upon the sequencing of character accesses with
regard to other types except in places where it uses sequencing barriers to
indicate such ordering).  I wonder if the Committee has explored any such
notions?  Since what compiler writers really need is freedom to reorder
effective memory accesses, and what programmers really need is a way to
know that ordering relations hold in certain narrow but important cases,
writing rules in such terms would make it easier to satisfy the needs of
both compiler writers and programmers.

[toc] | [prev] | [next] | [standalone]


#77308

FromTim Rentsch <txr@alumni.caltech.edu>
Date2015-11-27 23:38 -0800
Message-ID<kfntwo6y3ok.fsf@x-alumni2.alumni.caltech.edu>
In reply to#77234
Stephen Sprunk <stephen@sprunk.org> writes:

> On 25-Nov-15 19:16, Ben Bacarisse wrote:
>> Stephen Sprunk <stephen@sprunk.org> writes:
>>> This is where I think we need to reintroduce unions.  Does a
>>> union in static and/or auto storage benefit from the same
>>> guarantees as the allocated storage case above, as long as the
>>> compiler _knows_ it's dealing with a union?
>>
>> Sorry it's taken a while to get back to this.  I was not sure I
>> had the enthusiasm for more!
>>
>> I don't think simply giving a static buffer a union type helps.
>> Of course it's fine if everything knows about the union -- that's
>> what they are for -- but I don't think this:
>>
>>   void *alloc(void)
>>   {
>>       union types { int i; float f; };
>>       static union types storage[4];
>>       static int n;
>>       return &storage[n++ & 3];
>>   }
>>
>>   int *ip = alloc();
>>   *ip = 42;
>> ...
>
> I'll stop you right there and jump to the end:
>
>>> (Cases where you hide the union's nature are the next step, but
>>> let's not go there quite yet.)
>>
>> Is this such a case?  I was not sure what you meant by hiding
>> here.
>
> Yes.  Consider:
>
> union { float f; int i; } u, *up = &u;
> float *fp = &u.f; // or &up->f
> int *ip = &u.i; // or &up->i
>
> If you access u.f and u.i, or up->f and up->i, then the compiler
> knows it's dealing with a union and must act accordingly.  If you
> access *fp and *ip, however, the union's nature may become
> hidden--especially if passed to or returned from a function.
>
> A compiler _may_ be able to figure out that *fp and *ip point into
> the same union, but depending on how tricky your code is (or how
> dumb the compiler is), that may not be possible in all cases.
>
> OTOH, as long as you only access one of them (including after
> passing to or returning from a function), that seems perfectly
> fine since the union's nature is irrelevant in that case.
>
> Perhaps my mental model is backward (or just plain wrong), but it
> seems as if the effective type rules for allocated storage are
> simply treating such as unions of all possible types.

I've been wading through the discussion in this thread, looking
for a good place to jump in.  I guess here is okay.  There are
some general comments about aliasing and effective type rules
that should (at least IMO) be included in the discussion.

Effective type rules aren't the whole story for questions about
aliasing, and they aren't exactly right either.

WG14 knows this, and has for a long time (more than 10 years).

There has been work done in WG14 on getting a better formulation
of what's really required here, but that hasn't produced any
changes (as of C11) in the Standard.  I assume this is because
they aren't yet happy with any revised text that has been come up
with, and figure that the current text suffices for most purposes
(perhaps with specific questions being addressed in DR's), so
it's better to just leave the text as is for now.  (To repeat
myself, that last sentence is only my assumption.)

Attempting to parse the current wording of effective type rules
too closely may lead to incorrect conclusions.  To see what
really is required other documents should be consulted, and in
particular especially defect reports and the downstream material
that results from those.

If anyone is interested, a reasonable starting point is DR 219
and DR 236.

(End of general comments.)

One additional comment:  I have my own ideas/conclusions about
what is meant to be required here, but for this posting I am
limiting my remarks to statements that I believe everyone would
more or less agree on after looking at the historical evidence.

[toc] | [prev] | [next] | [standalone]


#77323

Fromsupercat@casperkitty.com
Date2015-11-28 07:22 -0800
Message-ID<e7bc690e-0de6-4916-8dcf-9f882273d529@googlegroups.com>
In reply to#77308
On Saturday, November 28, 2015 at 1:38:22 AM UTC-6, Tim Rentsch wrote:
> There has been work done in WG14 on getting a better formulation
> of what's really required here, but that hasn't produced any
> changes (as of C11) in the Standard.  I assume this is because
> they aren't yet happy with any revised text that has been come up
> with, and figure that the current text suffices for most purposes
> (perhaps with specific questions being addressed in DR's), so
> it's better to just leave the text as is for now.  (To repeat
> myself, that last sentence is only my assumption.)

What do you think of the idea of expressing rules in terms of sequencing?
While compatibility with earlier versions of C would preclude adding
stricter rules without directives indicating programmers were ready for
them, one could gain a lot of flexibility for compilers and programmers
alike if one said that given:

    void foo(int *i1, int *i2, char *c1, char *c2) ...

the accesses made via i1 and i2 would be Unsequenced relative to those
made via *c1 and *c2, **in the absence of other directives to force
sequencing**.  I don't think it makes sense to try to have the rules
vary depending upon what what the last thing stored via pointer happens
to be, and the C99 rules about copying via character arrays seem insane
since they're unclear about what one must do to copy bit patterns in
type-agnostic fashion, but the great thing about specifying the rules
in terms of sequencing is that it makes it very easy to offer "escape
hatches" which are much less harmful to efficiency than the "character
type" rules.

[toc] | [prev] | [next] | [standalone]


#78183

FromTim Rentsch <txr@alumni.caltech.edu>
Date2015-12-08 08:51 -0800
Message-ID<kfnzixkx4rc.fsf@x-alumni2.alumni.caltech.edu>
In reply to#77323
supercat@casperkitty.com writes:

> On Saturday, November 28, 2015 at 1:38:22 AM UTC-6, Tim Rentsch wrote:
>> There has been work done in WG14 on getting a better formulation
>> of what's really required here, but that hasn't produced any
>> changes (as of C11) in the Standard.  I assume this is because
>> they aren't yet happy with any revised text that has been come up
>> with, and figure that the current text suffices for most purposes
>> (perhaps with specific questions being addressed in DR's), so
>> it's better to just leave the text as is for now.  (To repeat
>> myself, that last sentence is only my assumption.)
>
> What do you think of the idea of expressing rules in terms of
> sequencing?  [...]

Personally I think it's not likely to be a fruitful direction,
but it doesn't really matter what I think - the question is
what would WG14 think?

[toc] | [prev] | [next] | [standalone]


#76957

Fromsupercat@casperkitty.com
Date2015-11-22 18:34 -0800
Message-ID<89b6e760-ea68-4509-aae2-81287fcb208b@googlegroups.com>
In reply to#76952
On Sunday, November 22, 2015 at 6:58:54 PM UTC-6, Ben Bacarisse wrote:
> The analysis must be done from the point of view of the C virtual
> machine, so *fp = 42; would make the effective type float first, and
> then *ip = 42; would make it int.  That is the last write before the
> valid access to *ip.  An implementation can re-order things in valid
> code only in so far as the result is undetectable.

I don't know that there's any sane way to interpret all the verbiage about
behavor with allocated objects in relation to what code which receives
pointers of unknown origin is allowed to do with them.  It would have been
a lot easier for the Standard to simply say that operations performed using
outer lvalues of sufficiently-different types will be unsequenced relative
to each other unless some special condition applies which would cause them
to be sequenced, in which case the rules describing the conditions that
would force sequencing would then not have to worry about where the objects
in question came from.

The hardships caused by the effective-type rules could easily be overcome
if there were suitable aliasing barriers to allow memory of any type to be
reused as any other, but defining the semantics of such barriers would first
require defining semantics in terms of sequencing.

[toc] | [prev] | [next] | [standalone]


#76981

FromJames Kuyper <jameskuyper@verizon.net>
Date2015-11-23 06:48 -0500
Message-ID<n2uu9e$5vv$1@dont-email.me>
In reply to#76952
On 11/22/2015 07:58 PM, Ben Bacarisse wrote:
> Stephen Sprunk <stephen@sprunk.org> writes:
> 
>> On 21-Nov-15 18:58, Ben Bacarisse wrote:
>>> Stephen Sprunk <stephen@sprunk.org> writes:
>>>> On 21-Nov-15 04:17, Ben Bacarisse wrote:
>>>>> It may well be able to re-order the writes but that does not make
>>>>> the code shown undefined.  It might break something else in the
>>>>> program, but the example is too brief to know.
>>>>
>>>> Okay, here's a very simple example:
>>>>
>>>> void foo(float *fp, int *ip) {
>>>>   *fp = 42.0;
>>>>   *ip = 42;
>>>>   printf("%d\n", *ip);
>>>> }
>>>>
>>>> If the compiler doesn't reorder the assignments, then the read is 
>>>> well-defined.  However, it is allowed to assume fp and ip are not 
>>>> aliases and thus reorder the assignments, but if they actually are 
>>>> aliases, then the read would become undefined.  Correct?
>>>
>>> I don't think so.  If ip and fp alias then they refer to some common 
>>> object.  If that has a declared type of int, then the assignment
>>> through *fp is undefined because it violates a "shall" in the
>>> standard. Similarly if it's an object declared to be float.  The read
>>> of *ip is not involved in any of that -- the code is already
>>> undefined before it gets there.

And the undefined behavior might take the form of causing this function
to malfunction because the writes are re-ordered. The fact that the
order only matters if they violate 6.5p7 is what allows the reordering.

>> Thanks; that explains why the pointers' origin matters.
>>
>>> But there is an other case.  If ip and fp both point to the same 
>>> properly sized and aligned allocated storage, then there is nothing 
>>> wrong with the above code.  The effective type rules mean that
>>> allocated storage gets it's effective type from the type of the
>>> lvalue expression last used to write it.

And 6.5p7 is violated by any attempt to write to that same location
using a type other than one of the ones listed in 6.5p7 - and if it is
one of those types, then the effective type remains unchanged. The
relevant verb is "access", which includes both reads and writes. It's
therefore only possible to set the effective type allocated memory; once
set, it cannot be changed.

>> That's where I keep getting hung up, so please excuse what probably
>> looks like a stupid question: does "last" really mean in source code
>> order, or could it mean "last" after the compiler reorders things?
> 
> The analysis must be done from the point of view of the C virtual
> machine, so *fp = 42; would make the effective type float first, and
> then *ip = 42; would make it int.  That is the last write before the
> valid access to *ip.  An implementation can re-order things in valid
> code only in so far as the result is undetectable.

If ip or fp violate anti-aliasing rules, the code is NOT valid - it has
undefined behavior.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#77003

FromKeith Thompson <kst-u@mib.org>
Date2015-11-23 08:28 -0800
Message-ID<lnoaek3ckd.fsf@kst-u.example.com>
In reply to#76981
James Kuyper <jameskuyper@verizon.net> writes:
[...]
> And 6.5p7 is violated by any attempt to write to that same location
> using a type other than one of the ones listed in 6.5p7 - and if it is
> one of those types, then the effective type remains unchanged. The
> relevant verb is "access", which includes both reads and writes. It's
> therefore only possible to set the effective type allocated memory; once
> set, it cannot be changed.
[...]

The definition of "access" (3.1) is:

    <execution-time action> to read or modify the value of an object

6.5p7 says (emphasis added):

    An object shall have *its stored value* accessed only by an lvalue
    expression that has one of the following types:
    ...

Writing to an object certainly accesses the object, but I wouldn't say
that it accesses the value of the object.  In fact I don't think
"accessing a value" is even defined.

    int i;
    i = 42;

The assignment accesses the object i, but not its value.  The value
before the assignment is indeterminate, and could be a trap
representation, but no undefined behavior occurs.

It's plausible that 6.5p7 is *intended* to refer to accessing the object
rather than its value (i.e., that it's meant to apply to both reads and
writes), but the wording is not as clear as it should be.

Perhaps 6.5p7 should be reworded to:

    An object shall be accessed only by an lvalue expression that has
    one of the following types:
    ...

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


Page 2 of 8 — ← Prev page 1 [2] 3 4 5 6 7 8  Next page →

Back to top | Article view | comp.lang.c


csiph-web