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


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

Sugestions for runtime polymorphism

Started byThiago Adams <thiago.adams@gmail.com>
First post2016-09-14 12:01 -0700
Last post2016-09-15 11:23 -0700
Articles 20 on this page of 99 — 14 participants

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


Contents

  Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-14 12:01 -0700
    Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-14 13:15 -0700
    Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-14 13:27 -0700
      Re: Sugestions for runtime polymorphism Richard Heathfield <rjh@cpax.org.uk> - 2016-09-14 21:50 +0100
        Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-14 14:20 -0700
          Re: Sugestions for runtime polymorphism "James R. Kuyper" <jameskuyper@verizon.net> - 2016-09-14 17:32 -0400
            Re: Sugestions for runtime polymorphism Keith Thompson <kst-u@mib.org> - 2016-09-14 16:30 -0700
              Re: Sugestions for runtime polymorphism "James R. Kuyper" <jameskuyper@verizon.net> - 2016-09-14 17:54 -0400
            Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-14 17:34 -0700
              Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-14 17:58 -0700
                Re: Sugestions for runtime polymorphism Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-14 19:50 -0700
                  Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-15 05:03 -0700
                Re: Sugestions for runtime polymorphism BartC <bc@freeuk.com> - 2016-09-15 10:43 +0100
                  Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-15 05:29 -0700
                    Re: Sugestions for runtime polymorphism BartC <bc@freeuk.com> - 2016-09-15 19:49 +0100
                      Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-15 11:58 -0700
                        Re: Sugestions for runtime polymorphism BartC <bc@freeuk.com> - 2016-09-15 20:29 +0100
                          Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-15 14:00 -0700
                            Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-16 07:27 -0700
                              Re: Sugestions for runtime polymorphism BartC <bc@freeuk.com> - 2016-09-16 16:34 +0100
                                Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-16 09:36 -0700
                                  Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-20 12:59 -0700
                                    Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-20 14:08 -0700
                                      Re: Sugestions for runtime polymorphism Ian Collins <ian-news@hotmail.com> - 2016-09-21 15:53 +1200
                                        Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-21 07:38 -0700
                                          Re: Sugestions for runtime polymorphism Ian Collins <ian-news@hotmail.com> - 2016-09-23 09:12 +1200
                                      Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-21 05:26 -0700
                                        Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-21 05:35 -0700
                                        Re: Sugestions for runtime polymorphism Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-21 06:01 -0700
                                        Re: Sugestions for runtime polymorphism Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-22 01:44 -0700
                                          Re: Sugestions for runtime polymorphism BartC <bc@freeuk.com> - 2016-09-22 13:16 +0100
                                            Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-22 08:02 -0700
                                              Re: Sugestions for runtime polymorphism Keith Thompson <kst-u@mib.org> - 2016-09-22 11:44 -0700
                                                Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-22 09:52 -0700
                                                  Re: Sugestions for runtime polymorphism David Brown <david.brown@hesbynett.no> - 2016-09-23 09:49 +0200
                                                    Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-23 07:55 -0700
                                                      Re: Sugestions for runtime polymorphism David Brown <david.brown@hesbynett.no> - 2016-09-24 16:29 +0200
                                                        Re: Sugestions for runtime polymorphism Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-09-24 15:56 +0100
                                                          Re: Sugestions for runtime polymorphism David Brown <david.brown@hesbynett.no> - 2016-09-24 17:50 +0200
                                                            Re: Sugestions for runtime polymorphism "James R. Kuyper" <jameskuyper@verizon.net> - 2016-09-24 13:45 -0400
                                                              Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-24 11:26 -0700
                                                                Re: Sugestions for runtime polymorphism Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-28 10:38 -0700
                                                            Re: Sugestions for runtime polymorphism Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-09-24 21:03 +0100
                                                              Re: Sugestions for runtime polymorphism David Brown <david.brown@hesbynett.no> - 2016-09-25 12:43 +0200
                                                                Re: Sugestions for runtime polymorphism "James R. Kuyper" <jameskuyper@verizon.net> - 2016-09-25 11:48 -0400
                                                                  Re: Sugestions for runtime polymorphism David Brown <david.brown@hesbynett.no> - 2016-09-25 18:39 +0200
                                                                    Re: Sugestions for runtime polymorphism "James R. Kuyper" <jameskuyper@verizon.net> - 2016-09-25 13:14 -0400
                                                                      Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-25 13:47 -0700
                                                                        Re: Sugestions for runtime polymorphism Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-28 10:39 -0700
                                                                      Re: Sugestions for runtime polymorphism David Brown <david.brown@hesbynett.no> - 2016-09-25 23:25 +0200
                                                                    Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-25 13:10 -0700
                                                                  Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-25 12:55 -0700
                                                                Re: Sugestions for runtime polymorphism Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-09-25 20:38 +0100
                                                                  Re: Sugestions for runtime polymorphism David Brown <david.brown@hesbynett.no> - 2016-09-25 23:20 +0200
                                                                  Re: Sugestions for runtime polymorphism Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-28 07:15 -0700
                                                                    Re: Sugestions for runtime polymorphism David Brown <david.brown@hesbynett.no> - 2016-09-28 21:29 +0200
                                                          Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-24 10:52 -0700
                                                        Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-24 10:33 -0700
                                                          Re: Sugestions for runtime polymorphism David Brown <david.brown@hesbynett.no> - 2016-09-25 12:46 +0200
                                                      Re: Sugestions for runtime polymorphism Keith Thompson <kst-u@mib.org> - 2016-09-24 13:58 -0700
                                                        Re: Sugestions for runtime polymorphism Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-28 04:46 -0700
                                                    Re: Sugestions for runtime polymorphism Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-24 00:07 -0700
                                            Re: Sugestions for runtime polymorphism Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-23 08:52 -0700
                                              Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-23 09:56 -0700
                                                Re: Sugestions for runtime polymorphism Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-23 12:00 -0700
                                      Re: Sugestions for runtime polymorphism Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-22 08:45 -0700
                                        Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-22 09:36 -0700
                                          Re: Sugestions for runtime polymorphism Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-23 12:06 -0700
                                            Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-23 15:29 -0700
                              Re: Sugestions for runtime polymorphism Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-29 07:56 -0700
                                Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-30 10:54 -0700
                                  Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-30 11:18 -0700
                                    Re: Sugestions for runtime polymorphism BartC <bc@freeuk.com> - 2016-09-30 19:26 +0100
                                    Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-30 12:41 -0700
                                      Re: Sugestions for runtime polymorphism Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-09-30 21:07 +0100
                                  Re: Sugestions for runtime polymorphism Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-30 23:30 -0700
                                    Re: Sugestions for runtime polymorphism Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-10-01 11:35 +0100
                                    Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-10-01 14:44 -0700
          Re: Sugestions for runtime polymorphism Richard Heathfield <rjh@cpax.org.uk> - 2016-09-14 22:56 +0100
            Re: Sugestions for runtime polymorphism David Brown <david.brown@hesbynett.no> - 2016-09-15 13:19 +0200
              Re: Sugestions for runtime polymorphism James Kuyper <jameskuyper@verizon.net> - 2016-09-15 08:07 -0400
                Re: Sugestions for runtime polymorphism David Brown <david.brown@hesbynett.no> - 2016-09-15 14:24 +0200
                  Re: Sugestions for runtime polymorphism Richard Heathfield <rjh@cpax.org.uk> - 2016-09-15 15:34 +0100
              Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-15 05:10 -0700
            Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-15 09:12 -0700
          Re: Sugestions for runtime polymorphism BartC <bc@freeuk.com> - 2016-09-14 23:32 +0100
          Re: Sugestions for runtime polymorphism "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-09-14 17:35 -0700
          Re: Sugestions for runtime polymorphism Ian Collins <ian-news@hotmail.com> - 2016-09-15 16:24 +1200
            Re: Sugestions for runtime polymorphism Keith Thompson <kst-u@mib.org> - 2016-09-15 10:31 -0700
      Re: Sugestions for runtime polymorphism BartC <bc@freeuk.com> - 2016-09-14 22:53 +0100
        Re: Sugestions for runtime polymorphism Keith Thompson <kst-u@mib.org> - 2016-09-14 16:56 -0700
          Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-14 15:58 -0700
            Re: Sugestions for runtime polymorphism Keith Thompson <kst-u@mib.org> - 2016-09-14 18:49 -0700
    Re: Sugestions for runtime polymorphism luser droog <luser.droog@gmail.com> - 2016-09-14 14:17 -0700
      Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-14 14:25 -0700
        Re: Sugestions for runtime polymorphism luser droog <luser.droog@gmail.com> - 2016-09-14 14:40 -0700
        Re: Sugestions for runtime polymorphism luser droog <luser.droog@gmail.com> - 2016-09-14 14:57 -0700
        Re: Sugestions for runtime polymorphism BartC <bc@freeuk.com> - 2016-09-14 23:10 +0100
    Re: Sugestions for runtime polymorphism Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-15 11:23 -0700

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


