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.3 required=5.0 tests=BAYES_00,INVALID_MSGID autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,baa6871d466e5af9 X-Google-Attributes: gid103376,public From: dewar@merv.cs.nyu.edu (Robert Dewar) Subject: Re: AQ&S Guidance on pragma Elaborate_Body Date: 1997/04/25 Message-ID: #1/1 X-Deja-AN: 237286712 References: <528878564wnr@diphi.demon.co.uk> <5jabeq$3ltk@info4.rus.uni-stuttgart.de> <335F5449.6644@elca-matrix.ch> Organization: New York University Newsgroups: comp.lang.ada Date: 1997-04-25T00:00:00+00:00 List-Id: <> The "solution" which for example is described in published papers from the Binghamton group (I believe they published at Tri-Ada, as well as an article in CACM), is indeed attractive, but there are two problems: 1. We have to decide how far to make a compiler go. Requiring the construction of a call graph covering the whole program is very expensive. 2. We have to worry about backwards compatibility. I actually pushed quite strongly during the Ada 9X process to try to solve this problem, but we just did not find a satisfactory solution. No one liked solutions that would require the construction of a full call graph. I don't know if Mats solution has this quality, but certainly the Binghamton papers expect this. Obviously you cannot completely solve the compatibility problem with any static approach, since it is trivial to show that soving the elaboration problem in full gnerality is equivalent to the halting problem (folks at Softech showed this early on, this discussion is not new, it was on the table during the Ada 83 design, and the static solutions involving call graph construction were well known at that time -- of course the engineering details in such schemes are always tricky!) If you build a full call graph, you can solve most practical problems (although there exist at least some test programs around which will defeat any static scheme). The question is whether there are schemes that are good enough, and compatible enough. I am hoping the GNAT scheme will turn out to be such a scheme. Basically in GNAT we do a full call graph analysis within units, but for references across unit boundaries, we assume pragma Elaborate_All in the default mode -- this seems to work pretty well in practice, though one can certainly concoct examples that will defeat it. (We have switches to revert to the fully dynamic view i that is what you want). The nastiest problem is with access typs (generic formal subprograms would cause the same problem if you had shared generics, but not with macro generics). The trouble is that if you compute X'Access at a point before the boxy of X is elaborated -- that is perfectly reasonable, and not in any sense an error, or even in any sense poor practice (consider the implicit case with tagged type dispatching tables for example). But if X is in a separate unit that is not Pure or Preelaborate or Elaborate_Body or predefned, you cannot avoiud a dynamic check. The GNAT approach in this situation is: (a) generate a warning (if you enable these special elaboration warnings) that this is happening. (b) generate a wrapper that does the dynamic check, and point to the wrapper (c) where possible (and in particular for dispatching tables), recompute all access types as soon as elaboration is complete to eliminate the wrapper overhead. Note that another goal of the GNAT approach is to provide a set of warnings that have the quality that if you eliminate all warnings, then not only is your program guaranteed not to raise Program_Error on any implementation, but also, at least in GANT, you are guaranteed that no dynamic checks will have been generated.