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=-0.9 required=5.0 tests=BAYES_00,FORGED_GMAIL_RCVD, FREEMAIL_FROM autolearn=no autolearn_force=no version=3.4.4 X-Google-Thread: 103376,f428ff2031155951 X-Google-NewGroupId: yes X-Google-Attributes: gida07f3367d7,domainid0,public,usenet X-Google-Language: ENGLISH,ASCII Path: g2news1.google.com!postnews.google.com!z3g2000prz.googlegroups.com!not-for-mail From: Maciej Sobczak Newsgroups: comp.lang.ada Subject: Re: Equivalent of dynamic_cast (downcast) for tagged types Date: Thu, 27 Jan 2011 14:35:28 -0800 (PST) Organization: http://groups.google.com Message-ID: <510d779c-d15b-4fc1-b831-bfc578ecdb4b@z3g2000prz.googlegroups.com> References: <375fb596-ab12-4cb0-a190-53d62b94b2e4@e9g2000vbi.googlegroups.com> NNTP-Posting-Host: 85.1.55.108 Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable X-Trace: posting.google.com 1296167728 5276 127.0.0.1 (27 Jan 2011 22:35:28 GMT) X-Complaints-To: groups-abuse@google.com NNTP-Posting-Date: Thu, 27 Jan 2011 22:35:28 +0000 (UTC) Complaints-To: groups-abuse@google.com Injection-Info: z3g2000prz.googlegroups.com; posting-host=85.1.55.108; posting-account=bMuEOQoAAACUUr_ghL3RBIi5neBZ5w_S User-Agent: G2/1.0 X-HTTP-UserAgent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.10) Gecko/20100914 Firefox/3.6.10,gzip(gfe) Xref: g2news1.google.com comp.lang.ada:16754 Date: 2011-01-27T14:35:28-08:00 List-Id: On Jan 27, 5:18=A0pm, "Dmitry A. Kazakov" wrote: > =A0 =A0if X in T'Class then > =A0 =A0 =A0 Do_Something (T (X)); =A0-- No dispatch > =A0 =A0end if; > > The above is a bad idea, because X might be a descendant of T which has > overridden Do_Something. So you might be looking for this > > =A0 =A0if X'Tag =3D T'Tag then -- X is of T > =A0 =A0 =A0 Do_Something (T (X)); =A0-- No dispatch > =A0 =A0end if; Thank you, this makes sense. > Adjust is not called on limited objects. Yeah, sure. :-D http://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D41845 I have submitted this bug report more than one year ago. Looks like nobody even bothered to check it. The bug submission states that Adjust is wrongly recognized as overriding, which it shouldn't be - but now I have hit something more interesting. I got an exception from a place where a regular dispatching operation on some class-wide type was done. After some debugging and analysis the exception appeared to come from s-finroo.adb:45, from System.Finalization_Root.Adjust, which just raises Program_Error. Why the heck this Adjust was called on my Controlled_Limited type is a mystery, but that was easy to confirm: I have added the Adjust operation for my type, just as in the bug report, and instrumented it and voila - this proved that the Adjust was really *called*. But that was just the beginning. I could live with a dummy implementation of Adjust for my limited (!) type, but the real problem was with the dispatching operation that I wanted to call. This operation is a function that returns some access value - it is declared to be abstract in the base interface and implemented in my type. There is nothing between the abstract declaration and my implemetation, but my implementation is *not* called (again, instrumented), but somehow the result of the call is null, which leads to a disaster few lines later. Looks like GNAT generated some dummy body for the abstract function and called that instead. So, to summarise: yes, Adjust is randomly called on Controlled_Limited types and it even dispatches properly (wow!), and no, my own operations do not dispatch and instead something dummy gives me equally dummy results. This happens in GNAT GPL 2010, but not in older compilers. It is really demotivating to see that object orientation in its basic form still doesn't work in GNAT. But in addition to downcasting, there is an alternative solution which I have discovered later on, although have not yet tested. The idea is if I know the actual type (T) in the procedure that accepts base interface, then apparently I'm working with a closed set of types, which is actually true. So instead of relying on class-wide types and dispatching in this particular place I will add another version of the same operation that accepts T and operates on it. A bit of code duplication, but with a chance to work around this not-so- funny GNAT bug. -- Maciej Sobczak * http://www.inspirel.com