#93639

FromThiago Adams <thiago.adams@gmail.com>
Date2016-09-16 09:36 -0700
Message-ID<e06bdc46-44cb-418e-8783-94c3147871f3@googlegroups.com>
In reply to#93627
On Friday, September 16, 2016 at 12:35:10 PM UTC-3, Bart wrote:
> On 16/09/2016 15:27, Thiago Adams wrote:
> >
> > Probably I will do this: (maybe this is my last version before implement)
> >
> > Any suggestion is welcome.
> >
> >
> > typedef enum {
> >   CatType,
> >   BananaType,
> >   AirplaneType
> > } Type;
> >
> > typedef struct
> > {
> >   Type type;
> >   int color;
> > } Banana;
> >
> > typedef struct
> > {
> >   Type type;
> >   int color;
> > } Cat;
> >
> > typedef struct TAirplane
> > {
> >   Type type;
> >   int color;
> > } Airplane;
> >
> >
> > typedef union {
> >   Cat* pCat;
> >   Banana* pBanana;
> > } Node2;
> >
> > typedef union {
> >   Airplane* pAirplane;
> >   Banana* pBanana;
> > } Node1;
> >
> > #define IS_TYPE(X, T) (((struct {Type type;}*) (&X))->type == T)
> >
> > int main()
> > {
> >     Node1 node;
> >     node.pAirplane = malloc(sizeof *node.pAirplane);
> >     node.pAirplane->type = AirplaneType;
> >
> >     if (IS_TYPE(node, AirplaneType))
> >     {
> >       //yes I am an airplane
> >     }
> >
> >     return 0;
> > }
> 
> It looks good, especially with the short, snappy identifiers.
> 
> However, you might consider taking the Type outside of the Airplane, 
> Banana and Cat structs. After all each struct knows what it is!
> 
> -- 
> Bartc

For the symbols, I think I will have a hash table pointing to the AST. 
So, I am not sure now, if I will point to something that I need to check the type. So, for now, I left the type intrusive. 

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


#93867

FromThiago Adams <thiago.adams@gmail.com>
Date2016-09-20 12:59 -0700
Message-ID<8e6459ac-a363-487b-96d8-3585fad04dd5@googlegroups.com>
In reply to#93639
After the second level of -> it was too complicated to identify what was "cast" and what was "child of", so, I gave up the union solution. 
The syntax also was uncommon.

//All this line could be 1 pointer
p->Type1->Type2->Type3

Now, I will use typedefs but they will work like tips - No check at compile time.

For instance:

typedef enum
{
//...
    TypeFuncVarDeclaration,
    TypeAssertDeclaration
//...
} Type;

//Works as a "base class"
typedef struct
{
    Type type;
} ObjectWithType;

typedef struct
{
    Type type;
    //more...
} TAssertDeclaration;

typedef struct
{
    Type type;
    //more...
} TFuncVarDeclaration;


//TAssertDeclaration | TFuncVarDeclaration
typedef ObjectWithType TDeclaration;

void TDeclaration_Delete(TDeclaration* pDeclaration);

I can add some run-time checks with asserts.
For instance:

void TDeclaration_Delete(TDeclaration* pDeclaration)
{
   assert(pDeclaration->type = TypeFuncVarDeclaration ||
          pDeclaration->type = TAssertDeclaration);
   //...
}


------

So, what I would like of one "external type system check" was the ability 
to check if the casts make sense at compile time.

TAssertDeclaration p = ...
(TDeclaration*) p2 = p; //OK
(TOther*) p2 = p; //ERROR

//@typedef TAssertDeclaration | TFuncVarDeclaration TDeclaration;

TDeclaration is a type with the intersection of TAssertDeclaration and TFuncVarDeclaration;

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


#93870

