Mercurial > hg > CbC > CbC_gcc
comparison gcc/ada/doc/gnat_ugn/elaboration_order_handling_in_gnat.rst @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 .. role:: switch(samp) | |
2 | |
3 .. |with| replace:: *with* | |
4 .. |withs| replace:: *with*\ s | |
5 .. |withed| replace:: *with*\ ed | |
6 .. |withing| replace:: *with*\ ing | |
7 | |
8 .. -- Example: A |withing| unit has a |with| clause, it |withs| a |withed| unit | |
9 | |
10 | |
11 .. _Elaboration_Order_Handling_in_GNAT: | |
12 | |
13 ********************************** | |
14 Elaboration Order Handling in GNAT | |
15 ********************************** | |
16 | |
17 .. index:: Order of elaboration | |
18 .. index:: Elaboration control | |
19 | |
20 This appendix describes the handling of elaboration code in Ada and GNAT, and | |
21 discusses how the order of elaboration of program units can be controlled in | |
22 GNAT, either automatically or with explicit programming features. | |
23 | |
24 .. _Elaboration_Code: | |
25 | |
26 Elaboration Code | |
27 ================ | |
28 | |
29 Ada defines the term *execution* as the process by which a construct achieves | |
30 its run-time effect. This process is also referred to as **elaboration** for | |
31 declarations and *evaluation* for expressions. | |
32 | |
33 The execution model in Ada allows for certain sections of an Ada program to be | |
34 executed prior to execution of the program itself, primarily with the intent of | |
35 initializing data. These sections are referred to as **elaboration code**. | |
36 Elaboration code is executed as follows: | |
37 | |
38 * All partitions of an Ada program are executed in parallel with one another, | |
39 possibly in a separate address space, and possibly on a separate computer. | |
40 | |
41 * The execution of a partition involves running the environment task for that | |
42 partition. | |
43 | |
44 * The environment task executes all elaboration code (if available) for all | |
45 units within that partition. This code is said to be executed at | |
46 **elaboration time**. | |
47 | |
48 * The environment task executes the Ada program (if available) for that | |
49 partition. | |
50 | |
51 In addition to the Ada terminology, this appendix defines the following terms: | |
52 | |
53 * *Scenario* | |
54 | |
55 A construct that is elaborated or executed by elaboration code is referred to | |
56 as an *elaboration scenario* or simply a **scenario**. GNAT recognizes the | |
57 following scenarios: | |
58 | |
59 - ``'Access`` of entries, operators, and subprograms | |
60 | |
61 - Activation of tasks | |
62 | |
63 - Calls to entries, operators, and subprograms | |
64 | |
65 - Instantiations of generic templates | |
66 | |
67 * *Target* | |
68 | |
69 A construct elaborated by a scenario is referred to as *elaboration target* | |
70 or simply **target**. GNAT recognizes the following targets: | |
71 | |
72 - For ``'Access`` of entries, operators, and subprograms, the target is the | |
73 entry, operator, or subprogram being aliased. | |
74 | |
75 - For activation of tasks, the target is the task body | |
76 | |
77 - For calls to entries, operators, and subprograms, the target is the entry, | |
78 operator, or subprogram being invoked. | |
79 | |
80 - For instantiations of generic templates, the target is the generic template | |
81 being instantiated. | |
82 | |
83 Elaboration code may appear in two distinct contexts: | |
84 | |
85 * *Library level* | |
86 | |
87 A scenario appears at the library level when it is encapsulated by a package | |
88 [body] compilation unit, ignoring any other package [body] declarations in | |
89 between. | |
90 | |
91 :: | |
92 | |
93 with Server; | |
94 package Client is | |
95 procedure Proc; | |
96 | |
97 package Nested is | |
98 Val : ... := Server.Func; | |
99 end Nested; | |
100 end Client; | |
101 | |
102 In the example above, the call to ``Server.Func`` is an elaboration scenario | |
103 because it appears at the library level of package ``Client``. Note that the | |
104 declaration of package ``Nested`` is ignored according to the definition | |
105 given above. As a result, the call to ``Server.Func`` will be executed when | |
106 the spec of unit ``Client`` is elaborated. | |
107 | |
108 * *Package body statements* | |
109 | |
110 A scenario appears within the statement sequence of a package body when it is | |
111 bounded by the region starting from the ``begin`` keyword of the package body | |
112 and ending at the ``end`` keyword of the package body. | |
113 | |
114 :: | |
115 | |
116 package body Client is | |
117 procedure Proc is | |
118 begin | |
119 ... | |
120 end Proc; | |
121 begin | |
122 Proc; | |
123 end Client; | |
124 | |
125 In the example above, the call to ``Proc`` is an elaboration scenario because | |
126 it appears within the statement sequence of package body ``Client``. As a | |
127 result, the call to ``Proc`` will be executed when the body of ``Client`` is | |
128 elaborated. | |
129 | |
130 .. _Elaboration_Order: | |
131 | |
132 Elaboration Order | |
133 ================= | |
134 | |
135 The sequence by which the elaboration code of all units within a partition is | |
136 executed is referred to as **elaboration order**. | |
137 | |
138 Within a single unit, elaboration code is executed in sequential order. | |
139 | |
140 :: | |
141 | |
142 package body Client is | |
143 Result : ... := Server.Func; | |
144 | |
145 procedure Proc is | |
146 package Inst is new Server.Gen; | |
147 begin | |
148 Inst.Eval (Result); | |
149 end Proc; | |
150 begin | |
151 Proc; | |
152 end Client; | |
153 | |
154 In the example above, the elaboration order within package body ``Client`` is | |
155 as follows: | |
156 | |
157 1. The object declaration of ``Result`` is elaborated. | |
158 | |
159 * Function ``Server.Func`` is invoked. | |
160 | |
161 2. The subprogram body of ``Proc`` is elaborated. | |
162 | |
163 3. Procedure ``Proc`` is invoked. | |
164 | |
165 * Generic unit ``Server.Gen`` is instantiated as ``Inst``. | |
166 | |
167 * Instance ``Inst`` is elaborated. | |
168 | |
169 * Procedure ``Inst.Eval`` is invoked. | |
170 | |
171 The elaboration order of all units within a partition depends on the following | |
172 factors: | |
173 | |
174 * |withed| units | |
175 | |
176 * purity of units | |
177 | |
178 * preelaborability of units | |
179 | |
180 * presence of elaboration control pragmas | |
181 | |
182 A program may have several elaboration orders depending on its structure. | |
183 | |
184 :: | |
185 | |
186 package Server is | |
187 function Func (Index : Integer) return Integer; | |
188 end Server; | |
189 | |
190 :: | |
191 | |
192 package body Server is | |
193 Results : array (1 .. 5) of Integer := (1, 2, 3, 4, 5); | |
194 | |
195 function Func (Index : Integer) return Integer is | |
196 begin | |
197 return Results (Index); | |
198 end Func; | |
199 end Server; | |
200 | |
201 :: | |
202 | |
203 with Server; | |
204 package Client is | |
205 Val : constant Integer := Server.Func (3); | |
206 end Client; | |
207 | |
208 :: | |
209 | |
210 with Client; | |
211 procedure Main is begin null; end Main; | |
212 | |
213 The following elaboration order exhibits a fundamental problem referred to as | |
214 *access-before-elaboration* or simply **ABE**. | |
215 | |
216 :: | |
217 | |
218 spec of Server | |
219 spec of Client | |
220 body of Server | |
221 body of Main | |
222 | |
223 The elaboration of ``Server``'s spec materializes function ``Func``, making it | |
224 callable. The elaboration of ``Client``'s spec elaborates the declaration of | |
225 ``Val``. This invokes function ``Server.Func``, however the body of | |
226 ``Server.Func`` has not been elaborated yet because ``Server``'s body comes | |
227 after ``Client``'s spec in the elaboration order. As a result, the value of | |
228 constant ``Val`` is now undefined. | |
229 | |
230 Without any guarantees from the language, an undetected ABE problem may hinder | |
231 proper initialization of data, which in turn may lead to undefined behavior at | |
232 run time. To prevent such ABE problems, Ada employs dynamic checks in the same | |
233 vein as index or null exclusion checks. A failed ABE check raises exception | |
234 ``Program_Error``. | |
235 | |
236 The following elaboration order avoids the ABE problem and the program can be | |
237 successfully elaborated. | |
238 | |
239 :: | |
240 | |
241 spec of Server | |
242 body of Server | |
243 spec of Client | |
244 body of Main | |
245 | |
246 Ada states that a total elaboration order must exist, but it does not define | |
247 what this order is. A compiler is thus tasked with choosing a suitable | |
248 elaboration order which satisfies the dependencies imposed by |with| clauses, | |
249 unit categorization, and elaboration control pragmas. Ideally an order which | |
250 avoids ABE problems should be chosen, however a compiler may not always find | |
251 such an order due to complications with respect to control and data flow. | |
252 | |
253 .. _Checking_the_Elaboration_Order: | |
254 | |
255 Checking the Elaboration Order | |
256 ============================== | |
257 | |
258 To avoid placing the entire elaboration order burden on the programmer, Ada | |
259 provides three lines of defense: | |
260 | |
261 * *Static semantics* | |
262 | |
263 Static semantic rules restrict the possible choice of elaboration order. For | |
264 instance, if unit Client |withs| unit Server, then the spec of Server is | |
265 always elaborated prior to Client. The same principle applies to child units | |
266 - the spec of a parent unit is always elaborated prior to the child unit. | |
267 | |
268 * *Dynamic semantics* | |
269 | |
270 Dynamic checks are performed at run time, to ensure that a target is | |
271 elaborated prior to a scenario that executes it, thus avoiding ABE problems. | |
272 A failed run-time check raises exception ``Program_Error``. The following | |
273 restrictions apply: | |
274 | |
275 - *Restrictions on calls* | |
276 | |
277 An entry, operator, or subprogram can be called from elaboration code only | |
278 when the corresponding body has been elaborated. | |
279 | |
280 - *Restrictions on instantiations* | |
281 | |
282 A generic unit can be instantiated by elaboration code only when the | |
283 corresponding body has been elaborated. | |
284 | |
285 - *Restrictions on task activation* | |
286 | |
287 A task can be activated by elaboration code only when the body of the | |
288 associated task type has been elaborated. | |
289 | |
290 The restrictions above can be summarized by the following rule: | |
291 | |
292 *If a target has a body, then this body must be elaborated prior to the | |
293 execution of the scenario that invokes, instantiates, or activates the | |
294 target.* | |
295 | |
296 * *Elaboration control* | |
297 | |
298 Pragmas are provided for the programmer to specify the desired elaboration | |
299 order. | |
300 | |
301 .. _Controlling_the_Elaboration_Order_in_Ada: | |
302 | |
303 Controlling the Elaboration Order in Ada | |
304 ======================================== | |
305 | |
306 Ada provides several idioms and pragmas to aid the programmer with specifying | |
307 the desired elaboration order and avoiding ABE problems altogether. | |
308 | |
309 * *Packages without a body* | |
310 | |
311 A library package which does not require a completing body does not suffer | |
312 from ABE problems. | |
313 | |
314 :: | |
315 | |
316 package Pack is | |
317 generic | |
318 type Element is private; | |
319 package Containers is | |
320 type Element_Array is array (1 .. 10) of Element; | |
321 end Containers; | |
322 end Pack; | |
323 | |
324 In the example above, package ``Pack`` does not require a body because it | |
325 does not contain any constructs which require completion in a body. As a | |
326 result, generic ``Pack.Containers`` can be instantiated without encountering | |
327 any ABE problems. | |
328 | |
329 .. index:: pragma Pure | |
330 | |
331 * *pragma Pure* | |
332 | |
333 Pragma ``Pure`` places sufficient restrictions on a unit to guarantee that no | |
334 scenario within the unit can result in an ABE problem. | |
335 | |
336 .. index:: pragma Preelaborate | |
337 | |
338 * *pragma Preelaborate* | |
339 | |
340 Pragma ``Preelaborate`` is slightly less restrictive than pragma ``Pure``, | |
341 but still strong enough to prevent ABE problems within a unit. | |
342 | |
343 .. index:: pragma Elaborate_Body | |
344 | |
345 * *pragma Elaborate_Body* | |
346 | |
347 Pragma ``Elaborate_Body`` requires that the body of a unit is elaborated | |
348 immediately after its spec. This restriction guarantees that no client | |
349 scenario can execute a server target before the target body has been | |
350 elaborated because the spec and body are effectively "glued" together. | |
351 | |
352 :: | |
353 | |
354 package Server is | |
355 pragma Elaborate_Body; | |
356 | |
357 function Func return Integer; | |
358 end Server; | |
359 | |
360 :: | |
361 | |
362 package body Server is | |
363 function Func return Integer is | |
364 begin | |
365 ... | |
366 end Func; | |
367 end Server; | |
368 | |
369 :: | |
370 | |
371 with Server; | |
372 package Client is | |
373 Val : constant Integer := Server.Func; | |
374 end Client; | |
375 | |
376 In the example above, pragma ``Elaborate_Body`` guarantees the following | |
377 elaboration order: | |
378 | |
379 :: | |
380 | |
381 spec of Server | |
382 body of Server | |
383 spec of Client | |
384 | |
385 because the spec of ``Server`` must be elaborated prior to ``Client`` by | |
386 virtue of the |with| clause, and in addition the body of ``Server`` must be | |
387 elaborated immediately after the spec of ``Server``. | |
388 | |
389 Removing pragma ``Elaborate_Body`` could result in the following incorrect | |
390 elaboration order: | |
391 | |
392 :: | |
393 | |
394 spec of Server | |
395 spec of Client | |
396 body of Server | |
397 | |
398 where ``Client`` invokes ``Server.Func``, but the body of ``Server.Func`` has | |
399 not been elaborated yet. | |
400 | |
401 The pragmas outlined above allow a server unit to guarantee safe elaboration | |
402 use by client units. Thus it is a good rule to mark units as ``Pure`` or | |
403 ``Preelaborate``, and if this is not possible, mark them as ``Elaborate_Body``. | |
404 | |
405 There are however situations where ``Pure``, ``Preelaborate``, and | |
406 ``Elaborate_Body`` are not applicable. Ada provides another set of pragmas for | |
407 use by client units to help ensure the elaboration safety of server units they | |
408 depend on. | |
409 | |
410 .. index:: pragma Elaborate (Unit) | |
411 | |
412 * *pragma Elaborate (Unit)* | |
413 | |
414 Pragma ``Elaborate`` can be placed in the context clauses of a unit, after a | |
415 |with| clause. It guarantees that both the spec and body of its argument will | |
416 be elaborated prior to the unit with the pragma. Note that other unrelated | |
417 units may be elaborated in between the spec and the body. | |
418 | |
419 :: | |
420 | |
421 package Server is | |
422 function Func return Integer; | |
423 end Server; | |
424 | |
425 :: | |
426 | |
427 package body Server is | |
428 function Func return Integer is | |
429 begin | |
430 ... | |
431 end Func; | |
432 end Server; | |
433 | |
434 :: | |
435 | |
436 with Server; | |
437 pragma Elaborate (Server); | |
438 package Client is | |
439 Val : constant Integer := Server.Func; | |
440 end Client; | |
441 | |
442 In the example above, pragma ``Elaborate`` guarantees the following | |
443 elaboration order: | |
444 | |
445 :: | |
446 | |
447 spec of Server | |
448 body of Server | |
449 spec of Client | |
450 | |
451 Removing pragma ``Elaborate`` could result in the following incorrect | |
452 elaboration order: | |
453 | |
454 :: | |
455 | |
456 spec of Server | |
457 spec of Client | |
458 body of Server | |
459 | |
460 where ``Client`` invokes ``Server.Func``, but the body of ``Server.Func`` | |
461 has not been elaborated yet. | |
462 | |
463 .. index:: pragma Elaborate_All (Unit) | |
464 | |
465 * *pragma Elaborate_All (Unit)* | |
466 | |
467 Pragma ``Elaborate_All`` is placed in the context clauses of a unit, after | |
468 a |with| clause. It guarantees that both the spec and body of its argument | |
469 will be elaborated prior to the unit with the pragma, as well as all units | |
470 |withed| by the spec and body of the argument, recursively. Note that other | |
471 unrelated units may be elaborated in between the spec and the body. | |
472 | |
473 :: | |
474 | |
475 package Math is | |
476 function Factorial (Val : Natural) return Natural; | |
477 end Math; | |
478 | |
479 :: | |
480 | |
481 package body Math is | |
482 function Factorial (Val : Natural) return Natural is | |
483 begin | |
484 ...; | |
485 end Factorial; | |
486 end Math; | |
487 | |
488 :: | |
489 | |
490 package Computer is | |
491 type Operation_Kind is (None, Op_Factorial); | |
492 | |
493 function Compute | |
494 (Val : Natural; | |
495 Op : Operation_Kind) return Natural; | |
496 end Computer; | |
497 | |
498 :: | |
499 | |
500 with Math; | |
501 package body Computer is | |
502 function Compute | |
503 (Val : Natural; | |
504 Op : Operation_Kind) return Natural | |
505 is | |
506 if Op = Op_Factorial then | |
507 return Math.Factorial (Val); | |
508 end if; | |
509 | |
510 return 0; | |
511 end Compute; | |
512 end Computer; | |
513 | |
514 :: | |
515 | |
516 with Computer; | |
517 pragma Elaborate_All (Computer); | |
518 package Client is | |
519 Val : constant Natural := | |
520 Computer.Compute (123, Computer.Op_Factorial); | |
521 end Client; | |
522 | |
523 In the example above, pragma ``Elaborate_All`` can result in the following | |
524 elaboration order: | |
525 | |
526 :: | |
527 | |
528 spec of Math | |
529 body of Math | |
530 spec of Computer | |
531 body of Computer | |
532 spec of Client | |
533 | |
534 Note that there are several allowable suborders for the specs and bodies of | |
535 ``Math`` and ``Computer``, but the point is that these specs and bodies will | |
536 be elaborated prior to ``Client``. | |
537 | |
538 Removing pragma ``Elaborate_All`` could result in the following incorrect | |
539 elaboration order | |
540 | |
541 :: | |
542 | |
543 spec of Math | |
544 spec of Computer | |
545 body of Computer | |
546 spec of Client | |
547 body of Math | |
548 | |
549 where ``Client`` invokes ``Computer.Compute``, which in turn invokes | |
550 ``Math.Factorial``, but the body of ``Math.Factorial`` has not been | |
551 elaborated yet. | |
552 | |
553 All pragmas shown above can be summarized by the following rule: | |
554 | |
555 *If a client unit elaborates a server target directly or indirectly, then if | |
556 the server unit requires a body and does not have pragma Pure, Preelaborate, | |
557 or Elaborate_Body, then the client unit should have pragma Elaborate or | |
558 Elaborate_All for the server unit.* | |
559 | |
560 If the rule outlined above is not followed, then a program may fall in one of | |
561 the following states: | |
562 | |
563 * *No elaboration order exists* | |
564 | |
565 In this case a compiler must diagnose the situation, and refuse to build an | |
566 executable program. | |
567 | |
568 * *One or more incorrect elaboration orders exist* | |
569 | |
570 In this case a compiler can build an executable program, but | |
571 ``Program_Error`` will be raised when the program is run. | |
572 | |
573 * *Several elaboration orders exist, some correct, some incorrect* | |
574 | |
575 In this case the programmer has not controlled the elaboration order. As a | |
576 result, a compiler may or may not pick one of the correct orders, and the | |
577 program may or may not raise ``Program_Error`` when it is run. This is the | |
578 worst possible state because the program may fail on another compiler, or | |
579 even another version of the same compiler. | |
580 | |
581 * *One or more correct orders exist* | |
582 | |
583 In this case a compiler can build an executable program, and the program is | |
584 run successfully. This state may be guaranteed by following the outlined | |
585 rules, or may be the result of good program architecture. | |
586 | |
587 Note that one additional advantage of using ``Elaborate`` and ``Elaborate_All`` | |
588 is that the program continues to stay in the last state (one or more correct | |
589 orders exist) even if maintenance changes the bodies of targets. | |
590 | |
591 .. _Controlling_the_Elaboration_Order_in_GNAT: | |
592 | |
593 Controlling the Elaboration Order in GNAT | |
594 ========================================= | |
595 | |
596 In addition to Ada semantics and rules synthesized from them, GNAT offers | |
597 three elaboration models to aid the programmer with specifying the correct | |
598 elaboration order and to diagnose elaboration problems. | |
599 | |
600 .. index:: Dynamic elaboration model | |
601 | |
602 * *Dynamic elaboration model* | |
603 | |
604 This is the most permissive of the three elaboration models. When the | |
605 dynamic model is in effect, GNAT assumes that all code within all units in | |
606 a partition is elaboration code. GNAT performs very few diagnostics and | |
607 generates run-time checks to verify the elaboration order of a program. This | |
608 behavior is identical to that specified by the Ada Reference Manual. The | |
609 dynamic model is enabled with compiler switch :switch:`-gnatE`. | |
610 | |
611 .. index:: Static elaboration model | |
612 | |
613 * *Static elaboration model* | |
614 | |
615 This is the middle ground of the three models. When the static model is in | |
616 effect, GNAT performs extensive diagnostics on a unit-by-unit basis for all | |
617 scenarios that elaborate or execute internal targets. GNAT also generates | |
618 run-time checks for all external targets and for all scenarios that may | |
619 exhibit ABE problems. Finally, GNAT installs implicit ``Elaborate`` and | |
620 ``Elaborate_All`` pragmas for server units based on the dependencies of | |
621 client units. The static model is the default model in GNAT. | |
622 | |
623 .. index:: SPARK elaboration model | |
624 | |
625 * *SPARK elaboration model* | |
626 | |
627 This is the most conservative of the three models and enforces the SPARK | |
628 rules of elaboration as defined in the SPARK Reference Manual, section 7.7. | |
629 The SPARK model is in effect only when a scenario and a target reside in a | |
630 region subject to SPARK_Mode On, otherwise the dynamic or static model is in | |
631 effect. | |
632 | |
633 .. _Common_Elaboration_Model_Traits": | |
634 | |
635 Common Elaboration-model Traits | |
636 =============================== | |
637 | |
638 All three GNAT models are able to detect elaboration problems related to | |
639 dispatching calls and a particular kind of ABE referred to as *guaranteed ABE*. | |
640 | |
641 * *Dispatching calls* | |
642 | |
643 GNAT installs run-time checks for each primitive subprogram of each tagged | |
644 type defined in a partition on the assumption that a dispatching call | |
645 invoked at elaboration time will execute one of these primitives. As a | |
646 result, a dispatching call that executes a primitive whose body has not | |
647 been elaborated yet will raise exception ``Program_Error`` at run time. The | |
648 checks can be suppressed using pragma ``Suppress (Elaboration_Check)``. | |
649 | |
650 * *Guaranteed ABE* | |
651 | |
652 A guaranteed ABE arises when the body of a target is not elaborated early | |
653 enough, and causes all scenarios that directly execute the target to fail. | |
654 | |
655 :: | |
656 | |
657 package body Guaranteed_ABE is | |
658 function ABE return Integer; | |
659 | |
660 Val : constant Integer := ABE; | |
661 | |
662 function ABE return Integer is | |
663 begin | |
664 ... | |
665 end ABE; | |
666 end Guaranteed_ABE; | |
667 | |
668 In the example above, the elaboration of ``Guaranteed_ABE``'s body elaborates | |
669 the declaration of ``Val``. This invokes function ``ABE``, however the body | |
670 of ``ABE`` has not been elaborated yet. GNAT emits similar diagnostics in all | |
671 three models: | |
672 | |
673 :: | |
674 | |
675 1. package body Guaranteed_ABE is | |
676 2. function ABE return Integer; | |
677 3. | |
678 4. Val : constant Integer := ABE; | |
679 | | |
680 >>> warning: cannot call "ABE" before body seen | |
681 >>> warning: Program_Error will be raised at run time | |
682 | |
683 5. | |
684 6. function ABE return Integer is | |
685 7. begin | |
686 8. ... | |
687 9. end ABE; | |
688 10. end Guaranteed_ABE; | |
689 | |
690 Note that GNAT emits warnings rather than hard errors whenever it encounters an | |
691 elaboration problem. This is because the elaboration model in effect may be too | |
692 conservative, or a particular scenario may not be elaborated or executed due to | |
693 data and control flow. The warnings can be suppressed with compiler switch | |
694 :switch:`-gnatws`. | |
695 | |
696 .. _Dynamic_Elaboration_Model_in_GNAT: | |
697 | |
698 Dynamic Elaboration Model in GNAT | |
699 ================================= | |
700 | |
701 The dynamic model assumes that all code within all units in a partition is | |
702 elaboration code. As a result, run-time checks are installed for each scenario | |
703 regardless of whether the target is internal or external. The checks can be | |
704 suppressed using pragma ``Suppress (Elaboration_Check)``. This behavior is | |
705 identical to that specified by the Ada Reference Manual. The following example | |
706 showcases run-time checks installed by GNAT to verify the elaboration state of | |
707 package ``Dynamic_Model``. | |
708 | |
709 :: | |
710 | |
711 with Server; | |
712 package body Dynamic_Model is | |
713 procedure API is | |
714 begin | |
715 ... | |
716 end API; | |
717 | |
718 <check that the body of Server.Gen is elaborated> | |
719 package Inst is new Server.Gen; | |
720 | |
721 T : Server.Task_Type; | |
722 | |
723 begin | |
724 <check that the body of Server.Task_Type is elaborated> | |
725 | |
726 <check that the body of Server.Proc is elaborated> | |
727 Server.Proc; | |
728 end Dynamic_Model; | |
729 | |
730 The checks verify that the body of a target has been successfully elaborated | |
731 before a scenario activates, calls, or instantiates a target. | |
732 | |
733 Note that no scenario within package ``Dynamic_Model`` calls procedure ``API``. | |
734 In fact, procedure ``API`` may not be invoked by elaboration code within the | |
735 partition, however the dynamic model assumes that this can happen. | |
736 | |
737 The dynamic model emits very few diagnostics, but can make suggestions on | |
738 missing ``Elaborate`` and ``Elaborate_All`` pragmas for library-level | |
739 scenarios. This information is available when compiler switch :switch:`-gnatel` | |
740 is in effect. | |
741 | |
742 :: | |
743 | |
744 1. with Server; | |
745 2. package body Dynamic_Model is | |
746 3. Val : constant Integer := Server.Func; | |
747 | | |
748 >>> info: call to "Func" during elaboration | |
749 >>> info: missing pragma "Elaborate_All" for unit "Server" | |
750 | |
751 4. end Dynamic_Model; | |
752 | |
753 .. _Static_Elaboration_Model_in_GNAT: | |
754 | |
755 Static Elaboration Model in GNAT | |
756 ================================ | |
757 | |
758 In contrast to the dynamic model, the static model is more precise in its | |
759 analysis of elaboration code. The model makes a clear distinction between | |
760 internal and external targets, and resorts to different diagnostics and | |
761 run-time checks based on the nature of the target. | |
762 | |
763 * *Internal targets* | |
764 | |
765 The static model performs extensive diagnostics on scenarios which elaborate | |
766 or execute internal targets. The warnings resulting from these diagnostics | |
767 are enabled by default, but can be suppressed using compiler switch | |
768 :switch:`-gnatws`. | |
769 | |
770 :: | |
771 | |
772 1. package body Static_Model is | |
773 2. generic | |
774 3. with function Func return Integer; | |
775 4. package Gen is | |
776 5. Val : constant Integer := Func; | |
777 6. end Gen; | |
778 7. | |
779 8. function ABE return Integer; | |
780 9. | |
781 10. function Cause_ABE return Boolean is | |
782 11. package Inst is new Gen (ABE); | |
783 | | |
784 >>> warning: in instantiation at line 5 | |
785 >>> warning: cannot call "ABE" before body seen | |
786 >>> warning: Program_Error may be raised at run time | |
787 >>> warning: body of unit "Static_Model" elaborated | |
788 >>> warning: function "Cause_ABE" called at line 16 | |
789 >>> warning: function "ABE" called at line 5, instance at line 11 | |
790 | |
791 12. begin | |
792 13. ... | |
793 14. end Cause_ABE; | |
794 15. | |
795 16. Val : constant Boolean := Cause_ABE; | |
796 17. | |
797 18. function ABE return Integer is | |
798 19. begin | |
799 20. ... | |
800 21. end ABE; | |
801 22. end Static_Model; | |
802 | |
803 The example above illustrates an ABE problem within package ``Static_Model``, | |
804 which is hidden by several layers of indirection. The elaboration of package | |
805 body ``Static_Model`` elaborates the declaration of ``Val``. This invokes | |
806 function ``Cause_ABE``, which instantiates generic unit ``Gen`` as ``Inst``. | |
807 The elaboration of ``Inst`` invokes function ``ABE``, however the body of | |
808 ``ABE`` has not been elaborated yet. | |
809 | |
810 * *External targets* | |
811 | |
812 The static model installs run-time checks to verify the elaboration status | |
813 of server targets only when the scenario that elaborates or executes that | |
814 target is part of the elaboration code of the client unit. The checks can be | |
815 suppressed using pragma ``Suppress (Elaboration_Check)``. | |
816 | |
817 :: | |
818 | |
819 with Server; | |
820 package body Static_Model is | |
821 generic | |
822 with function Func return Integer; | |
823 package Gen is | |
824 Val : constant Integer := Func; | |
825 end Gen; | |
826 | |
827 function Call_Func return Boolean is | |
828 <check that the body of Server.Func is elaborated> | |
829 package Inst is new Gen (Server.Func); | |
830 begin | |
831 ... | |
832 end Call_Func; | |
833 | |
834 Val : constant Boolean := Call_Func; | |
835 end Static_Model; | |
836 | |
837 In the example above, the elaboration of package body ``Static_Model`` | |
838 elaborates the declaration of ``Val``. This invokes function ``Call_Func``, | |
839 which instantiates generic unit ``Gen`` as ``Inst``. The elaboration of | |
840 ``Inst`` invokes function ``Server.Func``. Since ``Server.Func`` is an | |
841 external target, GNAT installs a run-time check to verify that its body has | |
842 been elaborated. | |
843 | |
844 In addition to checks, the static model installs implicit ``Elaborate`` and | |
845 ``Elaborate_All`` pragmas to guarantee safe elaboration use of server units. | |
846 This information is available when compiler switch :switch:`-gnatel` is in | |
847 effect. | |
848 | |
849 :: | |
850 | |
851 1. with Server; | |
852 2. package body Static_Model is | |
853 3. generic | |
854 4. with function Func return Integer; | |
855 5. package Gen is | |
856 6. Val : constant Integer := Func; | |
857 7. end Gen; | |
858 8. | |
859 9. function Call_Func return Boolean is | |
860 10. package Inst is new Gen (Server.Func); | |
861 | | |
862 >>> info: instantiation of "Gen" during elaboration | |
863 >>> info: in instantiation at line 6 | |
864 >>> info: call to "Func" during elaboration | |
865 >>> info: in instantiation at line 6 | |
866 >>> info: implicit pragma "Elaborate_All" generated for unit "Server" | |
867 >>> info: body of unit "Static_Model" elaborated | |
868 >>> info: function "Call_Func" called at line 15 | |
869 >>> info: function "Func" called at line 6, instance at line 10 | |
870 | |
871 11. begin | |
872 12. ... | |
873 13. end Call_Func; | |
874 14. | |
875 15. Val : constant Boolean := Call_Func; | |
876 | | |
877 >>> info: call to "Call_Func" during elaboration | |
878 | |
879 16. end Static_Model; | |
880 | |
881 In the example above, the elaboration of package body ``Static_Model`` | |
882 elaborates the declaration of ``Val``. This invokes function ``Call_Func``, | |
883 which instantiates generic unit ``Gen`` as ``Inst``. The elaboration of | |
884 ``Inst`` invokes function ``Server.Func``. Since ``Server.Func`` is an | |
885 external target, GNAT installs an implicit ``Elaborate_All`` pragma for unit | |
886 ``Server``. The pragma guarantees that both the spec and body of ``Server``, | |
887 along with any additional dependencies that ``Server`` may require, are | |
888 elaborated prior to the body of ``Static_Model``. | |
889 | |
890 .. _SPARK_Elaboration_Model_in_GNAT: | |
891 | |
892 SPARK Elaboration Model in GNAT | |
893 =============================== | |
894 | |
895 The SPARK model is identical to the static model in its handling of internal | |
896 targets. The SPARK model, however, requires explicit ``Elaborate`` or | |
897 ``Elaborate_All`` pragmas to be present in the program when a target is | |
898 external, and compiler switch :switch:`-gnatd.v` is in effect. | |
899 | |
900 :: | |
901 | |
902 1. with Server; | |
903 2. package body SPARK_Model with SPARK_Mode is | |
904 3. Val : constant Integer := Server.Func; | |
905 | | |
906 >>> call to "Func" during elaboration in SPARK | |
907 >>> unit "SPARK_Model" requires pragma "Elaborate_All" for "Server" | |
908 >>> body of unit "SPARK_Model" elaborated | |
909 >>> function "Func" called at line 3 | |
910 | |
911 4. end SPARK_Model; | |
912 | |
913 .. _Mixing_Elaboration_Models: | |
914 | |
915 Mixing Elaboration Models | |
916 ========================= | |
917 | |
918 It is possible to mix units compiled with a different elaboration model, | |
919 however the following rules must be observed: | |
920 | |
921 * A client unit compiled with the dynamic model can only |with| a server unit | |
922 that meets at least one of the following criteria: | |
923 | |
924 - The server unit is compiled with the dynamic model. | |
925 | |
926 - The server unit is a GNAT implementation unit from the Ada, GNAT, | |
927 Interfaces, or System hierarchies. | |
928 | |
929 - The server unit has pragma ``Pure`` or ``Preelaborate``. | |
930 | |
931 - The client unit has an explicit ``Elaborate_All`` pragma for the server | |
932 unit. | |
933 | |
934 These rules ensure that elaboration checks are not omitted. If the rules are | |
935 violated, the binder emits a warning: | |
936 | |
937 :: | |
938 | |
939 warning: "x.ads" has dynamic elaboration checks and with's | |
940 warning: "y.ads" which has static elaboration checks | |
941 | |
942 The warnings can be suppressed by binder switch :switch:`-ws`. | |
943 | |
944 .. _Elaboration_Circularities: | |
945 | |
946 Elaboration Circularities | |
947 ========================= | |
948 | |
949 If the binder cannot find an acceptable elaboration order, it outputs detailed | |
950 diagnostics describing an **elaboration circularity**. | |
951 | |
952 :: | |
953 | |
954 package Server is | |
955 function Func return Integer; | |
956 end Server; | |
957 | |
958 :: | |
959 | |
960 with Client; | |
961 package body Server is | |
962 function Func return Integer is | |
963 begin | |
964 ... | |
965 end Func; | |
966 end Server; | |
967 | |
968 :: | |
969 | |
970 with Server; | |
971 package Client is | |
972 Val : constant Integer := Server.Func; | |
973 end Client; | |
974 | |
975 :: | |
976 | |
977 with Client; | |
978 procedure Main is begin null; end Main; | |
979 | |
980 :: | |
981 | |
982 error: elaboration circularity detected | |
983 info: "server (body)" must be elaborated before "client (spec)" | |
984 info: reason: implicit Elaborate_All in unit "client (spec)" | |
985 info: recompile "client (spec)" with -gnatel for full details | |
986 info: "server (body)" | |
987 info: must be elaborated along with its spec: | |
988 info: "server (spec)" | |
989 info: which is withed by: | |
990 info: "client (spec)" | |
991 info: "client (spec)" must be elaborated before "server (body)" | |
992 info: reason: with clause | |
993 | |
994 In the example above, ``Client`` must be elaborated prior to ``Main`` by virtue | |
995 of a |with| clause. The elaboration of ``Client`` invokes ``Server.Func``, and | |
996 static model generates an implicit ``Elaborate_All`` pragma for ``Server``. The | |
997 pragma implies that both the spec and body of ``Server``, along with any units | |
998 they |with|, must be elaborated prior to ``Client``. However, ``Server``'s body | |
999 |withs| ``Client``, implying that ``Client`` must be elaborated prior to | |
1000 ``Server``. The end result is that ``Client`` must be elaborated prior to | |
1001 ``Client``, and this leads to a circularity. | |
1002 | |
1003 .. _Resolving_Elaboration_Circularities: | |
1004 | |
1005 Resolving Elaboration Circularities | |
1006 =================================== | |
1007 | |
1008 When faced with an elaboration circularity, a programmer has several options | |
1009 available. | |
1010 | |
1011 * *Fix the program* | |
1012 | |
1013 The most desirable option from the point of view of long-term maintenance | |
1014 is to rearrange the program so that the elaboration problems are avoided. | |
1015 One useful technique is to place the elaboration code into separate child | |
1016 packages. Another is to move some of the initialization code to explicitly | |
1017 invoked subprograms, where the program controls the order of initialization | |
1018 explicitly. Although this is the most desirable option, it may be impractical | |
1019 and involve too much modification, especially in the case of complex legacy | |
1020 code. | |
1021 | |
1022 * *Switch to more permissive elaboration model* | |
1023 | |
1024 If the compilation was performed using the static model, enable the dynamic | |
1025 model with compiler switch :switch:`-gnatE`. GNAT will no longer generate | |
1026 implicit ``Elaborate`` and ``Elaborate_All`` pragmas, resulting in a behavior | |
1027 identical to that specified by the Ada Reference Manual. The binder will | |
1028 generate an executable program that may or may not raise ``Program_Error``, | |
1029 and it is the programmer's responsibility to ensure that it does not raise | |
1030 ``Program_Error``. | |
1031 | |
1032 * *Suppress all elaboration checks* | |
1033 | |
1034 The drawback of run-time checks is that they generate overhead at run time, | |
1035 both in space and time. If the programmer is absolutely sure that a program | |
1036 will not raise an elaboration-related ``Program_Error``, then using the | |
1037 pragma ``Suppress (Elaboration_Check)`` globally (as a configuration pragma) | |
1038 will eliminate all run-time checks. | |
1039 | |
1040 * *Suppress elaboration checks selectively* | |
1041 | |
1042 If a scenario cannot possibly lead to an elaboration ``Program_Error``, | |
1043 and the binder nevertheless complains about implicit ``Elaborate`` and | |
1044 ``Elaborate_All`` pragmas that lead to elaboration circularities, it | |
1045 is possible to suppress the generation of implicit ``Elaborate`` and | |
1046 ``Elaborate_All`` pragmas, as well as run-time checks. Clearly this can | |
1047 be unsafe, and it is the responsibility of the programmer to make sure | |
1048 that the resulting program has no elaboration anomalies. Pragma | |
1049 ``Suppress (Elaboration_Check)`` can be used with different levels of | |
1050 granularity to achieve these effects. | |
1051 | |
1052 - *Target suppression* | |
1053 | |
1054 When the pragma is placed in a declarative part, without a second argument | |
1055 naming an entity, it will suppress implicit ``Elaborate`` and | |
1056 ``Elaborate_All`` pragma generation, as well as run-time checks, on all | |
1057 targets within the region. | |
1058 | |
1059 :: | |
1060 | |
1061 package Range_Suppress is | |
1062 pragma Suppress (Elaboration_Check); | |
1063 | |
1064 function Func return Integer; | |
1065 | |
1066 generic | |
1067 procedure Gen; | |
1068 | |
1069 pragma Unsuppress (Elaboration_Check); | |
1070 | |
1071 task type Tsk; | |
1072 end Range_Suppress; | |
1073 | |
1074 In the example above, a pair of Suppress/Unsuppress pragmas define a region | |
1075 of suppression within package ``Range_Suppress``. As a result, no implicit | |
1076 ``Elaborate`` and ``Elaborate_All`` pragmas, nor any run-time checks, will | |
1077 be generated by callers of ``Func`` and instantiators of ``Gen``. Note that | |
1078 task type ``Tsk`` is not within this region. | |
1079 | |
1080 An alternative to the region-based suppression is to use multiple | |
1081 ``Suppress`` pragmas with arguments naming specific entities for which | |
1082 elaboration checks should be suppressed: | |
1083 | |
1084 :: | |
1085 | |
1086 package Range_Suppress is | |
1087 function Func return Integer; | |
1088 pragma Suppress (Elaboration_Check, Func); | |
1089 | |
1090 generic | |
1091 procedure Gen; | |
1092 pragma Suppress (Elaboration_Check, Gen); | |
1093 | |
1094 task type Tsk; | |
1095 end Range_Suppress; | |
1096 | |
1097 - *Scenario suppression* | |
1098 | |
1099 When the pragma ``Suppress`` is placed in a declarative or statement | |
1100 part, without an entity argument, it will suppress implicit ``Elaborate`` | |
1101 and ``Elaborate_All`` pragma generation, as well as run-time checks, on | |
1102 all scenarios within the region. | |
1103 | |
1104 :: | |
1105 | |
1106 with Server; | |
1107 package body Range_Suppress is | |
1108 pragma Suppress (Elaboration_Check); | |
1109 | |
1110 function Func return Integer is | |
1111 begin | |
1112 return Server.Func; | |
1113 end Func; | |
1114 | |
1115 procedure Gen is | |
1116 begin | |
1117 Server.Proc; | |
1118 end Gen; | |
1119 | |
1120 pragma Unsuppress (Elaboration_Check); | |
1121 | |
1122 task body Tsk is | |
1123 begin | |
1124 Server.Proc; | |
1125 end Tsk; | |
1126 end Range_Suppress; | |
1127 | |
1128 In the example above, a pair of Suppress/Unsuppress pragmas define a region | |
1129 of suppression within package body ``Range_Suppress``. As a result, the | |
1130 calls to ``Server.Func`` in ``Func`` and ``Server.Proc`` in ``Gen`` will | |
1131 not generate any implicit ``Elaborate`` and ``Elaborate_All`` pragmas or | |
1132 run-time checks. | |
1133 | |
1134 .. _Resolving_Task_Issues: | |
1135 | |
1136 Resolving Task Issues | |
1137 ===================== | |
1138 | |
1139 The model of execution in Ada dictates that elaboration must first take place, | |
1140 and only then can the main program be started. Tasks which are activated during | |
1141 elaboration violate this model and may lead to serious concurrent problems at | |
1142 elaboration time. | |
1143 | |
1144 A task can be activated in two different ways: | |
1145 | |
1146 * The task is created by an allocator in which case it is activated immediately | |
1147 after the allocator is evaluated. | |
1148 | |
1149 * The task is declared at the library level or within some nested master in | |
1150 which case it is activated before starting execution of the statement | |
1151 sequence of the master defining the task. | |
1152 | |
1153 Since the elaboration of a partition is performed by the environment task | |
1154 servicing that partition, any tasks activated during elaboration may be in | |
1155 a race with the environment task, and lead to unpredictable state and behavior. | |
1156 The static model seeks to avoid such interactions by assuming that all code in | |
1157 the task body is executed at elaboration time, if the task was activated by | |
1158 elaboration code. | |
1159 | |
1160 :: | |
1161 | |
1162 package Decls is | |
1163 task Lib_Task is | |
1164 entry Start; | |
1165 end Lib_Task; | |
1166 | |
1167 type My_Int is new Integer; | |
1168 | |
1169 function Ident (M : My_Int) return My_Int; | |
1170 end Decls; | |
1171 | |
1172 :: | |
1173 | |
1174 with Utils; | |
1175 package body Decls is | |
1176 task body Lib_Task is | |
1177 begin | |
1178 accept Start; | |
1179 Utils.Put_Val (2); | |
1180 end Lib_Task; | |
1181 | |
1182 function Ident (M : My_Int) return My_Int is | |
1183 begin | |
1184 return M; | |
1185 end Ident; | |
1186 end Decls; | |
1187 | |
1188 :: | |
1189 | |
1190 with Decls; | |
1191 package Utils is | |
1192 procedure Put_Val (Arg : Decls.My_Int); | |
1193 end Utils; | |
1194 | |
1195 :: | |
1196 | |
1197 with Ada.Text_IO; use Ada.Text_IO; | |
1198 package body Utils is | |
1199 procedure Put_Val (Arg : Decls.My_Int) is | |
1200 begin | |
1201 Put_Line (Arg'Img); | |
1202 end Put_Val; | |
1203 end Utils; | |
1204 | |
1205 :: | |
1206 | |
1207 with Decls; | |
1208 procedure Main is | |
1209 begin | |
1210 Decls.Lib_Task.Start; | |
1211 end Main; | |
1212 | |
1213 When the above example is compiled with the static model, an elaboration | |
1214 circularity arises: | |
1215 | |
1216 :: | |
1217 | |
1218 error: elaboration circularity detected | |
1219 info: "decls (body)" must be elaborated before "decls (body)" | |
1220 info: reason: implicit Elaborate_All in unit "decls (body)" | |
1221 info: recompile "decls (body)" with -gnatel for full details | |
1222 info: "decls (body)" | |
1223 info: must be elaborated along with its spec: | |
1224 info: "decls (spec)" | |
1225 info: which is withed by: | |
1226 info: "utils (spec)" | |
1227 info: which is withed by: | |
1228 info: "decls (body)" | |
1229 | |
1230 In the above example, ``Decls`` must be elaborated prior to ``Main`` by virtue | |
1231 of a with clause. The elaboration of ``Decls`` activates task ``Lib_Task``. The | |
1232 static model conservatibely assumes that all code within the body of | |
1233 ``Lib_Task`` is executed, and generates an implicit ``Elaborate_All`` pragma | |
1234 for ``Units`` due to the call to ``Utils.Put_Val``. The pragma implies that | |
1235 both the spec and body of ``Utils``, along with any units they |with|, | |
1236 must be elaborated prior to ``Decls``. However, ``Utils``'s spec |withs| | |
1237 ``Decls``, implying that ``Decls`` must be elaborated before ``Utils``. The end | |
1238 result is that ``Utils`` must be elaborated prior to ``Utils``, and this | |
1239 leads to a circularity. | |
1240 | |
1241 In reality, the example above will not exhibit an ABE problem at run time. | |
1242 When the body of task ``Lib_Task`` is activated, execution will wait for entry | |
1243 ``Start`` to be accepted, and the call to ``Utils.Put_Val`` will not take place | |
1244 at elaboration time. Task ``Lib_Task`` will resume its execution after the main | |
1245 program is executed because ``Main`` performs a rendezvous with | |
1246 ``Lib_Task.Start``, and at that point all units have already been elaborated. | |
1247 As a result, the static model may seem overly conservative, partly because it | |
1248 does not take control and data flow into account. | |
1249 | |
1250 When faced with a task elaboration circularity, a programmer has several | |
1251 options available: | |
1252 | |
1253 * *Use the dynamic model* | |
1254 | |
1255 The dynamic model does not generate implicit ``Elaborate`` and | |
1256 ``Elaborate_All`` pragmas. Instead, it will install checks prior to every | |
1257 call in the example above, thus verifying the successful elaboration of | |
1258 ``Utils.Put_Val`` in case the call to it takes place at elaboration time. | |
1259 The dynamic model is enabled with compiler switch :switch:`-gnatE`. | |
1260 | |
1261 * *Isolate the tasks* | |
1262 | |
1263 Relocating tasks in their own separate package could decouple them from | |
1264 dependencies that would otherwise cause an elaboration circularity. The | |
1265 example above can be rewritten as follows: | |
1266 | |
1267 :: | |
1268 | |
1269 package Decls1 is -- new | |
1270 task Lib_Task is | |
1271 entry Start; | |
1272 end Lib_Task; | |
1273 end Decls1; | |
1274 | |
1275 :: | |
1276 | |
1277 with Utils; | |
1278 package body Decls1 is -- new | |
1279 task body Lib_Task is | |
1280 begin | |
1281 accept Start; | |
1282 Utils.Put_Val (2); | |
1283 end Lib_Task; | |
1284 end Decls1; | |
1285 | |
1286 :: | |
1287 | |
1288 package Decls2 is -- new | |
1289 type My_Int is new Integer; | |
1290 function Ident (M : My_Int) return My_Int; | |
1291 end Decls2; | |
1292 | |
1293 :: | |
1294 | |
1295 with Utils; | |
1296 package body Decls2 is -- new | |
1297 function Ident (M : My_Int) return My_Int is | |
1298 begin | |
1299 return M; | |
1300 end Ident; | |
1301 end Decls2; | |
1302 | |
1303 :: | |
1304 | |
1305 with Decls2; | |
1306 package Utils is | |
1307 procedure Put_Val (Arg : Decls2.My_Int); | |
1308 end Utils; | |
1309 | |
1310 :: | |
1311 | |
1312 with Ada.Text_IO; use Ada.Text_IO; | |
1313 package body Utils is | |
1314 procedure Put_Val (Arg : Decls2.My_Int) is | |
1315 begin | |
1316 Put_Line (Arg'Img); | |
1317 end Put_Val; | |
1318 end Utils; | |
1319 | |
1320 :: | |
1321 | |
1322 with Decls1; | |
1323 procedure Main is | |
1324 begin | |
1325 Decls1.Lib_Task.Start; | |
1326 end Main; | |
1327 | |
1328 * *Declare the tasks* | |
1329 | |
1330 The original example uses a single task declaration for ``Lib_Task``. An | |
1331 explicit task type declaration and a properly placed task object could avoid | |
1332 the dependencies that would otherwise cause an elaboration circularity. The | |
1333 example can be rewritten as follows: | |
1334 | |
1335 :: | |
1336 | |
1337 package Decls is | |
1338 task type Lib_Task is -- new | |
1339 entry Start; | |
1340 end Lib_Task; | |
1341 | |
1342 type My_Int is new Integer; | |
1343 | |
1344 function Ident (M : My_Int) return My_Int; | |
1345 end Decls; | |
1346 | |
1347 :: | |
1348 | |
1349 with Utils; | |
1350 package body Decls is | |
1351 task body Lib_Task is | |
1352 begin | |
1353 accept Start; | |
1354 Utils.Put_Val (2); | |
1355 end Lib_Task; | |
1356 | |
1357 function Ident (M : My_Int) return My_Int is | |
1358 begin | |
1359 return M; | |
1360 end Ident; | |
1361 end Decls; | |
1362 | |
1363 :: | |
1364 | |
1365 with Decls; | |
1366 package Utils is | |
1367 procedure Put_Val (Arg : Decls.My_Int); | |
1368 end Utils; | |
1369 | |
1370 :: | |
1371 | |
1372 with Ada.Text_IO; use Ada.Text_IO; | |
1373 package body Utils is | |
1374 procedure Put_Val (Arg : Decls.My_Int) is | |
1375 begin | |
1376 Put_Line (Arg'Img); | |
1377 end Put_Val; | |
1378 end Utils; | |
1379 | |
1380 :: | |
1381 | |
1382 with Decls; | |
1383 package Obj_Decls is -- new | |
1384 Task_Obj : Decls.Lib_Task; | |
1385 end Obj_Decls; | |
1386 | |
1387 :: | |
1388 | |
1389 with Obj_Decls; | |
1390 procedure Main is | |
1391 begin | |
1392 Obj_Decls.Task_Obj.Start; -- new | |
1393 end Main; | |
1394 | |
1395 * *Use restriction No_Entry_Calls_In_Elaboration_Code* | |
1396 | |
1397 The issue exhibited in the original example under this section revolves | |
1398 around the body of ``Lib_Task`` blocking on an accept statement. There is | |
1399 no rule to prevent elaboration code from performing entry calls, however in | |
1400 practice this is highly unusual. In addition, the pattern of starting tasks | |
1401 at elaboration time and then immediately blocking on accept or select | |
1402 statements is quite common. | |
1403 | |
1404 If a programmer knows that elaboration code will not perform any entry | |
1405 calls, then the programmer can indicate that the static model should not | |
1406 process the remainder of a task body once an accept or select statement has | |
1407 been encountered. This behavior can be specified by a configuration pragma: | |
1408 | |
1409 :: | |
1410 | |
1411 pragma Restrictions (No_Entry_Calls_In_Elaboration_Code); | |
1412 | |
1413 In addition to the change in behavior with respect to task bodies, the | |
1414 static model will verify that no entry calls take place at elaboration time. | |
1415 | |
1416 .. _Elaboration_Related_Compiler_Switches: | |
1417 | |
1418 Elaboration-related Compiler Switches | |
1419 ===================================== | |
1420 | |
1421 GNAT has several switches that affect the elaboration model and consequently | |
1422 the elaboration order chosen by the binder. | |
1423 | |
1424 .. index:: -gnatdE (gnat) | |
1425 | |
1426 :switch:`-gnatdE` | |
1427 Elaboration checks on predefined units | |
1428 | |
1429 When this switch is in effect, GNAT will consider scenarios and targets that | |
1430 come from the Ada, GNAT, Interfaces, and System hierarchies. This switch is | |
1431 useful when a programmer has defined a custom grandchild of those packages. | |
1432 | |
1433 .. index:: -gnatd.G (gnat) | |
1434 | |
1435 :switch:`-gnatd.G` | |
1436 Ignore calls through generic formal parameters for elaboration | |
1437 | |
1438 When this switch is in effect, GNAT will ignore calls that invoke generic | |
1439 actual entries, operators, or subprograms via generic formal subprograms. As | |
1440 a result, GNAT will not generate implicit ``Elaborate`` and ``Elaborate_All`` | |
1441 pragmas, and run-time checks for such calls. Note that this switch does not | |
1442 overlap with :switch:`-gnatdL`. | |
1443 | |
1444 :: | |
1445 | |
1446 package body Ignore_Calls is | |
1447 function ABE return Integer; | |
1448 | |
1449 generic | |
1450 with function Gen_Formal return Integer; | |
1451 package Gen is | |
1452 Val : constant Integer := Gen_Formal; | |
1453 end Gen; | |
1454 | |
1455 package Inst is new Gen (ABE); | |
1456 | |
1457 function ABE return Integer is | |
1458 begin | |
1459 ... | |
1460 end ABE; | |
1461 end Ignore_Calls; | |
1462 | |
1463 In the example above, the call to function ``ABE`` will be ignored because it | |
1464 occurs during the elaboration of instance ``Inst``, through a call to generic | |
1465 formal subprogram ``Gen_Formal``. | |
1466 | |
1467 .. index:: -gnatdL (gnat) | |
1468 | |
1469 :switch:`-gnatdL` | |
1470 Ignore external calls from instances for elaboration | |
1471 | |
1472 When this switch is in effect, GNAT will ignore calls that originate from | |
1473 within an instance and directly target an entry, operator, or subprogram | |
1474 defined outside the instance. As a result, GNAT will not generate implicit | |
1475 ``Elaborate`` and ``Elaborate_All`` pragmas, and run-time checks for such | |
1476 calls. Note that this switch does not overlap with :switch:`-gnatd.G`. | |
1477 | |
1478 :: | |
1479 | |
1480 package body Ignore_Calls is | |
1481 function ABE return Integer; | |
1482 | |
1483 generic | |
1484 package Gen is | |
1485 Val : constant Integer := ABE; | |
1486 end Gen; | |
1487 | |
1488 package Inst is new Gen; | |
1489 | |
1490 function ABE return Integer is | |
1491 begin | |
1492 ... | |
1493 end ABE; | |
1494 end Ignore_Calls; | |
1495 | |
1496 In the example above, the call to function ``ABE`` will be ignored because it | |
1497 originates from within an instance and targets a subprogram defined outside | |
1498 the instance. | |
1499 | |
1500 .. index:: -gnatd.o (gnat) | |
1501 | |
1502 :switch:`-gnatd.o` | |
1503 Conservative elaboration order for indirect calls | |
1504 | |
1505 When this switch is in effect, GNAT will treat ``'Access`` of an entry, | |
1506 operator, or subprogram as an immediate call to that target. As a result, | |
1507 GNAT will generate implicit ``Elaborate`` and ``Elaborate_All`` pragmas as | |
1508 well as run-time checks for such attribute references. | |
1509 | |
1510 :: | |
1511 | |
1512 1. package body Attribute_Call is | |
1513 2. function Func return Integer; | |
1514 3. type Func_Ptr is access function return Integer; | |
1515 4. | |
1516 5. Ptr : constant Func_Ptr := Func'Access; | |
1517 | | |
1518 >>> warning: cannot call "Func" before body seen | |
1519 >>> warning: Program_Error may be raised at run time | |
1520 >>> warning: body of unit "Attribute_Call" elaborated | |
1521 >>> warning: "Access" of "Func" taken at line 5 | |
1522 >>> warning: function "Func" called at line 5 | |
1523 | |
1524 6. | |
1525 7. function Func return Integer is | |
1526 8. begin | |
1527 9. ... | |
1528 10. end Func; | |
1529 11. end Attribute_Call; | |
1530 | |
1531 In the example above, the elaboration of declaration ``Ptr`` is assigned | |
1532 ``Func'Access`` before the body of ``Func`` has been elaborated. | |
1533 | |
1534 .. index:: -gnatd.U (gnat) | |
1535 | |
1536 :switch:`-gnatd.U` | |
1537 Ignore indirect calls for static elaboration | |
1538 | |
1539 When this switch is in effect, GNAT will ignore ``'Access`` of an entry, | |
1540 operator, or subprogram when the static model is in effect. | |
1541 | |
1542 .. index:: -gnatd.v (gnat) | |
1543 | |
1544 :switch:`-gnatd.v` | |
1545 Enforce SPARK elaboration rules in SPARK code | |
1546 | |
1547 When this switch is in effect, GNAT will enforce the SPARK rules of | |
1548 elaboration as defined in the SPARK Reference Manual, section 7.7. As a | |
1549 result, constructs which violate the SPARK elaboration rules are no longer | |
1550 accepted, even if GNAT is able to statically ensure that these constructs | |
1551 will not lead to ABE problems. | |
1552 | |
1553 .. index:: -gnatd.y (gnat) | |
1554 | |
1555 :switch:`-gnatd.y` | |
1556 Disable implicit pragma Elaborate[_All] on task bodies | |
1557 | |
1558 When this switch is in effect, GNAT will not generate ``Elaborate`` and | |
1559 ``Elaborate_All`` pragmas if the need for the pragma came directly or | |
1560 indirectly from a task body. | |
1561 | |
1562 :: | |
1563 | |
1564 with Server; | |
1565 package body Disable_Task is | |
1566 task T; | |
1567 | |
1568 task body T is | |
1569 begin | |
1570 Server.Proc; | |
1571 end T; | |
1572 end Disable_Task; | |
1573 | |
1574 In the example above, the activation of single task ``T`` invokes | |
1575 ``Server.Proc``, which implies that ``Server`` requires ``Elaborate_All``, | |
1576 however GNAT will not generate the pragma. | |
1577 | |
1578 .. index:: -gnatE (gnat) | |
1579 | |
1580 :switch:`-gnatE` | |
1581 Dynamic elaboration checking mode enabled | |
1582 | |
1583 When this switch is in effect, GNAT activates the dynamic elaboration model. | |
1584 | |
1585 .. index:: -gnatel (gnat) | |
1586 | |
1587 :switch:`-gnatel` | |
1588 Turn on info messages on generated Elaborate[_All] pragmas | |
1589 | |
1590 When this switch is in effect, GNAT will emit the following supplementary | |
1591 information depending on the elaboration model in effect. | |
1592 | |
1593 - *Dynamic model* | |
1594 | |
1595 GNAT will indicate missing ``Elaborate`` and ``Elaborate_All`` pragmas for | |
1596 all library-level scenarios within the partition. | |
1597 | |
1598 - *Static model* | |
1599 | |
1600 GNAT will indicate all scenarios executed during elaboration. In addition, | |
1601 it will provide detailed traceback when an implicit ``Elaborate`` or | |
1602 ``Elaborate_All`` pragma is generated. | |
1603 | |
1604 - *SPARK model* | |
1605 | |
1606 GNAT will indicate how an elaboration requirement is met by the context of | |
1607 a unit. This diagnostic requires compiler switch :switch:`-gnatd.v`. | |
1608 | |
1609 :: | |
1610 | |
1611 1. with Server; pragma Elaborate_All (Server); | |
1612 2. package Client with SPARK_Mode is | |
1613 3. Val : constant Integer := Server.Func; | |
1614 | | |
1615 >>> info: call to "Func" during elaboration in SPARK | |
1616 >>> info: "Elaborate_All" requirement for unit "Server" met by pragma at line 1 | |
1617 | |
1618 4. end Client; | |
1619 | |
1620 .. index:: -gnatw.f (gnat) | |
1621 | |
1622 :switch:`-gnatw.f` | |
1623 Turn on warnings for suspicious Subp'Access | |
1624 | |
1625 When this switch is in effect, GNAT will treat ``'Access`` of an entry, | |
1626 operator, or subprogram as a potential call to the target and issue warnings: | |
1627 | |
1628 :: | |
1629 | |
1630 1. package body Attribute_Call is | |
1631 2. function Func return Integer; | |
1632 3. type Func_Ptr is access function return Integer; | |
1633 4. | |
1634 5. Ptr : constant Func_Ptr := Func'Access; | |
1635 | | |
1636 >>> warning: "Access" attribute of "Func" before body seen | |
1637 >>> warning: possible Program_Error on later references | |
1638 >>> warning: body of unit "Attribute_Call" elaborated | |
1639 >>> warning: "Access" of "Func" taken at line 5 | |
1640 | |
1641 6. | |
1642 7. function Func return Integer is | |
1643 8. begin | |
1644 9. ... | |
1645 10. end Func; | |
1646 11. end Attribute_Call; | |
1647 | |
1648 In the example above, the elaboration of declaration ``Ptr`` is assigned | |
1649 ``Func'Access`` before the body of ``Func`` has been elaborated. | |
1650 | |
1651 .. _Summary_of_Procedures_for_Elaboration_Control: | |
1652 | |
1653 Summary of Procedures for Elaboration Control | |
1654 ============================================= | |
1655 | |
1656 A programmer should first compile the program with the default options, using | |
1657 none of the binder or compiler switches. If the binder succeeds in finding an | |
1658 elaboration order, then apart from possible cases involing dispatching calls | |
1659 and access-to-subprogram types, the program is free of elaboration errors. | |
1660 If it is important for the program to be portable to compilers other than GNAT, | |
1661 then the programmer should use compiler switch :switch:`-gnatel` and consider | |
1662 the messages about missing or implicitly created ``Elaborate`` and | |
1663 ``Elaborate_All`` pragmas. | |
1664 | |
1665 If the binder reports an elaboration circularity, the programmer has several | |
1666 options: | |
1667 | |
1668 * Ensure that warnings are enabled. This will allow the static model to output | |
1669 trace information of elaboration issues. The trace information could shed | |
1670 light on previously unforeseen dependencies, as well as their origins. | |
1671 | |
1672 * Use switch :switch:`-gnatel` to obtain messages on generated implicit | |
1673 ``Elaborate`` and ``Elaborate_All`` pragmas. The trace information could | |
1674 indicate why a server unit must be elaborated prior to a client unit. | |
1675 | |
1676 * If the warnings produced by the static model indicate that a task is | |
1677 involved, consider the options in the section on resolving task issues as | |
1678 well as compiler switch :switch:`-gnatd.y`. | |
1679 | |
1680 * If the warnings produced by the static model indicate that an generic | |
1681 instantiations are involved, consider using compiler switches | |
1682 :switch:`-gnatd.G` and :switch:`-gnatdL`. | |
1683 | |
1684 * If none of the steps outlined above resolve the circularity, recompile the | |
1685 program using the dynamic model by using compiler switch :switch:`-gnatE`. | |
1686 | |
1687 .. _Inspecting_the_Chosen_Elaboration_Order: | |
1688 | |
1689 Inspecting the Chosen Elaboration Order | |
1690 ======================================= | |
1691 | |
1692 To see the elaboration order chosen by the binder, inspect the contents of file | |
1693 `b~xxx.adb`. On certain targets, this file appears as `b_xxx.adb`. The | |
1694 elaboration order appears as a sequence of calls to ``Elab_Body`` and | |
1695 ``Elab_Spec``, interspersed with assignments to `Exxx` which indicates that a | |
1696 particular unit is elaborated. For example: | |
1697 | |
1698 :: | |
1699 | |
1700 System.Soft_Links'Elab_Body; | |
1701 E14 := True; | |
1702 System.Secondary_Stack'Elab_Body; | |
1703 E18 := True; | |
1704 System.Exception_Table'Elab_Body; | |
1705 E24 := True; | |
1706 Ada.Io_Exceptions'Elab_Spec; | |
1707 E67 := True; | |
1708 Ada.Tags'Elab_Spec; | |
1709 Ada.Streams'Elab_Spec; | |
1710 E43 := True; | |
1711 Interfaces.C'Elab_Spec; | |
1712 E69 := True; | |
1713 System.Finalization_Root'Elab_Spec; | |
1714 E60 := True; | |
1715 System.Os_Lib'Elab_Body; | |
1716 E71 := True; | |
1717 System.Finalization_Implementation'Elab_Spec; | |
1718 System.Finalization_Implementation'Elab_Body; | |
1719 E62 := True; | |
1720 Ada.Finalization'Elab_Spec; | |
1721 E58 := True; | |
1722 Ada.Finalization.List_Controller'Elab_Spec; | |
1723 E76 := True; | |
1724 System.File_Control_Block'Elab_Spec; | |
1725 E74 := True; | |
1726 System.File_Io'Elab_Body; | |
1727 E56 := True; | |
1728 Ada.Tags'Elab_Body; | |
1729 E45 := True; | |
1730 Ada.Text_Io'Elab_Spec; | |
1731 Ada.Text_Io'Elab_Body; | |
1732 E07 := True; | |
1733 | |
1734 Note also binder switch :switch:`-l`, which outputs the chosen elaboration | |
1735 order and provides a more readable form of the above: | |
1736 | |
1737 :: | |
1738 | |
1739 ada (spec) | |
1740 interfaces (spec) | |
1741 system (spec) | |
1742 system.case_util (spec) | |
1743 system.case_util (body) | |
1744 system.concat_2 (spec) | |
1745 system.concat_2 (body) | |
1746 system.concat_3 (spec) | |
1747 system.concat_3 (body) | |
1748 system.htable (spec) | |
1749 system.parameters (spec) | |
1750 system.parameters (body) | |
1751 system.crtl (spec) | |
1752 interfaces.c_streams (spec) | |
1753 interfaces.c_streams (body) | |
1754 system.restrictions (spec) | |
1755 system.restrictions (body) | |
1756 system.standard_library (spec) | |
1757 system.exceptions (spec) | |
1758 system.exceptions (body) | |
1759 system.storage_elements (spec) | |
1760 system.storage_elements (body) | |
1761 system.secondary_stack (spec) | |
1762 system.stack_checking (spec) | |
1763 system.stack_checking (body) | |
1764 system.string_hash (spec) | |
1765 system.string_hash (body) | |
1766 system.htable (body) | |
1767 system.strings (spec) | |
1768 system.strings (body) | |
1769 system.traceback (spec) | |
1770 system.traceback (body) | |
1771 system.traceback_entries (spec) | |
1772 system.traceback_entries (body) | |
1773 ada.exceptions (spec) | |
1774 ada.exceptions.last_chance_handler (spec) | |
1775 system.soft_links (spec) | |
1776 system.soft_links (body) | |
1777 ada.exceptions.last_chance_handler (body) | |
1778 system.secondary_stack (body) | |
1779 system.exception_table (spec) | |
1780 system.exception_table (body) | |
1781 ada.io_exceptions (spec) | |
1782 ada.tags (spec) | |
1783 ada.streams (spec) | |
1784 interfaces.c (spec) | |
1785 interfaces.c (body) | |
1786 system.finalization_root (spec) | |
1787 system.finalization_root (body) | |
1788 system.memory (spec) | |
1789 system.memory (body) | |
1790 system.standard_library (body) | |
1791 system.os_lib (spec) | |
1792 system.os_lib (body) | |
1793 system.unsigned_types (spec) | |
1794 system.stream_attributes (spec) | |
1795 system.stream_attributes (body) | |
1796 system.finalization_implementation (spec) | |
1797 system.finalization_implementation (body) | |
1798 ada.finalization (spec) | |
1799 ada.finalization (body) | |
1800 ada.finalization.list_controller (spec) | |
1801 ada.finalization.list_controller (body) | |
1802 system.file_control_block (spec) | |
1803 system.file_io (spec) | |
1804 system.file_io (body) | |
1805 system.val_uns (spec) | |
1806 system.val_util (spec) | |
1807 system.val_util (body) | |
1808 system.val_uns (body) | |
1809 system.wch_con (spec) | |
1810 system.wch_con (body) | |
1811 system.wch_cnv (spec) | |
1812 system.wch_jis (spec) | |
1813 system.wch_jis (body) | |
1814 system.wch_cnv (body) | |
1815 system.wch_stw (spec) | |
1816 system.wch_stw (body) | |
1817 ada.tags (body) | |
1818 ada.exceptions (body) | |
1819 ada.text_io (spec) | |
1820 ada.text_io (body) | |
1821 text_io (spec) | |
1822 gdbstr (body) |