From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: a07f3367d7,d23826ff0acb491b X-Google-Attributes: gida07f3367d7,public,usenet X-Google-NewGroupId: yes X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news2.google.com!news2.google.com!news.glorb.com!gegeweb.org!news.ecp.fr!news.jacob-sparre.dk!pnx.dk!not-for-mail From: "Randy Brukardt" Newsgroups: comp.lang.ada Subject: Re: Gem 39 - compiler specific? Date: Wed, 2 Sep 2009 18:20:36 -0500 Organization: Jacob Sparre Andersen Message-ID: References: <9e0bbbcd-260f-48ed-8043-d6280c633e85@h3g2000yqa.googlegroups.com> NNTP-Posting-Host: static-69-95-181-76.mad.choiceone.net X-Trace: munin.nbi.dk 1251933713 7175 69.95.181.76 (2 Sep 2009 23:21:53 GMT) X-Complaints-To: news@jacob-sparre.dk NNTP-Posting-Date: Wed, 2 Sep 2009 23:21:53 +0000 (UTC) X-Priority: 3 X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 6.00.2900.5512 X-RFC2646: Format=Flowed; Original X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.5579 Xref: g2news2.google.com comp.lang.ada:8117 Date: 2009-09-02T18:20:36-05:00 List-Id: "Maciej Sobczak" wrote in message news:9e0bbbcd-260f-48ed-8043-d6280c633e85@h3g2000yqa.googlegroups.com... > Consider: > > http://www.adacore.com/2008/06/09/gem-39/ > > The example code performs Unchecked_Conversion between addresses of > two different array types. > As far as I understand, there is no standard provision for arrays to > occupy contiguous memory space (and not even for the alignment of > their components) and such a conversion relies heavily on the > assumption that arrays can be "overlaid" by plain address > reinterpretation. > > Still, this technique is quite attractive. What is the chance (in > practice) to hit the compiler that does not get it "right"? This is horrible code; it should never be written in Ada 95 or newer! The problem is that System.Address is not necessarily the same as a general access type, so this Unchecked_Conversion may not work (or may not even compile) on another implementation. (It won't on at least some versions of Janus/Ada, for instance.) Ada 95 provides System.Address_to_Access_Conversions for this purpose, so at the very least the writer of the Rock (it surely isn't a "Gem"!!!) should have used it: procedure Write_Buffer (Stream : not null access Ada.Streams.Root_Stream_Type'Class; Item : in Buffer) is Item_Size : constant Stream_Element_Offset := Buffer'Object_Size / Stream_Element'Size; subtype SEA is Stream_Element_Array (1..Item_Size); package A2A is new System.Address_to_Access_Conversions (SEA); begin Ada.Streams.Write (Stream.all, A2A.To_Pointer (Item'Address).all); end Write_Buffer; (As an aside, this technique could not work in Janus/Ada if Buffer was an unconstrained array: 'Address of an unconstrained array points at the array descriptor, not the data. (That's in fact true for all objects in Janus/Ada: there is a static part and an optional dynamic part, and all operations like 'Address and 'Size point at the static part. That was decided long before Ada 95 came around and tried to change these definitions; it's not practical to change in Janus/Ada as address clauses could not be made to work - among other things - if the static part is ignored.) IMHO, using System.Address is for anything other than address clauses is *always* wrong in Ada 95: there are always ways to use general access types in order to deal with any "pointer" type issue. But we don't even need to do *that* here - you can directly used Unchecked_Conversion to directly convert between the array types: procedure Write_Buffer (Stream : not null access Ada.Streams.Root_Stream_Type'Class; Item : in Buffer) is Item_Size : constant Stream_Element_Offset := Buffer'Object_Size / Stream_Element'Size; subtype SEA is Stream_Element_Array (1..Item_Size); function To_SEA is new Ada.Unchecked_Conversion (Source => Buffer, Target => SEA); begin Ada.Streams.Write (Stream.all, To_SEA (Item)); end Write_Buffer; And now there is no use of Address or access types at all (other than for the stream, of course). Any decent compiler will compile this conversion into nothing: No code is needed or should be generated for it. (Janus/Ada can do this, and it is pretty dumb. Indeed, it can does this precisely because this example needs to work cheaply, as it is the way the majority of user-defined stream attributes ought to be written.) Randy.