Fromsupercat@casperkitty.com
Date2016-09-20 14:08 -0700
Message-ID<7ee4b7c9-5d16-40bf-acb0-738ae7e3bc86@googlegroups.com>
In reply to#93867
On Tuesday, September 20, 2016 at 3:00:06 PM UTC-5, Thiago Adams wrote:
> Now, I will use typedefs but they will work like tips - No check at compile time.
> 
> For instance:
> //Works as a "base class"
> typedef struct
> {
>     Type type;
> } ObjectWithType;
> 
> typedef struct
> {
>     Type type;
>     //more...
> } TAssertDeclaration;
> 
> typedef struct
> {
>     Type type;
>     //more...
> } TFuncVarDeclaration;

At least among microcomputer programming circles code like the above would
have been considered non-controversial in the 1990s (I have no idea what
mainframe compilers were doing).  The authors of the C99 Standard added
a requirement that if a T1* is used to access members of the common initial
sequence of a T2, then a declaration of a complete union type containing
both T1 and T2 must be visible to the compiler at the point where the
objects are used.  If compiler writers recognize that a major purpose of the
CIS was to allow code similar to what you show, and avoid making aliasing
assumptions if such a declaration is visible at *either* the places where the
type is used as a T1 or at places where it is used as a T2, the requirement
for a visible union declaration will not adversely affect the semantic
usefulness of the construct.

Unfortunately, the authors of gcc have no interest in supporting such
constructs except in "-fno-strict-aliasing" mode.  While some people claim
the language never supported such constructs, they were supported in
commonplace implementations, and such support was semantically useful.
Today, however, code which relies upon such useful semantics is viewed by
compiler writers as "broken".

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


#93871

FromIan Collins <ian-news@hotmail.com>
Date2016-09-21 15:53 +1200
Message-ID<e4eei6Fm7t3U1@mid.individual.net>
In reply to#93870
On 09/21/16 09:08 AM, supercat@casperkitty.com wrote:
> On Tuesday, September 20, 2016 at 3:00:06 PM UTC-5, Thiago Adams wrote:
>> Now, I will use typedefs but they will work like tips - No check at compile time.
>>
>> For instance:
>> //Works as a "base class"
>> typedef struct
>> {
>>      Type type;
>> } ObjectWithType;
>>
>> typedef struct
>> {
>>      Type type;
>>      //more...
>> } TAssertDeclaration;
>>
>> typedef struct
>> {
>>      Type type;
>>      //more...
>> } TFuncVarDeclaration;
>
> At least among microcomputer programming circles code like the above would
> have been considered non-controversial in the 1990s (I have no idea what
> mainframe compilers were doing).  The authors of the C99 Standard added
> a requirement that if a T1* is used to access members of the common initial
> sequence of a T2, then a declaration of a complete union type containing
> both T1 and T2 must be visible to the compiler at the point where the
> objects are used.

The use of a containing union has also been around for decades; the X11 
XEvent is a good example.

-- 
Ian

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


#93876

Fromsupercat@casperkitty.com
Date2016-09-21 07:38 -0700
Message-ID<548c3be9-5c69-4362-b27c-707b738841be@googlegroups.com>
In reply to#93871
On Tuesday, September 20, 2016 at 10:53:52 PM UTC-5, Ian Collins wrote:
> > At least among microcomputer programming circles code like the above would
> > have been considered non-controversial in the 1990s (I have no idea what
> > mainframe compilers were doing).  The authors of the C99 Standard added
> > a requirement that if a T1* is used to access members of the common initial
> > sequence of a T2, then a declaration of a complete union type containing
> > both T1 and T2 must be visible to the compiler at the point where the
> > objects are used.
> 
> The use of a containing union has also been around for decades; the X11 
> XEvent is a good example.

Are you referring to the practice of having a number of types that start
with the same fields, and having a function receive a pointer to a "generic"
object that starts with those fields?  What role do you see the union as
playing?  If the structures have massively different sizes, it's not
practical to require that all instances be declared as union instances, and
the Standard does not in general allow a pointer to an object which is not
a union instance to be cast to a pointer to a union type containing a
member of that type.  If there were a form of quasi-union type such that
a pointer to any type could be cast to any quasi-union type with a member
of that type, provided that the pointer was only used to access suitably-
aligned members, that would fix a lot of semantic weaknesses, but at present
C includes no such types.

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


#93918

FromIan Collins <ian-news@hotmail.com>
Date2016-09-23 09:12 +1200
Message-ID<e4ivqhF9kntU1@mid.individual.net>
In reply to#93876
On 09/22/16 02:38 AM, supercat@casperkitty.com wrote:
> On Tuesday, September 20, 2016 at 10:53:52 PM UTC-5, Ian Collins wrote:
>>> At least among microcomputer programming circles code like the above would
>>> have been considered non-controversial in the 1990s (I have no idea what
>>> mainframe compilers were doing).  The authors of the C99 Standard added
>>> a requirement that if a T1* is used to access members of the common initial
>>> sequence of a T2, then a declaration of a complete union type containing
>>> both T1 and T2 must be visible to the compiler at the point where the
>>> objects are used.
>>
>> The use of a containing union has also been around for decades; the X11
>> XEvent is a good example.
>
> Are you referring to the practice of having a number of types that start
> with the same fields, and having a function receive a pointer to a "generic"
> object that starts with those fields?

Looking back to some old (early 90s) code, we used message structs in 
enums in the same way as XEvent.  XEvent its self is quite old!

> What role do you see the union as
> playing?  If the structures have massively different sizes, it's not
> practical to require that all instances be declared as union instances, and
> the Standard does not in general allow a pointer to an object which is not
> a union instance to be cast to a pointer to a union type containing a
> member of that type.

Code had to work with any message, so enum size problem was moot.

-- 
Ian

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


#93872

FromThiago Adams <thiago.adams@gmail.com>
Date2016-09-21 05:26 -0700
Message-ID<9179e698-fe07-416c-a885-cca3f6b5d606@googlegroups.com>
In reply to#93870
On Tuesday, September 20, 2016 at 6:09:28 PM UTC-3, supe...@casperkitty.com wrote:
> On Tuesday, September 20, 2016 at 3:00:06 PM UTC-5, Thiago Adams wrote:
> > Now, I will use typedefs but they will work like tips - No check at compile time.
> > 
> > For instance:
> > //Works as a "base class"
> > typedef struct
> > {
> >     Type type;
> > } ObjectWithType;
> > 
> > typedef struct
> > {
> >     Type type;
> >     //more...
> > } TAssertDeclaration;
> > 
> > typedef struct
> > {
> >     Type type;
> >     //more...
> > } TFuncVarDeclaration;
> 
> At least among microcomputer programming circles code like the above would
> have been considered non-controversial in the 1990s (I have no idea what
> mainframe compilers were doing).  The authors of the C99 Standard added
> a requirement that if a T1* is used to access members of the common initial
> sequence of a T2, then a declaration of a complete union type containing
> both T1 and T2 must be visible to the compiler at the point where the
> objects are used.  If compiler writers recognize that a major purpose of the
> CIS was to allow code similar to what you show, and avoid making aliasing
> assumptions if such a declaration is visible at *either* the places where the
> type is used as a T1 or at places where it is used as a T2, the requirement
> for a visible union declaration will not adversely affect the semantic
> usefulness of the construct.
> 
> Unfortunately, the authors of gcc have no interest in supporting such
> constructs except in "-fno-strict-aliasing" mode.  While some people claim
> the language never supported such constructs, they were supported in
> commonplace implementations, and such support was semantically useful.
> Today, however, code which relies upon such useful semantics is viewed by
> compiler writers as "broken".

So, how to fix it?

I need to allocate these structures on the heap. 

Can I allocate less memory than the union, If I promises that I will not change the type? See "ParseModified"



(Where XEvent is created, on the stack?)

typedef struct
{
  int type;
} ObjectWithType;

typedef struct
{
  int type;
  //more... 
} TAssertDeclaration;

typedef struct
{
  int type;
  //more... 
} TFuncVarDeclaration;

typedef union
{
  int type;
  ObjectWithType ObjectWithType;
  TAssertDeclaration AssertDeclaration;
  TFuncVarDeclaration FuncVarDeclaration;
} Declaration;

//???
void ParseModified(Declaration** pp)
{
  TFuncVarDeclaration * pFuncVarDeclaration = malloc(sizeof* pFuncVarDeclaration);

  //I promise, I will not change the type 
  *pp = (Declaration*)pFuncVarDeclaration;
}


void Parse(Declaration** pp)
{
  Declaration * pDeclaration = malloc(sizeof* pDeclaration);
  //pDeclaration->FuncVarDeclaration = ...
  *pp = pDeclaration;
}

int main()
{
  Declaration* p;

  Parse(&p);

  return 0;
}

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


#93873

FromThiago Adams <thiago.adams@gmail.com>
Date2016-09-21 05:35 -0700
Message-ID<21a06cbd-1bc3-4fd0-a05a-9c7eecddb030@googlegroups.com>
In reply to#93872
I am avoiding a non-intrusive type like this:

struct TypePtr
{
  int type;
  void *p;
};

struct TypePtr
{
  int type;
  union {
    T1 *p1;
    T2 *p2;
  };
};

Because I will have two pointers pointing for the same object, and then the "type" will be duplicated. 

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


#93874

FromMalcolm McLean <malcolm.mclean5@btinternet.com>
Date2016-09-21 06:01 -0700
Message-ID<e90c387f-5e5a-4662-a542-659edce1f7a7@googlegroups.com>
In reply to#93872
On Wednesday, September 21, 2016 at 1:26:35 PM UTC+1, Thiago Adams wrote:
> On Tuesday, September 20, 2016 at 6:09:28 PM UTC-3, supe...@casperkitty.com wrote:
>
> I need to allocate these structures on the heap. 
> 
> Can I allocate less memory than the union, If I promises that I will not change the type? See "ParseModified"
> 
> (Where XEvent is created, on the stack?)
> 
> typedef struct
> {
>   int type;
> } ObjectWithType;
> 
> typedef struct
> {
>   int type;
>   //more... 
> } TAssertDeclaration;
> 
>
Yes, but I'm not sure about unions.

The first field in a structure s guaranteed to be aligned with the structure
itself and be first in memory. Precisely so you can do that sort of thing.
Pass the data about as void *s, then when you need to retrieve, cast
to ObjectWithType, retrieve the type tag, then cast to whatever the
structure is identified as. 

However if you declare a big union I'm not sure what happens if you also
declare a pointer to it that contains only one of the smaller members.
I suspect it will usually work but is formally forbidden. 

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


#93886

FromTim Rentsch <txr@alumni.caltech.edu>
Date2016-09-22 01:44 -0700
Message-ID<kfn8tukfhmp.fsf@x-alumni2.alumni.caltech.edu>
In reply to#93872
Thiago Adams <thiago.adams@gmail.com> writes:

> [accomplishing type changing using a 'union' pattern]
>
> So, how to fix it?
>
> I need to allocate these structures on the heap.

I suggest following a pattern like the following.  First,
the interface/header part:

    /****************************************************/
    /* Header file */

    typedef enum object_type_encoding_e {
        OT_bogus,
        OT_Foo,
        OT_Bas,
        /*...etc...*/
        OT_no_more_values
    } object_type_encoding;


    typedef struct object_s {
        object_type_encoding type;
    } *Object;                       /* This is the generic type */


    typedef struct foo_s *Foo;       /* These are subtypes */
    typedef struct bas_s *Bas;
    /*...etc...*/


    /* These functions provide type conversion */
    static inline Foo as_Foo( Object it ){ return (Foo)it; }
    static inline Bas as_Bas( Object it ){ return (Bas)it; }
    /*...etc...*/


    struct foo_s {
        struct object_s prefix;
        unsigned florble;
        /* ... */
    };                                 /* An example subtype struct */

    struct bas_s {
        struct object_s prefix;
        double blarble;
        /* ... */
    };                                 /* An example subtype struct */

    /*...etc...*/                      /* .. more of the above .. */


Next, an example of usage, and functions illustrating how new
instances are created and initialized.

    /******************************************************/
    /* .c file (or more, for the constructors, if wanted) */

    int
    example_usage( Object it ){
        switch(  it->type  ){
            case  OT_Foo:   return  as_Foo(it)->florble;
            case  OT_Bas:   return  as_Bas(it)->blarble;
            default:        return  -1;
        }
    }


    #include <stdlib.h>

    Object
    new_Foo(){
        Foo result = malloc( sizeof *result );
        /* .. check for null return value .. */
        result->prefix.type = OT_Foo;
        result->florble = 0;
        /* ... */
        return  &result->prefix;
    }

    Object
    new_Bas(){
        Bas result = malloc( sizeof *result );
        /* .. check for null return value .. */
        result->prefix.type = OT_Bas;
        result->blarble = 0;
        /* ... */
        return  &result->prefix;
    }

    /*...etc...*/


Taking an approach along these lines gets rid of any need to use
unions, and the behavior it relies on is blessed by the Standard.
As long as uses of the conversion functions are predicated on
the appropriate type tag being found, it's all type safe and
everything is copacetic.  (Of course the constructor functions
have to put correct values in the type tag field of the struct
too.)

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


#93891

FromBartC <bc@freeuk.com>
Date2016-09-22 13:16 +0100
Message-ID<ns0i2u$nb8$1@dont-email.me>
In reply to#93886
On 22/09/2016 09:44, Tim Rentsch wrote:
> Thiago Adams <thiago.adams@gmail.com> writes:
>
>> [accomplishing type changing using a 'union' pattern]

>     /* These functions provide type conversion */
>     static inline Foo as_Foo( Object it ){ return (Foo)it; }
>     static inline Bas as_Bas( Object it ){ return (Bas)it; }

> Taking an approach along these lines gets rid of any need to use
> unions, and the behavior it relies on is blessed by the Standard.

So you've got rid of unions by using casts everywhere instead 
(presumably as being the lesser 'evil').

But unions result in less intrusion within the code.

(Also, depending on the actual arrangement, they can make it easier to 
share common fields other than just .type.)

-- 
Bartc

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


#93898

Fromsupercat@casperkitty.com
Date2016-09-22 08:02 -0700
Message-ID<09902938-21f0-4c45-9d71-bde7b5398bd2@googlegroups.com>
In reply to#93891
On Thursday, September 22, 2016 at 7:16:46 AM UTC-5, Bart wrote:
> So you've got rid of unions by using casts everywhere instead 
> (presumably as being the lesser 'evil').
> 
> But unions result in less intrusion within the code.
> 
> (Also, depending on the actual arrangement, they can make it easier to 
> share common fields other than just .type.)

It's best to think of C as two languages--one which became popular in the
1990s because it was designed to allow a simple compiler to achieve decent
performance on typical microcomputer and minicomputer platforms, and one
which is designed for fancier compilers but only allows programmers to
achieve desired semantics by expressing things in much clunkier fashion in
the hopes that a compiler will turn them into something efficient.  The
techniques you like are supported by the former language, but not the latter.

Note that gcc does not (as of 6.2) reliably handle code that uses memory
as different types at different times *even in cases which are 100%
unambiguously defined by the Standard*.  If code can afford to use malloc
and free every time memory is re-purposed, allowing a compiler to regard
operations on different types as unsequenced relative to each other may
sometimes offer useful performance gains.  If achieving good performance
would require repurposing memory, however, using -fno-strict-aliasing will
be more reliable than trying to abide by the Standard and hope that gcc's
optimization bugs don't break your code.

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


#93909

FromKeith Thompson <kst-u@mib.org>
Date2016-09-22 11:44 -0700
Message-ID<lnvaxnvkp9.fsf@kst-u.example.com>
In reply to#93898
supercat@casperkitty.com writes:
[...]
> Note that gcc does not (as of 6.2) reliably handle code that uses memory
> as different types at different times *even in cases which are 100%
> unambiguously defined by the Standard*.

Have you submitted a bug report (or can you cite an existing one)?

-- 
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]


#93913

Fromsupercat@casperkitty.com
Date2016-09-22 09:52 -0700
Message-ID<233fb759-60f4-4113-ba1c-0949c8fdb924@googlegroups.com>
In reply to#93909
On Thursday, September 22, 2016 at 10:49:09 AM UTC-5, Keith Thompson wrote:
> supercat writes:
> [...]
> > Note that gcc does not (as of 6.2) reliably handle code that uses memory
> > as different types at different times *even in cases which are 100%
> > unambiguously defined by the Standard*.
> 
> Have you submitted a bug report (or can you cite an existing one)?

I've observed the behavior and posted about it here.  People who actually
use gcc may want to file a bug report.

I do not believe it is possible, practical, or useful for a compiler to
try to exploit every possible aliasing optimization which the Standard
does not forbid.  The easiest bug fix would be to have gcc apply a less
aggressive form of optimization which would be compatible with a lot of
code which otherwise requires -fno-strict-aliasing, but I see no reason
to believe the authors of gcc are interested in such an approach.

Aliasing bugs exist because the authors of gcc are taking rules that were
written to facilitate simple optimizations and trying to use them in ways
for which they were never designed, thus creating many more corner cases
than the authors of the Standard could reasonably have intended.  Even
if the maintainers of gcc manage to fix many wrongly-handled cases I see
no reason to believe they'll ever find them all.

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


#93930

FromDavid Brown <david.brown@hesbynett.no>
Date2016-09-23 09:49 +0200
Message-ID<ns2mq7$bqh$1@dont-email.me>
In reply to#93913
On 22/09/16 18:52, supercat@casperkitty.com wrote:
> On Thursday, September 22, 2016 at 10:49:09 AM UTC-5, Keith Thompson wrote:
>> supercat writes:
>> [...]
>>> Note that gcc does not (as of 6.2) reliably handle code that uses memory
>>> as different types at different times *even in cases which are 100%
>>> unambiguously defined by the Standard*.
>>
>> Have you submitted a bug report (or can you cite an existing one)?
> 
> I've observed the behavior and posted about it here.  People who actually
> use gcc may want to file a bug report.
> 
> I do not believe it is possible, practical, or useful for a compiler to
> try to exploit every possible aliasing optimization which the Standard
> does not forbid.  The easiest bug fix would be to have gcc apply a less
> aggressive form of optimization which would be compatible with a lot of
> code which otherwise requires -fno-strict-aliasing, but I see no reason
> to believe the authors of gcc are interested in such an approach.
> 
> Aliasing bugs exist because the authors of gcc are taking rules that were
> written to facilitate simple optimizations and trying to use them in ways
> for which they were never designed, thus creating many more corner cases
> than the authors of the Standard could reasonably have intended.  Even
> if the maintainers of gcc manage to fix many wrongly-handled cases I see
> no reason to believe they'll ever find them all.
> 

Your first claim was that gcc (6.2) incorrectly handles code in a way
that goes against the unambiguous rules of the standards.  This is a
serious allegation, and should be backed up with concrete examples and
bug reports.  The gcc team take all "incorrect code generation" bugs
extremely seriously.  And while /you/ might not use gcc, millions of
others do use it.  Someone here (such as me) will happily file a bug
report if you have a specific bug.

But now you have modified back to your usual "gcc optimises too well -
it follows the requirements of the real C standards, rather than my
imaginary specifications of thirty years ago".

So which is it?  Can you give us a concrete example of buggy code, that
we can paste into <http://gcc.godbolt.org/#> and compare results with
different gcc versions and different compilers?  You can't just refer to
"I've posted about it before" - you have posted hundreds or thousands of
snippets in this group.


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


#93948

Fromsupercat@casperkitty.com
Date2016-09-23 07:55 -0700
Message-ID<58c2a8d6-5609-458e-93f9-0811123a96ff@googlegroups.com>
In reply to#93930
On Friday, September 23, 2016 at 2:49:43 AM UTC-5, David Brown wrote:
> On 22/09/16 18:52, supercat wrote:
> Your first claim was that gcc (6.2) incorrectly handles code in a way
> that goes against the unambiguous rules of the standards.  This is a
> serious allegation, and should be backed up with concrete examples and
> bug reports.  The gcc team take all "incorrect code generation" bugs
> extremely seriously.  And while /you/ might not use gcc, millions of
> others do use it.  Someone here (such as me) will happily file a bug
> report if you have a specific bug.
> 
> But now you have modified back to your usual "gcc optimises too well -
> it follows the requirements of the real C standards, rather than my
> imaginary specifications of thirty years ago".
> 
> So which is it?  Can you give us a concrete example of buggy code, that
> we can paste into <http://gcc.godbolt.org/#> and compare results with
> different gcc versions and different compilers?  You can't just refer to
> "I've posted about it before" - you have posted hundreds or thousands of
> snippets in this group.

    #include <stdint.h>
    #include <string.h>
    #include <stdlib.h>
    #include <stdio.h>

    typedef long long T1;
    typedef int64_t T2;
    #define T1FMT "%lld"
    #define T1VALUE 1
    #define T2VALUE 2

    T1 blah3(void *p1, void *p2)
    {
      T1 *t1p, *t1p2;
      T2 *t2p;
      T1 temp;

      t1p = p1;
      t2p = p2;
      *t1p = T1VALUE;   // Write as T1
      *t2p = T2VALUE;   // Write as T2
      temp = *t2p;      // Read as T2
      t1p2 = (T1*)t2p;  // Visible T2 to T1 pointer conversion
      *t1p2 = temp;     // Write as T1
      return *t1p;      // Read as T1
    }

    T1 test3(void)
    {
      void *p = malloc(sizeof (T1) + sizeof (T2));
      T1 result = blah3(p,p);
      free(p);
      return result;
    }
    int main(void)
    {
      T1 result = test3();
      printf("The result is " T1FMT, result);
      return 0;      
    }

Since you wanted me to dig it up, here's the example I posted before.

https://godbolt.org/g/75oLGx

The visible pointer conversion I mention in the comments shouldn't affect
conformity (reading the variable to "temp" and writing it back in two
separate operations makes things defined regardless) but should provide a
second hint to the compiler that it should be cautious about trying to
cache values of type T1.

So there's a sample of buggy code.  Similar thing can happen if there are
two structure types that have the same representation.

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


#93977

FromDavid Brown <david.brown@hesbynett.no>
Date2016-09-24 16:29 +0200
Message-ID<ns62k1$i6j$1@dont-email.me>
In reply to#93948
On 23/09/16 16:55, supercat@casperkitty.com wrote:
> On Friday, September 23, 2016 at 2:49:43 AM UTC-5, David Brown wrote:
>> On 22/09/16 18:52, supercat wrote:
>> Your first claim was that gcc (6.2) incorrectly handles code in a way
>> that goes against the unambiguous rules of the standards.  This is a
>> serious allegation, and should be backed up with concrete examples and
>> bug reports.  The gcc team take all "incorrect code generation" bugs
>> extremely seriously.  And while /you/ might not use gcc, millions of
>> others do use it.  Someone here (such as me) will happily file a bug
>> report if you have a specific bug.
>>
>> But now you have modified back to your usual "gcc optimises too well -
>> it follows the requirements of the real C standards, rather than my
>> imaginary specifications of thirty years ago".
>>
>> So which is it?  Can you give us a concrete example of buggy code, that
>> we can paste into <http://gcc.godbolt.org/#> and compare results with
>> different gcc versions and different compilers?  You can't just refer to
>> "I've posted about it before" - you have posted hundreds or thousands of
>> snippets in this group.
>
>      #include <stdint.h>
>      #include <string.h>
>      #include <stdlib.h>
>      #include <stdio.h>
>
>      typedef long long T1;
>      typedef int64_t T2;
>      #define T1FMT "%lld"
>      #define T1VALUE 1
>      #define T2VALUE 2
>
>      T1 blah3(void *p1, void *p2)
>      {
>        T1 *t1p, *t1p2;
>        T2 *t2p;
>        T1 temp;
>
>        t1p = p1;
>        t2p = p2;
>        *t1p = T1VALUE;   // Write as T1
>        *t2p = T2VALUE;   // Write as T2
>        temp = *t2p;      // Read as T2
>        t1p2 = (T1*)t2p;  // Visible T2 to T1 pointer conversion
>        *t1p2 = temp;     // Write as T1
>        return *t1p;      // Read as T1
>      }
>
>      T1 test3(void)
>      {
>        void *p = malloc(sizeof (T1) + sizeof (T2));
>        T1 result = blah3(p,p);
>        free(p);
>        return result;
>      }
>      int main(void)
>      {
>        T1 result = test3();
>        printf("The result is " T1FMT, result);
>        return 0;
>      }

If T1 and T2 are compatible types (as might be the case, such as on 
Windows), then the answer will be 2.  If they are incompatible types, 
such as on 64-bit Linux, the answer is undefined - you are trying to 
access the same object through pointers to two incompatible types.  Some 
compiler and optimisation options will give 2, others will give 1, 
others could, in theory, give something else - but I think that's 
unlikely in practice.

gcc gives 1 with optimisation -O2 and above, on 64-bit Linux.  There is 
no bug here in gcc as far as I can see - your code is incorrect.

>
> Since you wanted me to dig it up, here's the example I posted before.
>
> https://godbolt.org/g/75oLGx
>

Maybe the link is not working as expected - it appeared to have the code:

// Type your code here, or load an example.
int square(int num) {
   return num * num;
}

I don't see how this relates to your point.

> The visible pointer conversion I mention in the comments shouldn't affect
> conformity (reading the variable to "temp" and writing it back in two
> separate operations makes things defined regardless) but should provide a
> second hint to the compiler that it should be cautious about trying to
> cache values of type T1.
>
> So there's a sample of buggy code.  Similar thing can happen if there are
> two structure types that have the same representation.
>

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


#93980

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2016-09-24 15:56 +0100
Message-ID<87twd5fitb.fsf@bsb.me.uk>
In reply to#93977
David Brown <david.brown@hesbynett.no> writes:

> On 23/09/16 16:55, supercat@casperkitty.com wrote:
>> On Friday, September 23, 2016 at 2:49:43 AM UTC-5, David Brown wrote:
<snip>
>>> ...  Can you give us a concrete example of buggy code, that
>>> we can paste into <http://gcc.godbolt.org/#> and compare results with
>>> different gcc versions and different compilers?  You can't just refer to
>>> "I've posted about it before" - you have posted hundreds or thousands of
>>> snippets in this group.
>>
>>      #include <stdint.h>
>>      #include <string.h>
>>      #include <stdlib.h>
>>      #include <stdio.h>
>>
>>      typedef long long T1;
>>      typedef int64_t T2;
>>      #define T1FMT "%lld"
>>      #define T1VALUE 1
>>      #define T2VALUE 2
>>
>>      T1 blah3(void *p1, void *p2)
>>      {
>>        T1 *t1p, *t1p2;
>>        T2 *t2p;
>>        T1 temp;
>>
>>        t1p = p1;
>>        t2p = p2;
>>        *t1p = T1VALUE;   // Write as T1
>>        *t2p = T2VALUE;   // Write as T2
>>        temp = *t2p;      // Read as T2
>>        t1p2 = (T1*)t2p;  // Visible T2 to T1 pointer conversion
>>        *t1p2 = temp;     // Write as T1
>>        return *t1p;      // Read as T1
>>      }
>>
>>      T1 test3(void)
>>      {
>>        void *p = malloc(sizeof (T1) + sizeof (T2));
>>        T1 result = blah3(p,p);
>>        free(p);
>>        return result;
>>      }
>>      int main(void)
>>      {
>>        T1 result = test3();
>>        printf("The result is " T1FMT, result);
>>        return 0;
>>      }
>
> If T1 and T2 are compatible types (as might be the case, such as on
> Windows), then the answer will be 2.  If they are incompatible types,
> such as on 64-bit Linux, the answer is undefined - you are trying to
> access the same object through pointers to two incompatible types.

That's not a thing!  There are rules about how you can access objects,
but they are much more complex that this summary and I'm not sure where
you think the violation occurs.  Can you point to the line and give the
rule being broken?

> Some compiler and optimisation options will give 2, others will give
> 1, others could, in theory, give something else - but I think that's
> unlikely in practice.
>
> gcc gives 1 with optimisation -O2 and above, on 64-bit Linux.  There
> is no bug here in gcc as far as I can see - your code is incorrect.

My gcc (5.2.1 20151010) gives 2 for all -Ox.  Presumably you have a
newer version?

<snip>
-- 
Ben.

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


#93982

FromDavid Brown <david.brown@hesbynett.no>
Date2016-09-24 17:50 +0200
Message-ID<ns67c3$25n$1@dont-email.me>
In reply to#93980
On 24/09/16 16:56, Ben Bacarisse wrote:
> David Brown <david.brown@hesbynett.no> writes:
>
>> On 23/09/16 16:55, supercat@casperkitty.com wrote:
>>> On Friday, September 23, 2016 at 2:49:43 AM UTC-5, David Brown wrote:
> <snip>
>>>> ...  Can you give us a concrete example of buggy code, that
>>>> we can paste into <http://gcc.godbolt.org/#> and compare results with
>>>> different gcc versions and different compilers?  You can't just refer to
>>>> "I've posted about it before" - you have posted hundreds or thousands of
>>>> snippets in this group.
>>>
>>>       #include <stdint.h>
>>>       #include <string.h>
>>>       #include <stdlib.h>
>>>       #include <stdio.h>
>>>
>>>       typedef long long T1;
>>>       typedef int64_t T2;
>>>       #define T1FMT "%lld"
>>>       #define T1VALUE 1
>>>       #define T2VALUE 2
>>>
>>>       T1 blah3(void *p1, void *p2)
>>>       {
>>>         T1 *t1p, *t1p2;
>>>         T2 *t2p;
>>>         T1 temp;
>>>
>>>         t1p = p1;
>>>         t2p = p2;
>>>         *t1p = T1VALUE;   // Write as T1
>>>         *t2p = T2VALUE;   // Write as T2
>>>         temp = *t2p;      // Read as T2
>>>         t1p2 = (T1*)t2p;  // Visible T2 to T1 pointer conversion
>>>         *t1p2 = temp;     // Write as T1
>>>         return *t1p;      // Read as T1
>>>       }
>>>
>>>       T1 test3(void)
>>>       {
>>>         void *p = malloc(sizeof (T1) + sizeof (T2));
>>>         T1 result = blah3(p,p);
>>>         free(p);
>>>         return result;
>>>       }
>>>       int main(void)
>>>       {
>>>         T1 result = test3();
>>>         printf("The result is " T1FMT, result);
>>>         return 0;
>>>       }
>>
>> If T1 and T2 are compatible types (as might be the case, such as on
>> Windows), then the answer will be 2.  If they are incompatible types,
>> such as on 64-bit Linux, the answer is undefined - you are trying to
>> access the same object through pointers to two incompatible types.
>
> That's not a thing!  There are rules about how you can access objects,
> but they are much more complex that this summary and I'm not sure where
> you think the violation occurs.  Can you point to the line and give the
> rule being broken?
>

I am thinking of the rules in 6.5, paragraph 7 about how "an object 
shall have its stored value accessed".  It does not explicitly say that 
accessing the same data through pointers to incompatible types is 
undefined - but it is implicitly undefined behaviour by virtue of not 
being defined behaviour.

But I could be wrong - and if this really is incorrect behaviour from 
gcc, then it needs reported and fixed.

>> Some compiler and optimisation options will give 2, others will give
>> 1, others could, in theory, give something else - but I think that's
>> unlikely in practice.
>>
>> gcc gives 1 with optimisation -O2 and above, on 64-bit Linux.  There
>> is no bug here in gcc as far as I can see - your code is incorrect.
>
> My gcc (5.2.1 20151010) gives 2 for all -Ox.  Presumably you have a
> newer version?
>

I am testing here with <https://gcc.godbolt.org/> for convenience.  It 
is targeting 64-bit Linux, and the result is 1 for -O2 and above, on gcc 
4.7 onwards.  gcc 4.5 and 4.6 give 2.  64-bit versions of MIPS, PPC and 
ARM also give 1, while all the 32-bit versions give 2 (which is to be 
expected - on 32-bit targets, "int64_t" will be "long long int").

clang and icc both give 2 on the combinations I checked.

(I haven't run the code, but it's easy to see the value from the 
assembly output.)

Note that the online compiler here is set up for C++ - you can use the 
"-x c" flag to force C compilation.

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


#93985

From"James R. Kuyper" <jameskuyper@verizon.net>
Date2016-09-24 13:45 -0400
Message-ID<0420caa0-b66b-bf32-d5e0-df864f463056@verizon.net>
In reply to#93982
On 09/24/2016 11:50 AM, David Brown wrote:
> On 24/09/16 16:56, Ben Bacarisse wrote:
>> David Brown <david.brown@hesbynett.no> writes:
>>
>>> On 23/09/16 16:55, supercat@casperkitty.com wrote:
>>>> On Friday, September 23, 2016 at 2:49:43 AM UTC-5, David Brown wrote:
>> <snip>
>>>>> ...  Can you give us a concrete example of buggy code, that
>>>>> we can paste into <http://gcc.godbolt.org/#> and compare results with
>>>>> different gcc versions and different compilers?  You can't just refer to
>>>>> "I've posted about it before" - you have posted hundreds or thousands of
>>>>> snippets in this group.
>>>>
>>>>       #include <stdint.h>
>>>>       #include <string.h>
>>>>       #include <stdlib.h>
>>>>       #include <stdio.h>
>>>>
>>>>       typedef long long T1;
>>>>       typedef int64_t T2;
>>>>       #define T1FMT "%lld"
>>>>       #define T1VALUE 1
>>>>       #define T2VALUE 2
>>>>
>>>>       T1 blah3(void *p1, void *p2)
>>>>       {
>>>>         T1 *t1p, *t1p2;
>>>>         T2 *t2p;
>>>>         T1 temp;
>>>>
>>>>         t1p = p1;
>>>>         t2p = p2;
>>>>         *t1p = T1VALUE;   // Write as T1
>>>>         *t2p = T2VALUE;   // Write as T2
>>>>         temp = *t2p;      // Read as T2
>>>>         t1p2 = (T1*)t2p;  // Visible T2 to T1 pointer conversion
>>>>         *t1p2 = temp;     // Write as T1
>>>>         return *t1p;      // Read as T1
>>>>       }
>>>>
>>>>       T1 test3(void)
>>>>       {
>>>>         void *p = malloc(sizeof (T1) + sizeof (T2));
>>>>         T1 result = blah3(p,p);
>>>>         free(p);
>>>>         return result;
>>>>       }
>>>>       int main(void)
>>>>       {
>>>>         T1 result = test3();
>>>>         printf("The result is " T1FMT, result);
>>>>         return 0;
>>>>       }
>>>
>>> If T1 and T2 are compatible types (as might be the case, such as on
>>> Windows), then the answer will be 2.  If they are incompatible types,
>>> such as on 64-bit Linux, the answer is undefined - you are trying to
>>> access the same object through pointers to two incompatible types.
>>
>> That's not a thing!  There are rules about how you can access objects,
>> but they are much more complex that this summary and I'm not sure where
>> you think the violation occurs.  Can you point to the line and give the
>> rule being broken?
>>
>
> I am thinking of the rules in 6.5, paragraph 7 about how "an object
> shall have its stored value accessed".  It does not explicitly say that
> accessing the same data through pointers to incompatible types is
> undefined - but it is implicitly undefined behaviour by virtue of not
> being defined behaviour.

4p2 says "Undefined behavior is otherwise indicated ... by the omission 
of any explicit definition of the behavior". But you have to be careful 
about applying that rule. Nowhere in the standard does it say explicitly 
what the behavior of the expression 1+1 is if executed on Friday the 
13th at 13:13:13. However, it does say "The result of the binary + 
operator is the sum of the operands.". That applies regardless of what 
the values of the operands are, and regardless of the time of day. 
Therefore, there is no "omission of any explicit definition", just 
because there is no mention of Friday the 13th. The definition of the 
behavior covers the possibility of time-dependent behavior by failing to 
mention any time dependence, rendering time-dependent behavior 
impermissible.

There are rules defining the behavior when accessing the values stored 
in objects through dereferenced pointers, and those rules continue to 
apply regardless of whether other pointers of incompatible types were 
also used to access those value - except when the behavior is explicitly 
said to be undefined somewhere else. Therefore, there is no "omission of 
any explicit definition".

6.5p7 does say that "An object shall have its stored value accessed only 
by an lvalue expression that has one of the following types:", and it 
lists 6 different possibilities. Violation of a "shall" that occurs 
outside of a constraint clause renders the behavior undefined (4p2). 
However, in every case, your code accesses the value stored in that 
memory using an lvalue that qualifies according to the first item in 
that list: "a type compatible with the effective type of the object".

That code accesses the object many times using an incompatible type, but 
whenever it does so, it is writing a new value for the object. Those 
accesses do not qualify as accessing the "stored value" of the object.
Every time that code accesses by reading the stored value, the read is 
preceded by a write to that object through an lvalue of the same type as 
the read. For an object with no declared type (which is what you create 
by calling malloc()), the effective type is always the same as the type 
of the last write to that memory through an lvalue that is not of 
character type.

<pedantic>
There is one obscure case which is not covered by the first item on 
6.5p7's list. If CHAR_BIT==64, it's possible for T2 to be a character 
type. As a result, the effective type would only change as a result of 
writing through lvalues with type T1. In that case, the first item on 
the list for 6.5p7 doesn't apply when reading through lvalues of type 
T2. Instead, the sixth item on that list applies: "a character type", 
since that's what T2 is in that case.
</pedantic>

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


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

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


csiph-web