comparison gcc/ada/sem_spark.adb @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children
comparison
equal deleted inserted replaced
111:04ced10e8804 131:84e7813d76e9
4 -- -- 4 -- --
5 -- S E M _ S P A R K -- 5 -- S E M _ S P A R K --
6 -- -- 6 -- --
7 -- B o d y -- 7 -- B o d y --
8 -- -- 8 -- --
9 -- Copyright (C) 2017, Free Software Foundation, Inc. -- 9 -- Copyright (C) 2017-2018, Free Software Foundation, Inc. --
10 -- -- 10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under -- 11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- -- 12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- -- 13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- 14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
50 Elaboration_Context_Max : constant := 1009; 50 Elaboration_Context_Max : constant := 1009;
51 -- The hash range 51 -- The hash range
52 52
53 type Elaboration_Context_Index is range 0 .. Elaboration_Context_Max - 1; 53 type Elaboration_Context_Index is range 0 .. Elaboration_Context_Max - 1;
54 54
55 function Elaboration_Context_Hash 55 function Elaboration_Context_Hash (Key : Entity_Id)
56 (Key : Entity_Id) return Elaboration_Context_Index; 56 return Elaboration_Context_Index;
57 -- Function to hash any node of the AST 57 -- Function to hash any node of the AST
58 58
59 type Perm_Kind is (No_Access, Read_Only, Read_Write, Write_Only); 59 type Perm_Kind is (Borrowed, Observed, Unrestricted, Moved);
60 -- Permission type associated with paths 60 -- Permission type associated with paths. The Moved permission is
61 61 -- equivalent to the Unrestricted one (same permissions). The Moved is
62 subtype Read_Perm is Perm_Kind range Read_Only .. Read_Write; 62 -- however used to mark the RHS after a move (which still unrestricted).
63 subtype Write_Perm is Perm_Kind range Read_Write .. Write_Only; 63 -- This way, we may generate warnings when manipulating the RHS
64 -- afterwads since it is set to Null after the assignment.
64 65
65 type Perm_Tree_Wrapper; 66 type Perm_Tree_Wrapper;
66 67
67 type Perm_Tree_Access is access Perm_Tree_Wrapper; 68 type Perm_Tree_Access is access Perm_Tree_Wrapper;
68 -- A tree of permissions is defined, where the root is a whole object 69 -- A tree of permissions is defined, where the root is a whole object
92 -- extensions of a Record_Component node (that can have name x, y, ...). 93 -- extensions of a Record_Component node (that can have name x, y, ...).
93 94
94 -- The definition of permission trees. This is a tree, which has a 95 -- The definition of permission trees. This is a tree, which has a
95 -- permission at each node, and depending on the type of the node, 96 -- permission at each node, and depending on the type of the node,
96 -- can have zero, one, or more children pointed to by an access to tree. 97 -- can have zero, one, or more children pointed to by an access to tree.
98
97 type Perm_Tree (Kind : Path_Kind := Entire_Object) is record 99 type Perm_Tree (Kind : Path_Kind := Entire_Object) is record
98 Permission : Perm_Kind; 100 Permission : Perm_Kind;
99 -- Permission at this level in the path 101 -- Permission at this level in the path
100 102
101 Is_Node_Deep : Boolean; 103 Is_Node_Deep : Boolean;
102 -- Whether this node is of a deep type, to be used when moving the 104 -- Whether this node is of a deep type, to be used when moving the
103 -- path. 105 -- path.
104 106
105 case Kind is 107 case Kind is
106
107 -- An entire object is either a leaf (an object which cannot be 108 -- An entire object is either a leaf (an object which cannot be
108 -- extended further in a path) or a subtree in folded form (which 109 -- extended further in a path) or a subtree in folded form (which
109 -- could later be unfolded further in another kind of node). The 110 -- could later be unfolded further in another kind of node). The
110 -- field Children_Permission specifies a permission for every 111 -- field Children_Permission specifies a permission for every
111 -- extension of that node if that permission is different from 112 -- extension of that node if that permission is different from
112 -- the node's permission. 113 -- the node's permission.
113 114
114 when Entire_Object => 115 when Entire_Object =>
115 Children_Permission : Perm_Kind; 116 Children_Permission : Perm_Kind;
116 117
117 -- Unfolded path of access type. The permission of the object 118 -- Unfolded path of access type. The permission of the object
118 -- pointed to is given in Get_All. 119 -- pointed to is given in Get_All.
119 120
120 when Reference => 121 when Reference =>
121 Get_All : Perm_Tree_Access; 122 Get_All : Perm_Tree_Access;
122 123
123 -- Unfolded path of array type. The permission of the elements is 124 -- Unfolded path of array type. The permission of the elements is
124 -- given in Get_Elem. 125 -- given in Get_Elem.
125 126
126 when Array_Component => 127 when Array_Component =>
127 Get_Elem : Perm_Tree_Access; 128 Get_Elem : Perm_Tree_Access;
128 129
129 -- Unfolded path of record type. The permission of the regular 130 -- Unfolded path of record type. The permission of the regular
130 -- components is given in Component. The permission of unknown 131 -- components is given in Component. The permission of unknown
131 -- components (for objects of tagged type) is given in 132 -- components (for objects of tagged type) is given in
227 -------------------- 228 --------------------
228 -- Error Messages -- 229 -- Error Messages --
229 -------------------- 230 --------------------
230 231
231 procedure Perm_Mismatch 232 procedure Perm_Mismatch
232 (Exp_Perm, Act_Perm : Perm_Kind; 233 (Exp_Perm, Act_Perm : Perm_Kind;
233 N : Node_Id); 234 N : Node_Id);
234 -- Issues a continuation error message about a mismatch between a 235 -- Issues a continuation error message about a mismatch between a
235 -- desired permission Exp_Perm and a permission obtained Act_Perm. N 236 -- desired permission Exp_Perm and a permission obtained Act_Perm. N
236 -- is the node on which the error is reported. 237 -- is the node on which the error is reported.
237 238
241 242
242 ------------------------- 243 -------------------------
243 -- Children_Permission -- 244 -- Children_Permission --
244 ------------------------- 245 -------------------------
245 246
246 function Children_Permission 247 function Children_Permission (T : Perm_Tree_Access) return Perm_Kind is
247 (T : Perm_Tree_Access)
248 return Perm_Kind
249 is
250 begin 248 begin
251 return T.all.Tree.Children_Permission; 249 return T.all.Tree.Children_Permission;
252 end Children_Permission; 250 end Children_Permission;
253 251
254 --------------- 252 ---------------
255 -- Component -- 253 -- Component --
256 --------------- 254 ---------------
257 255
258 function Component 256 function Component
259 (T : Perm_Tree_Access) 257 (T : Perm_Tree_Access)
260 return Perm_Tree_Maps.Instance 258 return Perm_Tree_Maps.Instance
261 is 259 is
262 begin 260 begin
263 return T.all.Tree.Component; 261 return T.all.Tree.Component;
264 end Component; 262 end Component;
265 263
266 -------------- 264 --------------
267 -- Copy_Env -- 265 -- Copy_Env --
268 -------------- 266 --------------
269 267
270 procedure Copy_Env 268 procedure Copy_Env (From : Perm_Env; To : in out Perm_Env) is
271 (From : Perm_Env;
272 To : in out Perm_Env)
273 is
274 Comp_From : Perm_Tree_Access; 269 Comp_From : Perm_Tree_Access;
275 Key_From : Perm_Tree_Maps.Key_Option; 270 Key_From : Perm_Tree_Maps.Key_Option;
276 Son : Perm_Tree_Access; 271 Son : Perm_Tree_Access;
277 272
278 begin 273 begin
279 Reset (To); 274 Reset (To);
280 Key_From := Get_First_Key (From); 275 Key_From := Get_First_Key (From);
281 while Key_From.Present loop 276 while Key_From.Present loop
294 -- Copy_Init_Map -- 289 -- Copy_Init_Map --
295 ------------------- 290 -------------------
296 291
297 procedure Copy_Init_Map 292 procedure Copy_Init_Map
298 (From : Initialization_Map; 293 (From : Initialization_Map;
299 To : in out Initialization_Map) 294 To : in out Initialization_Map)
300 is 295 is
301 Comp_From : Boolean; 296 Comp_From : Boolean;
302 Key_From : Boolean_Variables_Maps.Key_Option; 297 Key_From : Boolean_Variables_Maps.Key_Option;
303 298
304 begin 299 begin
313 308
314 --------------- 309 ---------------
315 -- Copy_Tree -- 310 -- Copy_Tree --
316 --------------- 311 ---------------
317 312
318 procedure Copy_Tree 313 procedure Copy_Tree (From : Perm_Tree_Access; To : Perm_Tree_Access) is
319 (From : Perm_Tree_Access;
320 To : Perm_Tree_Access)
321 is
322 begin 314 begin
323 To.all := From.all; 315 To.all := From.all;
324
325 case Kind (From) is 316 case Kind (From) is
326 when Entire_Object => 317 when Entire_Object =>
327 null; 318 null;
328 319
329 when Reference => 320 when Reference =>
330 To.all.Tree.Get_All := new Perm_Tree_Wrapper; 321 To.all.Tree.Get_All := new Perm_Tree_Wrapper;
331
332 Copy_Tree (Get_All (From), Get_All (To)); 322 Copy_Tree (Get_All (From), Get_All (To));
333 323
334 when Array_Component => 324 when Array_Component =>
335 To.all.Tree.Get_Elem := new Perm_Tree_Wrapper; 325 To.all.Tree.Get_Elem := new Perm_Tree_Wrapper;
336
337 Copy_Tree (Get_Elem (From), Get_Elem (To)); 326 Copy_Tree (Get_Elem (From), Get_Elem (To));
338 327
339 when Record_Component => 328 when Record_Component =>
340 declare 329 declare
341 Comp_From : Perm_Tree_Access; 330 Comp_From : Perm_Tree_Access;
344 Hash_Table : Perm_Tree_Maps.Instance; 333 Hash_Table : Perm_Tree_Maps.Instance;
345 begin 334 begin
346 -- We put a new hash table, so that it gets dealiased from the 335 -- We put a new hash table, so that it gets dealiased from the
347 -- Component (From) hash table. 336 -- Component (From) hash table.
348 To.all.Tree.Component := Hash_Table; 337 To.all.Tree.Component := Hash_Table;
349
350 To.all.Tree.Other_Components := 338 To.all.Tree.Other_Components :=
351 new Perm_Tree_Wrapper'(Other_Components (From).all); 339 new Perm_Tree_Wrapper'(Other_Components (From).all);
352
353 Copy_Tree (Other_Components (From), Other_Components (To)); 340 Copy_Tree (Other_Components (From), Other_Components (To));
354
355 Key_From := Perm_Tree_Maps.Get_First_Key 341 Key_From := Perm_Tree_Maps.Get_First_Key
356 (Component (From)); 342 (Component (From));
343
357 while Key_From.Present loop 344 while Key_From.Present loop
358 Comp_From := Perm_Tree_Maps.Get 345 Comp_From := Perm_Tree_Maps.Get
359 (Component (From), Key_From.K); 346 (Component (From), Key_From.K);
360
361 pragma Assert (Comp_From /= null); 347 pragma Assert (Comp_From /= null);
362 Son := new Perm_Tree_Wrapper; 348 Son := new Perm_Tree_Wrapper;
363
364 Copy_Tree (Comp_From, Son); 349 Copy_Tree (Comp_From, Son);
365
366 Perm_Tree_Maps.Set 350 Perm_Tree_Maps.Set
367 (To.all.Tree.Component, Key_From.K, Son); 351 (To.all.Tree.Component, Key_From.K, Son);
368
369 Key_From := Perm_Tree_Maps.Get_Next_Key 352 Key_From := Perm_Tree_Maps.Get_Next_Key
370 (Component (From)); 353 (Component (From));
371 end loop; 354 end loop;
372 end; 355 end;
373 end case; 356 end case;
357
374 end Copy_Tree; 358 end Copy_Tree;
375 359
376 ------------------------------ 360 ------------------------------
377 -- Elaboration_Context_Hash -- 361 -- Elaboration_Context_Hash --
378 ------------------------------ 362 ------------------------------
400 384
401 -------------------- 385 --------------------
402 -- Free_Perm_Tree -- 386 -- Free_Perm_Tree --
403 -------------------- 387 --------------------
404 388
405 procedure Free_Perm_Tree 389 procedure Free_Perm_Tree (PT : in out Perm_Tree_Access) is
406 (PT : in out Perm_Tree_Access)
407 is
408 procedure Free_Perm_Tree_Dealloc is 390 procedure Free_Perm_Tree_Dealloc is
409 new Ada.Unchecked_Deallocation 391 new Ada.Unchecked_Deallocation
410 (Perm_Tree_Wrapper, Perm_Tree_Access); 392 (Perm_Tree_Wrapper, Perm_Tree_Access);
411 -- The deallocator for permission_trees 393 -- The deallocator for permission_trees
412 394
428 410
429 begin 411 begin
430 Free_Perm_Tree (PT.all.Tree.Other_Components); 412 Free_Perm_Tree (PT.all.Tree.Other_Components);
431 Comp := Perm_Tree_Maps.Get_First (Component (PT)); 413 Comp := Perm_Tree_Maps.Get_First (Component (PT));
432 while Comp /= null loop 414 while Comp /= null loop
415
433 -- Free every Component subtree 416 -- Free every Component subtree
434 417
435 Free_Perm_Tree (Comp); 418 Free_Perm_Tree (Comp);
436 Comp := Perm_Tree_Maps.Get_Next (Component (PT)); 419 Comp := Perm_Tree_Maps.Get_Next (Component (PT));
437 end loop; 420 end loop;
442 425
443 ------------- 426 -------------
444 -- Get_All -- 427 -- Get_All --
445 ------------- 428 -------------
446 429
447 function Get_All 430 function Get_All (T : Perm_Tree_Access) return Perm_Tree_Access is
448 (T : Perm_Tree_Access)
449 return Perm_Tree_Access
450 is
451 begin 431 begin
452 return T.all.Tree.Get_All; 432 return T.all.Tree.Get_All;
453 end Get_All; 433 end Get_All;
454 434
455 -------------- 435 --------------
456 -- Get_Elem -- 436 -- Get_Elem --
457 -------------- 437 --------------
458 438
459 function Get_Elem 439 function Get_Elem (T : Perm_Tree_Access) return Perm_Tree_Access is
460 (T : Perm_Tree_Access)
461 return Perm_Tree_Access
462 is
463 begin 440 begin
464 return T.all.Tree.Get_Elem; 441 return T.all.Tree.Get_Elem;
465 end Get_Elem; 442 end Get_Elem;
466 443
467 ------------------ 444 ------------------
468 -- Is_Node_Deep -- 445 -- Is_Node_Deep --
469 ------------------ 446 ------------------
470 447
471 function Is_Node_Deep 448 function Is_Node_Deep (T : Perm_Tree_Access) return Boolean is
472 (T : Perm_Tree_Access)
473 return Boolean
474 is
475 begin 449 begin
476 return T.all.Tree.Is_Node_Deep; 450 return T.all.Tree.Is_Node_Deep;
477 end Is_Node_Deep; 451 end Is_Node_Deep;
478 452
479 ---------- 453 ----------
480 -- Kind -- 454 -- Kind --
481 ---------- 455 ----------
482 456
483 function Kind 457 function Kind (T : Perm_Tree_Access) return Path_Kind is
484 (T : Perm_Tree_Access)
485 return Path_Kind
486 is
487 begin 458 begin
488 return T.all.Tree.Kind; 459 return T.all.Tree.Kind;
489 end Kind; 460 end Kind;
490 461
491 ---------------------- 462 ----------------------
492 -- Other_Components -- 463 -- Other_Components --
493 ---------------------- 464 ----------------------
494 465
495 function Other_Components 466 function Other_Components
496 (T : Perm_Tree_Access) 467 (T : Perm_Tree_Access)
497 return Perm_Tree_Access 468 return Perm_Tree_Access
498 is 469 is
499 begin 470 begin
500 return T.all.Tree.Other_Components; 471 return T.all.Tree.Other_Components;
501 end Other_Components; 472 end Other_Components;
502 473
503 ---------------- 474 ----------------
504 -- Permission -- 475 -- Permission --
505 ---------------- 476 ----------------
506 477
507 function Permission 478 function Permission (T : Perm_Tree_Access) return Perm_Kind is
508 (T : Perm_Tree_Access)
509 return Perm_Kind
510 is
511 begin 479 begin
512 return T.all.Tree.Permission; 480 return T.all.Tree.Permission;
513 end Permission; 481 end Permission;
514 482
515 ------------------- 483 -------------------
516 -- Perm_Mismatch -- 484 -- Perm_Mismatch --
517 ------------------- 485 -------------------
518 486
519 procedure Perm_Mismatch 487 procedure Perm_Mismatch (Exp_Perm, Act_Perm : Perm_Kind; N : Node_Id) is
520 (Exp_Perm, Act_Perm : Perm_Kind;
521 N : Node_Id)
522 is
523 begin 488 begin
524 Error_Msg_N ("\expected at least `" 489 Error_Msg_N ("\expected state `"
525 & Perm_Kind'Image (Exp_Perm) & "`, got `" 490 & Perm_Kind'Image (Exp_Perm) & "` at least, got `"
526 & Perm_Kind'Image (Act_Perm) & "`", N); 491 & Perm_Kind'Image (Act_Perm) & "`", N);
527 end Perm_Mismatch; 492 end Perm_Mismatch;
528 493
529 end Permissions; 494 end Permissions;
530 495
538 -- found in the code should be moved, borrowed, or observed. 503 -- found in the code should be moved, borrowed, or observed.
539 504
540 type Checking_Mode is 505 type Checking_Mode is
541 506
542 (Read, 507 (Read,
543 -- Default mode. Checks that paths have Read_Perm permission. 508 -- Default mode
544 509
545 Move, 510 Move,
546 -- Regular moving semantics (not under 'Access). Checks that paths have 511 -- Regular moving semantics. Checks that paths have Unrestricted
547 -- Read_Write permission. After moving a path, its permission is set to 512 -- permission. After moving a path, the permission of both it and
548 -- Write_Only and the permission of its extensions is set to No_Access. 513 -- its extensions are set to Unrestricted.
549 514
550 Assign, 515 Assign,
551 -- Used for the target of an assignment, or an actual parameter with 516 -- Used for the target of an assignment, or an actual parameter with
552 -- mode OUT. Checks that paths have Write_Perm permission. After 517 -- mode OUT. Checks that paths have Unrestricted permission. After
553 -- assigning to a path, its permission is set to Read_Write. 518 -- assigning to a path, its permission is set to Unrestricted.
554 519
555 Super_Move, 520 Borrow,
556 -- Enhanced moving semantics (under 'Access). Checks that paths have 521 -- Used for the source of an assignement when initializes a stand alone
557 -- Read_Write permission. After moving a path, its permission is set 522 -- object of anonymous type, constant, or IN parameter and also OUT
558 -- to No_Access, as well as the permission of its extensions and the 523 -- or IN OUT composite object.
559 -- permission of its prefixes up to the first Reference node. 524 -- In the borrowed state, the access object is completely "dead".
560
561 Borrow_Out,
562 -- Used for actual OUT parameters. Checks that paths have Write_Perm
563 -- permission. After checking a path, its permission is set to Read_Only
564 -- when of a by-copy type, to No_Access otherwise. After the call, its
565 -- permission is set to Read_Write.
566 525
567 Observe 526 Observe
568 -- Used for actual IN parameters of a scalar type. Checks that paths 527 -- Used for actual IN parameters of a scalar type. Checks that paths
569 -- have Read_Perm permission. After checking a path, its permission 528 -- have Read_Perm permission. After checking a path, its permission
570 -- is set to Read_Only. 529 -- is set to Observed.
571 -- 530 --
572 -- Also used for formal IN parameters 531 -- Also used for formal IN parameters
532
573 ); 533 );
574 534
575 type Result_Kind is (Folded, Unfolded, Function_Call); 535 type Result_Kind is (Folded, Unfolded, Function_Call);
576 -- The type declaration to discriminate in the Perm_Or_Tree type 536 -- The type declaration to discriminate in the Perm_Or_Tree type
577 537
590 550
591 ----------------------- 551 -----------------------
592 -- Local subprograms -- 552 -- Local subprograms --
593 ----------------------- 553 -----------------------
594 554
595 function "<=" (P1, P2 : Perm_Kind) return Boolean;
596 function ">=" (P1, P2 : Perm_Kind) return Boolean;
597 function Glb (P1, P2 : Perm_Kind) return Perm_Kind;
598 function Lub (P1, P2 : Perm_Kind) return Perm_Kind;
599
600 -- Checking proceduress for safe pointer usage. These procedures traverse 555 -- Checking proceduress for safe pointer usage. These procedures traverse
601 -- the AST, check nodes for correct permissions according to SPARK RM 556 -- the AST, check nodes for correct permissions according to SPARK RM
602 -- 6.4.2, and update permissions depending on the node kind. 557 -- 6.4.2, and update permissions depending on the node kind.
603 558
604 procedure Check_Call_Statement (Call : Node_Id); 559 procedure Check_Call_Statement (Call : Node_Id);
605 560
606 procedure Check_Callable_Body (Body_N : Node_Id); 561 procedure Check_Callable_Body (Body_N : Node_Id);
607 -- We are not in End_Of_Callee mode, hence we will save the environment 562 -- We are not in End_Of_Callee mode, hence we will save the environment
608 -- and start from a new one. We will add in the environment all formal 563 -- and start from a new one. We will add in the environment all formal
609 -- parameters as well as global used during the subprogram, with the 564 -- parameters as well as global used during the subprogram, with the
610 -- appropriate permissions (write-only for out, read-only for observed, 565 -- appropriate permissions (unrestricted for borrowed and moved, observed
611 -- read-write for others). 566 -- for observed names).
612 --
613 -- After that we analyze the body of the function, and finaly, we check
614 -- that each borrowed parameter and global has read-write permission. We
615 -- then clean up the environment and put back the saved environment.
616 567
617 procedure Check_Declaration (Decl : Node_Id); 568 procedure Check_Declaration (Decl : Node_Id);
618 569
619 procedure Check_Expression (Expr : Node_Id); 570 procedure Check_Expression (Expr : Node_Id);
620 571
621 procedure Check_Globals (N : Node_Id; Check_Mode : Checking_Mode); 572 procedure Check_Globals (N : Node_Id);
622 -- This procedure takes a global pragma and checks depending on mode: 573 -- This procedure takes a global pragma and checks it
623 -- Mode Read: every in global is readable
624 -- Mode Observe: same as Check_Param_Observes but on globals
625 -- Mode Borrow_Out: Check_Param_Outs for globals
626 -- Mode Move: Check_Param for globals with mode Read
627 -- Mode Assign: Check_Param for globals with mode Assign
628 574
629 procedure Check_List (L : List_Id); 575 procedure Check_List (L : List_Id);
630 -- Calls Check_Node on each element of the list 576 -- Calls Check_Node on each element of the list
631 577
632 procedure Check_Loop_Statement (Loop_N : Node_Id); 578 procedure Check_Loop_Statement (Loop_N : Node_Id);
635 -- Main traversal procedure to check safe pointer usage. This procedure is 581 -- Main traversal procedure to check safe pointer usage. This procedure is
636 -- mutually recursive with the specialized procedures that follow. 582 -- mutually recursive with the specialized procedures that follow.
637 583
638 procedure Check_Package_Body (Pack : Node_Id); 584 procedure Check_Package_Body (Pack : Node_Id);
639 585
640 procedure Check_Param (Formal : Entity_Id; Actual : Node_Id); 586 procedure Check_Param_In (Formal : Entity_Id; Actual : Node_Id);
641 -- This procedure takes a formal and an actual parameter and calls the
642 -- analyze node if the parameter is borrowed with mode in out, with the
643 -- appropriate Checking_Mode (Move).
644
645 procedure Check_Param_Observes (Formal : Entity_Id; Actual : Node_Id);
646 -- This procedure takes a formal and an actual parameter and calls
647 -- the analyze node if the parameter is observed, with the appropriate
648 -- Checking_Mode.
649
650 procedure Check_Param_Outs (Formal : Entity_Id; Actual : Node_Id);
651 -- This procedure takes a formal and an actual parameter and calls the
652 -- analyze node if the parameter is of mode out, with the appropriate
653 -- Checking_Mode.
654
655 procedure Check_Param_Read (Formal : Entity_Id; Actual : Node_Id);
656 -- This procedure takes a formal and an actual parameter and checks the 587 -- This procedure takes a formal and an actual parameter and checks the
657 -- readability of every in-mode parameter. This includes observed in, and 588 -- permission of every in-mode parameter. This includes Observing and
658 -- also borrowed in, that are then checked afterwards. 589 -- Borrowing.
590
591 procedure Check_Param_Out (Formal : Entity_Id; Actual : Node_Id);
592 -- This procedure takes a formal and an actual parameter and checks the
593 -- state of every out-mode and in out-mode parameter. This includes
594 -- Moving and Borrowing.
659 595
660 procedure Check_Statement (Stmt : Node_Id); 596 procedure Check_Statement (Stmt : Node_Id);
661 597
662 function Get_Perm (N : Node_Id) return Perm_Kind; 598 function Get_Perm (N : Node_Id) return Perm_Kind;
663 -- The function that takes a name as input and returns a permission 599 -- The function that takes a name as input and returns a permission
671 function Get_Perm_Tree (N : Node_Id) return Perm_Tree_Access; 607 function Get_Perm_Tree (N : Node_Id) return Perm_Tree_Access;
672 -- This function gets a Node_Id and looks recursively to find the 608 -- This function gets a Node_Id and looks recursively to find the
673 -- appropriate subtree for that Node_Id. If the tree is folded, then 609 -- appropriate subtree for that Node_Id. If the tree is folded, then
674 -- it unrolls the tree up to the appropriate level. 610 -- it unrolls the tree up to the appropriate level.
675 611
676 function Has_Alias
677 (N : Node_Id)
678 return Boolean;
679 -- Function that returns whether the path given as parameter contains an
680 -- extension that is declared as aliased.
681
682 function Has_Array_Component (N : Node_Id) return Boolean;
683 -- This function gets a Node_Id and looks recursively to find if the given
684 -- path has any array component.
685
686 function Has_Function_Component (N : Node_Id) return Boolean;
687 -- This function gets a Node_Id and looks recursively to find if the given
688 -- path has any function component.
689
690 procedure Hp (P : Perm_Env); 612 procedure Hp (P : Perm_Env);
691 -- A procedure that outputs the hash table. This function is used only in 613 -- A procedure that outputs the hash table. This function is used only in
692 -- the debugger to look into a hash table. 614 -- the debugger to look into a hash table.
693 pragma Unreferenced (Hp); 615 pragma Unreferenced (Hp);
694 616
695 procedure Illegal_Global_Usage (N : Node_Or_Entity_Id); 617 procedure Illegal_Global_Usage (N : Node_Or_Entity_Id);
696 pragma No_Return (Illegal_Global_Usage); 618 pragma No_Return (Illegal_Global_Usage);
697 -- A procedure that is called when deep globals or aliased globals are used 619 -- A procedure that is called when deep globals or aliased globals are used
698 -- without any global aspect. 620 -- without any global aspect.
699 621
700 function Is_Borrowed_In (E : Entity_Id) return Boolean;
701 -- Function that tells if the given entity is a borrowed in a formal
702 -- parameter, that is, if it is an access-to-variable type.
703
704 function Is_Deep (E : Entity_Id) return Boolean; 622 function Is_Deep (E : Entity_Id) return Boolean;
705 -- A function that can tell if a type is deep or not. Returns true if the 623 -- A function that can tell if a type is deep or not. Returns true if the
706 -- type passed as argument is deep. 624 -- type passed as argument is deep.
707 625
708 function Is_Shallow (E : Entity_Id) return Boolean;
709 -- A function that can tell if a type is shallow or not. Returns true if
710 -- the type passed as argument is shallow.
711
712 function Loop_Of_Exit (N : Node_Id) return Entity_Id;
713 -- A function that takes an exit statement node and returns the entity of
714 -- the loop that this statement is exiting from.
715
716 procedure Merge_Envs (Target : in out Perm_Env; Source : in out Perm_Env);
717 -- Merge Target and Source into Target, and then deallocate the Source
718
719 procedure Perm_Error 626 procedure Perm_Error
720 (N : Node_Id; 627 (N : Node_Id;
721 Perm : Perm_Kind; 628 Perm : Perm_Kind;
722 Found_Perm : Perm_Kind); 629 Found_Perm : Perm_Kind);
723 -- A procedure that is called when the permissions found contradict the 630 -- A procedure that is called when the permissions found contradict the
724 -- rules established by the RM. This function is called with the node, its 631 -- rules established by the RM. This function is called with the node, its
725 -- entity and the permission that was expected, and adds an error message 632 -- entity and the permission that was expected, and adds an error message
726 -- with the appropriate values. 633 -- with the appropriate values.
739 procedure Process_Path (N : Node_Id); 646 procedure Process_Path (N : Node_Id);
740 647
741 procedure Return_Declarations (L : List_Id); 648 procedure Return_Declarations (L : List_Id);
742 -- Check correct permissions on every declared object at the end of a 649 -- Check correct permissions on every declared object at the end of a
743 -- callee. Used at the end of the body of a callable entity. Checks that 650 -- callee. Used at the end of the body of a callable entity. Checks that
744 -- paths of all borrowed formal parameters and global have Read_Write 651 -- paths of all borrowed formal parameters and global have Unrestricted
745 -- permission. 652 -- permission.
746 653
747 procedure Return_Globals (Subp : Entity_Id); 654 procedure Return_Globals (Subp : Entity_Id);
748 -- Takes a subprogram as input, and checks that all borrowed global items 655 -- Takes a subprogram as input, and checks that all borrowed global items
749 -- of the subprogram indeed have RW permission at the end of the subprogram 656 -- of the subprogram indeed have RW permission at the end of the subprogram
750 -- execution. 657 -- execution.
751 658
752 procedure Return_Parameter_Or_Global 659 procedure Return_The_Global
753 (Id : Entity_Id; 660 (Id : Entity_Id;
754 Mode : Formal_Kind; 661 Mode : Formal_Kind;
755 Subp : Entity_Id); 662 Subp : Entity_Id);
756 -- Auxiliary procedure to Return_Parameters and Return_Globals 663 -- Auxiliary procedure to Return_Globals
757 664 -- There is no need to return parameters because they will be reassigned
758 procedure Return_Parameters (Subp : Entity_Id); 665 -- their state once the subprogram returns. Local variables that have
759 -- Takes a subprogram as input, and checks that all borrowed parameters of 666 -- borrowed, observed, or moved an actual parameter go out of the scope.
760 -- the subprogram indeed have RW permission at the end of the subprogram
761 -- execution.
762 667
763 procedure Set_Perm_Extensions (T : Perm_Tree_Access; P : Perm_Kind); 668 procedure Set_Perm_Extensions (T : Perm_Tree_Access; P : Perm_Kind);
764 -- This procedure takes an access to a permission tree and modifies the 669 -- This procedure takes an access to a permission tree and modifies the
765 -- tree so that any strict extensions of the given tree become of the 670 -- tree so that any strict extensions of the given tree become of the
766 -- access specified by parameter P. 671 -- access specified by parameter P.
767 672
768 procedure Set_Perm_Extensions_Move (T : Perm_Tree_Access; E : Entity_Id); 673 function Set_Perm_Prefixes_Borrow (N : Node_Id) return Perm_Tree_Access;
769 -- Set permissions to
770 -- No for any extension with more .all
771 -- W for any deep extension with same number of .all
772 -- RW for any shallow extension with same number of .all
773
774 function Set_Perm_Prefixes_Assign (N : Node_Id) return Perm_Tree_Access;
775 -- This function takes a name as an input and sets in the permission
776 -- tree the given permission to the given name. The general rule here is
777 -- that everybody updates the permission of the subtree it is returning.
778 -- The permission of the assigned path has been set to RW by the caller.
779 --
780 -- Case where we have to normalize a tree after the correct permissions
781 -- have been assigned already. We look for the right subtree at the given
782 -- path, actualize its permissions, and then call the normalization on its
783 -- parent.
784 --
785 -- Example: We assign x.y and x.z then during Set_Perm_Prefixes_Move will
786 -- change the permission of x to RW because all of its components have
787 -- permission have permission RW.
788
789 function Set_Perm_Prefixes_Borrow_Out (N : Node_Id) return Perm_Tree_Access;
790 -- This function modifies the permissions of a given node_id in the 674 -- This function modifies the permissions of a given node_id in the
791 -- permission environment as well as in all the prefixes of the path, 675 -- permission environment as well as in all the prefixes of the path,
792 -- given that the path is borrowed with mode out. 676 -- given that the path is borrowed with mode out.
793 677
794 function Set_Perm_Prefixes_Move 678 function Set_Perm_Prefixes
795 (N : Node_Id; Mode : Checking_Mode) 679 (N : Node_Id;
680 New_Perm : Perm_Kind)
796 return Perm_Tree_Access; 681 return Perm_Tree_Access;
797 pragma Precondition (Mode = Move or Mode = Super_Move); 682 -- This function sets the permissions of a given node_id in the
798 -- Given a node and a mode (that can be either Move or Super_Move), this 683 -- permission environment as well as in all the prefixes of the path
799 -- function modifies the permissions of a given node_id in the permission 684 -- to the one given in parameter (P).
800 -- environment as well as all the prefixes of the path, given that the path
801 -- is moved with or without 'Access. The general rule here is everybody
802 -- updates the permission of the subtree they are returning.
803 --
804 -- This case describes a move either under 'Access or without 'Access.
805
806 function Set_Perm_Prefixes_Observe (N : Node_Id) return Perm_Tree_Access;
807 -- This function modifies the permissions of a given node_id in the
808 -- permission environment as well as all the prefixes of the path,
809 -- given that the path is observed.
810 685
811 procedure Setup_Globals (Subp : Entity_Id); 686 procedure Setup_Globals (Subp : Entity_Id);
812 -- Takes a subprogram as input, and sets up the environment by adding 687 -- Takes a subprogram as input, and sets up the environment by adding
813 -- global items with appropriate permissions. 688 -- global items with appropriate permissions.
814 689
815 procedure Setup_Parameter_Or_Global 690 procedure Setup_Parameter_Or_Global
816 (Id : Entity_Id; 691 (Id : Entity_Id;
817 Mode : Formal_Kind); 692 Mode : Formal_Kind;
693 Global_Var : Boolean);
818 -- Auxiliary procedure to Setup_Parameters and Setup_Globals 694 -- Auxiliary procedure to Setup_Parameters and Setup_Globals
819 695
820 procedure Setup_Parameters (Subp : Entity_Id); 696 procedure Setup_Parameters (Subp : Entity_Id);
821 -- Takes a subprogram as input, and sets up the environment by adding 697 -- Takes a subprogram as input, and sets up the environment by adding
822 -- formal parameters with appropriate permissions. 698 -- formal parameters with appropriate permissions.
699
700 function Has_Ownership_Aspect_True
701 (N : Node_Id;
702 Msg : String)
703 return Boolean;
704 -- Takes a node as an input, and finds out whether it has ownership aspect
705 -- True or False. This function is recursive whenever the node has a
706 -- composite type. Access-to-objects have ownership aspect False if they
707 -- have a general access type.
823 708
824 ---------------------- 709 ----------------------
825 -- Global Variables -- 710 -- Global Variables --
826 ---------------------- 711 ----------------------
827 712
856 -- This variable contains a map that binds each variable of the analyzed 741 -- This variable contains a map that binds each variable of the analyzed
857 -- source code to a boolean that becomes true whenever the variable is used 742 -- source code to a boolean that becomes true whenever the variable is used
858 -- after declaration. Hence we can exclude from analysis variables that 743 -- after declaration. Hence we can exclude from analysis variables that
859 -- are just declared and never accessed, typically at package declaration. 744 -- are just declared and never accessed, typically at package declaration.
860 745
861 ----------
862 -- "<=" --
863 ----------
864
865 function "<=" (P1, P2 : Perm_Kind) return Boolean
866 is
867 begin
868 return P2 >= P1;
869 end "<=";
870
871 ----------
872 -- ">=" --
873 ----------
874
875 function ">=" (P1, P2 : Perm_Kind) return Boolean
876 is
877 begin
878 case P2 is
879 when No_Access => return True;
880 when Read_Only => return P1 in Read_Perm;
881 when Write_Only => return P1 in Write_Perm;
882 when Read_Write => return P1 = Read_Write;
883 end case;
884 end ">=";
885
886 -------------------------- 746 --------------------------
887 -- Check_Call_Statement -- 747 -- Check_Call_Statement --
888 -------------------------- 748 --------------------------
889 749
890 procedure Check_Call_Statement (Call : Node_Id) is 750 procedure Check_Call_Statement (Call : Node_Id) is
891 Saved_Env : Perm_Env; 751 Saved_Env : Perm_Env;
892 752
893 procedure Iterate_Call is new 753 procedure Iterate_Call_In is new
894 Iterate_Call_Parameters (Check_Param); 754 Iterate_Call_Parameters (Check_Param_In);
895 procedure Iterate_Call_Observes is new 755 procedure Iterate_Call_Out is new
896 Iterate_Call_Parameters (Check_Param_Observes); 756 Iterate_Call_Parameters (Check_Param_Out);
897 procedure Iterate_Call_Outs is new
898 Iterate_Call_Parameters (Check_Param_Outs);
899 procedure Iterate_Call_Read is new
900 Iterate_Call_Parameters (Check_Param_Read);
901 757
902 begin 758 begin
903 -- Save environment, so that the modifications done by analyzing the 759 -- Save environment, so that the modifications done by analyzing the
904 -- parameters are not kept at the end of the call. 760 -- parameters are not kept at the end of the call.
905 Copy_Env (Current_Perm_Env, 761
906 Saved_Env); 762 Copy_Env (Current_Perm_Env, Saved_Env);
907 763
908 -- We first check the Read access on every in parameter 764 -- We first check the globals then parameters to handle the
765 -- No_Parameter_Aliasing Restriction. An out or in-out global is
766 -- considered as borrowing while a parameter with the same mode is
767 -- a move. This order disallow passing a part of a variable to a
768 -- subprogram if it is referenced as a global by the callable (when
769 -- writable).
770 -- For paremeters, we fisrt check in parameters and then the out ones.
771 -- This is to avoid Observing or Borrowing objects that are already
772 -- moved. This order is not mandatory but allows to catch runtime
773 -- errors like null pointer dereferencement at the analysis time.
909 774
910 Current_Checking_Mode := Read; 775 Current_Checking_Mode := Read;
911 Iterate_Call_Read (Call); 776 Check_Globals (Get_Pragma (Get_Called_Entity (Call), Pragma_Global));
912 Check_Globals (Get_Pragma 777 Iterate_Call_In (Call);
913 (Get_Called_Entity (Call), Pragma_Global), Read); 778 Iterate_Call_Out (Call);
914
915 -- We first observe, then borrow with mode out, and then with other
916 -- modes. This ensures that we do not have to check for by-copy types
917 -- specially, because we read them before borrowing them.
918
919 Iterate_Call_Observes (Call);
920 Check_Globals (Get_Pragma
921 (Get_Called_Entity (Call), Pragma_Global),
922 Observe);
923
924 Iterate_Call_Outs (Call);
925 Check_Globals (Get_Pragma
926 (Get_Called_Entity (Call), Pragma_Global),
927 Borrow_Out);
928
929 Iterate_Call (Call);
930 Check_Globals (Get_Pragma
931 (Get_Called_Entity (Call), Pragma_Global), Move);
932 779
933 -- Restore environment, because after borrowing/observing actual 780 -- Restore environment, because after borrowing/observing actual
934 -- parameters, they get their permission reverted to the ones before 781 -- parameters, they get their permission reverted to the ones before
935 -- the call. 782 -- the call.
936 783
937 Free_Env (Current_Perm_Env); 784 Free_Env (Current_Perm_Env);
938 785 Copy_Env (Saved_Env, Current_Perm_Env);
939 Copy_Env (Saved_Env,
940 Current_Perm_Env);
941
942 Free_Env (Saved_Env); 786 Free_Env (Saved_Env);
943
944 -- We assign the out parameters (necessarily borrowed per RM)
945 Current_Checking_Mode := Assign;
946 Iterate_Call (Call);
947 Check_Globals (Get_Pragma
948 (Get_Called_Entity (Call), Pragma_Global),
949 Assign);
950
951 end Check_Call_Statement; 787 end Check_Call_Statement;
952 788
953 ------------------------- 789 -------------------------
954 -- Check_Callable_Body -- 790 -- Check_Callable_Body --
955 ------------------------- 791 -------------------------
956 792
957 procedure Check_Callable_Body (Body_N : Node_Id) is 793 procedure Check_Callable_Body (Body_N : Node_Id) is
958 794
959 Mode_Before : constant Checking_Mode := Current_Checking_Mode; 795 Mode_Before : constant Checking_Mode := Current_Checking_Mode;
960 796 Saved_Env : Perm_Env;
961 Saved_Env : Perm_Env;
962 Saved_Init_Map : Initialization_Map; 797 Saved_Init_Map : Initialization_Map;
963 798 New_Env : Perm_Env;
964 New_Env : Perm_Env; 799 Body_Id : constant Entity_Id := Defining_Entity (Body_N);
965 800 Spec_Id : constant Entity_Id := Unique_Entity (Body_Id);
966 Body_Id : constant Entity_Id := Defining_Entity (Body_N);
967 Spec_Id : constant Entity_Id := Unique_Entity (Body_Id);
968 801
969 begin 802 begin
970 -- Check if SPARK pragma is not set to Off 803 -- Check if SPARK pragma is not set to Off
971 804
972 if Present (SPARK_Pragma (Defining_Entity (Body_N))) then 805 if Present (SPARK_Pragma (Defining_Entity (Body_N))) then
984 Copy_Env (Current_Perm_Env, Saved_Env); 817 Copy_Env (Current_Perm_Env, Saved_Env);
985 818
986 -- Save initialization map 819 -- Save initialization map
987 820
988 Copy_Init_Map (Current_Initialization_Map, Saved_Init_Map); 821 Copy_Init_Map (Current_Initialization_Map, Saved_Init_Map);
989
990 Current_Checking_Mode := Read; 822 Current_Checking_Mode := Read;
991 Current_Perm_Env := New_Env; 823 Current_Perm_Env := New_Env;
992 824
993 -- Add formals and globals to the environment with adequate permissions 825 -- Add formals and globals to the environment with adequate permissions
994 826
995 if Is_Subprogram_Or_Entry (Spec_Id) then 827 if Is_Subprogram_Or_Entry (Spec_Id) then
996 Setup_Parameters (Spec_Id); 828 Setup_Parameters (Spec_Id);
1005 -- Check the read-write permissions of borrowed parameters/globals 837 -- Check the read-write permissions of borrowed parameters/globals
1006 838
1007 if Ekind_In (Spec_Id, E_Procedure, E_Entry) 839 if Ekind_In (Spec_Id, E_Procedure, E_Entry)
1008 and then not No_Return (Spec_Id) 840 and then not No_Return (Spec_Id)
1009 then 841 then
1010 Return_Parameters (Spec_Id);
1011 Return_Globals (Spec_Id); 842 Return_Globals (Spec_Id);
1012 end if; 843 end if;
1013 844
1014 -- Free the environments 845 -- Free the environments
1015 846
1016 Free_Env (Current_Perm_Env); 847 Free_Env (Current_Perm_Env);
1017 848 Copy_Env (Saved_Env, Current_Perm_Env);
1018 Copy_Env (Saved_Env,
1019 Current_Perm_Env);
1020
1021 Free_Env (Saved_Env); 849 Free_Env (Saved_Env);
1022 850
1023 -- Restore initialization map 851 -- Restore initialization map
1024 852
1025 Copy_Init_Map (Saved_Init_Map, Current_Initialization_Map); 853 Copy_Init_Map (Saved_Init_Map, Current_Initialization_Map);
1026
1027 Reset (Saved_Init_Map); 854 Reset (Saved_Init_Map);
1028 855
1029 -- The assignment of all out parameters will be done by caller 856 -- The assignment of all out parameters will be done by caller
1030 857
1031 Current_Checking_Mode := Mode_Before; 858 Current_Checking_Mode := Mode_Before;
1034 ----------------------- 861 -----------------------
1035 -- Check_Declaration -- 862 -- Check_Declaration --
1036 ----------------------- 863 -----------------------
1037 864
1038 procedure Check_Declaration (Decl : Node_Id) is 865 procedure Check_Declaration (Decl : Node_Id) is
866
867 Target_Ent : constant Entity_Id := Defining_Identifier (Decl);
868 Target_Typ : Node_Id renames Etype (Target_Ent);
869
870 Target_View_Typ : Entity_Id;
871
872 Check : Boolean := True;
1039 begin 873 begin
874 if Present (Full_View (Target_Typ)) then
875 Target_View_Typ := Full_View (Target_Typ);
876 else
877 Target_View_Typ := Target_Typ;
878 end if;
879
1040 case N_Declaration'(Nkind (Decl)) is 880 case N_Declaration'(Nkind (Decl)) is
1041 when N_Full_Type_Declaration => 881 when N_Full_Type_Declaration =>
1042 -- Nothing to do here ??? NOT TRUE IF CONSTRAINT ON TYPE 882 if not Has_Ownership_Aspect_True (Target_Ent, "type declaration")
1043 null; 883 then
884 Check := False;
885 end if;
886
887 -- ??? What about component declarations with defaults.
1044 888
1045 when N_Object_Declaration => 889 when N_Object_Declaration =>
1046 -- First move the right-hand side 890 if (Is_Access_Type (Target_View_Typ)
1047 Current_Checking_Mode := Move; 891 or else Is_Deep (Target_Typ))
1048 Check_Node (Expression (Decl)); 892 and then not Has_Ownership_Aspect_True
893 (Target_Ent, "Object declaration ")
894 then
895 Check := False;
896 end if;
897
898 if Is_Anonymous_Access_Type (Target_View_Typ)
899 and then not Present (Expression (Decl))
900 then
901
902 -- ??? Check the case of default value (AI)
903 -- ??? How an anonymous access type can be with default exp?
904
905 Error_Msg_NE ("? object declaration & has OAF (Anonymous "
906 & "access-to-object with no initialization)",
907 Decl, Target_Ent);
908
909 -- If it it an initialization
910
911 elsif Present (Expression (Decl)) and Check then
912
913 -- Find out the operation to be done on the right-hand side
914
915 -- Initializing object, access type
916
917 if Is_Access_Type (Target_View_Typ) then
918
919 -- Initializing object, constant access type
920
921 if Is_Constant_Object (Target_Ent) then
922
923 -- Initializing object, constant access to variable type
924
925 if not Is_Access_Constant (Target_View_Typ) then
926 Current_Checking_Mode := Borrow;
927
928 -- Initializing object, constant access to constant type
929
930 -- Initializing object,
931 -- constant access to constant anonymous type.
932
933 elsif Is_Anonymous_Access_Type (Target_View_Typ) then
934
935 -- This is an object declaration so the target
936 -- of the assignement is a stand-alone object.
937
938 Current_Checking_Mode := Observe;
939
940 -- Initializing object, constant access to constant
941 -- named type.
942
943 else
944 -- If named then it is a general access type
945 -- Hence, Has_Ownership_Aspec_True is False.
946
947 raise Program_Error;
948 end if;
949
950 -- Initializing object, variable access type
951
952 else
953 -- Initializing object, variable access to variable type
954
955 if not Is_Access_Constant (Target_View_Typ) then
956
957 -- Initializing object, variable named access to
958 -- variable type.
959
960 if not Is_Anonymous_Access_Type (Target_View_Typ) then
961 Current_Checking_Mode := Move;
962
963 -- Initializing object, variable anonymous access to
964 -- variable type.
965
966 else
967 -- This is an object declaration so the target
968 -- object of the assignement is a stand-alone
969 -- object.
970
971 Current_Checking_Mode := Borrow;
972 end if;
973
974 -- Initializing object, variable access to constant type
975
976 else
977 -- Initializing object,
978 -- variable named access to constant type.
979
980 if not Is_Anonymous_Access_Type (Target_View_Typ) then
981 Error_Msg_N ("assignment not allowed, Ownership "
982 & "Aspect False (Anonymous Access "
983 & "Object)", Decl);
984 Check := False;
985
986 -- Initializing object,
987 -- variable anonymous access to constant type.
988
989 else
990 -- This is an object declaration so the target
991 -- of the assignement is a stand-alone object.
992
993 Current_Checking_Mode := Observe;
994 end if;
995 end if;
996 end if;
997
998 -- Initializing object, composite (deep) type
999
1000 elsif Is_Deep (Target_Typ) then
1001
1002 -- Initializing object, constant composite type
1003
1004 if Is_Constant_Object (Target_Ent) then
1005 Current_Checking_Mode := Observe;
1006
1007 -- Initializing object, variable composite type
1008
1009 else
1010
1011 -- Initializing object, variable anonymous composite type
1012
1013 if Nkind (Object_Definition (Decl)) =
1014 N_Constrained_Array_Definition
1015
1016 -- An N_Constrained_Array_Definition is an anonymous
1017 -- array (to be checked). Record types are always
1018 -- named and are considered in the else part.
1019
1020 then
1021 declare
1022 Com_Ty : constant Node_Id :=
1023 Component_Type (Etype (Target_Typ));
1024 begin
1025
1026 if Is_Access_Type (Com_Ty) then
1027
1028 -- If components are of anonymous type
1029
1030 if Is_Anonymous_Access_Type (Com_Ty) then
1031 if Is_Access_Constant (Com_Ty) then
1032 Current_Checking_Mode := Observe;
1033
1034 else
1035 Current_Checking_Mode := Borrow;
1036 end if;
1037
1038 else
1039 Current_Checking_Mode := Move;
1040 end if;
1041
1042 elsif Is_Deep (Com_Ty) then
1043
1044 -- This is certainly named so it is a move
1045
1046 Current_Checking_Mode := Move;
1047 end if;
1048 end;
1049
1050 else
1051 Current_Checking_Mode := Move;
1052 end if;
1053 end if;
1054
1055 end if;
1056 end if;
1057
1058 if Check then
1059 Check_Node (Expression (Decl));
1060 end if;
1061
1062 -- If lhs is not a pointer, we still give it the unrestricted
1063 -- state which is useless but not harmful.
1049 1064
1050 declare 1065 declare
1051 Elem : Perm_Tree_Access; 1066 Elem : Perm_Tree_Access;
1067 Deep : constant Boolean := Is_Deep (Target_Typ);
1052 1068
1053 begin 1069 begin
1054 Elem := new Perm_Tree_Wrapper' 1070 -- Note that all declared variables are set to the unrestricted
1055 (Tree => 1071 -- state.
1056 (Kind => Entire_Object, 1072 --
1057 Is_Node_Deep => 1073 -- If variables are not initialized:
1058 Is_Deep (Etype (Defining_Identifier (Decl))), 1074 -- unrestricted to every declared object.
1059 Permission => Read_Write, 1075 -- Exp:
1060 Children_Permission => Read_Write)); 1076 -- R : Rec
1061 1077 -- S : Rec := (...)
1062 -- If unitialized declaration, then set to Write_Only. If a 1078 -- R := S
1063 -- pointer declaration, it has a null default initialization. 1079 -- The assignement R := S is not allowed in the new rules
1064 if Nkind (Expression (Decl)) = N_Empty 1080 -- if R is not unrestricted.
1065 and then not Has_Full_Default_Initialization 1081 --
1066 (Etype (Defining_Identifier (Decl))) 1082 -- If variables are initialized:
1067 and then not Is_Access_Type 1083 -- If it is a move, then the target is unrestricted
1068 (Etype (Defining_Identifier (Decl))) 1084 -- If it is a borrow, then the target is unrestricted
1069 then 1085 -- If it is an observe, then the target should be observed
1070 Elem.all.Tree.Permission := Write_Only; 1086
1071 Elem.all.Tree.Children_Permission := Write_Only; 1087 if Current_Checking_Mode = Observe then
1088 Elem := new Perm_Tree_Wrapper'
1089 (Tree =>
1090 (Kind => Entire_Object,
1091 Is_Node_Deep => Deep,
1092 Permission => Observed,
1093 Children_Permission => Observed));
1094 else
1095 Elem := new Perm_Tree_Wrapper'
1096 (Tree =>
1097 (Kind => Entire_Object,
1098 Is_Node_Deep => Deep,
1099 Permission => Unrestricted,
1100 Children_Permission => Unrestricted));
1072 end if; 1101 end if;
1073 1102
1074 -- Create new tree for defining identifier 1103 -- Create new tree for defining identifier
1075 1104
1076 Set (Current_Perm_Env, 1105 Set (Current_Perm_Env,
1077 Unique_Entity (Defining_Identifier (Decl)), 1106 Unique_Entity (Defining_Identifier (Decl)),
1078 Elem); 1107 Elem);
1079 1108 pragma Assert (Get_First (Current_Perm_Env) /= null);
1080 pragma Assert (Get_First (Current_Perm_Env)
1081 /= null);
1082
1083 end; 1109 end;
1084 1110
1085 when N_Subtype_Declaration => 1111 when N_Subtype_Declaration =>
1086 Check_Node (Subtype_Indication (Decl)); 1112 Check_Node (Subtype_Indication (Decl));
1087 1113
1088 when N_Iterator_Specification => 1114 when N_Iterator_Specification =>
1089 pragma Assert (Is_Shallow (Etype (Defining_Identifier (Decl))));
1090 null; 1115 null;
1091 1116
1092 when N_Loop_Parameter_Specification => 1117 when N_Loop_Parameter_Specification =>
1093 pragma Assert (Is_Shallow (Etype (Defining_Identifier (Decl))));
1094 null; 1118 null;
1095 1119
1096 -- Checking should not be called directly on these nodes 1120 -- Checking should not be called directly on these nodes
1097 1121
1098 when N_Component_Declaration 1122 when N_Function_Specification
1099 | N_Function_Specification
1100 | N_Entry_Declaration 1123 | N_Entry_Declaration
1101 | N_Procedure_Specification 1124 | N_Procedure_Specification
1125 | N_Component_Declaration
1102 => 1126 =>
1103 raise Program_Error; 1127 raise Program_Error;
1104 1128
1105 -- Ignored constructs for pointer checking 1129 -- Ignored constructs for pointer checking
1106 1130
1126 1150
1127 procedure Check_Expression (Expr : Node_Id) is 1151 procedure Check_Expression (Expr : Node_Id) is
1128 Mode_Before : constant Checking_Mode := Current_Checking_Mode; 1152 Mode_Before : constant Checking_Mode := Current_Checking_Mode;
1129 begin 1153 begin
1130 case N_Subexpr'(Nkind (Expr)) is 1154 case N_Subexpr'(Nkind (Expr)) is
1131 when N_Procedure_Call_Statement => 1155 when N_Procedure_Call_Statement
1156 | N_Function_Call
1157 =>
1132 Check_Call_Statement (Expr); 1158 Check_Call_Statement (Expr);
1133 1159
1134 when N_Identifier 1160 when N_Identifier
1135 | N_Expanded_Name 1161 | N_Expanded_Name
1136 => 1162 =>
1137 -- Check if identifier is pointing to nothing (On/Off/...) 1163 -- Check if identifier is pointing to nothing (On/Off/...)
1164
1138 if not Present (Entity (Expr)) then 1165 if not Present (Entity (Expr)) then
1139 return; 1166 return;
1140 end if; 1167 end if;
1141 1168
1142 -- Do not analyze things that are not of object Kind 1169 -- Do not analyze things that are not of object Kind
1170
1143 if Ekind (Entity (Expr)) not in Object_Kind then 1171 if Ekind (Entity (Expr)) not in Object_Kind then
1144 return; 1172 return;
1145 end if; 1173 end if;
1146 1174
1147 -- Consider as ident 1175 -- Consider as ident
1176
1148 Process_Path (Expr); 1177 Process_Path (Expr);
1149 1178
1150 -- Switch to read mode and then check the readability of each operand 1179 -- Switch to read mode and then check the readability of each operand
1151 1180
1152 when N_Binary_Op => 1181 when N_Binary_Op =>
1153
1154 Current_Checking_Mode := Read; 1182 Current_Checking_Mode := Read;
1155 Check_Node (Left_Opnd (Expr)); 1183 Check_Node (Left_Opnd (Expr));
1156 Check_Node (Right_Opnd (Expr)); 1184 Check_Node (Right_Opnd (Expr));
1157 1185
1158 -- Switch to read mode and then check the readability of each operand 1186 -- Switch to read mode and then check the readability of each operand
1160 when N_Op_Abs 1188 when N_Op_Abs
1161 | N_Op_Minus 1189 | N_Op_Minus
1162 | N_Op_Not 1190 | N_Op_Not
1163 | N_Op_Plus 1191 | N_Op_Plus
1164 => 1192 =>
1165 pragma Assert (Is_Shallow (Etype (Expr)));
1166 Current_Checking_Mode := Read; 1193 Current_Checking_Mode := Read;
1167 Check_Node (Right_Opnd (Expr)); 1194 Check_Node (Right_Opnd (Expr));
1168 1195
1169 -- Forbid all deep expressions for Attribute ??? 1196 -- Forbid all deep expressions for Attribute ???
1197 -- What about generics? (formal parameters).
1170 1198
1171 when N_Attribute_Reference => 1199 when N_Attribute_Reference =>
1172 case Attribute_Name (Expr) is 1200 case Attribute_Name (Expr) is
1173 when Name_Access => 1201 when Name_Access =>
1174 case Current_Checking_Mode is 1202 Error_Msg_N ("access attribute not allowed", Expr);
1175 when Read =>
1176 Check_Node (Prefix (Expr));
1177
1178 when Move =>
1179 Current_Checking_Mode := Super_Move;
1180 Check_Node (Prefix (Expr));
1181
1182 -- Only assign names, not expressions
1183
1184 when Assign =>
1185 raise Program_Error;
1186
1187 -- Prefix in Super_Move should be a name, error here
1188
1189 when Super_Move =>
1190 raise Program_Error;
1191
1192 -- Could only borrow names of mode out, not n'Access
1193
1194 when Borrow_Out =>
1195 raise Program_Error;
1196
1197 when Observe =>
1198 Check_Node (Prefix (Expr));
1199 end case;
1200 1203
1201 when Name_Last 1204 when Name_Last
1202 | Name_First 1205 | Name_First
1203 => 1206 =>
1204 Current_Checking_Mode := Read; 1207 Current_Checking_Mode := Read;
1207 when Name_Min => 1210 when Name_Min =>
1208 Current_Checking_Mode := Read; 1211 Current_Checking_Mode := Read;
1209 Check_Node (Prefix (Expr)); 1212 Check_Node (Prefix (Expr));
1210 1213
1211 when Name_Image => 1214 when Name_Image =>
1215 Check_List (Expressions (Expr));
1216
1217 when Name_Img =>
1212 Check_Node (Prefix (Expr)); 1218 Check_Node (Prefix (Expr));
1213 1219
1214 when Name_SPARK_Mode => 1220 when Name_SPARK_Mode =>
1215 null; 1221 null;
1216 1222
1221 when Name_Update => 1227 when Name_Update =>
1222 Check_List (Expressions (Expr)); 1228 Check_List (Expressions (Expr));
1223 Check_Node (Prefix (Expr)); 1229 Check_Node (Prefix (Expr));
1224 1230
1225 when Name_Pred 1231 when Name_Pred
1226 | Name_Succ 1232 | Name_Succ
1227 => 1233 =>
1228 Check_List (Expressions (Expr)); 1234 Check_List (Expressions (Expr));
1229 Check_Node (Prefix (Expr)); 1235 Check_Node (Prefix (Expr));
1230 1236
1231 when Name_Length => 1237 when Name_Length =>
1236 -- in the analysis. This means that taking the address of a 1242 -- in the analysis. This means that taking the address of a
1237 -- variable makes a silent alias that is not rejected by the 1243 -- variable makes a silent alias that is not rejected by the
1238 -- analysis. 1244 -- analysis.
1239 1245
1240 when Name_Address 1246 when Name_Address
1241 | Name_Alignment 1247 | Name_Alignment
1242 | Name_Component_Size 1248 | Name_Component_Size
1243 | Name_First_Bit 1249 | Name_First_Bit
1244 | Name_Last_Bit 1250 | Name_Last_Bit
1245 | Name_Size 1251 | Name_Size
1246 | Name_Position 1252 | Name_Position
1247 => 1253 =>
1248 null; 1254 null;
1249 1255
1250 -- Attributes referring to types (get values from types), hence 1256 -- Attributes referring to types (get values from types), hence
1251 -- no need to check either for borrows or any loans. 1257 -- no need to check either for borrows or any loans.
1252 1258
1253 when Name_Base 1259 when Name_Base
1254 | Name_Val 1260 | Name_Val
1255 => 1261 =>
1256 null; 1262 null;
1257
1258 -- Other attributes that fall out of the scope of the analysis 1263 -- Other attributes that fall out of the scope of the analysis
1259 1264
1260 when others => 1265 when others =>
1261 null; 1266 null;
1262 end case; 1267 end case;
1274 -- Switch to read mode and then check the readability of each operand 1279 -- Switch to read mode and then check the readability of each operand
1275 1280
1276 when N_And_Then 1281 when N_And_Then
1277 | N_Or_Else 1282 | N_Or_Else
1278 => 1283 =>
1279 pragma Assert (Is_Shallow (Etype (Expr)));
1280 Current_Checking_Mode := Read; 1284 Current_Checking_Mode := Read;
1281 Check_Node (Left_Opnd (Expr)); 1285 Check_Node (Left_Opnd (Expr));
1282 Check_Node (Right_Opnd (Expr)); 1286 Check_Node (Right_Opnd (Expr));
1283 1287
1284 -- Check the arguments of the call 1288 -- Check the arguments of the call
1285 1289
1286 when N_Function_Call =>
1287 Current_Checking_Mode := Read;
1288 Check_List (Parameter_Associations (Expr));
1289
1290 when N_Explicit_Dereference => 1290 when N_Explicit_Dereference =>
1291 Process_Path (Expr); 1291 Process_Path (Expr);
1292 1292
1293 -- Copy environment, run on each branch, and then merge 1293 -- Copy environment, run on each branch, and then merge
1294 1294
1297 Saved_Env : Perm_Env; 1297 Saved_Env : Perm_Env;
1298 1298
1299 -- Accumulator for the different branches 1299 -- Accumulator for the different branches
1300 1300
1301 New_Env : Perm_Env; 1301 New_Env : Perm_Env;
1302 1302 Elmt : Node_Id := First (Expressions (Expr));
1303 Elmt : Node_Id := First (Expressions (Expr));
1304 1303
1305 begin 1304 begin
1306 Current_Checking_Mode := Read; 1305 Current_Checking_Mode := Read;
1307
1308 Check_Node (Elmt); 1306 Check_Node (Elmt);
1309
1310 Current_Checking_Mode := Mode_Before; 1307 Current_Checking_Mode := Mode_Before;
1311 1308
1312 -- Save environment 1309 -- Save environment
1313 1310
1314 Copy_Env (Current_Perm_Env, 1311 Copy_Env (Current_Perm_Env, Saved_Env);
1315 Saved_Env);
1316 1312
1317 -- Here we have the original env in saved, current with a fresh 1313 -- Here we have the original env in saved, current with a fresh
1318 -- copy, and new aliased. 1314 -- copy, and new aliased.
1319 1315
1320 -- THEN PART 1316 -- THEN PART
1323 Check_Node (Elmt); 1319 Check_Node (Elmt);
1324 1320
1325 -- Here the new_environment contains curr env after then block 1321 -- Here the new_environment contains curr env after then block
1326 1322
1327 -- ELSE part 1323 -- ELSE part
1328
1329 -- Restore environment before if 1324 -- Restore environment before if
1330 Copy_Env (Current_Perm_Env, 1325 Copy_Env (Current_Perm_Env, New_Env);
1331 New_Env);
1332
1333 Free_Env (Current_Perm_Env); 1326 Free_Env (Current_Perm_Env);
1334 1327 Copy_Env (Saved_Env, Current_Perm_Env);
1335 Copy_Env (Saved_Env,
1336 Current_Perm_Env);
1337 1328
1338 -- Here new environment contains the environment after then and 1329 -- Here new environment contains the environment after then and
1339 -- current the fresh copy of old one. 1330 -- current the fresh copy of old one.
1340 1331
1341 Next (Elmt); 1332 Next (Elmt);
1342 Check_Node (Elmt); 1333 Check_Node (Elmt);
1343 1334
1344 Merge_Envs (New_Env,
1345 Current_Perm_Env);
1346
1347 -- CLEANUP 1335 -- CLEANUP
1348 1336
1349 Copy_Env (New_Env, 1337 Copy_Env (New_Env, Current_Perm_Env);
1350 Current_Perm_Env);
1351
1352 Free_Env (New_Env); 1338 Free_Env (New_Env);
1353 Free_Env (Saved_Env); 1339 Free_Env (Saved_Env);
1354 end; 1340 end;
1355 1341
1356 when N_Indexed_Component => 1342 when N_Indexed_Component =>
1362 Check_Node (Expression (Expr)); 1348 Check_Node (Expression (Expr));
1363 1349
1364 when N_Quantified_Expression => 1350 when N_Quantified_Expression =>
1365 declare 1351 declare
1366 Saved_Env : Perm_Env; 1352 Saved_Env : Perm_Env;
1353
1367 begin 1354 begin
1368 Copy_Env (Current_Perm_Env, Saved_Env); 1355 Copy_Env (Current_Perm_Env, Saved_Env);
1369 Current_Checking_Mode := Read; 1356 Current_Checking_Mode := Read;
1370 Check_Node (Iterator_Specification (Expr)); 1357 Check_Node (Iterator_Specification (Expr));
1371 Check_Node (Loop_Parameter_Specification (Expr)); 1358 Check_Node (Loop_Parameter_Specification (Expr));
1373 Check_Node (Condition (Expr)); 1360 Check_Node (Condition (Expr));
1374 Free_Env (Current_Perm_Env); 1361 Free_Env (Current_Perm_Env);
1375 Copy_Env (Saved_Env, Current_Perm_Env); 1362 Copy_Env (Saved_Env, Current_Perm_Env);
1376 Free_Env (Saved_Env); 1363 Free_Env (Saved_Env);
1377 end; 1364 end;
1378
1379 -- Analyze the list of associations in the aggregate 1365 -- Analyze the list of associations in the aggregate
1380 1366
1381 when N_Aggregate => 1367 when N_Aggregate =>
1382 Check_List (Expressions (Expr)); 1368 Check_List (Expressions (Expr));
1383 Check_List (Component_Associations (Expr)); 1369 Check_List (Component_Associations (Expr));
1390 Saved_Env : Perm_Env; 1376 Saved_Env : Perm_Env;
1391 1377
1392 -- Accumulator for the different branches 1378 -- Accumulator for the different branches
1393 1379
1394 New_Env : Perm_Env; 1380 New_Env : Perm_Env;
1395
1396 Elmt : Node_Id := First (Alternatives (Expr)); 1381 Elmt : Node_Id := First (Alternatives (Expr));
1397 1382
1398 begin 1383 begin
1399 Current_Checking_Mode := Read; 1384 Current_Checking_Mode := Read;
1400 Check_Node (Expression (Expr)); 1385 Check_Node (Expression (Expr));
1401
1402 Current_Checking_Mode := Mode_Before; 1386 Current_Checking_Mode := Mode_Before;
1403 1387
1404 -- Save environment 1388 -- Save environment
1405 1389
1406 Copy_Env (Current_Perm_Env, 1390 Copy_Env (Current_Perm_Env, Saved_Env);
1407 Saved_Env);
1408 1391
1409 -- Here we have the original env in saved, current with a fresh 1392 -- Here we have the original env in saved, current with a fresh
1410 -- copy, and new aliased. 1393 -- copy, and new aliased.
1411 1394
1412 -- First alternative 1395 -- First alternative
1413 1396
1414 Check_Node (Elmt); 1397 Check_Node (Elmt);
1415 Next (Elmt); 1398 Next (Elmt);
1416 1399 Copy_Env (Current_Perm_Env, New_Env);
1417 Copy_Env (Current_Perm_Env,
1418 New_Env);
1419
1420 Free_Env (Current_Perm_Env); 1400 Free_Env (Current_Perm_Env);
1421 1401
1422 -- Other alternatives 1402 -- Other alternatives
1423 1403
1424 while Present (Elmt) loop 1404 while Present (Elmt) loop
1405
1425 -- Restore environment 1406 -- Restore environment
1426 1407
1427 Copy_Env (Saved_Env, 1408 Copy_Env (Saved_Env, Current_Perm_Env);
1428 Current_Perm_Env);
1429
1430 Check_Node (Elmt); 1409 Check_Node (Elmt);
1431
1432 -- Merge Current_Perm_Env into New_Env
1433
1434 Merge_Envs (New_Env,
1435 Current_Perm_Env);
1436
1437 Next (Elmt); 1410 Next (Elmt);
1438 end loop; 1411 end loop;
1439
1440 -- CLEANUP 1412 -- CLEANUP
1441 Copy_Env (New_Env, 1413
1442 Current_Perm_Env); 1414 Copy_Env (Saved_Env, Current_Perm_Env);
1443
1444 Free_Env (New_Env); 1415 Free_Env (New_Env);
1445 Free_Env (Saved_Env); 1416 Free_Env (Saved_Env);
1446 end; 1417 end;
1447
1448 -- Analyze the list of associates in the aggregate as well as the 1418 -- Analyze the list of associates in the aggregate as well as the
1449 -- ancestor part. 1419 -- ancestor part.
1450 1420
1451 when N_Extension_Aggregate => 1421 when N_Extension_Aggregate =>
1452
1453 Check_Node (Ancestor_Part (Expr)); 1422 Check_Node (Ancestor_Part (Expr));
1454 Check_List (Expressions (Expr)); 1423 Check_List (Expressions (Expr));
1455 1424
1456 when N_Range => 1425 when N_Range =>
1457 Check_Node (Low_Bound (Expr)); 1426 Check_Node (Low_Bound (Expr));
1489 | N_Operator_Symbol 1458 | N_Operator_Symbol
1490 | N_Raise_Expression 1459 | N_Raise_Expression
1491 | N_Raise_xxx_Error 1460 | N_Raise_xxx_Error
1492 => 1461 =>
1493 null; 1462 null;
1494
1495 -- The following nodes are never generated in GNATprove mode 1463 -- The following nodes are never generated in GNATprove mode
1496 1464
1497 when N_Expression_With_Actions 1465 when N_Expression_With_Actions
1498 | N_Reference 1466 | N_Reference
1499 | N_Unchecked_Expression 1467 | N_Unchecked_Expression
1500 => 1468 =>
1501 raise Program_Error; 1469 raise Program_Error;
1502
1503 end case; 1470 end case;
1504 end Check_Expression; 1471 end Check_Expression;
1505 1472
1506 ------------------- 1473 -------------------
1507 -- Check_Globals -- 1474 -- Check_Globals --
1508 ------------------- 1475 -------------------
1509 1476
1510 procedure Check_Globals (N : Node_Id; Check_Mode : Checking_Mode) is 1477 procedure Check_Globals (N : Node_Id) is
1511 begin 1478 begin
1512 if Nkind (N) = N_Empty then 1479 if Nkind (N) = N_Empty then
1513 return; 1480 return;
1514 end if; 1481 end if;
1515 1482
1516 declare 1483 declare
1517 pragma Assert 1484 pragma Assert (List_Length (Pragma_Argument_Associations (N)) = 1);
1518 (List_Length (Pragma_Argument_Associations (N)) = 1); 1485 PAA : constant Node_Id := First (Pragma_Argument_Associations (N));
1519
1520 PAA : constant Node_Id :=
1521 First (Pragma_Argument_Associations (N));
1522 pragma Assert (Nkind (PAA) = N_Pragma_Argument_Association); 1486 pragma Assert (Nkind (PAA) = N_Pragma_Argument_Association);
1523
1524 Row : Node_Id; 1487 Row : Node_Id;
1525 The_Mode : Name_Id; 1488 The_Mode : Name_Id;
1526 RHS : Node_Id; 1489 RHS : Node_Id;
1527 1490
1528 procedure Process (Mode : Name_Id; 1491 procedure Process (Mode : Name_Id; The_Global : Entity_Id);
1529 The_Global : Entity_Id); 1492 procedure Process (Mode : Name_Id; The_Global : Node_Id) is
1530 1493 Ident_Elt : constant Entity_Id :=
1531 procedure Process (Mode : Name_Id;
1532 The_Global : Node_Id)
1533 is
1534 Ident_Elt : constant Entity_Id :=
1535 Unique_Entity (Entity (The_Global)); 1494 Unique_Entity (Entity (The_Global));
1536
1537 Mode_Before : constant Checking_Mode := Current_Checking_Mode; 1495 Mode_Before : constant Checking_Mode := Current_Checking_Mode;
1538 1496
1539 begin 1497 begin
1540 if Ekind (Ident_Elt) = E_Abstract_State then 1498 if Ekind (Ident_Elt) = E_Abstract_State then
1541 return; 1499 return;
1542 end if; 1500 end if;
1543 1501 case Mode is
1544 case Check_Mode is 1502 when Name_Input
1545 when Read => 1503 | Name_Proof_In
1546 case Mode is 1504 =>
1547 when Name_Input 1505 Current_Checking_Mode := Observe;
1548 | Name_Proof_In
1549 =>
1550 Check_Node (The_Global);
1551
1552 when Name_Output
1553 | Name_In_Out
1554 =>
1555 null;
1556
1557 when others =>
1558 raise Program_Error;
1559
1560 end case;
1561
1562 when Observe =>
1563 case Mode is
1564 when Name_Input
1565 | Name_Proof_In
1566 =>
1567 if not Is_Borrowed_In (Ident_Elt) then
1568 -- Observed in
1569
1570 Current_Checking_Mode := Observe;
1571 Check_Node (The_Global);
1572 end if;
1573
1574 when others =>
1575 null;
1576
1577 end case;
1578
1579 when Borrow_Out =>
1580
1581 case Mode is
1582 when Name_Output =>
1583 -- Borrowed out
1584 Current_Checking_Mode := Borrow_Out;
1585 Check_Node (The_Global);
1586
1587 when others =>
1588 null;
1589
1590 end case;
1591
1592 when Move =>
1593 case Mode is
1594 when Name_Input
1595 | Name_Proof_In
1596 =>
1597 if Is_Borrowed_In (Ident_Elt) then
1598 -- Borrowed in
1599
1600 Current_Checking_Mode := Move;
1601 else
1602 -- Observed
1603
1604 return;
1605 end if;
1606
1607 when Name_Output =>
1608 return;
1609
1610 when Name_In_Out =>
1611 -- Borrowed in out
1612
1613 Current_Checking_Mode := Move;
1614
1615 when others =>
1616 raise Program_Error;
1617 end case;
1618
1619 Check_Node (The_Global); 1506 Check_Node (The_Global);
1620 when Assign => 1507
1621 case Mode is 1508 when Name_Output
1622 when Name_Input 1509 | Name_In_Out
1623 | Name_Proof_In 1510 =>
1624 => 1511 -- ??? Borrow not Move?
1625 null; 1512 Current_Checking_Mode := Borrow;
1626 1513 Check_Node (The_Global);
1627 when Name_Output
1628 | Name_In_Out
1629 =>
1630 -- Borrowed out or in out
1631
1632 Process_Path (The_Global);
1633
1634 when others =>
1635 raise Program_Error;
1636 end case;
1637 1514
1638 when others => 1515 when others =>
1639 raise Program_Error; 1516 raise Program_Error;
1640 end case; 1517 end case;
1641
1642 Current_Checking_Mode := Mode_Before; 1518 Current_Checking_Mode := Mode_Before;
1643 end Process; 1519 end Process;
1644 1520
1645 begin 1521 begin
1646 if Nkind (Expression (PAA)) = N_Null then 1522 if Nkind (Expression (PAA)) = N_Null then
1523
1647 -- global => null 1524 -- global => null
1648 -- No globals, nothing to do 1525 -- No globals, nothing to do
1526
1649 return; 1527 return;
1650 1528
1651 elsif Nkind_In (Expression (PAA), N_Identifier, N_Expanded_Name) then 1529 elsif Nkind_In (Expression (PAA), N_Identifier, N_Expanded_Name) then
1530
1652 -- global => foo 1531 -- global => foo
1653 -- A single input 1532 -- A single input
1533
1654 Process (Name_Input, Expression (PAA)); 1534 Process (Name_Input, Expression (PAA));
1655 1535
1656 elsif Nkind (Expression (PAA)) = N_Aggregate 1536 elsif Nkind (Expression (PAA)) = N_Aggregate
1657 and then Expressions (Expression (PAA)) /= No_List 1537 and then Expressions (Expression (PAA)) /= No_List
1658 then 1538 then
1659 -- global => (foo, bar) 1539 -- global => (foo, bar)
1660 -- Inputs 1540 -- Inputs
1541
1661 RHS := First (Expressions (Expression (PAA))); 1542 RHS := First (Expressions (Expression (PAA)));
1662 while Present (RHS) loop 1543 while Present (RHS) loop
1663 case Nkind (RHS) is 1544 case Nkind (RHS) is
1664 when N_Identifier 1545 when N_Identifier
1665 | N_Expanded_Name 1546 | N_Expanded_Name
1669 when N_Numeric_Or_String_Literal => 1550 when N_Numeric_Or_String_Literal =>
1670 Process (Name_Input, Original_Node (RHS)); 1551 Process (Name_Input, Original_Node (RHS));
1671 1552
1672 when others => 1553 when others =>
1673 raise Program_Error; 1554 raise Program_Error;
1674
1675 end case; 1555 end case;
1676 RHS := Next (RHS); 1556 RHS := Next (RHS);
1677 end loop; 1557 end loop;
1678 1558
1679 elsif Nkind (Expression (PAA)) = N_Aggregate 1559 elsif Nkind (Expression (PAA)) = N_Aggregate
1689 begin 1569 begin
1690 Row := First (CA); 1570 Row := First (CA);
1691 while Present (Row) loop 1571 while Present (Row) loop
1692 pragma Assert (List_Length (Choices (Row)) = 1); 1572 pragma Assert (List_Length (Choices (Row)) = 1);
1693 The_Mode := Chars (First (Choices (Row))); 1573 The_Mode := Chars (First (Choices (Row)));
1694
1695 RHS := Expression (Row); 1574 RHS := Expression (Row);
1575
1696 case Nkind (RHS) is 1576 case Nkind (RHS) is
1697 when N_Aggregate => 1577 when N_Aggregate =>
1698 RHS := First (Expressions (RHS)); 1578 RHS := First (Expressions (RHS));
1699 while Present (RHS) loop 1579 while Present (RHS) loop
1700 case Nkind (RHS) is 1580 case Nkind (RHS) is
1701 when N_Numeric_Or_String_Literal => 1581 when N_Numeric_Or_String_Literal =>
1702 Process (The_Mode, Original_Node (RHS)); 1582 Process (The_Mode, Original_Node (RHS));
1703 1583
1704 when others => 1584 when others =>
1705 Process (The_Mode, RHS); 1585 Process (The_Mode, RHS);
1706
1707 end case; 1586 end case;
1708 RHS := Next (RHS); 1587 RHS := Next (RHS);
1709 end loop; 1588 end loop;
1710 1589
1711 when N_Identifier 1590 when N_Identifier
1719 when N_Numeric_Or_String_Literal => 1598 when N_Numeric_Or_String_Literal =>
1720 Process (The_Mode, Original_Node (RHS)); 1599 Process (The_Mode, Original_Node (RHS));
1721 1600
1722 when others => 1601 when others =>
1723 raise Program_Error; 1602 raise Program_Error;
1724
1725 end case; 1603 end case;
1726
1727 Row := Next (Row); 1604 Row := Next (Row);
1728 end loop; 1605 end loop;
1729 end; 1606 end;
1730 1607
1731 else 1608 else
1752 -- Check_Loop_Statement -- 1629 -- Check_Loop_Statement --
1753 -------------------------- 1630 --------------------------
1754 1631
1755 procedure Check_Loop_Statement (Loop_N : Node_Id) is 1632 procedure Check_Loop_Statement (Loop_N : Node_Id) is
1756 1633
1757 -- Local Subprograms
1758
1759 procedure Check_Is_Less_Restrictive_Env
1760 (Exiting_Env : Perm_Env;
1761 Entry_Env : Perm_Env);
1762 -- This procedure checks that the Exiting_Env environment is less
1763 -- restrictive than the Entry_Env environment.
1764
1765 procedure Check_Is_Less_Restrictive_Tree
1766 (New_Tree : Perm_Tree_Access;
1767 Orig_Tree : Perm_Tree_Access;
1768 E : Entity_Id);
1769 -- Auxiliary procedure to check that the tree New_Tree is less
1770 -- restrictive than the tree Orig_Tree for the entity E.
1771
1772 procedure Perm_Error_Loop_Exit
1773 (E : Entity_Id;
1774 Loop_Id : Node_Id;
1775 Perm : Perm_Kind;
1776 Found_Perm : Perm_Kind);
1777 -- A procedure that is called when the permissions found contradict
1778 -- the rules established by the RM at the exit of loops. This function
1779 -- is called with the entity, the node of the enclosing loop, the
1780 -- permission that was expected and the permission found, and issues
1781 -- an appropriate error message.
1782
1783 -----------------------------------
1784 -- Check_Is_Less_Restrictive_Env --
1785 -----------------------------------
1786
1787 procedure Check_Is_Less_Restrictive_Env
1788 (Exiting_Env : Perm_Env;
1789 Entry_Env : Perm_Env)
1790 is
1791 Comp_Entry : Perm_Tree_Maps.Key_Option;
1792 Iter_Entry, Iter_Exit : Perm_Tree_Access;
1793
1794 begin
1795 Comp_Entry := Get_First_Key (Entry_Env);
1796 while Comp_Entry.Present loop
1797 Iter_Entry := Get (Entry_Env, Comp_Entry.K);
1798 pragma Assert (Iter_Entry /= null);
1799 Iter_Exit := Get (Exiting_Env, Comp_Entry.K);
1800 pragma Assert (Iter_Exit /= null);
1801 Check_Is_Less_Restrictive_Tree
1802 (New_Tree => Iter_Exit,
1803 Orig_Tree => Iter_Entry,
1804 E => Comp_Entry.K);
1805 Comp_Entry := Get_Next_Key (Entry_Env);
1806 end loop;
1807 end Check_Is_Less_Restrictive_Env;
1808
1809 ------------------------------------
1810 -- Check_Is_Less_Restrictive_Tree --
1811 ------------------------------------
1812
1813 procedure Check_Is_Less_Restrictive_Tree
1814 (New_Tree : Perm_Tree_Access;
1815 Orig_Tree : Perm_Tree_Access;
1816 E : Entity_Id)
1817 is
1818 -----------------------
1819 -- Local Subprograms --
1820 -----------------------
1821
1822 procedure Check_Is_Less_Restrictive_Tree_Than
1823 (Tree : Perm_Tree_Access;
1824 Perm : Perm_Kind;
1825 E : Entity_Id);
1826 -- Auxiliary procedure to check that the tree N is less restrictive
1827 -- than the given permission P.
1828
1829 procedure Check_Is_More_Restrictive_Tree_Than
1830 (Tree : Perm_Tree_Access;
1831 Perm : Perm_Kind;
1832 E : Entity_Id);
1833 -- Auxiliary procedure to check that the tree N is more restrictive
1834 -- than the given permission P.
1835
1836 -----------------------------------------
1837 -- Check_Is_Less_Restrictive_Tree_Than --
1838 -----------------------------------------
1839
1840 procedure Check_Is_Less_Restrictive_Tree_Than
1841 (Tree : Perm_Tree_Access;
1842 Perm : Perm_Kind;
1843 E : Entity_Id)
1844 is
1845 begin
1846 if not (Permission (Tree) >= Perm) then
1847 Perm_Error_Loop_Exit
1848 (E, Loop_N, Permission (Tree), Perm);
1849 end if;
1850
1851 case Kind (Tree) is
1852 when Entire_Object =>
1853 if not (Children_Permission (Tree) >= Perm) then
1854 Perm_Error_Loop_Exit
1855 (E, Loop_N, Children_Permission (Tree), Perm);
1856
1857 end if;
1858
1859 when Reference =>
1860 Check_Is_Less_Restrictive_Tree_Than
1861 (Get_All (Tree), Perm, E);
1862
1863 when Array_Component =>
1864 Check_Is_Less_Restrictive_Tree_Than
1865 (Get_Elem (Tree), Perm, E);
1866
1867 when Record_Component =>
1868 declare
1869 Comp : Perm_Tree_Access;
1870 begin
1871 Comp := Perm_Tree_Maps.Get_First (Component (Tree));
1872 while Comp /= null loop
1873 Check_Is_Less_Restrictive_Tree_Than (Comp, Perm, E);
1874 Comp :=
1875 Perm_Tree_Maps.Get_Next (Component (Tree));
1876 end loop;
1877
1878 Check_Is_Less_Restrictive_Tree_Than
1879 (Other_Components (Tree), Perm, E);
1880 end;
1881 end case;
1882 end Check_Is_Less_Restrictive_Tree_Than;
1883
1884 -----------------------------------------
1885 -- Check_Is_More_Restrictive_Tree_Than --
1886 -----------------------------------------
1887
1888 procedure Check_Is_More_Restrictive_Tree_Than
1889 (Tree : Perm_Tree_Access;
1890 Perm : Perm_Kind;
1891 E : Entity_Id)
1892 is
1893 begin
1894 if not (Perm >= Permission (Tree)) then
1895 Perm_Error_Loop_Exit
1896 (E, Loop_N, Permission (Tree), Perm);
1897 end if;
1898
1899 case Kind (Tree) is
1900 when Entire_Object =>
1901 if not (Perm >= Children_Permission (Tree)) then
1902 Perm_Error_Loop_Exit
1903 (E, Loop_N, Children_Permission (Tree), Perm);
1904 end if;
1905
1906 when Reference =>
1907 Check_Is_More_Restrictive_Tree_Than
1908 (Get_All (Tree), Perm, E);
1909
1910 when Array_Component =>
1911 Check_Is_More_Restrictive_Tree_Than
1912 (Get_Elem (Tree), Perm, E);
1913
1914 when Record_Component =>
1915 declare
1916 Comp : Perm_Tree_Access;
1917 begin
1918 Comp := Perm_Tree_Maps.Get_First (Component (Tree));
1919 while Comp /= null loop
1920 Check_Is_More_Restrictive_Tree_Than (Comp, Perm, E);
1921 Comp :=
1922 Perm_Tree_Maps.Get_Next (Component (Tree));
1923 end loop;
1924
1925 Check_Is_More_Restrictive_Tree_Than
1926 (Other_Components (Tree), Perm, E);
1927 end;
1928 end case;
1929 end Check_Is_More_Restrictive_Tree_Than;
1930
1931 -- Start of processing for Check_Is_Less_Restrictive_Tree
1932
1933 begin
1934 if not (Permission (New_Tree) <= Permission (Orig_Tree)) then
1935 Perm_Error_Loop_Exit
1936 (E => E,
1937 Loop_Id => Loop_N,
1938 Perm => Permission (New_Tree),
1939 Found_Perm => Permission (Orig_Tree));
1940 end if;
1941
1942 case Kind (New_Tree) is
1943
1944 -- Potentially folded tree. We check the other tree Orig_Tree to
1945 -- check whether it is folded or not. If folded we just compare
1946 -- their Permission and Children_Permission, if not, then we
1947 -- look at the Children_Permission of the folded tree against
1948 -- the unfolded tree Orig_Tree.
1949
1950 when Entire_Object =>
1951 case Kind (Orig_Tree) is
1952 when Entire_Object =>
1953 if not (Children_Permission (New_Tree) <=
1954 Children_Permission (Orig_Tree))
1955 then
1956 Perm_Error_Loop_Exit
1957 (E, Loop_N,
1958 Children_Permission (New_Tree),
1959 Children_Permission (Orig_Tree));
1960 end if;
1961
1962 when Reference =>
1963 Check_Is_More_Restrictive_Tree_Than
1964 (Get_All (Orig_Tree), Children_Permission (New_Tree), E);
1965
1966 when Array_Component =>
1967 Check_Is_More_Restrictive_Tree_Than
1968 (Get_Elem (Orig_Tree), Children_Permission (New_Tree), E);
1969
1970 when Record_Component =>
1971 declare
1972 Comp : Perm_Tree_Access;
1973 begin
1974 Comp := Perm_Tree_Maps.Get_First
1975 (Component (Orig_Tree));
1976 while Comp /= null loop
1977 Check_Is_More_Restrictive_Tree_Than
1978 (Comp, Children_Permission (New_Tree), E);
1979 Comp := Perm_Tree_Maps.Get_Next
1980 (Component (Orig_Tree));
1981 end loop;
1982
1983 Check_Is_More_Restrictive_Tree_Than
1984 (Other_Components (Orig_Tree),
1985 Children_Permission (New_Tree), E);
1986 end;
1987 end case;
1988
1989 when Reference =>
1990 case Kind (Orig_Tree) is
1991 when Entire_Object =>
1992 Check_Is_Less_Restrictive_Tree_Than
1993 (Get_All (New_Tree), Children_Permission (Orig_Tree), E);
1994
1995 when Reference =>
1996 Check_Is_Less_Restrictive_Tree
1997 (Get_All (New_Tree), Get_All (Orig_Tree), E);
1998
1999 when others =>
2000 raise Program_Error;
2001 end case;
2002
2003 when Array_Component =>
2004 case Kind (Orig_Tree) is
2005 when Entire_Object =>
2006 Check_Is_Less_Restrictive_Tree_Than
2007 (Get_Elem (New_Tree), Children_Permission (Orig_Tree), E);
2008
2009 when Array_Component =>
2010 Check_Is_Less_Restrictive_Tree
2011 (Get_Elem (New_Tree), Get_Elem (Orig_Tree), E);
2012
2013 when others =>
2014 raise Program_Error;
2015 end case;
2016
2017 when Record_Component =>
2018 declare
2019 CompN : Perm_Tree_Access;
2020 begin
2021 CompN :=
2022 Perm_Tree_Maps.Get_First (Component (New_Tree));
2023 case Kind (Orig_Tree) is
2024 when Entire_Object =>
2025 while CompN /= null loop
2026 Check_Is_Less_Restrictive_Tree_Than
2027 (CompN, Children_Permission (Orig_Tree), E);
2028
2029 CompN :=
2030 Perm_Tree_Maps.Get_Next (Component (New_Tree));
2031 end loop;
2032
2033 Check_Is_Less_Restrictive_Tree_Than
2034 (Other_Components (New_Tree),
2035 Children_Permission (Orig_Tree),
2036 E);
2037
2038 when Record_Component =>
2039 declare
2040
2041 KeyO : Perm_Tree_Maps.Key_Option;
2042 CompO : Perm_Tree_Access;
2043 begin
2044 KeyO := Perm_Tree_Maps.Get_First_Key
2045 (Component (Orig_Tree));
2046 while KeyO.Present loop
2047 pragma Assert (CompO /= null);
2048
2049 Check_Is_Less_Restrictive_Tree (CompN, CompO, E);
2050
2051 KeyO := Perm_Tree_Maps.Get_Next_Key
2052 (Component (Orig_Tree));
2053 CompN := Perm_Tree_Maps.Get
2054 (Component (New_Tree), KeyO.K);
2055 CompO := Perm_Tree_Maps.Get
2056 (Component (Orig_Tree), KeyO.K);
2057 end loop;
2058
2059 Check_Is_Less_Restrictive_Tree
2060 (Other_Components (New_Tree),
2061 Other_Components (Orig_Tree),
2062 E);
2063 end;
2064
2065 when others =>
2066 raise Program_Error;
2067 end case;
2068 end;
2069 end case;
2070 end Check_Is_Less_Restrictive_Tree;
2071
2072 --------------------------
2073 -- Perm_Error_Loop_Exit --
2074 --------------------------
2075
2076 procedure Perm_Error_Loop_Exit
2077 (E : Entity_Id;
2078 Loop_Id : Node_Id;
2079 Perm : Perm_Kind;
2080 Found_Perm : Perm_Kind)
2081 is
2082 begin
2083 Error_Msg_Node_2 := Loop_Id;
2084 Error_Msg_N ("insufficient permission for & when exiting loop &", E);
2085 Perm_Mismatch (Exp_Perm => Perm,
2086 Act_Perm => Found_Perm,
2087 N => Loop_Id);
2088 end Perm_Error_Loop_Exit;
2089
2090 -- Local variables 1634 -- Local variables
2091 1635
2092 Loop_Name : constant Entity_Id := Entity (Identifier (Loop_N)); 1636 Loop_Name : constant Entity_Id := Entity (Identifier (Loop_N));
2093 Loop_Env : constant Perm_Env_Access := new Perm_Env; 1637 Loop_Env : constant Perm_Env_Access := new Perm_Env;
2094 1638
2108 -- populated by analyzing exit statements. 1652 -- populated by analyzing exit statements.
2109 1653
2110 if Present (Iteration_Scheme (Loop_N)) then 1654 if Present (Iteration_Scheme (Loop_N)) then
2111 declare 1655 declare
2112 Exit_Env : constant Perm_Env_Access := new Perm_Env; 1656 Exit_Env : constant Perm_Env_Access := new Perm_Env;
1657
2113 begin 1658 begin
2114 Copy_Env (From => Current_Perm_Env, To => Exit_Env.all); 1659 Copy_Env (From => Current_Perm_Env, To => Exit_Env.all);
2115 Set (Current_Loops_Accumulators, Loop_Name, Exit_Env); 1660 Set (Current_Loops_Accumulators, Loop_Name, Exit_Env);
2116 end; 1661 end;
2117 end if; 1662 end if;
2118 1663
2119 -- Analyze loop 1664 -- Analyze loop
2120 1665
2121 Check_Node (Iteration_Scheme (Loop_N)); 1666 Check_Node (Iteration_Scheme (Loop_N));
2122 Check_List (Statements (Loop_N)); 1667 Check_List (Statements (Loop_N));
2123
2124 -- Check that environment gets less restrictive at end of loop
2125
2126 Check_Is_Less_Restrictive_Env
2127 (Exiting_Env => Current_Perm_Env,
2128 Entry_Env => Loop_Env.all);
2129 1668
2130 -- Set environment to the one for exiting the loop 1669 -- Set environment to the one for exiting the loop
2131 1670
2132 declare 1671 declare
2133 Exit_Env : constant Perm_Env_Access := 1672 Exit_Env : constant Perm_Env_Access :=
2143 -- avoid spurious errors by having at least variables in scope inside 1682 -- avoid spurious errors by having at least variables in scope inside
2144 -- the environment. 1683 -- the environment.
2145 1684
2146 if Exit_Env /= null then 1685 if Exit_Env /= null then
2147 Copy_Env (From => Exit_Env.all, To => Current_Perm_Env); 1686 Copy_Env (From => Exit_Env.all, To => Current_Perm_Env);
1687 Free_Env (Loop_Env.all);
1688 Free_Env (Exit_Env.all);
2148 else 1689 else
2149 Copy_Env (From => Loop_Env.all, To => Current_Perm_Env); 1690 Copy_Env (From => Loop_Env.all, To => Current_Perm_Env);
1691 Free_Env (Loop_Env.all);
2150 end if; 1692 end if;
2151
2152 Free_Env (Loop_Env.all);
2153 Free_Env (Exit_Env.all);
2154 end; 1693 end;
2155 end Check_Loop_Statement; 1694 end Check_Loop_Statement;
2156 1695
2157 ---------------- 1696 ----------------
2158 -- Check_Node -- 1697 -- Check_Node --
2190 Check_List (Declarations (N)); 1729 Check_List (Declarations (N));
2191 1730
2192 when N_Package_Declaration => 1731 when N_Package_Declaration =>
2193 declare 1732 declare
2194 Spec : constant Node_Id := Specification (N); 1733 Spec : constant Node_Id := Specification (N);
1734
2195 begin 1735 begin
2196 Current_Checking_Mode := Read; 1736 Current_Checking_Mode := Read;
2197 Check_List (Visible_Declarations (Spec)); 1737 Check_List (Visible_Declarations (Spec));
2198 Check_List (Private_Declarations (Spec)); 1738 Check_List (Private_Declarations (Spec));
2199 1739
2256 | N_Defining_Operator_Symbol 1796 | N_Defining_Operator_Symbol
2257 | N_Defining_Program_Unit_Name 1797 | N_Defining_Program_Unit_Name
2258 | N_Delay_Alternative 1798 | N_Delay_Alternative
2259 | N_Derived_Type_Definition 1799 | N_Derived_Type_Definition
2260 | N_Designator 1800 | N_Designator
2261 | N_Discriminant_Association
2262 | N_Discriminant_Specification 1801 | N_Discriminant_Specification
2263 | N_Elsif_Part 1802 | N_Elsif_Part
2264 | N_Entry_Body_Formal_Part 1803 | N_Entry_Body_Formal_Part
2265 | N_Enumeration_Type_Definition 1804 | N_Enumeration_Type_Definition
2266 | N_Entry_Call_Alternative 1805 | N_Entry_Call_Alternative
2347 | N_Task_Type_Declaration 1886 | N_Task_Type_Declaration
2348 | N_Use_Package_Clause 1887 | N_Use_Package_Clause
2349 | N_With_Clause 1888 | N_With_Clause
2350 | N_Use_Type_Clause 1889 | N_Use_Type_Clause
2351 | N_Validate_Unchecked_Conversion 1890 | N_Validate_Unchecked_Conversion
1891 | N_Variable_Reference_Marker
1892 | N_Discriminant_Association
1893
1894 -- ??? check whether we should do sth special for
1895 -- N_Discriminant_Association, or maybe raise a program error.
2352 => 1896 =>
2353 null; 1897 null;
2354
2355 -- The following nodes are rewritten by semantic analysis 1898 -- The following nodes are rewritten by semantic analysis
2356 1899
2357 when N_Single_Protected_Declaration 1900 when N_Single_Protected_Declaration
2358 | N_Single_Task_Declaration 1901 | N_Single_Task_Declaration
2359 => 1902 =>
2389 1932
2390 Check_List (Visible_Declarations (CorSp)); 1933 Check_List (Visible_Declarations (CorSp));
2391 1934
2392 -- Save environment 1935 -- Save environment
2393 1936
2394 Copy_Env (Current_Perm_Env, 1937 Copy_Env (Current_Perm_Env, Saved_Env);
2395 Saved_Env);
2396
2397 Check_List (Private_Declarations (CorSp)); 1938 Check_List (Private_Declarations (CorSp));
2398 1939
2399 -- Set mode to Read, and then analyze declarations and statements 1940 -- Set mode to Read, and then analyze declarations and statements
2400 1941
2401 Current_Checking_Mode := Read; 1942 Current_Checking_Mode := Read;
2402
2403 Check_List (Declarations (Pack)); 1943 Check_List (Declarations (Pack));
2404 Check_Node (Handled_Statement_Sequence (Pack)); 1944 Check_Node (Handled_Statement_Sequence (Pack));
2405 1945
2406 -- Check RW for every stateful variable (i.e. in declarations) 1946 -- Check RW for every stateful variable (i.e. in declarations)
2407 1947
2411 1951
2412 -- Restore previous environment (i.e. delete every nonvisible 1952 -- Restore previous environment (i.e. delete every nonvisible
2413 -- declaration) from environment. 1953 -- declaration) from environment.
2414 1954
2415 Free_Env (Current_Perm_Env); 1955 Free_Env (Current_Perm_Env);
2416 Copy_Env (Saved_Env, 1956 Copy_Env (Saved_Env, Current_Perm_Env);
2417 Current_Perm_Env);
2418 end Check_Package_Body; 1957 end Check_Package_Body;
2419 1958
2420 ----------------- 1959 --------------------
2421 -- Check_Param -- 1960 -- Check_Param_In --
2422 ----------------- 1961 --------------------
2423 1962
2424 procedure Check_Param (Formal : Entity_Id; Actual : Node_Id) is 1963 procedure Check_Param_In (Formal : Entity_Id; Actual : Node_Id) is
2425 Mode : constant Entity_Kind := Ekind (Formal); 1964 Mode : constant Entity_Kind := Ekind (Formal);
2426 Mode_Before : constant Checking_Mode := Current_Checking_Mode; 1965 Mode_Before : constant Checking_Mode := Current_Checking_Mode;
2427
2428 begin 1966 begin
2429 case Current_Checking_Mode is 1967 case Formal_Kind'(Mode) is
2430 when Read => 1968
2431 case Formal_Kind'(Mode) is 1969 -- Formal IN parameter
2432 when E_In_Parameter => 1970
2433 if Is_Borrowed_In (Formal) then 1971 when E_In_Parameter =>
2434 -- Borrowed in 1972
2435 1973 -- Formal IN parameter, access type
2436 Current_Checking_Mode := Move; 1974
1975 if Is_Access_Type (Etype (Formal)) then
1976
1977 -- Formal IN parameter, access to variable type
1978
1979 if not Is_Access_Constant (Etype (Formal)) then
1980
1981 -- Formal IN parameter, named/anonymous access-to-variable
1982 -- type.
1983 --
1984 -- In SPARK, IN access-to-variable is an observe operation
1985 -- for a function, and a borrow operation for a procedure.
1986
1987 if Ekind (Scope (Formal)) = E_Function then
1988 Current_Checking_Mode := Observe;
1989 Check_Node (Actual);
2437 else 1990 else
2438 -- Observed 1991 Current_Checking_Mode := Borrow;
2439 1992 Check_Node (Actual);
2440 return;
2441 end if; 1993 end if;
2442 1994
2443 when E_Out_Parameter => 1995 -- Formal IN parameter, access-to-constant type
2444 return; 1996 -- Formal IN parameter, access-to-named-constant type
2445 1997
2446 when E_In_Out_Parameter => 1998 elsif not Is_Anonymous_Access_Type (Etype (Formal)) then
2447 -- Borrowed in out 1999 Error_Msg_N ("assignment not allowed, Ownership Aspect"
2448 2000 & " False (Named general access type)",
2449 Current_Checking_Mode := Move; 2001 Formal);
2450 2002
2451 end case; 2003 -- Formal IN parameter, access to anonymous constant type
2452 2004
2453 Check_Node (Actual); 2005 else
2454 2006 Current_Checking_Mode := Observe;
2455 when Assign => 2007 Check_Node (Actual);
2456 case Formal_Kind'(Mode) is 2008 end if;
2457 when E_In_Parameter => 2009
2458 null; 2010 -- Formal IN parameter, composite type
2459 2011
2460 when E_Out_Parameter 2012 elsif Is_Deep (Etype (Formal)) then
2461 | E_In_Out_Parameter 2013
2462 => 2014 -- Composite formal types should be named
2463 -- Borrowed out or in out 2015 -- Formal IN parameter, composite named type
2464
2465 Process_Path (Actual);
2466
2467 end case;
2468
2469 when others =>
2470 raise Program_Error;
2471
2472 end case;
2473 Current_Checking_Mode := Mode_Before;
2474 end Check_Param;
2475
2476 --------------------------
2477 -- Check_Param_Observes --
2478 --------------------------
2479
2480 procedure Check_Param_Observes (Formal : Entity_Id; Actual : Node_Id) is
2481 Mode : constant Entity_Kind := Ekind (Formal);
2482 Mode_Before : constant Checking_Mode := Current_Checking_Mode;
2483
2484 begin
2485 case Mode is
2486 when E_In_Parameter =>
2487 if not Is_Borrowed_In (Formal) then
2488 -- Observed in
2489 2016
2490 Current_Checking_Mode := Observe; 2017 Current_Checking_Mode := Observe;
2491 Check_Node (Actual); 2018 Check_Node (Actual);
2492 end if; 2019 end if;
2493
2494 when others =>
2495 null;
2496
2497 end case;
2498
2499 Current_Checking_Mode := Mode_Before;
2500 end Check_Param_Observes;
2501
2502 ----------------------
2503 -- Check_Param_Outs --
2504 ----------------------
2505
2506 procedure Check_Param_Outs (Formal : Entity_Id; Actual : Node_Id) is
2507 Mode : constant Entity_Kind := Ekind (Formal);
2508 Mode_Before : constant Checking_Mode := Current_Checking_Mode;
2509
2510 begin
2511
2512 case Mode is
2513 when E_Out_Parameter =>
2514 -- Borrowed out
2515 Current_Checking_Mode := Borrow_Out;
2516 Check_Node (Actual);
2517
2518 when others =>
2519 null;
2520
2521 end case;
2522
2523 Current_Checking_Mode := Mode_Before;
2524 end Check_Param_Outs;
2525
2526 ----------------------
2527 -- Check_Param_Read --
2528 ----------------------
2529
2530 procedure Check_Param_Read (Formal : Entity_Id; Actual : Node_Id) is
2531 Mode : constant Entity_Kind := Ekind (Formal);
2532
2533 begin
2534 pragma Assert (Current_Checking_Mode = Read);
2535
2536 case Formal_Kind'(Mode) is
2537 when E_In_Parameter =>
2538 Check_Node (Actual);
2539 2020
2540 when E_Out_Parameter 2021 when E_Out_Parameter
2541 | E_In_Out_Parameter 2022 | E_In_Out_Parameter
2542 => 2023 =>
2543 null; 2024 null;
2544
2545 end case; 2025 end case;
2546 end Check_Param_Read; 2026
2027 Current_Checking_Mode := Mode_Before;
2028 end Check_Param_In;
2029
2030 ----------------------
2031 -- Check_Param_Out --
2032 ----------------------
2033
2034 procedure Check_Param_Out (Formal : Entity_Id; Actual : Node_Id) is
2035 Mode : constant Entity_Kind := Ekind (Formal);
2036 Mode_Before : constant Checking_Mode := Current_Checking_Mode;
2037
2038 begin
2039 case Formal_Kind'(Mode) is
2040
2041 -- Formal OUT/IN OUT parameter
2042
2043 when E_Out_Parameter
2044 | E_In_Out_Parameter
2045 =>
2046
2047 -- Formal OUT/IN OUT parameter, access type
2048
2049 if Is_Access_Type (Etype (Formal)) then
2050
2051 -- Formal OUT/IN OUT parameter, access to variable type
2052
2053 if not Is_Access_Constant (Etype (Formal)) then
2054
2055 -- Cannot have anonymous out access parameter
2056 -- Formal out/in out parameter, access to named variable
2057 -- type.
2058
2059 Current_Checking_Mode := Move;
2060 Check_Node (Actual);
2061
2062 -- Formal out/in out parameter, access to constant type
2063
2064 else
2065 Error_Msg_N ("assignment not allowed, Ownership Aspect False"
2066 & " (Named general access type)", Formal);
2067
2068 end if;
2069
2070 -- Formal out/in out parameter, composite type
2071
2072 elsif Is_Deep (Etype (Formal)) then
2073
2074 -- Composite formal types should be named
2075 -- Formal out/in out Parameter, Composite Named type.
2076
2077 Current_Checking_Mode := Borrow;
2078 Check_Node (Actual);
2079 end if;
2080
2081 when E_In_Parameter =>
2082 null;
2083 end case;
2084
2085 Current_Checking_Mode := Mode_Before;
2086 end Check_Param_Out;
2547 2087
2548 ------------------------- 2088 -------------------------
2549 -- Check_Safe_Pointers -- 2089 -- Check_Safe_Pointers --
2550 ------------------------- 2090 -------------------------
2551 2091
2586 end Initialize; 2126 end Initialize;
2587 2127
2588 -- Local variables 2128 -- Local variables
2589 2129
2590 Prag : Node_Id; 2130 Prag : Node_Id;
2131
2591 -- SPARK_Mode pragma in application 2132 -- SPARK_Mode pragma in application
2592 2133
2593 -- Start of processing for Check_Safe_Pointers 2134 -- Start of processing for Check_Safe_Pointers
2594 2135
2595 begin 2136 begin
2596 Initialize; 2137 Initialize;
2597
2598 case Nkind (N) is 2138 case Nkind (N) is
2599 when N_Compilation_Unit => 2139 when N_Compilation_Unit =>
2600 Check_Safe_Pointers (Unit (N)); 2140 Check_Safe_Pointers (Unit (N));
2601 2141
2602 when N_Package_Body 2142 when N_Package_Body
2628 -- Check_Statement -- 2168 -- Check_Statement --
2629 --------------------- 2169 ---------------------
2630 2170
2631 procedure Check_Statement (Stmt : Node_Id) is 2171 procedure Check_Statement (Stmt : Node_Id) is
2632 Mode_Before : constant Checking_Mode := Current_Checking_Mode; 2172 Mode_Before : constant Checking_Mode := Current_Checking_Mode;
2173 State_N : Perm_Kind;
2174 Check : Boolean := True;
2175 St_Name : Node_Id;
2176 Ty_St_Name : Node_Id;
2177
2178 function Get_Root (Comp_Stmt : Node_Id) return Node_Id;
2179 -- Return the root of the name given as input
2180
2181 function Get_Root (Comp_Stmt : Node_Id) return Node_Id is
2182 begin
2183 case Nkind (Comp_Stmt) is
2184 when N_Identifier
2185 | N_Expanded_Name
2186 => return Comp_Stmt;
2187
2188 when N_Type_Conversion
2189 | N_Unchecked_Type_Conversion
2190 | N_Qualified_Expression
2191 =>
2192 return Get_Root (Expression (Comp_Stmt));
2193
2194 when N_Parameter_Specification =>
2195 return Get_Root (Defining_Identifier (Comp_Stmt));
2196
2197 when N_Selected_Component
2198 | N_Indexed_Component
2199 | N_Slice
2200 | N_Explicit_Dereference
2201 =>
2202 return Get_Root (Prefix (Comp_Stmt));
2203
2204 when others =>
2205 raise Program_Error;
2206 end case;
2207 end Get_Root;
2208
2633 begin 2209 begin
2634 case N_Statement_Other_Than_Procedure_Call'(Nkind (Stmt)) is 2210 case N_Statement_Other_Than_Procedure_Call'(Nkind (Stmt)) is
2635 when N_Entry_Call_Statement => 2211 when N_Entry_Call_Statement =>
2636 Check_Call_Statement (Stmt); 2212 Check_Call_Statement (Stmt);
2637 2213
2638 -- Move right-hand side first, and then assign left-hand side 2214 -- Move right-hand side first, and then assign left-hand side
2639 2215
2640 when N_Assignment_Statement => 2216 when N_Assignment_Statement =>
2641 if Is_Deep (Etype (Expression (Stmt))) then 2217
2642 Current_Checking_Mode := Move; 2218 St_Name := Name (Stmt);
2643 else 2219 Ty_St_Name := Etype (Name (Stmt));
2644 Current_Checking_Mode := Read; 2220
2221 -- Check that is not a *general* access type
2222
2223 if Has_Ownership_Aspect_True (St_Name, "assigning to") then
2224
2225 -- Assigning to access type
2226
2227 if Is_Access_Type (Ty_St_Name) then
2228
2229 -- Assigning to access to variable type
2230
2231 if not Is_Access_Constant (Ty_St_Name) then
2232
2233 -- Assigning to named access to variable type
2234
2235 if not Is_Anonymous_Access_Type (Ty_St_Name) then
2236 Current_Checking_Mode := Move;
2237
2238 -- Assigning to anonymous access to variable type
2239
2240 else
2241 -- Target /= source root
2242
2243 if Nkind_In (Expression (Stmt), N_Allocator, N_Null)
2244 or else Entity (St_Name) /=
2245 Entity (Get_Root (Expression (Stmt)))
2246 then
2247 Error_Msg_N ("assignment not allowed, anonymous "
2248 & "access Object with Different Root",
2249 Stmt);
2250 Check := False;
2251
2252 -- Target = source root
2253
2254 else
2255 -- Here we do nothing on the source nor on the
2256 -- target. However, we check the the legality rule:
2257 -- "The source shall be an owning access object
2258 -- denoted by a name that is not in the observed
2259 -- state".
2260
2261 State_N := Get_Perm (Expression (Stmt));
2262 if State_N = Observed then
2263 Error_Msg_N ("assignment not allowed, Anonymous "
2264 & "access object with the same root"
2265 & " but source Observed", Stmt);
2266 Check := False;
2267 end if;
2268 end if;
2269 end if;
2270
2271 -- else access-to-constant
2272
2273 -- Assigning to anonymous access-to-constant type
2274
2275 elsif Is_Anonymous_Access_Type (Ty_St_Name) then
2276
2277 -- ??? Check the follwing condition. We may have to
2278 -- add that the root is in the observed state too.
2279
2280 State_N := Get_Perm (Expression (Stmt));
2281 if State_N /= Observed then
2282 Error_Msg_N ("assignment not allowed, anonymous "
2283 & "access-to-constant object not in "
2284 & "the observed state)", Stmt);
2285 Check := False;
2286
2287 else
2288 Error_Msg_N ("?here check accessibility level cited in"
2289 & " the second legality rule of assign",
2290 Stmt);
2291 Check := False;
2292 end if;
2293
2294 -- Assigning to named access-to-constant type:
2295 -- This case should have been detected when checking
2296 -- Has_Onwership_Aspect_True (Name (Stmt), "msg").
2297
2298 else
2299 raise Program_Error;
2300 end if;
2301
2302 -- Assigning to composite (deep) type.
2303
2304 elsif Is_Deep (Ty_St_Name) then
2305 if Ekind_In (Ty_St_Name,
2306 E_Record_Type,
2307 E_Record_Subtype)
2308 then
2309 declare
2310 Elmt : Entity_Id :=
2311 First_Component_Or_Discriminant (Ty_St_Name);
2312
2313 begin
2314 while Present (Elmt) loop
2315 if Is_Anonymous_Access_Type (Etype (Elmt)) or
2316 Ekind (Elmt) = E_General_Access_Type
2317 then
2318 Error_Msg_N ("assignment not allowed, Ownership "
2319 & "Aspect False (Components have "
2320 & "Ownership Aspect False)", Stmt);
2321 Check := False;
2322 exit;
2323 end if;
2324
2325 Next_Component_Or_Discriminant (Elmt);
2326 end loop;
2327 end;
2328
2329 -- Record types are always named so this is a move
2330
2331 if Check then
2332 Current_Checking_Mode := Move;
2333 end if;
2334
2335 elsif Ekind_In (Ty_St_Name,
2336 E_Array_Type,
2337 E_Array_Subtype)
2338 and then Check
2339 then
2340 Current_Checking_Mode := Move;
2341 end if;
2342
2343 -- Now handle legality rules of using a borrowed, observed,
2344 -- or moved name as a prefix in an assignment.
2345
2346 else
2347 if Nkind_In (St_Name,
2348 N_Attribute_Reference,
2349 N_Expanded_Name,
2350 N_Explicit_Dereference,
2351 N_Indexed_Component,
2352 N_Reference,
2353 N_Selected_Component,
2354 N_Slice)
2355 then
2356
2357 if Is_Access_Type (Etype (Prefix (St_Name))) or
2358 Is_Deep (Etype (Prefix (St_Name)))
2359 then
2360
2361 -- We set the Check variable to True so that we can
2362 -- Check_Node of the expression and the name first
2363 -- under the assumption of Current_Checking_Mode =
2364 -- Read => nothing to be done for the RHS if the
2365 -- following check on the expression fails, and
2366 -- Current_Checking_Mode := Assign => the name should
2367 -- not be borrowed or observed so that we can use it
2368 -- as a prefix in the target of an assignement.
2369 --
2370 -- Note that we do not need to check the OA here
2371 -- because we are allowed to read and write "through"
2372 -- an object of OAF (example: traversing a DS).
2373
2374 Check := True;
2375 end if;
2376 end if;
2377
2378 if Nkind_In (Expression (Stmt),
2379 N_Attribute_Reference,
2380 N_Expanded_Name,
2381 N_Explicit_Dereference,
2382 N_Indexed_Component,
2383 N_Reference,
2384 N_Selected_Component,
2385 N_Slice)
2386 then
2387
2388 if Is_Access_Type (Etype (Prefix (Expression (Stmt))))
2389 or else Is_Deep (Etype (Prefix (Expression (Stmt))))
2390 then
2391 Current_Checking_Mode := Observe;
2392 Check := True;
2393 end if;
2394 end if;
2395 end if;
2396
2397 if Check then
2398 Check_Node (Expression (Stmt));
2399 Current_Checking_Mode := Assign;
2400 Check_Node (St_Name);
2401 end if;
2645 end if; 2402 end if;
2646
2647 Check_Node (Expression (Stmt));
2648 Current_Checking_Mode := Assign;
2649 Check_Node (Name (Stmt));
2650 2403
2651 when N_Block_Statement => 2404 when N_Block_Statement =>
2652 declare 2405 declare
2653 Saved_Env : Perm_Env; 2406 Saved_Env : Perm_Env;
2654
2655 begin 2407 begin
2656 -- Save environment 2408 -- Save environment
2657 2409
2658 Copy_Env (Current_Perm_Env, 2410 Copy_Env (Current_Perm_Env, Saved_Env);
2659 Saved_Env);
2660 2411
2661 -- Analyze declarations and Handled_Statement_Sequences 2412 -- Analyze declarations and Handled_Statement_Sequences
2662 2413
2663 Current_Checking_Mode := Read; 2414 Current_Checking_Mode := Read;
2664 Check_List (Declarations (Stmt)); 2415 Check_List (Declarations (Stmt));
2665 Check_Node (Handled_Statement_Sequence (Stmt)); 2416 Check_Node (Handled_Statement_Sequence (Stmt));
2666 2417
2667 -- Restore environment 2418 -- Restore environment
2668 2419
2669 Free_Env (Current_Perm_Env); 2420 Free_Env (Current_Perm_Env);
2670 Copy_Env (Saved_Env, 2421 Copy_Env (Saved_Env, Current_Perm_Env);
2671 Current_Perm_Env);
2672 end; 2422 end;
2673 2423
2674 when N_Case_Statement => 2424 when N_Case_Statement =>
2675 declare 2425 declare
2676 Saved_Env : Perm_Env; 2426 Saved_Env : Perm_Env;
2677 2427
2678 -- Accumulator for the different branches 2428 -- Accumulator for the different branches
2679 2429
2680 New_Env : Perm_Env; 2430 New_Env : Perm_Env;
2681
2682 Elmt : Node_Id := First (Alternatives (Stmt)); 2431 Elmt : Node_Id := First (Alternatives (Stmt));
2683 2432
2684 begin 2433 begin
2685 Current_Checking_Mode := Read; 2434 Current_Checking_Mode := Read;
2686 Check_Node (Expression (Stmt)); 2435 Check_Node (Expression (Stmt));
2687 Current_Checking_Mode := Mode_Before; 2436 Current_Checking_Mode := Mode_Before;
2688 2437
2689 -- Save environment 2438 -- Save environment
2690 2439
2691 Copy_Env (Current_Perm_Env, 2440 Copy_Env (Current_Perm_Env, Saved_Env);
2692 Saved_Env);
2693 2441
2694 -- Here we have the original env in saved, current with a fresh 2442 -- Here we have the original env in saved, current with a fresh
2695 -- copy, and new aliased. 2443 -- copy, and new aliased.
2696 2444
2697 -- First alternative 2445 -- First alternative
2698 2446
2699 Check_Node (Elmt); 2447 Check_Node (Elmt);
2700 Next (Elmt); 2448 Next (Elmt);
2701 2449 Copy_Env (Current_Perm_Env, New_Env);
2702 Copy_Env (Current_Perm_Env,
2703 New_Env);
2704 Free_Env (Current_Perm_Env); 2450 Free_Env (Current_Perm_Env);
2705 2451
2706 -- Other alternatives 2452 -- Other alternatives
2707 2453
2708 while Present (Elmt) loop 2454 while Present (Elmt) loop
2455
2709 -- Restore environment 2456 -- Restore environment
2710 2457
2711 Copy_Env (Saved_Env, 2458 Copy_Env (Saved_Env, Current_Perm_Env);
2712 Current_Perm_Env);
2713
2714 Check_Node (Elmt); 2459 Check_Node (Elmt);
2715
2716 -- Merge Current_Perm_Env into New_Env
2717
2718 Merge_Envs (New_Env,
2719 Current_Perm_Env);
2720
2721 Next (Elmt); 2460 Next (Elmt);
2722 end loop; 2461 end loop;
2723 2462
2724 -- CLEANUP 2463 Copy_Env (Saved_Env, Current_Perm_Env);
2725 Copy_Env (New_Env,
2726 Current_Perm_Env);
2727
2728 Free_Env (New_Env); 2464 Free_Env (New_Env);
2729 Free_Env (Saved_Env); 2465 Free_Env (Saved_Env);
2730 end; 2466 end;
2731 2467
2732 when N_Delay_Relative_Statement => 2468 when N_Delay_Relative_Statement =>
2736 Check_Node (Expression (Stmt)); 2472 Check_Node (Expression (Stmt));
2737 2473
2738 when N_Loop_Statement => 2474 when N_Loop_Statement =>
2739 Check_Loop_Statement (Stmt); 2475 Check_Loop_Statement (Stmt);
2740 2476
2741 -- If deep type expression, then move, else read 2477 -- If deep type expression, then move, else read
2742 2478
2743 when N_Simple_Return_Statement => 2479 when N_Simple_Return_Statement =>
2744 case Nkind (Expression (Stmt)) is 2480 case Nkind (Expression (Stmt)) is
2745 when N_Empty => 2481 when N_Empty =>
2746 declare 2482 declare
2748 -- a simple return inside an extended return statement 2484 -- a simple return inside an extended return statement
2749 -- applies to the extended return statement. 2485 -- applies to the extended return statement.
2750 Subp : constant Entity_Id := 2486 Subp : constant Entity_Id :=
2751 Return_Applies_To (Return_Statement_Entity (Stmt)); 2487 Return_Applies_To (Return_Statement_Entity (Stmt));
2752 begin 2488 begin
2753 Return_Parameters (Subp);
2754 Return_Globals (Subp); 2489 Return_Globals (Subp);
2755 end; 2490 end;
2756 2491
2757 when others => 2492 when others =>
2758 if Is_Deep (Etype (Expression (Stmt))) then 2493 if Is_Deep (Etype (Expression (Stmt))) then
2759 Current_Checking_Mode := Move; 2494 Current_Checking_Mode := Move;
2760 elsif Is_Shallow (Etype (Expression (Stmt))) then
2761 Current_Checking_Mode := Read;
2762 else 2495 else
2763 raise Program_Error; 2496 Check := False;
2764 end if; 2497 end if;
2765 2498
2766 Check_Node (Expression (Stmt)); 2499 if Check then
2500 Check_Node (Expression (Stmt));
2501 end if;
2767 end case; 2502 end case;
2768 2503
2769 when N_Extended_Return_Statement => 2504 when N_Extended_Return_Statement =>
2770 Check_List (Return_Object_Declarations (Stmt)); 2505 Check_List (Return_Object_Declarations (Stmt));
2771 Check_Node (Handled_Statement_Sequence (Stmt)); 2506 Check_Node (Handled_Statement_Sequence (Stmt));
2772
2773 Return_Declarations (Return_Object_Declarations (Stmt)); 2507 Return_Declarations (Return_Object_Declarations (Stmt));
2774
2775 declare 2508 declare
2776 -- ??? This does not take into account the fact that a simple 2509 -- ??? This does not take into account the fact that a simple
2777 -- return inside an extended return statement applies to the 2510 -- return inside an extended return statement applies to the
2778 -- extended return statement. 2511 -- extended return statement.
2779 Subp : constant Entity_Id := 2512 Subp : constant Entity_Id :=
2780 Return_Applies_To (Return_Statement_Entity (Stmt)); 2513 Return_Applies_To (Return_Statement_Entity (Stmt));
2514
2781 begin 2515 begin
2782 Return_Parameters (Subp);
2783 Return_Globals (Subp); 2516 Return_Globals (Subp);
2784 end; 2517 end;
2785 2518
2786 -- Merge the current_Perm_Env with the accumulator for the given loop 2519 -- Nothing to do when exiting a loop. No merge needed
2787 2520
2788 when N_Exit_Statement => 2521 when N_Exit_Statement =>
2789 declare 2522 null;
2790 Loop_Name : constant Entity_Id := Loop_Of_Exit (Stmt); 2523
2791 2524 -- Copy environment, run on each branch
2792 Saved_Accumulator : constant Perm_Env_Access :=
2793 Get (Current_Loops_Accumulators, Loop_Name);
2794
2795 Environment_Copy : constant Perm_Env_Access :=
2796 new Perm_Env;
2797 begin
2798
2799 Copy_Env (Current_Perm_Env,
2800 Environment_Copy.all);
2801
2802 if Saved_Accumulator = null then
2803 Set (Current_Loops_Accumulators,
2804 Loop_Name, Environment_Copy);
2805 else
2806 Merge_Envs (Saved_Accumulator.all,
2807 Environment_Copy.all);
2808 end if;
2809 end;
2810
2811 -- Copy environment, run on each branch, and then merge
2812 2525
2813 when N_If_Statement => 2526 when N_If_Statement =>
2814 declare 2527 declare
2815 Saved_Env : Perm_Env; 2528 Saved_Env : Perm_Env;
2816 2529
2817 -- Accumulator for the different branches 2530 -- Accumulator for the different branches
2818 2531
2819 New_Env : Perm_Env; 2532 New_Env : Perm_Env;
2820 2533
2821 begin 2534 begin
2822
2823 Check_Node (Condition (Stmt)); 2535 Check_Node (Condition (Stmt));
2824 2536
2825 -- Save environment 2537 -- Save environment
2826 2538
2827 Copy_Env (Current_Perm_Env, 2539 Copy_Env (Current_Perm_Env, Saved_Env);
2828 Saved_Env);
2829 2540
2830 -- Here we have the original env in saved, current with a fresh 2541 -- Here we have the original env in saved, current with a fresh
2831 -- copy. 2542 -- copy.
2832 2543
2833 -- THEN PART 2544 -- THEN PART
2834 2545
2835 Check_List (Then_Statements (Stmt)); 2546 Check_List (Then_Statements (Stmt));
2836 2547 Copy_Env (Current_Perm_Env, New_Env);
2837 Copy_Env (Current_Perm_Env,
2838 New_Env);
2839
2840 Free_Env (Current_Perm_Env); 2548 Free_Env (Current_Perm_Env);
2841 2549
2842 -- Here the new_environment contains curr env after then block 2550 -- Here the new_environment contains curr env after then block
2843 2551
2844 -- ELSIF part 2552 -- ELSIF part
2553
2845 declare 2554 declare
2846 Elmt : Node_Id; 2555 Elmt : Node_Id;
2847 2556
2848 begin 2557 begin
2849 Elmt := First (Elsif_Parts (Stmt)); 2558 Elmt := First (Elsif_Parts (Stmt));
2850 while Present (Elmt) loop 2559 while Present (Elmt) loop
2560
2851 -- Transfer into accumulator, and restore from save 2561 -- Transfer into accumulator, and restore from save
2852 2562
2853 Copy_Env (Saved_Env, 2563 Copy_Env (Saved_Env, Current_Perm_Env);
2854 Current_Perm_Env);
2855
2856 Check_Node (Condition (Elmt)); 2564 Check_Node (Condition (Elmt));
2857 Check_List (Then_Statements (Stmt)); 2565 Check_List (Then_Statements (Stmt));
2858
2859 -- Merge Current_Perm_Env into New_Env
2860
2861 Merge_Envs (New_Env,
2862 Current_Perm_Env);
2863
2864 Next (Elmt); 2566 Next (Elmt);
2865 end loop; 2567 end loop;
2866 end; 2568 end;
2867 2569
2868 -- ELSE part 2570 -- ELSE part
2869 2571
2870 -- Restore environment before if 2572 -- Restore environment before if
2871 2573
2872 Copy_Env (Saved_Env, 2574 Copy_Env (Saved_Env, Current_Perm_Env);
2873 Current_Perm_Env);
2874 2575
2875 -- Here new environment contains the environment after then and 2576 -- Here new environment contains the environment after then and
2876 -- current the fresh copy of old one. 2577 -- current the fresh copy of old one.
2877 2578
2878 Check_List (Else_Statements (Stmt)); 2579 Check_List (Else_Statements (Stmt));
2879 2580
2880 Merge_Envs (New_Env,
2881 Current_Perm_Env);
2882
2883 -- CLEANUP 2581 -- CLEANUP
2884 2582
2885 Copy_Env (New_Env, 2583 Copy_Env (Saved_Env, Current_Perm_Env);
2886 Current_Perm_Env);
2887 2584
2888 Free_Env (New_Env); 2585 Free_Env (New_Env);
2889 Free_Env (Saved_Env); 2586 Free_Env (Saved_Env);
2890 end; 2587 end;
2891 2588
2937 2634
2938 -- We encoutered a function call, hence the memory area is fresh, 2635 -- We encoutered a function call, hence the memory area is fresh,
2939 -- which means that the association permission is RW. 2636 -- which means that the association permission is RW.
2940 2637
2941 when Function_Call => 2638 when Function_Call =>
2942 return Read_Write; 2639 return Unrestricted;
2943
2944 end case; 2640 end case;
2945 end Get_Perm; 2641 end Get_Perm;
2946 2642
2947 ---------------------- 2643 ----------------------
2948 -- Get_Perm_Or_Tree -- 2644 -- Get_Perm_Or_Tree --
2961 when N_Identifier 2657 when N_Identifier
2962 | N_Expanded_Name 2658 | N_Expanded_Name
2963 => 2659 =>
2964 declare 2660 declare
2965 P : constant Entity_Id := Entity (N); 2661 P : constant Entity_Id := Entity (N);
2966
2967 C : constant Perm_Tree_Access := 2662 C : constant Perm_Tree_Access :=
2968 Get (Current_Perm_Env, Unique_Entity (P)); 2663 Get (Current_Perm_Env, Unique_Entity (P));
2969 2664
2970 begin 2665 begin
2971 -- Setting the initialization map to True, so that this 2666 -- Setting the initialization map to True, so that this
2972 -- variable cannot be ignored anymore when looking at end 2667 -- variable cannot be ignored anymore when looking at end
2973 -- of elaboration of package. 2668 -- of elaboration of package.
2974 2669
2975 Set (Current_Initialization_Map, Unique_Entity (P), True); 2670 Set (Current_Initialization_Map, Unique_Entity (P), True);
2976
2977 if C = null then 2671 if C = null then
2978 -- No null possible here, there are no parents for the path. 2672 -- No null possible here, there are no parents for the path.
2979 -- This means we are using a global variable without adding 2673 -- This means we are using a global variable without adding
2980 -- it in environment with a global aspect. 2674 -- it in environment with a global aspect.
2981 2675
2982 Illegal_Global_Usage (N); 2676 Illegal_Global_Usage (N);
2677
2983 else 2678 else
2984 return (R => Unfolded, Tree_Access => C); 2679 return (R => Unfolded, Tree_Access => C);
2985 end if; 2680 end if;
2986 end; 2681 end;
2987 2682
3004 -- leaf that folds its children, we take the children's permission 2699 -- leaf that folds its children, we take the children's permission
3005 -- and return it using the discriminant Folded. 2700 -- and return it using the discriminant Folded.
3006 2701
3007 when N_Selected_Component => 2702 when N_Selected_Component =>
3008 declare 2703 declare
3009 C : constant Perm_Or_Tree := 2704 C : constant Perm_Or_Tree := Get_Perm_Or_Tree (Prefix (N));
3010 Get_Perm_Or_Tree (Prefix (N));
3011 2705
3012 begin 2706 begin
3013 case C.R is 2707 case C.R is
3014 when Folded 2708 when Folded
3015 | Function_Call 2709 | Function_Call
3016 => 2710 =>
3017 return C; 2711 return C;
3018 2712
3019 when Unfolded => 2713 when Unfolded =>
3020 pragma Assert (C.Tree_Access /= null); 2714 pragma Assert (C.Tree_Access /= null);
3021
3022 pragma Assert (Kind (C.Tree_Access) = Entire_Object 2715 pragma Assert (Kind (C.Tree_Access) = Entire_Object
3023 or else 2716 or else
3024 Kind (C.Tree_Access) = Record_Component); 2717 Kind (C.Tree_Access) = Record_Component);
3025 2718
3026 if Kind (C.Tree_Access) = Record_Component then 2719 if Kind (C.Tree_Access) = Record_Component then
3027 declare 2720 declare
3028 Selected_Component : constant Entity_Id := 2721 Selected_Component : constant Entity_Id :=
3029 Entity (Selector_Name (N)); 2722 Entity (Selector_Name (N));
3030
3031 Selected_C : constant Perm_Tree_Access := 2723 Selected_C : constant Perm_Tree_Access :=
3032 Perm_Tree_Maps.Get 2724 Perm_Tree_Maps.Get
3033 (Component (C.Tree_Access), Selected_Component); 2725 (Component (C.Tree_Access), Selected_Component);
3034 2726
3035 begin 2727 begin
3036 if Selected_C = null then 2728 if Selected_C = null then
3037 return (R => Unfolded, 2729 return (R => Unfolded,
3038 Tree_Access => 2730 Tree_Access =>
3039 Other_Components (C.Tree_Access)); 2731 Other_Components (C.Tree_Access));
2732
3040 else 2733 else
3041 return (R => Unfolded, 2734 return (R => Unfolded,
3042 Tree_Access => Selected_C); 2735 Tree_Access => Selected_C);
3043 end if; 2736 end if;
3044 end; 2737 end;
2738
3045 elsif Kind (C.Tree_Access) = Entire_Object then 2739 elsif Kind (C.Tree_Access) = Entire_Object then
3046 return (R => Folded, Found_Permission => 2740 return (R => Folded,
2741 Found_Permission =>
3047 Children_Permission (C.Tree_Access)); 2742 Children_Permission (C.Tree_Access));
2743
3048 else 2744 else
3049 raise Program_Error; 2745 raise Program_Error;
3050 end if; 2746 end if;
3051 end case; 2747 end case;
3052 end; 2748 end;
3053
3054 -- We get the permission tree of its prefix, and then get either the 2749 -- We get the permission tree of its prefix, and then get either the
3055 -- subtree associated with that specific selection, or if we have a 2750 -- subtree associated with that specific selection, or if we have a
3056 -- leaf that folds its children, we take the children's permission 2751 -- leaf that folds its children, we take the children's permission
3057 -- and return it using the discriminant Folded. 2752 -- and return it using the discriminant Folded.
3058 2753
3059 when N_Indexed_Component 2754 when N_Indexed_Component
3060 | N_Slice 2755 | N_Slice
3061 => 2756 =>
3062 declare 2757 declare
3063 C : constant Perm_Or_Tree := 2758 C : constant Perm_Or_Tree := Get_Perm_Or_Tree (Prefix (N));
3064 Get_Perm_Or_Tree (Prefix (N));
3065 2759
3066 begin 2760 begin
3067 case C.R is 2761 case C.R is
3068 when Folded 2762 when Folded
3069 | Function_Call 2763 | Function_Call
3070 => 2764 =>
3071 return C; 2765 return C;
3072 2766
3073 when Unfolded => 2767 when Unfolded =>
3074 pragma Assert (C.Tree_Access /= null); 2768 pragma Assert (C.Tree_Access /= null);
3075
3076 pragma Assert (Kind (C.Tree_Access) = Entire_Object 2769 pragma Assert (Kind (C.Tree_Access) = Entire_Object
3077 or else 2770 or else
3078 Kind (C.Tree_Access) = Array_Component); 2771 Kind (C.Tree_Access) = Array_Component);
3079 2772
3080 if Kind (C.Tree_Access) = Array_Component then 2773 if Kind (C.Tree_Access) = Array_Component then
3081 pragma Assert (Get_Elem (C.Tree_Access) /= null); 2774 pragma Assert (Get_Elem (C.Tree_Access) /= null);
3082
3083 return (R => Unfolded, 2775 return (R => Unfolded,
3084 Tree_Access => Get_Elem (C.Tree_Access)); 2776 Tree_Access => Get_Elem (C.Tree_Access));
2777
3085 elsif Kind (C.Tree_Access) = Entire_Object then 2778 elsif Kind (C.Tree_Access) = Entire_Object then
3086 return (R => Folded, Found_Permission => 2779 return (R => Folded, Found_Permission =>
3087 Children_Permission (C.Tree_Access)); 2780 Children_Permission (C.Tree_Access));
2781
3088 else 2782 else
3089 raise Program_Error; 2783 raise Program_Error;
3090 end if; 2784 end if;
3091 end case; 2785 end case;
3092 end; 2786 end;
3093
3094 -- We get the permission tree of its prefix, and then get either the 2787 -- We get the permission tree of its prefix, and then get either the
3095 -- subtree associated with that specific selection, or if we have a 2788 -- subtree associated with that specific selection, or if we have a
3096 -- leaf that folds its children, we take the children's permission 2789 -- leaf that folds its children, we take the children's permission
3097 -- and return it using the discriminant Folded. 2790 -- and return it using the discriminant Folded.
3098 2791
3099 when N_Explicit_Dereference => 2792 when N_Explicit_Dereference =>
3100 declare 2793 declare
3101 C : constant Perm_Or_Tree := 2794 C : constant Perm_Or_Tree := Get_Perm_Or_Tree (Prefix (N));
3102 Get_Perm_Or_Tree (Prefix (N));
3103 2795
3104 begin 2796 begin
3105 case C.R is 2797 case C.R is
3106 when Folded 2798 when Folded
3107 | Function_Call 2799 | Function_Call
3108 => 2800 =>
3109 return C; 2801 return C;
3110 2802
3111 when Unfolded => 2803 when Unfolded =>
3112 pragma Assert (C.Tree_Access /= null); 2804 pragma Assert (C.Tree_Access /= null);
3113
3114 pragma Assert (Kind (C.Tree_Access) = Entire_Object 2805 pragma Assert (Kind (C.Tree_Access) = Entire_Object
3115 or else 2806 or else
3116 Kind (C.Tree_Access) = Reference); 2807 Kind (C.Tree_Access) = Reference);
3117 2808
3118 if Kind (C.Tree_Access) = Reference then 2809 if Kind (C.Tree_Access) = Reference then
3119 if Get_All (C.Tree_Access) = null then 2810 if Get_All (C.Tree_Access) = null then
2811
3120 -- Hash_Table_Error 2812 -- Hash_Table_Error
2813
3121 raise Program_Error; 2814 raise Program_Error;
2815
3122 else 2816 else
3123 return 2817 return
3124 (R => Unfolded, 2818 (R => Unfolded,
3125 Tree_Access => Get_All (C.Tree_Access)); 2819 Tree_Access => Get_All (C.Tree_Access));
3126 end if; 2820 end if;
2821
3127 elsif Kind (C.Tree_Access) = Entire_Object then 2822 elsif Kind (C.Tree_Access) = Entire_Object then
3128 return (R => Folded, Found_Permission => 2823 return (R => Folded, Found_Permission =>
3129 Children_Permission (C.Tree_Access)); 2824 Children_Permission (C.Tree_Access));
2825
3130 else 2826 else
3131 raise Program_Error; 2827 raise Program_Error;
3132 end if; 2828 end if;
3133 end case; 2829 end case;
3134 end; 2830 end;
3135
3136 -- The name contains a function call, hence the given path is always 2831 -- The name contains a function call, hence the given path is always
3137 -- new. We do not have to check for anything. 2832 -- new. We do not have to check for anything.
3138 2833
3139 when N_Function_Call => 2834 when N_Function_Call =>
3140 return (R => Function_Call); 2835 return (R => Function_Call);
3146 2841
3147 ------------------- 2842 -------------------
3148 -- Get_Perm_Tree -- 2843 -- Get_Perm_Tree --
3149 ------------------- 2844 -------------------
3150 2845
3151 function Get_Perm_Tree 2846 function Get_Perm_Tree (N : Node_Id) return Perm_Tree_Access is
3152 (N : Node_Id)
3153 return Perm_Tree_Access
3154 is
3155 begin 2847 begin
3156 case Nkind (N) is 2848 case Nkind (N) is
3157 2849
3158 -- Base identifier. Normally those are the roots of the trees stored 2850 -- Base identifier. Normally those are the roots of the trees stored
3159 -- in the permission environment. 2851 -- in the permission environment.
3164 when N_Identifier 2856 when N_Identifier
3165 | N_Expanded_Name 2857 | N_Expanded_Name
3166 => 2858 =>
3167 declare 2859 declare
3168 P : constant Node_Id := Entity (N); 2860 P : constant Node_Id := Entity (N);
3169
3170 C : constant Perm_Tree_Access := 2861 C : constant Perm_Tree_Access :=
3171 Get (Current_Perm_Env, Unique_Entity (P)); 2862 Get (Current_Perm_Env, Unique_Entity (P));
3172 2863
3173 begin 2864 begin
3174 -- Setting the initialization map to True, so that this 2865 -- Setting the initialization map to True, so that this
3175 -- variable cannot be ignored anymore when looking at end 2866 -- variable cannot be ignored anymore when looking at end
3176 -- of elaboration of package. 2867 -- of elaboration of package.
3177 2868
3178 Set (Current_Initialization_Map, Unique_Entity (P), True); 2869 Set (Current_Initialization_Map, Unique_Entity (P), True);
3179
3180 if C = null then 2870 if C = null then
3181 -- No null possible here, there are no parents for the path. 2871 -- No null possible here, there are no parents for the path.
3182 -- This means we are using a global variable without adding 2872 -- This means we are using a global variable without adding
3183 -- it in environment with a global aspect. 2873 -- it in environment with a global aspect.
3184 2874
3185 Illegal_Global_Usage (N); 2875 Illegal_Global_Usage (N);
2876
3186 else 2877 else
3187 return C; 2878 return C;
3188 end if; 2879 end if;
3189 end; 2880 end;
3190 2881
3201 -- subtree associated with that specific selection, or if we have a 2892 -- subtree associated with that specific selection, or if we have a
3202 -- leaf that folds its children, we unroll it in one step. 2893 -- leaf that folds its children, we unroll it in one step.
3203 2894
3204 when N_Selected_Component => 2895 when N_Selected_Component =>
3205 declare 2896 declare
3206 C : constant Perm_Tree_Access := 2897 C : constant Perm_Tree_Access := Get_Perm_Tree (Prefix (N));
3207 Get_Perm_Tree (Prefix (N));
3208 2898
3209 begin 2899 begin
3210 if C = null then 2900 if C = null then
2901
3211 -- If null then it means we went through a function call 2902 -- If null then it means we went through a function call
3212 2903
3213 return null; 2904 return null;
3214 end if; 2905 end if;
3215 2906
3216 pragma Assert (Kind (C) = Entire_Object 2907 pragma Assert (Kind (C) = Entire_Object
3217 or else Kind (C) = Record_Component); 2908 or else Kind (C) = Record_Component);
3218 2909
3219 if Kind (C) = Record_Component then 2910 if Kind (C) = Record_Component then
2911
3220 -- The tree is unfolded. We just return the subtree. 2912 -- The tree is unfolded. We just return the subtree.
3221 2913
3222 declare 2914 declare
3223 Selected_Component : constant Entity_Id := 2915 Selected_Component : constant Entity_Id :=
3224 Entity (Selector_Name (N)); 2916 Entity (Selector_Name (N));
3228 2920
3229 begin 2921 begin
3230 if Selected_C = null then 2922 if Selected_C = null then
3231 return Other_Components (C); 2923 return Other_Components (C);
3232 end if; 2924 end if;
3233
3234 return Selected_C; 2925 return Selected_C;
3235 end; 2926 end;
2927
3236 elsif Kind (C) = Entire_Object then 2928 elsif Kind (C) = Entire_Object then
3237 declare 2929 declare
3238 -- Expand the tree. Replace the node with 2930 -- Expand the tree. Replace the node with
3239 -- Record_Component. 2931 -- Record_Component.
3240 2932
3246 2938
3247 Child_Perm : constant Perm_Kind := 2939 Child_Perm : constant Perm_Kind :=
3248 Children_Permission (C); 2940 Children_Permission (C);
3249 2941
3250 begin 2942 begin
3251
3252 -- We change the current node from Entire_Object to 2943 -- We change the current node from Entire_Object to
3253 -- Record_Component with same permission and an empty 2944 -- Record_Component with same permission and an empty
3254 -- hash table as component list. 2945 -- hash table as component list.
3255 2946
3256 C.all.Tree := 2947 C.all.Tree :=
3269 ) 2960 )
3270 ); 2961 );
3271 2962
3272 -- We fill the hash table with all sons of the record, 2963 -- We fill the hash table with all sons of the record,
3273 -- with basic Entire_Objects nodes. 2964 -- with basic Entire_Objects nodes.
2965
3274 Elem := First_Component_Or_Discriminant 2966 Elem := First_Component_Or_Discriminant
3275 (Etype (Prefix (N))); 2967 (Etype (Prefix (N)));
3276 2968
3277 while Present (Elem) loop 2969 while Present (Elem) loop
3278 Son := new Perm_Tree_Wrapper' 2970 Son := new Perm_Tree_Wrapper'
3282 Permission => Child_Perm, 2974 Permission => Child_Perm,
3283 Children_Permission => Child_Perm)); 2975 Children_Permission => Child_Perm));
3284 2976
3285 Perm_Tree_Maps.Set 2977 Perm_Tree_Maps.Set
3286 (C.all.Tree.Component, Elem, Son); 2978 (C.all.Tree.Component, Elem, Son);
3287
3288 Next_Component_Or_Discriminant (Elem); 2979 Next_Component_Or_Discriminant (Elem);
3289 end loop; 2980 end loop;
3290
3291 -- we return the tree to the sons, so that the recursion 2981 -- we return the tree to the sons, so that the recursion
3292 -- can continue. 2982 -- can continue.
3293 2983
3294 declare 2984 declare
3295 Selected_Component : constant Entity_Id := 2985 Selected_Component : constant Entity_Id :=
3299 Perm_Tree_Maps.Get 2989 Perm_Tree_Maps.Get
3300 (Component (C), Selected_Component); 2990 (Component (C), Selected_Component);
3301 2991
3302 begin 2992 begin
3303 pragma Assert (Selected_C /= null); 2993 pragma Assert (Selected_C /= null);
3304
3305 return Selected_C; 2994 return Selected_C;
3306 end; 2995 end;
3307
3308 end; 2996 end;
3309 else 2997 else
3310 raise Program_Error; 2998 raise Program_Error;
3311 end if; 2999 end if;
3312 end; 3000 end;
3313
3314 -- We set the permission tree of its prefix, and then we extract from 3001 -- We set the permission tree of its prefix, and then we extract from
3315 -- the returned pointer the subtree. If folded, we unroll the tree at 3002 -- the returned pointer the subtree. If folded, we unroll the tree at
3316 -- one step. 3003 -- one step.
3317 3004
3318 when N_Indexed_Component 3005 when N_Indexed_Component
3319 | N_Slice 3006 | N_Slice
3320 => 3007 =>
3321 declare 3008 declare
3322 C : constant Perm_Tree_Access := 3009 C : constant Perm_Tree_Access := Get_Perm_Tree (Prefix (N));
3323 Get_Perm_Tree (Prefix (N));
3324 3010
3325 begin 3011 begin
3326 if C = null then 3012 if C = null then
3327 -- If null then we went through a function call 3013 -- If null then we went through a function call
3328 3014
3329 return null; 3015 return null;
3330 end if; 3016 end if;
3331
3332 pragma Assert (Kind (C) = Entire_Object 3017 pragma Assert (Kind (C) = Entire_Object
3333 or else Kind (C) = Array_Component); 3018 or else Kind (C) = Array_Component);
3334 3019
3335 if Kind (C) = Array_Component then 3020 if Kind (C) = Array_Component then
3021
3336 -- The tree is unfolded. We just return the elem subtree 3022 -- The tree is unfolded. We just return the elem subtree
3337 3023
3338 pragma Assert (Get_Elem (C) = null); 3024 pragma Assert (Get_Elem (C) = null);
3339
3340 return Get_Elem (C); 3025 return Get_Elem (C);
3026
3341 elsif Kind (C) = Entire_Object then 3027 elsif Kind (C) = Entire_Object then
3342 declare 3028 declare
3343 -- Expand the tree. Replace node with Array_Component. 3029 -- Expand the tree. Replace node with Array_Component.
3344 3030
3345 Son : Perm_Tree_Access; 3031 Son : Perm_Tree_Access;
3358 3044
3359 C.all.Tree := (Kind => Array_Component, 3045 C.all.Tree := (Kind => Array_Component,
3360 Is_Node_Deep => Is_Node_Deep (C), 3046 Is_Node_Deep => Is_Node_Deep (C),
3361 Permission => Permission (C), 3047 Permission => Permission (C),
3362 Get_Elem => Son); 3048 Get_Elem => Son);
3363
3364 return Get_Elem (C); 3049 return Get_Elem (C);
3365 end; 3050 end;
3366 else 3051 else
3367 raise Program_Error; 3052 raise Program_Error;
3368 end if; 3053 end if;
3369 end; 3054 end;
3370
3371 -- We get the permission tree of its prefix, and then get either the 3055 -- We get the permission tree of its prefix, and then get either the
3372 -- subtree associated with that specific selection, or if we have a 3056 -- subtree associated with that specific selection, or if we have a
3373 -- leaf that folds its children, we unroll the tree. 3057 -- leaf that folds its children, we unroll the tree.
3374 3058
3375 when N_Explicit_Dereference => 3059 when N_Explicit_Dereference =>
3378 3062
3379 begin 3063 begin
3380 C := Get_Perm_Tree (Prefix (N)); 3064 C := Get_Perm_Tree (Prefix (N));
3381 3065
3382 if C = null then 3066 if C = null then
3067
3383 -- If null, we went through a function call 3068 -- If null, we went through a function call
3384 3069
3385 return null; 3070 return null;
3386 end if; 3071 end if;
3387 3072
3388 pragma Assert (Kind (C) = Entire_Object 3073 pragma Assert (Kind (C) = Entire_Object
3389 or else Kind (C) = Reference); 3074 or else Kind (C) = Reference);
3390 3075
3391 if Kind (C) = Reference then 3076 if Kind (C) = Reference then
3077
3392 -- The tree is unfolded. We return the elem subtree 3078 -- The tree is unfolded. We return the elem subtree
3393 3079
3394 if Get_All (C) = null then 3080 if Get_All (C) = null then
3081
3395 -- Hash_Table_Error 3082 -- Hash_Table_Error
3083
3396 raise Program_Error; 3084 raise Program_Error;
3397 end if; 3085 end if;
3398
3399 return Get_All (C); 3086 return Get_All (C);
3087
3400 elsif Kind (C) = Entire_Object then 3088 elsif Kind (C) = Entire_Object then
3401 declare 3089 declare
3402 -- Expand the tree. Replace the node with Reference. 3090 -- Expand the tree. Replace the node with Reference.
3403 3091
3404 Son : Perm_Tree_Access; 3092 Son : Perm_Tree_Access;
3413 3101
3414 -- We change the current node from Entire_Object to 3102 -- We change the current node from Entire_Object to
3415 -- Reference with same permission and the previous son. 3103 -- Reference with same permission and the previous son.
3416 3104
3417 pragma Assert (Is_Node_Deep (C)); 3105 pragma Assert (Is_Node_Deep (C));
3418
3419 C.all.Tree := (Kind => Reference, 3106 C.all.Tree := (Kind => Reference,
3420 Is_Node_Deep => Is_Node_Deep (C), 3107 Is_Node_Deep => Is_Node_Deep (C),
3421 Permission => Permission (C), 3108 Permission => Permission (C),
3422 Get_All => Son); 3109 Get_All => Son);
3423
3424 return Get_All (C); 3110 return Get_All (C);
3425 end; 3111 end;
3426 else 3112 else
3427 raise Program_Error; 3113 raise Program_Error;
3428 end if; 3114 end if;
3429 end; 3115 end;
3430
3431 -- No permission tree for function calls 3116 -- No permission tree for function calls
3432 3117
3433 when N_Function_Call => 3118 when N_Function_Call =>
3434 return null; 3119 return null;
3435 3120
3436 when others => 3121 when others =>
3437 raise Program_Error; 3122 raise Program_Error;
3438 end case; 3123 end case;
3439 end Get_Perm_Tree; 3124 end Get_Perm_Tree;
3440
3441 ---------
3442 -- Glb --
3443 ---------
3444
3445 function Glb (P1, P2 : Perm_Kind) return Perm_Kind
3446 is
3447 begin
3448 case P1 is
3449 when No_Access =>
3450 return No_Access;
3451
3452 when Read_Only =>
3453 case P2 is
3454 when No_Access
3455 | Write_Only
3456 =>
3457 return No_Access;
3458
3459 when Read_Perm =>
3460 return Read_Only;
3461 end case;
3462
3463 when Write_Only =>
3464 case P2 is
3465 when No_Access
3466 | Read_Only
3467 =>
3468 return No_Access;
3469
3470 when Write_Perm =>
3471 return Write_Only;
3472 end case;
3473
3474 when Read_Write =>
3475 return P2;
3476 end case;
3477 end Glb;
3478
3479 ---------------
3480 -- Has_Alias --
3481 ---------------
3482
3483 function Has_Alias
3484 (N : Node_Id)
3485 return Boolean
3486 is
3487 function Has_Alias_Deep (Typ : Entity_Id) return Boolean;
3488 function Has_Alias_Deep (Typ : Entity_Id) return Boolean
3489 is
3490 Comp : Node_Id;
3491 begin
3492
3493 if Is_Array_Type (Typ)
3494 and then Has_Aliased_Components (Typ)
3495 then
3496 return True;
3497
3498 -- Note: Has_Aliased_Components applies only to arrays
3499
3500 elsif Is_Record_Type (Typ) then
3501 -- It is possible to have an aliased discriminant, so they must be
3502 -- checked along with normal components.
3503
3504 Comp := First_Component_Or_Discriminant (Typ);
3505 while Present (Comp) loop
3506 if Is_Aliased (Comp)
3507 or else Is_Aliased (Etype (Comp))
3508 then
3509 return True;
3510 end if;
3511
3512 if Has_Alias_Deep (Etype (Comp)) then
3513 return True;
3514 end if;
3515
3516 Next_Component_Or_Discriminant (Comp);
3517 end loop;
3518 return False;
3519 else
3520 return Is_Aliased (Typ);
3521 end if;
3522 end Has_Alias_Deep;
3523
3524 begin
3525 case Nkind (N) is
3526
3527 when N_Identifier
3528 | N_Expanded_Name
3529 =>
3530 return Has_Alias_Deep (Etype (N));
3531
3532 when N_Defining_Identifier =>
3533 return Has_Alias_Deep (Etype (N));
3534
3535 when N_Type_Conversion
3536 | N_Unchecked_Type_Conversion
3537 | N_Qualified_Expression
3538 =>
3539 return Has_Alias (Expression (N));
3540
3541 when N_Parameter_Specification =>
3542 return Has_Alias (Defining_Identifier (N));
3543
3544 when N_Selected_Component =>
3545 case Nkind (Selector_Name (N)) is
3546 when N_Identifier =>
3547 if Is_Aliased (Entity (Selector_Name (N))) then
3548 return True;
3549 end if;
3550
3551 when others => null;
3552
3553 end case;
3554
3555 return Has_Alias (Prefix (N));
3556
3557 when N_Indexed_Component
3558 | N_Slice
3559 =>
3560 return Has_Alias (Prefix (N));
3561
3562 when N_Explicit_Dereference =>
3563 return True;
3564
3565 when N_Function_Call =>
3566 return False;
3567
3568 when N_Attribute_Reference =>
3569 if Is_Deep (Etype (Prefix (N))) then
3570 raise Program_Error;
3571 end if;
3572 return False;
3573
3574 when others =>
3575 return False;
3576 end case;
3577 end Has_Alias;
3578
3579 -------------------------
3580 -- Has_Array_Component --
3581 -------------------------
3582
3583 function Has_Array_Component (N : Node_Id) return Boolean is
3584 begin
3585 case Nkind (N) is
3586 -- Base identifier. There is no array component here.
3587
3588 when N_Identifier
3589 | N_Expanded_Name
3590 | N_Defining_Identifier
3591 =>
3592 return False;
3593
3594 -- We check if the expression inside the conversion has an array
3595 -- component.
3596
3597 when N_Type_Conversion
3598 | N_Unchecked_Type_Conversion
3599 | N_Qualified_Expression
3600 =>
3601 return Has_Array_Component (Expression (N));
3602
3603 -- We check if the prefix has an array component
3604
3605 when N_Selected_Component =>
3606 return Has_Array_Component (Prefix (N));
3607
3608 -- We found the array component, return True
3609
3610 when N_Indexed_Component
3611 | N_Slice
3612 =>
3613 return True;
3614
3615 -- We check if the prefix has an array component
3616
3617 when N_Explicit_Dereference =>
3618 return Has_Array_Component (Prefix (N));
3619
3620 when N_Function_Call =>
3621 return False;
3622
3623 when others =>
3624 raise Program_Error;
3625 end case;
3626 end Has_Array_Component;
3627
3628 ----------------------------
3629 -- Has_Function_Component --
3630 ----------------------------
3631
3632 function Has_Function_Component (N : Node_Id) return Boolean is
3633 begin
3634 case Nkind (N) is
3635 -- Base identifier. There is no function component here.
3636
3637 when N_Identifier
3638 | N_Expanded_Name
3639 | N_Defining_Identifier
3640 =>
3641 return False;
3642
3643 -- We check if the expression inside the conversion has a function
3644 -- component.
3645
3646 when N_Type_Conversion
3647 | N_Unchecked_Type_Conversion
3648 | N_Qualified_Expression
3649 =>
3650 return Has_Function_Component (Expression (N));
3651
3652 -- We check if the prefix has a function component
3653
3654 when N_Selected_Component =>
3655 return Has_Function_Component (Prefix (N));
3656
3657 -- We check if the prefix has a function component
3658
3659 when N_Indexed_Component
3660 | N_Slice
3661 =>
3662 return Has_Function_Component (Prefix (N));
3663
3664 -- We check if the prefix has a function component
3665
3666 when N_Explicit_Dereference =>
3667 return Has_Function_Component (Prefix (N));
3668
3669 -- We found the function component, return True
3670
3671 when N_Function_Call =>
3672 return True;
3673
3674 when others =>
3675 raise Program_Error;
3676
3677 end case;
3678 end Has_Function_Component;
3679 3125
3680 -------- 3126 --------
3681 -- Hp -- 3127 -- Hp --
3682 -------- 3128 --------
3683 3129
3698 3144
3699 procedure Illegal_Global_Usage (N : Node_Or_Entity_Id) is 3145 procedure Illegal_Global_Usage (N : Node_Or_Entity_Id) is
3700 begin 3146 begin
3701 Error_Msg_NE ("cannot use global variable & of deep type", N, N); 3147 Error_Msg_NE ("cannot use global variable & of deep type", N, N);
3702 Error_Msg_N ("\without prior declaration in a Global aspect", N); 3148 Error_Msg_N ("\without prior declaration in a Global aspect", N);
3703
3704 Errout.Finalize (Last_Call => True); 3149 Errout.Finalize (Last_Call => True);
3705 Errout.Output_Messages; 3150 Errout.Output_Messages;
3706 Exit_Program (E_Errors); 3151 Exit_Program (E_Errors);
3707 end Illegal_Global_Usage; 3152 end Illegal_Global_Usage;
3708 3153
3709 --------------------
3710 -- Is_Borrowed_In --
3711 --------------------
3712
3713 function Is_Borrowed_In (E : Entity_Id) return Boolean is
3714 begin
3715 return Is_Access_Type (Etype (E))
3716 and then not Is_Access_Constant (Etype (E));
3717 end Is_Borrowed_In;
3718
3719 ------------- 3154 -------------
3720 -- Is_Deep -- 3155 -- Is_Deep --
3721 ------------- 3156 -------------
3722 3157
3723 function Is_Deep (E : Entity_Id) return Boolean is 3158 function Is_Deep (E : Entity_Id) return Boolean is
3724 function Is_Private_Entity_Mode_Off (E : Entity_Id) return Boolean; 3159 function Is_Private_Entity_Mode_Off (E : Entity_Id) return Boolean;
3725
3726 function Is_Private_Entity_Mode_Off (E : Entity_Id) return Boolean is 3160 function Is_Private_Entity_Mode_Off (E : Entity_Id) return Boolean is
3727 Decl : Node_Id; 3161 Decl : Node_Id;
3728 Pack_Decl : Node_Id; 3162 Pack_Decl : Node_Id;
3729 3163
3730 begin 3164 begin
3743 return 3177 return
3744 Present (SPARK_Aux_Pragma (Defining_Entity (Pack_Decl))) 3178 Present (SPARK_Aux_Pragma (Defining_Entity (Pack_Decl)))
3745 and then Get_SPARK_Mode_From_Annotation 3179 and then Get_SPARK_Mode_From_Annotation
3746 (SPARK_Aux_Pragma (Defining_Entity (Pack_Decl))) = Off; 3180 (SPARK_Aux_Pragma (Defining_Entity (Pack_Decl))) = Off;
3747 end Is_Private_Entity_Mode_Off; 3181 end Is_Private_Entity_Mode_Off;
3182
3748 begin 3183 begin
3749 pragma Assert (Is_Type (E)); 3184 pragma Assert (Is_Type (E));
3750
3751 case Ekind (E) is 3185 case Ekind (E) is
3752 when Scalar_Kind => 3186 when Scalar_Kind =>
3753 return False; 3187 return False;
3754 3188
3755 when Access_Kind => 3189 when Access_Kind =>
3774 3208
3775 -- ??? What about hidden components 3209 -- ??? What about hidden components
3776 3210
3777 when E_Record_Type 3211 when E_Record_Type
3778 | E_Record_Subtype 3212 | E_Record_Subtype
3779 => 3213 =>
3780 declare 3214 declare
3781 Elmt : Entity_Id; 3215 Elmt : Entity_Id;
3782 3216
3783 begin 3217 begin
3784 Elmt := First_Component_Or_Discriminant (E); 3218 Elmt := First_Component_Or_Discriminant (E);
3787 return True; 3221 return True;
3788 else 3222 else
3789 Next_Component_Or_Discriminant (Elmt); 3223 Next_Component_Or_Discriminant (Elmt);
3790 end if; 3224 end if;
3791 end loop; 3225 end loop;
3792
3793 return False; 3226 return False;
3794 end; 3227 end;
3795 3228
3796 when Private_Kind => 3229 when Private_Kind =>
3797 if Is_Private_Entity_Mode_Off (E) then 3230 if Is_Private_Entity_Mode_Off (E) then
3802 else 3235 else
3803 return True; 3236 return True;
3804 end if; 3237 end if;
3805 end if; 3238 end if;
3806 3239
3807 when E_Incomplete_Type => 3240 when E_Incomplete_Type
3808 return True; 3241 | E_Incomplete_Subtype
3809 3242 =>
3810 when E_Incomplete_Subtype =>
3811 return True; 3243 return True;
3812 3244
3813 -- No problem with synchronized types 3245 -- No problem with synchronized types
3814 3246
3815 when E_Protected_Type 3247 when E_Protected_Type
3824 3256
3825 when others => 3257 when others =>
3826 raise Program_Error; 3258 raise Program_Error;
3827 end case; 3259 end case;
3828 end Is_Deep; 3260 end Is_Deep;
3829
3830 ----------------
3831 -- Is_Shallow --
3832 ----------------
3833
3834 function Is_Shallow (E : Entity_Id) return Boolean is
3835 begin
3836 pragma Assert (Is_Type (E));
3837 return not Is_Deep (E);
3838 end Is_Shallow;
3839
3840 ------------------
3841 -- Loop_Of_Exit --
3842 ------------------
3843
3844 function Loop_Of_Exit (N : Node_Id) return Entity_Id is
3845 Nam : Node_Id := Name (N);
3846 Stmt : Node_Id := N;
3847 begin
3848 if No (Nam) then
3849 while Present (Stmt) loop
3850 Stmt := Parent (Stmt);
3851 if Nkind (Stmt) = N_Loop_Statement then
3852 Nam := Identifier (Stmt);
3853 exit;
3854 end if;
3855 end loop;
3856 end if;
3857 return Entity (Nam);
3858 end Loop_Of_Exit;
3859 ---------
3860 -- Lub --
3861 ---------
3862
3863 function Lub (P1, P2 : Perm_Kind) return Perm_Kind
3864 is
3865 begin
3866 case P1 is
3867 when No_Access =>
3868 return P2;
3869
3870 when Read_Only =>
3871 case P2 is
3872 when No_Access
3873 | Read_Only
3874 =>
3875 return Read_Only;
3876
3877 when Write_Perm =>
3878 return Read_Write;
3879 end case;
3880
3881 when Write_Only =>
3882 case P2 is
3883 when No_Access
3884 | Write_Only
3885 =>
3886 return Write_Only;
3887
3888 when Read_Perm =>
3889 return Read_Write;
3890 end case;
3891
3892 when Read_Write =>
3893 return Read_Write;
3894 end case;
3895 end Lub;
3896
3897 ----------------
3898 -- Merge_Envs --
3899 ----------------
3900
3901 procedure Merge_Envs
3902 (Target : in out Perm_Env;
3903 Source : in out Perm_Env)
3904 is
3905 procedure Merge_Trees
3906 (Target : Perm_Tree_Access;
3907 Source : Perm_Tree_Access);
3908
3909 procedure Merge_Trees
3910 (Target : Perm_Tree_Access;
3911 Source : Perm_Tree_Access)
3912 is
3913 procedure Apply_Glb_Tree
3914 (A : Perm_Tree_Access;
3915 P : Perm_Kind);
3916
3917 procedure Apply_Glb_Tree
3918 (A : Perm_Tree_Access;
3919 P : Perm_Kind)
3920 is
3921 begin
3922 A.all.Tree.Permission := Glb (Permission (A), P);
3923
3924 case Kind (A) is
3925 when Entire_Object =>
3926 A.all.Tree.Children_Permission :=
3927 Glb (Children_Permission (A), P);
3928
3929 when Reference =>
3930 Apply_Glb_Tree (Get_All (A), P);
3931
3932 when Array_Component =>
3933 Apply_Glb_Tree (Get_Elem (A), P);
3934
3935 when Record_Component =>
3936 declare
3937 Comp : Perm_Tree_Access;
3938 begin
3939 Comp := Perm_Tree_Maps.Get_First (Component (A));
3940 while Comp /= null loop
3941 Apply_Glb_Tree (Comp, P);
3942 Comp := Perm_Tree_Maps.Get_Next (Component (A));
3943 end loop;
3944
3945 Apply_Glb_Tree (Other_Components (A), P);
3946 end;
3947 end case;
3948 end Apply_Glb_Tree;
3949
3950 Perm : constant Perm_Kind :=
3951 Glb (Permission (Target), Permission (Source));
3952
3953 begin
3954 pragma Assert (Is_Node_Deep (Target) = Is_Node_Deep (Source));
3955 Target.all.Tree.Permission := Perm;
3956
3957 case Kind (Target) is
3958 when Entire_Object =>
3959 declare
3960 Child_Perm : constant Perm_Kind :=
3961 Children_Permission (Target);
3962
3963 begin
3964 case Kind (Source) is
3965 when Entire_Object =>
3966 Target.all.Tree.Children_Permission :=
3967 Glb (Child_Perm, Children_Permission (Source));
3968
3969 when Reference =>
3970 Copy_Tree (Source, Target);
3971 Target.all.Tree.Permission := Perm;
3972 Apply_Glb_Tree (Get_All (Target), Child_Perm);
3973
3974 when Array_Component =>
3975 Copy_Tree (Source, Target);
3976 Target.all.Tree.Permission := Perm;
3977 Apply_Glb_Tree (Get_Elem (Target), Child_Perm);
3978
3979 when Record_Component =>
3980 Copy_Tree (Source, Target);
3981 Target.all.Tree.Permission := Perm;
3982 declare
3983 Comp : Perm_Tree_Access;
3984
3985 begin
3986 Comp :=
3987 Perm_Tree_Maps.Get_First (Component (Target));
3988 while Comp /= null loop
3989 -- Apply glb tree on every component subtree
3990
3991 Apply_Glb_Tree (Comp, Child_Perm);
3992 Comp := Perm_Tree_Maps.Get_Next
3993 (Component (Target));
3994 end loop;
3995 end;
3996 Apply_Glb_Tree (Other_Components (Target), Child_Perm);
3997
3998 end case;
3999 end;
4000 when Reference =>
4001 case Kind (Source) is
4002 when Entire_Object =>
4003 Apply_Glb_Tree (Get_All (Target),
4004 Children_Permission (Source));
4005
4006 when Reference =>
4007 Merge_Trees (Get_All (Target), Get_All (Source));
4008
4009 when others =>
4010 raise Program_Error;
4011
4012 end case;
4013
4014 when Array_Component =>
4015 case Kind (Source) is
4016 when Entire_Object =>
4017 Apply_Glb_Tree (Get_Elem (Target),
4018 Children_Permission (Source));
4019
4020 when Array_Component =>
4021 Merge_Trees (Get_Elem (Target), Get_Elem (Source));
4022
4023 when others =>
4024 raise Program_Error;
4025
4026 end case;
4027
4028 when Record_Component =>
4029 case Kind (Source) is
4030 when Entire_Object =>
4031 declare
4032 Child_Perm : constant Perm_Kind :=
4033 Children_Permission (Source);
4034
4035 Comp : Perm_Tree_Access;
4036
4037 begin
4038 Comp := Perm_Tree_Maps.Get_First
4039 (Component (Target));
4040 while Comp /= null loop
4041 -- Apply glb tree on every component subtree
4042
4043 Apply_Glb_Tree (Comp, Child_Perm);
4044 Comp :=
4045 Perm_Tree_Maps.Get_Next (Component (Target));
4046 end loop;
4047 Apply_Glb_Tree (Other_Components (Target), Child_Perm);
4048 end;
4049
4050 when Record_Component =>
4051 declare
4052 Key_Source : Perm_Tree_Maps.Key_Option;
4053 CompTarget : Perm_Tree_Access;
4054 CompSource : Perm_Tree_Access;
4055
4056 begin
4057 Key_Source := Perm_Tree_Maps.Get_First_Key
4058 (Component (Source));
4059
4060 while Key_Source.Present loop
4061 CompSource := Perm_Tree_Maps.Get
4062 (Component (Source), Key_Source.K);
4063 CompTarget := Perm_Tree_Maps.Get
4064 (Component (Target), Key_Source.K);
4065
4066 pragma Assert (CompSource /= null);
4067 Merge_Trees (CompTarget, CompSource);
4068
4069 Key_Source := Perm_Tree_Maps.Get_Next_Key
4070 (Component (Source));
4071 end loop;
4072
4073 Merge_Trees (Other_Components (Target),
4074 Other_Components (Source));
4075 end;
4076
4077 when others =>
4078 raise Program_Error;
4079
4080 end case;
4081 end case;
4082 end Merge_Trees;
4083
4084 CompTarget : Perm_Tree_Access;
4085 CompSource : Perm_Tree_Access;
4086 KeyTarget : Perm_Tree_Maps.Key_Option;
4087
4088 begin
4089 KeyTarget := Get_First_Key (Target);
4090 -- Iterate over every tree of the environment in the target, and merge
4091 -- it with the source if there is such a similar one that exists. If
4092 -- there is none, then skip.
4093 while KeyTarget.Present loop
4094
4095 CompSource := Get (Source, KeyTarget.K);
4096 CompTarget := Get (Target, KeyTarget.K);
4097
4098 pragma Assert (CompTarget /= null);
4099
4100 if CompSource /= null then
4101 Merge_Trees (CompTarget, CompSource);
4102 Remove (Source, KeyTarget.K);
4103 end if;
4104
4105 KeyTarget := Get_Next_Key (Target);
4106 end loop;
4107
4108 -- Iterate over every tree of the environment of the source. And merge
4109 -- again. If there is not any tree of the target then just copy the tree
4110 -- from source to target.
4111 declare
4112 KeySource : Perm_Tree_Maps.Key_Option;
4113 begin
4114 KeySource := Get_First_Key (Source);
4115 while KeySource.Present loop
4116
4117 CompSource := Get (Source, KeySource.K);
4118 CompTarget := Get (Target, KeySource.K);
4119
4120 if CompTarget = null then
4121 CompTarget := new Perm_Tree_Wrapper'(CompSource.all);
4122 Copy_Tree (CompSource, CompTarget);
4123 Set (Target, KeySource.K, CompTarget);
4124 else
4125 Merge_Trees (CompTarget, CompSource);
4126 end if;
4127
4128 KeySource := Get_Next_Key (Source);
4129 end loop;
4130 end;
4131
4132 Free_Env (Source);
4133 end Merge_Envs;
4134 3261
4135 ---------------- 3262 ----------------
4136 -- Perm_Error -- 3263 -- Perm_Error --
4137 ---------------- 3264 ----------------
4138 3265
4183 3310
4184 when others => 3311 when others =>
4185 raise Program_Error; 3312 raise Program_Error;
4186 end case; 3313 end case;
4187 end Set_Root_Object; 3314 end Set_Root_Object;
4188
4189 -- Local variables 3315 -- Local variables
4190 3316
4191 Root : Entity_Id; 3317 Root : Entity_Id;
4192 Is_Deref : Boolean; 3318 Is_Deref : Boolean;
4193 3319
4226 ------------------ 3352 ------------------
4227 -- Process_Path -- 3353 -- Process_Path --
4228 ------------------ 3354 ------------------
4229 3355
4230 procedure Process_Path (N : Node_Id) is 3356 procedure Process_Path (N : Node_Id) is
4231 Root : constant Entity_Id := Get_Enclosing_Object (N); 3357 Root : constant Entity_Id := Get_Enclosing_Object (N);
3358 State_N : Perm_Kind;
4232 begin 3359 begin
4233 -- We ignore if yielding to synchronized 3360 -- We ignore if yielding to synchronized
4234 3361
4235 if Present (Root) 3362 if Present (Root)
4236 and then Is_Synchronized_Object (Root) 3363 and then Is_Synchronized_Object (Root)
4237 then 3364 then
4238 return; 3365 return;
4239 end if; 3366 end if;
4240 3367
4241 -- We ignore shallow unaliased. They are checked in flow analysis, 3368 State_N := Get_Perm (N);
4242 -- allowing backward compatibility. 3369
4243 3370 case Current_Checking_Mode is
4244 if not Has_Alias (N) 3371
4245 and then Is_Shallow (Etype (N)) 3372 -- Check permission R, do nothing
4246 then 3373
4247 return; 3374 when Read =>
4248 end if; 3375
4249 3376 -- This condition should be removed when removing the read
4250 declare 3377 -- checking mode.
4251 Perm_N : constant Perm_Kind := Get_Perm (N); 3378
4252 3379 return;
4253 begin 3380
4254 3381 when Move =>
4255 case Current_Checking_Mode is 3382
4256 -- Check permission R, do nothing 3383 -- The rhs object in an assignment statement (including copy in
4257 3384 -- and copy back) should be in the Unrestricted or Moved state.
4258 when Read => 3385 -- Otherwise the move is not allowed.
4259 if Perm_N not in Read_Perm then 3386 -- This applies to both stand-alone and composite objects.
4260 Perm_Error (N, Read_Only, Perm_N); 3387 -- If the state of the source is Moved, then a warning message
4261 end if; 3388 -- is prompt to make the user aware of reading a nullified
4262 3389 -- object.
4263 -- If shallow type no need for RW, only R 3390
4264 3391 if State_N /= Unrestricted and State_N /= Moved then
4265 when Move => 3392 Perm_Error (N, Unrestricted, State_N);
4266 if Is_Shallow (Etype (N)) then 3393 return;
4267 if Perm_N not in Read_Perm then 3394 end if;
4268 Perm_Error (N, Read_Only, Perm_N); 3395
4269 end if; 3396 -- In the AI, after moving a path nothing to do since the rhs
4270 else 3397 -- object was in the Unrestricted state and it shall be
4271 -- Check permission RW if deep 3398 -- refreshed to Unrestricted. The object should be nullified
4272 3399 -- however. To avoid moving again a name that has already been
4273 if Perm_N /= Read_Write then 3400 -- moved, in this implementation we set the state of the moved
4274 Perm_Error (N, Read_Write, Perm_N); 3401 -- object to "Moved". This shall be used to prompt a warning
4275 end if; 3402 -- when manipulating a null pointer and also to implement
4276 3403 -- the no aliasing parameter restriction.
4277 declare 3404
4278 -- Set permission to W to the path and any of its prefix 3405 if State_N = Moved then
4279 3406 Error_Msg_N ("?the source or one of its extensions has"
4280 Tree : constant Perm_Tree_Access := 3407 & " already been moved", N);
4281 Set_Perm_Prefixes_Move (N, Move); 3408 end if;
4282 3409
4283 begin 3410 declare
4284 if Tree = null then 3411 -- Set state to Moved to the path and any of its prefixes
4285 -- We went through a function call, no permission to 3412
4286 -- modify. 3413 Tree : constant Perm_Tree_Access :=
4287 3414 Set_Perm_Prefixes (N, Moved);
4288 return; 3415
4289 end if; 3416 begin
4290 3417 if Tree = null then
4291 -- Set permissions to 3418
4292 -- No for any extension with more .all 3419 -- We went through a function call, no permission to
4293 -- W for any deep extension with same number of .all 3420 -- modify.
4294 -- RW for any shallow extension with same number of .all 3421
4295
4296 Set_Perm_Extensions_Move (Tree, Etype (N));
4297 end;
4298 end if;
4299
4300 -- Check permission RW
4301
4302 when Super_Move =>
4303 if Perm_N /= Read_Write then
4304 Perm_Error (N, Read_Write, Perm_N);
4305 end if;
4306
4307 declare
4308 -- Set permission to No to the path and any of its prefix up
4309 -- to the first .all and then W.
4310
4311 Tree : constant Perm_Tree_Access :=
4312 Set_Perm_Prefixes_Move (N, Super_Move);
4313
4314 begin
4315 if Tree = null then
4316 -- We went through a function call, no permission to
4317 -- modify.
4318
4319 return;
4320 end if;
4321
4322 -- Set permissions to No on any strict extension of the path
4323
4324 Set_Perm_Extensions (Tree, No_Access);
4325 end;
4326
4327 -- Check permission W
4328
4329 when Assign =>
4330 if Perm_N not in Write_Perm then
4331 Perm_Error (N, Write_Only, Perm_N);
4332 end if;
4333
4334 -- If the tree has an array component, then the permissions do
4335 -- not get modified by the assignment.
4336
4337 if Has_Array_Component (N) then
4338 return; 3422 return;
4339 end if; 3423 end if;
4340 3424
4341 -- Same if has function component 3425 -- Set state to Moved on any strict extension of the path
4342 3426
4343 if Has_Function_Component (N) then 3427 Set_Perm_Extensions (Tree, Moved);
3428 end;
3429
3430 when Assign =>
3431
3432 -- The lhs object in an assignment statement (including copy in
3433 -- and copy back) should be in the Unrestricted state.
3434 -- Otherwise the move is not allowed.
3435 -- This applies to both stand-alone and composite objects.
3436
3437 if State_N /= Unrestricted and State_N /= Moved then
3438 Perm_Error (N, Unrestricted, State_N);
3439 return;
3440 end if;
3441
3442 -- After assigning to a path nothing to do since it was in the
3443 -- Unrestricted state and it would be refreshed to
3444 -- Unrestricted.
3445
3446 when Borrow =>
3447
3448 -- Borrowing is only allowed on Unrestricted objects.
3449
3450 if State_N /= Unrestricted and State_N /= Moved then
3451 Perm_Error (N, Unrestricted, State_N);
3452 end if;
3453
3454 if State_N = Moved then
3455 Error_Msg_N ("?the source or one of its extensions has"
3456 & " already been moved", N);
3457 end if;
3458
3459 declare
3460 -- Set state to Borrowed to the path and any of its prefixes
3461
3462 Tree : constant Perm_Tree_Access :=
3463 Set_Perm_Prefixes (N, Borrowed);
3464
3465 begin
3466 if Tree = null then
3467
3468 -- We went through a function call, no permission to
3469 -- modify.
3470
4344 return; 3471 return;
4345 end if; 3472 end if;
4346 3473
4347 declare 3474 -- Set state to Borrowed on any strict extension of the path
4348 -- Get the permission tree for the path 3475
4349 3476 Set_Perm_Extensions (Tree, Borrowed);
4350 Tree : constant Perm_Tree_Access := 3477 end;
4351 Get_Perm_Tree (N); 3478
4352 3479 when Observe =>
4353 Dummy : Perm_Tree_Access; 3480 if State_N /= Unrestricted
4354 3481 and then State_N /= Observed
4355 begin 3482 then
4356 if Tree = null then 3483 Perm_Error (N, Observed, State_N);
4357 -- We went through a function call, no permission to 3484 end if;
4358 -- modify. 3485
4359 3486 declare
4360 return; 3487 -- Set permission to Observed on the path and any of its
4361 end if; 3488 -- prefixes if it is of a deep type. Actually, some operation
4362 3489 -- like reading from an object of access type is considered as
4363 -- Set permission RW for it and all of its extensions 3490 -- observe while it should not affect the permissions of
4364 3491 -- the considered tree.
4365 Tree.all.Tree.Permission := Read_Write; 3492
4366 3493 Tree : Perm_Tree_Access;
4367 Set_Perm_Extensions (Tree, Read_Write); 3494
4368 3495 begin
4369 -- Normalize the permission tree 3496 if Is_Deep (Etype (N)) then
4370 3497 Tree := Set_Perm_Prefixes (N, Observed);
4371 Dummy := Set_Perm_Prefixes_Assign (N); 3498 else
4372 end; 3499 Tree := null;
4373
4374 -- Check permission W
4375
4376 when Borrow_Out =>
4377 if Perm_N not in Write_Perm then
4378 Perm_Error (N, Write_Only, Perm_N);
4379 end if; 3500 end if;
4380 3501
4381 declare 3502 if Tree = null then
4382 -- Set permission to No to the path and any of its prefixes 3503
4383 3504 -- We went through a function call, no permission to
4384 Tree : constant Perm_Tree_Access := 3505 -- modify.
4385 Set_Perm_Prefixes_Borrow_Out (N); 3506
4386
4387 begin
4388 if Tree = null then
4389 -- We went through a function call, no permission to
4390 -- modify.
4391
4392 return;
4393 end if;
4394
4395 -- Set permissions to No on any strict extension of the path
4396
4397 Set_Perm_Extensions (Tree, No_Access);
4398 end;
4399
4400 when Observe =>
4401 if Perm_N not in Read_Perm then
4402 Perm_Error (N, Read_Only, Perm_N);
4403 end if;
4404
4405 if Is_By_Copy_Type (Etype (N)) then
4406 return; 3507 return;
4407 end if; 3508 end if;
4408 3509
4409 declare 3510 -- Set permissions to No on any strict extension of the path
4410 -- Set permission to No on the path and any of its prefixes 3511
4411 3512 Set_Perm_Extensions (Tree, Observed);
4412 Tree : constant Perm_Tree_Access := 3513 end;
4413 Set_Perm_Prefixes_Observe (N); 3514 end case;
4414
4415 begin
4416 if Tree = null then
4417 -- We went through a function call, no permission to
4418 -- modify.
4419
4420 return;
4421 end if;
4422
4423 -- Set permissions to No on any strict extension of the path
4424
4425 Set_Perm_Extensions (Tree, Read_Only);
4426 end;
4427 end case;
4428 end;
4429 end Process_Path; 3515 end Process_Path;
4430 3516
4431 ------------------------- 3517 -------------------------
4432 -- Return_Declarations -- 3518 -- Return_Declarations --
4433 ------------------------- 3519 -------------------------
4434 3520
4435 procedure Return_Declarations (L : List_Id) is 3521 procedure Return_Declarations (L : List_Id) is
4436
4437 procedure Return_Declaration (Decl : Node_Id); 3522 procedure Return_Declaration (Decl : Node_Id);
4438 -- Check correct permissions for every declared object 3523 -- Check correct permissions for every declared object
4439 3524
4440 ------------------------ 3525 ------------------------
4441 -- Return_Declaration -- 3526 -- Return_Declaration --
4442 ------------------------ 3527 ------------------------
4443 3528
4444 procedure Return_Declaration (Decl : Node_Id) is 3529 procedure Return_Declaration (Decl : Node_Id) is
4445 begin 3530 begin
4446 if Nkind (Decl) = N_Object_Declaration then 3531 if Nkind (Decl) = N_Object_Declaration then
3532
4447 -- Check RW for object declared, unless the object has never been 3533 -- Check RW for object declared, unless the object has never been
4448 -- initialized. 3534 -- initialized.
4449 3535
4450 if Get (Current_Initialization_Map, 3536 if Get (Current_Initialization_Map,
4451 Unique_Entity (Defining_Identifier (Decl))) = False 3537 Unique_Entity (Defining_Identifier (Decl))) = False
4452 then 3538 then
4453 return; 3539 return;
4454 end if; 3540 end if;
4455 3541
4456 -- We ignore shallow unaliased. They are checked in flow analysis,
4457 -- allowing backward compatibility.
4458
4459 if not Has_Alias (Defining_Identifier (Decl))
4460 and then Is_Shallow (Etype (Defining_Identifier (Decl)))
4461 then
4462 return;
4463 end if;
4464
4465 declare 3542 declare
4466 Elem : constant Perm_Tree_Access := 3543 Elem : constant Perm_Tree_Access :=
4467 Get (Current_Perm_Env, 3544 Get (Current_Perm_Env,
4468 Unique_Entity (Defining_Identifier (Decl))); 3545 Unique_Entity (Defining_Identifier (Decl)));
4469 3546
4470 begin 3547 begin
4471 if Elem = null then 3548 if Elem = null then
3549
4472 -- Here we are on a declaration. Hence it should have been 3550 -- Here we are on a declaration. Hence it should have been
4473 -- added in the environment when analyzing this node with 3551 -- added in the environment when analyzing this node with
4474 -- mode Read. Hence it is not possible to find a null 3552 -- mode Read. Hence it is not possible to find a null
4475 -- pointer here. 3553 -- pointer here.
4476 3554
4477 -- Hash_Table_Error 3555 -- Hash_Table_Error
3556
4478 raise Program_Error; 3557 raise Program_Error;
4479 end if; 3558 end if;
4480 3559
4481 if Permission (Elem) /= Read_Write then 3560 if Permission (Elem) /= Unrestricted then
4482 Perm_Error (Decl, Read_Write, Permission (Elem)); 3561 Perm_Error (Decl, Unrestricted, Permission (Elem));
4483 end if; 3562 end if;
4484 end; 3563 end;
4485 end if; 3564 end if;
4486 end Return_Declaration; 3565 end Return_Declaration;
4487
4488 -- Local Variables 3566 -- Local Variables
4489 3567
4490 N : Node_Id; 3568 N : Node_Id;
4491 3569
4492 -- Start of processing for Return_Declarations 3570 -- Start of processing for Return_Declarations
4502 -------------------- 3580 --------------------
4503 -- Return_Globals -- 3581 -- Return_Globals --
4504 -------------------- 3582 --------------------
4505 3583
4506 procedure Return_Globals (Subp : Entity_Id) is 3584 procedure Return_Globals (Subp : Entity_Id) is
4507
4508 procedure Return_Globals_From_List 3585 procedure Return_Globals_From_List
4509 (First_Item : Node_Id; 3586 (First_Item : Node_Id;
4510 Kind : Formal_Kind); 3587 Kind : Formal_Kind);
4511 -- Return global items from the list starting at Item 3588 -- Return global items from the list starting at Item
4512 3589
4531 -- Ignore abstract states, which play no role in pointer aliasing 3608 -- Ignore abstract states, which play no role in pointer aliasing
4532 3609
4533 if Ekind (E) = E_Abstract_State then 3610 if Ekind (E) = E_Abstract_State then
4534 null; 3611 null;
4535 else 3612 else
4536 Return_Parameter_Or_Global (E, Kind, Subp); 3613 Return_The_Global (E, Kind, Subp);
4537 end if; 3614 end if;
4538 Next_Global (Item); 3615 Next_Global (Item);
4539 end loop; 3616 end loop;
4540 end Return_Globals_From_List; 3617 end Return_Globals_From_List;
4541 3618
4546 procedure Return_Globals_Of_Mode (Global_Mode : Name_Id) is 3623 procedure Return_Globals_Of_Mode (Global_Mode : Name_Id) is
4547 Kind : Formal_Kind; 3624 Kind : Formal_Kind;
4548 3625
4549 begin 3626 begin
4550 case Global_Mode is 3627 case Global_Mode is
4551 when Name_Input | Name_Proof_In => 3628 when Name_Input
3629 | Name_Proof_In
3630 =>
4552 Kind := E_In_Parameter; 3631 Kind := E_In_Parameter;
4553 when Name_Output => 3632 when Name_Output =>
4554 Kind := E_Out_Parameter; 3633 Kind := E_Out_Parameter;
4555 when Name_In_Out => 3634 when Name_In_Out =>
4556 Kind := E_In_Out_Parameter; 3635 Kind := E_In_Out_Parameter;
4576 3655
4577 -------------------------------- 3656 --------------------------------
4578 -- Return_Parameter_Or_Global -- 3657 -- Return_Parameter_Or_Global --
4579 -------------------------------- 3658 --------------------------------
4580 3659
4581 procedure Return_Parameter_Or_Global 3660 procedure Return_The_Global
4582 (Id : Entity_Id; 3661 (Id : Entity_Id;
4583 Mode : Formal_Kind; 3662 Mode : Formal_Kind;
4584 Subp : Entity_Id) 3663 Subp : Entity_Id)
4585 is 3664 is
4586 Elem : constant Perm_Tree_Access := Get (Current_Perm_Env, Id); 3665 Elem : constant Perm_Tree_Access := Get (Current_Perm_Env, Id);
4587 pragma Assert (Elem /= null); 3666 pragma Assert (Elem /= null);
4588 3667
4589 begin 3668 begin
4590 -- Shallow unaliased parameters and globals cannot introduce pointer
4591 -- aliasing.
4592
4593 if not Has_Alias (Id) and then Is_Shallow (Etype (Id)) then
4594 null;
4595
4596 -- Observed IN parameters and globals need not return a permission to 3669 -- Observed IN parameters and globals need not return a permission to
4597 -- the caller. 3670 -- the caller.
4598 3671
4599 elsif Mode = E_In_Parameter and then not Is_Borrowed_In (Id) then 3672 if Mode = E_In_Parameter
4600 null; 3673
4601 3674 -- Check this for read-only globals.
4602 -- All other parameters and globals should return with mode RW to the 3675
4603 -- caller. 3676 then
4604 3677 if Permission (Elem) /= Unrestricted
4605 else 3678 and then Permission (Elem) /= Observed
4606 if Permission (Elem) /= Read_Write then 3679 then
4607 Perm_Error_Subprogram_End 3680 Perm_Error_Subprogram_End
4608 (E => Id, 3681 (E => Id,
4609 Subp => Subp, 3682 Subp => Subp,
4610 Perm => Read_Write, 3683 Perm => Observed,
3684 Found_Perm => Permission (Elem));
3685 end if;
3686
3687 -- All globals of mode out or in/out should return with mode
3688 -- Unrestricted.
3689
3690 else
3691 if Permission (Elem) /= Unrestricted then
3692 Perm_Error_Subprogram_End
3693 (E => Id,
3694 Subp => Subp,
3695 Perm => Unrestricted,
4611 Found_Perm => Permission (Elem)); 3696 Found_Perm => Permission (Elem));
4612 end if; 3697 end if;
4613 end if; 3698 end if;
4614 end Return_Parameter_Or_Global; 3699 end Return_The_Global;
4615
4616 -----------------------
4617 -- Return_Parameters --
4618 -----------------------
4619
4620 procedure Return_Parameters (Subp : Entity_Id) is
4621 Formal : Entity_Id;
4622
4623 begin
4624 Formal := First_Formal (Subp);
4625 while Present (Formal) loop
4626 Return_Parameter_Or_Global (Formal, Ekind (Formal), Subp);
4627 Next_Formal (Formal);
4628 end loop;
4629 end Return_Parameters;
4630 3700
4631 ------------------------- 3701 -------------------------
4632 -- Set_Perm_Extensions -- 3702 -- Set_Perm_Extensions --
4633 ------------------------- 3703 -------------------------
4634 3704
4635 procedure Set_Perm_Extensions 3705 procedure Set_Perm_Extensions (T : Perm_Tree_Access; P : Perm_Kind) is
4636 (T : Perm_Tree_Access;
4637 P : Perm_Kind)
4638 is
4639 procedure Free_Perm_Tree_Children (T : Perm_Tree_Access); 3706 procedure Free_Perm_Tree_Children (T : Perm_Tree_Access);
4640 3707 procedure Free_Perm_Tree_Children (T : Perm_Tree_Access) is
4641 procedure Free_Perm_Tree_Children (T : Perm_Tree_Access)
4642 is
4643 begin 3708 begin
4644 case Kind (T) is 3709 case Kind (T) is
4645 when Entire_Object => 3710 when Entire_Object =>
4646 null; 3711 null;
4647 3712
4680 Free_Perm_Tree_Children (T); 3745 Free_Perm_Tree_Children (T);
4681 T.all.Tree := Son; 3746 T.all.Tree := Son;
4682 end Set_Perm_Extensions; 3747 end Set_Perm_Extensions;
4683 3748
4684 ------------------------------ 3749 ------------------------------
4685 -- Set_Perm_Extensions_Move -- 3750 -- Set_Perm_Prefixes --
4686 ------------------------------ 3751 ------------------------------
4687 3752
4688 procedure Set_Perm_Extensions_Move 3753 function Set_Perm_Prefixes
4689 (T : Perm_Tree_Access; 3754 (N : Node_Id;
4690 E : Entity_Id) 3755 New_Perm : Perm_Kind)
3756 return Perm_Tree_Access
4691 is 3757 is
4692 begin 3758 begin
4693 if not Is_Node_Deep (T) then 3759
4694 -- We are a shallow extension with same number of .all 3760 case Nkind (N) is
4695 3761
4696 Set_Perm_Extensions (T, Read_Write); 3762 when N_Identifier
4697 return; 3763 | N_Expanded_Name
4698 end if; 3764 | N_Defining_Identifier
4699 3765 =>
4700 -- We are a deep extension here (or the moved deep path) 3766 if Nkind (N) = N_Defining_Identifier
4701 3767 and then New_Perm = Borrowed
4702 T.all.Tree.Permission := Write_Only; 3768 then
4703 3769 raise Program_Error;
4704 case T.all.Tree.Kind is 3770 end if;
4705 -- Unroll the tree depending on the type 3771
4706 3772 declare
4707 when Entire_Object => 3773 P : Node_Id;
4708 case Ekind (E) is 3774 C : Perm_Tree_Access;
4709 when Scalar_Kind 3775
4710 | E_String_Literal_Subtype 3776 begin
4711 => 3777 if Nkind (N) = N_Defining_Identifier then
4712 Set_Perm_Extensions (T, No_Access); 3778 P := N;
4713 3779 else
4714 -- No need to unroll here, directly put sons to No_Access 3780 P := Entity (N);
4715 3781 end if;
4716 when Access_Kind => 3782
4717 if Ekind (E) in Access_Subprogram_Kind then 3783 C := Get (Current_Perm_Env, Unique_Entity (P));
4718 null; 3784 pragma Assert (C /= null);
4719 else 3785
4720 Set_Perm_Extensions (T, No_Access); 3786 -- Setting the initialization map to True, so that this
4721 end if; 3787 -- variable cannot be ignored anymore when looking at end
4722 3788 -- of elaboration of package.
4723 -- No unrolling done, too complicated 3789
4724 3790 Set (Current_Initialization_Map, Unique_Entity (P), True);
4725 when E_Class_Wide_Subtype 3791 if New_Perm = Observed
4726 | E_Class_Wide_Type 3792 and then C = null
4727 | E_Incomplete_Type 3793 then
4728 | E_Incomplete_Subtype 3794
4729 | E_Exception_Type 3795 -- No null possible here, there are no parents for the path.
4730 | E_Task_Type 3796 -- This means we are using a global variable without adding
4731 | E_Task_Subtype 3797 -- it in environment with a global aspect.
4732 => 3798
4733 Set_Perm_Extensions (T, No_Access); 3799 Illegal_Global_Usage (N);
4734 3800 end if;
4735 -- Expand the tree. Replace the node with Array component. 3801
4736 3802 C.all.Tree.Permission := New_Perm;
4737 when E_Array_Type 3803 return C;
4738 | E_Array_Subtype => 3804 end;
3805
3806 when N_Type_Conversion
3807 | N_Unchecked_Type_Conversion
3808 | N_Qualified_Expression
3809 =>
3810 return Set_Perm_Prefixes (Expression (N), New_Perm);
3811
3812 when N_Parameter_Specification =>
3813 raise Program_Error;
3814
3815 -- We set the permission tree of its prefix, and then we extract
3816 -- our subtree from the returned pointer and assign an adequate
3817 -- permission to it, if unfolded. If folded, we unroll the tree
3818 -- in one step.
3819
3820 when N_Selected_Component =>
3821 declare
3822 C : constant Perm_Tree_Access :=
3823 Set_Perm_Prefixes (Prefix (N), New_Perm);
3824
3825 begin
3826 if C = null then
3827
3828 -- We went through a function call, do nothing
3829
3830 return null;
3831 end if;
3832
3833 pragma Assert (Kind (C) = Entire_Object
3834 or else Kind (C) = Record_Component);
3835
3836 if Kind (C) = Record_Component then
3837 -- The tree is unfolded. We just modify the permission and
3838 -- return the record subtree.
3839
4739 declare 3840 declare
4740 Son : Perm_Tree_Access; 3841 Selected_Component : constant Entity_Id :=
3842 Entity (Selector_Name (N));
3843
3844 Selected_C : Perm_Tree_Access :=
3845 Perm_Tree_Maps.Get
3846 (Component (C), Selected_Component);
4741 3847
4742 begin 3848 begin
4743 Son := new Perm_Tree_Wrapper' 3849 if Selected_C = null then
4744 (Tree => 3850 Selected_C := Other_Components (C);
4745 (Kind => Entire_Object, 3851 end if;
4746 Is_Node_Deep => Is_Node_Deep (T), 3852
4747 Permission => Read_Write, 3853 pragma Assert (Selected_C /= null);
4748 Children_Permission => Read_Write)); 3854 Selected_C.all.Tree.Permission := New_Perm;
4749 3855 return Selected_C;
4750 Set_Perm_Extensions_Move (Son, Component_Type (E));
4751
4752 -- We change the current node from Entire_Object to
4753 -- Reference with Write_Only and the previous son.
4754
4755 pragma Assert (Is_Node_Deep (T));
4756
4757 T.all.Tree := (Kind => Array_Component,
4758 Is_Node_Deep => Is_Node_Deep (T),
4759 Permission => Write_Only,
4760 Get_Elem => Son);
4761 end; 3856 end;
4762 3857
4763 -- Unroll, and set permission extensions with component type 3858 elsif Kind (C) = Entire_Object then
4764
4765 when E_Record_Type
4766 | E_Record_Subtype
4767 | E_Record_Type_With_Private
4768 | E_Record_Subtype_With_Private
4769 | E_Protected_Type
4770 | E_Protected_Subtype
4771 =>
4772 declare 3859 declare
4773 -- Expand the tree. Replace the node with 3860 -- Expand the tree. Replace the node with
4774 -- Record_Component. 3861 -- Record_Component.
4775 3862
4776 Elem : Node_Id; 3863 Elem : Node_Id;
4777 3864
4778 Son : Perm_Tree_Access; 3865 -- Create an empty hash table
3866
3867 Hashtbl : Perm_Tree_Maps.Instance;
3868
3869 -- We create the unrolled nodes, that will all have same
3870 -- permission than parent.
3871
3872 Son : Perm_Tree_Access;
3873 Children_Perm : constant Perm_Kind :=
3874 Children_Permission (C);
4779 3875
4780 begin 3876 begin
4781 -- We change the current node from Entire_Object to 3877 -- We change the current node from Entire_Object to
4782 -- Record_Component with same permission and an empty 3878 -- Record_Component with same permission and an empty
4783 -- hash table as component list. 3879 -- hash table as component list.
4784 3880
4785 pragma Assert (Is_Node_Deep (T)); 3881 C.all.Tree :=
4786 3882 (Kind => Record_Component,
4787 T.all.Tree := 3883 Is_Node_Deep => Is_Node_Deep (C),
4788 (Kind => Record_Component, 3884 Permission => Permission (C),
4789 Is_Node_Deep => Is_Node_Deep (T), 3885 Component => Hashtbl,
4790 Permission => Write_Only,
4791 Component => Perm_Tree_Maps.Nil,
4792 Other_Components => 3886 Other_Components =>
4793 new Perm_Tree_Wrapper' 3887 new Perm_Tree_Wrapper'
4794 (Tree => 3888 (Tree =>
4795 (Kind => Entire_Object, 3889 (Kind => Entire_Object,
4796 Is_Node_Deep => True, 3890 Is_Node_Deep => True,
4797 Permission => Read_Write, 3891 Permission => Children_Perm,
4798 Children_Permission => Read_Write) 3892 Children_Permission => Children_Perm)
4799 ) 3893 ));
4800 );
4801 3894
4802 -- We fill the hash table with all sons of the record, 3895 -- We fill the hash table with all sons of the record,
4803 -- with basic Entire_Objects nodes. 3896 -- with basic Entire_Objects nodes.
4804 Elem := First_Component_Or_Discriminant (E); 3897
3898 Elem := First_Component_Or_Discriminant
3899 (Etype (Prefix (N)));
3900
4805 while Present (Elem) loop 3901 while Present (Elem) loop
4806 Son := new Perm_Tree_Wrapper' 3902 Son := new Perm_Tree_Wrapper'
4807 (Tree => 3903 (Tree =>
4808 (Kind => Entire_Object, 3904 (Kind => Entire_Object,
4809 Is_Node_Deep => Is_Deep (Etype (Elem)), 3905 Is_Node_Deep => Is_Deep (Etype (Elem)),
4810 Permission => Read_Write, 3906 Permission => Children_Perm,
4811 Children_Permission => Read_Write)); 3907 Children_Permission => Children_Perm));
4812 3908
4813 Set_Perm_Extensions_Move (Son, Etype (Elem)); 3909 Perm_Tree_Maps.Set (C.all.Tree.Component, Elem, Son);
4814
4815 Perm_Tree_Maps.Set
4816 (T.all.Tree.Component, Elem, Son);
4817
4818 Next_Component_Or_Discriminant (Elem); 3910 Next_Component_Or_Discriminant (Elem);
4819 end loop; 3911 end loop;
3912 -- Now we set the right field to Borrowed, and then we
3913 -- return the tree to the sons, so that the recursion can
3914 -- continue.
3915
3916 declare
3917 Selected_Component : constant Entity_Id :=
3918 Entity (Selector_Name (N));
3919 Selected_C : Perm_Tree_Access :=
3920 Perm_Tree_Maps.Get
3921 (Component (C), Selected_Component);
3922
3923 begin
3924 if Selected_C = null then
3925 Selected_C := Other_Components (C);
3926 end if;
3927
3928 pragma Assert (Selected_C /= null);
3929 Selected_C.all.Tree.Permission := New_Perm;
3930 return Selected_C;
3931 end;
4820 end; 3932 end;
4821 3933 else
4822 when E_Private_Type
4823 | E_Private_Subtype
4824 | E_Limited_Private_Type
4825 | E_Limited_Private_Subtype
4826 =>
4827 Set_Perm_Extensions_Move (T, Underlying_Type (E));
4828
4829 when others =>
4830 raise Program_Error; 3934 raise Program_Error;
4831 end case; 3935 end if;
4832
4833 when Reference =>
4834 -- Now the son does not have the same number of .all
4835 Set_Perm_Extensions (T, No_Access);
4836
4837 when Array_Component =>
4838 Set_Perm_Extensions_Move (Get_Elem (T), Component_Type (E));
4839
4840 when Record_Component =>
4841 declare
4842 Comp : Perm_Tree_Access;
4843 It : Node_Id;
4844
4845 begin
4846 It := First_Component_Or_Discriminant (E);
4847 while It /= Empty loop
4848 Comp := Perm_Tree_Maps.Get (Component (T), It);
4849 pragma Assert (Comp /= null);
4850 Set_Perm_Extensions_Move (Comp, It);
4851 It := Next_Component_Or_Discriminant (E);
4852 end loop;
4853
4854 Set_Perm_Extensions (Other_Components (T), No_Access);
4855 end; 3936 end;
4856 end case; 3937
4857 end Set_Perm_Extensions_Move; 3938 -- We set the permission tree of its prefix, and then we extract
4858 3939 -- from the returned pointer the subtree and assign an adequate
4859 ------------------------------ 3940 -- permission to it, if unfolded. If folded, we unroll the tree in
4860 -- Set_Perm_Prefixes_Assign -- 3941 -- one step.
4861 ------------------------------
4862
4863 function Set_Perm_Prefixes_Assign
4864 (N : Node_Id)
4865 return Perm_Tree_Access
4866 is
4867 C : constant Perm_Tree_Access := Get_Perm_Tree (N);
4868
4869 begin
4870 pragma Assert (Current_Checking_Mode = Assign);
4871
4872 -- The function should not be called if has_function_component
4873
4874 pragma Assert (C /= null);
4875
4876 case Kind (C) is
4877 when Entire_Object =>
4878 pragma Assert (Children_Permission (C) = Read_Write);
4879 C.all.Tree.Permission := Read_Write;
4880
4881 when Reference =>
4882 pragma Assert (Get_All (C) /= null);
4883
4884 C.all.Tree.Permission :=
4885 Lub (Permission (C), Permission (Get_All (C)));
4886
4887 when Array_Component =>
4888 pragma Assert (C.all.Tree.Get_Elem /= null);
4889
4890 -- Given that it is not possible to know which element has been
4891 -- assigned, then the permissions do not get changed in case of
4892 -- Array_Component.
4893
4894 null;
4895
4896 when Record_Component =>
4897 declare
4898 Perm : Perm_Kind := Read_Write;
4899
4900 Comp : Perm_Tree_Access;
4901
4902 begin
4903 -- We take the Glb of all the descendants, and then update the
4904 -- permission of the node with it.
4905 Comp := Perm_Tree_Maps.Get_First (Component (C));
4906 while Comp /= null loop
4907 Perm := Glb (Perm, Permission (Comp));
4908 Comp := Perm_Tree_Maps.Get_Next (Component (C));
4909 end loop;
4910
4911 Perm := Glb (Perm, Permission (Other_Components (C)));
4912
4913 C.all.Tree.Permission := Lub (Permission (C), Perm);
4914 end;
4915 end case;
4916
4917 case Nkind (N) is
4918 -- Base identifier. End recursion here.
4919
4920 when N_Identifier
4921 | N_Expanded_Name
4922 | N_Defining_Identifier
4923 =>
4924 return null;
4925
4926 when N_Type_Conversion
4927 | N_Unchecked_Type_Conversion
4928 | N_Qualified_Expression
4929 =>
4930 return Set_Perm_Prefixes_Assign (Expression (N));
4931
4932 when N_Parameter_Specification =>
4933 raise Program_Error;
4934
4935 -- Continue recursion on prefix
4936
4937 when N_Selected_Component =>
4938 return Set_Perm_Prefixes_Assign (Prefix (N));
4939
4940 -- Continue recursion on prefix
4941 3942
4942 when N_Indexed_Component 3943 when N_Indexed_Component
4943 | N_Slice 3944 | N_Slice
4944 => 3945 =>
4945 return Set_Perm_Prefixes_Assign (Prefix (N)); 3946 declare
4946 3947 C : constant Perm_Tree_Access :=
4947 -- Continue recursion on prefix 3948 Set_Perm_Prefixes (Prefix (N), New_Perm);
3949
3950 begin
3951 if C = null then
3952
3953 -- We went through a function call, do nothing
3954
3955 return null;
3956 end if;
3957
3958 pragma Assert (Kind (C) = Entire_Object
3959 or else Kind (C) = Array_Component);
3960
3961 if Kind (C) = Array_Component then
3962
3963 -- The tree is unfolded. We just modify the permission and
3964 -- return the elem subtree.
3965
3966 pragma Assert (Get_Elem (C) /= null);
3967 C.all.Tree.Get_Elem.all.Tree.Permission := New_Perm;
3968 return Get_Elem (C);
3969
3970 elsif Kind (C) = Entire_Object then
3971 declare
3972 -- Expand the tree. Replace node with Array_Component.
3973
3974 Son : Perm_Tree_Access;
3975
3976 begin
3977 Son := new Perm_Tree_Wrapper'
3978 (Tree =>
3979 (Kind => Entire_Object,
3980 Is_Node_Deep => Is_Node_Deep (C),
3981 Permission => New_Perm,
3982 Children_Permission => Children_Permission (C)));
3983
3984 -- Children_Permission => Children_Permission (C)
3985 -- this line should be checked maybe New_Perm
3986 -- instead of Children_Permission (C)
3987
3988 -- We change the current node from Entire_Object
3989 -- to Array_Component with same permission and the
3990 -- previously defined son.
3991
3992 C.all.Tree := (Kind => Array_Component,
3993 Is_Node_Deep => Is_Node_Deep (C),
3994 Permission => New_Perm,
3995 Get_Elem => Son);
3996 return Get_Elem (C);
3997 end;
3998 else
3999 raise Program_Error;
4000 end if;
4001 end;
4002
4003 -- We set the permission tree of its prefix, and then we extract
4004 -- from the returned pointer the subtree and assign an adequate
4005 -- permission to it, if unfolded. If folded, we unroll the tree
4006 -- at one step.
4948 4007
4949 when N_Explicit_Dereference => 4008 when N_Explicit_Dereference =>
4950 return Set_Perm_Prefixes_Assign (Prefix (N)); 4009 declare
4010 C : constant Perm_Tree_Access :=
4011 Set_Perm_Prefixes (Prefix (N), New_Perm);
4012
4013 begin
4014 if C = null then
4015
4016 -- We went through a function call. Do nothing.
4017
4018 return null;
4019 end if;
4020
4021 pragma Assert (Kind (C) = Entire_Object
4022 or else Kind (C) = Reference);
4023
4024 if Kind (C) = Reference then
4025
4026 -- The tree is unfolded. We just modify the permission and
4027 -- return the elem subtree.
4028
4029 pragma Assert (Get_All (C) /= null);
4030 C.all.Tree.Get_All.all.Tree.Permission := New_Perm;
4031 return Get_All (C);
4032
4033 elsif Kind (C) = Entire_Object then
4034 declare
4035 -- Expand the tree. Replace the node with Reference.
4036
4037 Son : Perm_Tree_Access;
4038
4039 begin
4040 Son := new Perm_Tree_Wrapper'
4041 (Tree =>
4042 (Kind => Entire_Object,
4043 Is_Node_Deep => Is_Deep (Etype (N)),
4044 Permission => New_Perm,
4045 Children_Permission => Children_Permission (C)));
4046
4047 -- We change the current node from Entire_Object to
4048 -- Reference with Borrowed and the previous son.
4049
4050 pragma Assert (Is_Node_Deep (C));
4051 C.all.Tree := (Kind => Reference,
4052 Is_Node_Deep => Is_Node_Deep (C),
4053 Permission => New_Perm,
4054 Get_All => Son);
4055 return Get_All (C);
4056 end;
4057
4058 else
4059 raise Program_Error;
4060 end if;
4061 end;
4951 4062
4952 when N_Function_Call => 4063 when N_Function_Call =>
4953 raise Program_Error; 4064 return null;
4954 4065
4955 when others => 4066 when others =>
4956 raise Program_Error; 4067 raise Program_Error;
4957
4958 end case; 4068 end case;
4959 end Set_Perm_Prefixes_Assign; 4069 end Set_Perm_Prefixes;
4960 4070
4961 ---------------------------------- 4071 ------------------------------
4962 -- Set_Perm_Prefixes_Borrow_Out -- 4072 -- Set_Perm_Prefixes_Borrow --
4963 ---------------------------------- 4073 ------------------------------
4964 4074
4965 function Set_Perm_Prefixes_Borrow_Out 4075 function Set_Perm_Prefixes_Borrow (N : Node_Id) return Perm_Tree_Access
4966 (N : Node_Id)
4967 return Perm_Tree_Access
4968 is 4076 is
4969 begin 4077 begin
4970 pragma Assert (Current_Checking_Mode = Borrow_Out); 4078 pragma Assert (Current_Checking_Mode = Borrow);
4971
4972 case Nkind (N) is 4079 case Nkind (N) is
4973 -- Base identifier. Set permission to No.
4974 4080
4975 when N_Identifier 4081 when N_Identifier
4976 | N_Expanded_Name 4082 | N_Expanded_Name
4977 => 4083 =>
4978 declare 4084 declare
4979 P : constant Node_Id := Entity (N); 4085 P : constant Node_Id := Entity (N);
4980
4981 C : constant Perm_Tree_Access := 4086 C : constant Perm_Tree_Access :=
4982 Get (Current_Perm_Env, Unique_Entity (P)); 4087 Get (Current_Perm_Env, Unique_Entity (P));
4983
4984 pragma Assert (C /= null); 4088 pragma Assert (C /= null);
4985 4089
4986 begin 4090 begin
4987 -- Setting the initialization map to True, so that this 4091 -- Setting the initialization map to True, so that this
4988 -- variable cannot be ignored anymore when looking at end 4092 -- variable cannot be ignored anymore when looking at end
4989 -- of elaboration of package. 4093 -- of elaboration of package.
4990 4094
4991 Set (Current_Initialization_Map, Unique_Entity (P), True); 4095 Set (Current_Initialization_Map, Unique_Entity (P), True);
4992 4096 C.all.Tree.Permission := Borrowed;
4993 C.all.Tree.Permission := No_Access;
4994 return C; 4097 return C;
4995 end; 4098 end;
4996 4099
4997 when N_Type_Conversion 4100 when N_Type_Conversion
4998 | N_Unchecked_Type_Conversion 4101 | N_Unchecked_Type_Conversion
4999 | N_Qualified_Expression 4102 | N_Qualified_Expression
5000 => 4103 =>
5001 return Set_Perm_Prefixes_Borrow_Out (Expression (N)); 4104 return Set_Perm_Prefixes_Borrow (Expression (N));
5002 4105
5003 when N_Parameter_Specification 4106 when N_Parameter_Specification
5004 | N_Defining_Identifier 4107 | N_Defining_Identifier
5005 => 4108 =>
5006 raise Program_Error; 4109 raise Program_Error;
5011 -- in one step. 4114 -- in one step.
5012 4115
5013 when N_Selected_Component => 4116 when N_Selected_Component =>
5014 declare 4117 declare
5015 C : constant Perm_Tree_Access := 4118 C : constant Perm_Tree_Access :=
5016 Set_Perm_Prefixes_Borrow_Out (Prefix (N)); 4119 Set_Perm_Prefixes_Borrow (Prefix (N));
5017 4120
5018 begin 4121 begin
5019 if C = null then 4122 if C = null then
4123
5020 -- We went through a function call, do nothing 4124 -- We went through a function call, do nothing
5021 4125
5022 return null; 4126 return null;
5023 end if; 4127 end if;
5024 4128
5025 -- The permission of the returned node should be No 4129 -- The permission of the returned node should be No
5026 4130
5027 pragma Assert (Permission (C) = No_Access); 4131 pragma Assert (Permission (C) = Borrowed);
5028
5029 pragma Assert (Kind (C) = Entire_Object 4132 pragma Assert (Kind (C) = Entire_Object
5030 or else Kind (C) = Record_Component); 4133 or else Kind (C) = Record_Component);
5031 4134
5032 if Kind (C) = Record_Component then 4135 if Kind (C) = Record_Component then
4136
5033 -- The tree is unfolded. We just modify the permission and 4137 -- The tree is unfolded. We just modify the permission and
5034 -- return the record subtree. 4138 -- return the record subtree.
5035 4139
5036 declare 4140 declare
5037 Selected_Component : constant Entity_Id := 4141 Selected_Component : constant Entity_Id :=
5038 Entity (Selector_Name (N)); 4142 Entity (Selector_Name (N));
5039
5040 Selected_C : Perm_Tree_Access := 4143 Selected_C : Perm_Tree_Access :=
5041 Perm_Tree_Maps.Get 4144 Perm_Tree_Maps.Get
5042 (Component (C), Selected_Component); 4145 (Component (C), Selected_Component);
5043 4146
5044 begin 4147 begin
5045 if Selected_C = null then 4148 if Selected_C = null then
5046 Selected_C := Other_Components (C); 4149 Selected_C := Other_Components (C);
5047 end if; 4150 end if;
5048 4151
5049 pragma Assert (Selected_C /= null); 4152 pragma Assert (Selected_C /= null);
5050 4153 Selected_C.all.Tree.Permission := Borrowed;
5051 Selected_C.all.Tree.Permission := No_Access;
5052
5053 return Selected_C; 4154 return Selected_C;
5054 end; 4155 end;
4156
5055 elsif Kind (C) = Entire_Object then 4157 elsif Kind (C) = Entire_Object then
5056 declare 4158 declare
5057 -- Expand the tree. Replace the node with 4159 -- Expand the tree. Replace the node with
5058 -- Record_Component. 4160 -- Record_Component.
5059 4161
5065 4167
5066 -- We create the unrolled nodes, that will all have same 4168 -- We create the unrolled nodes, that will all have same
5067 -- permission than parent. 4169 -- permission than parent.
5068 4170
5069 Son : Perm_Tree_Access; 4171 Son : Perm_Tree_Access;
5070
5071 ChildrenPerm : constant Perm_Kind := 4172 ChildrenPerm : constant Perm_Kind :=
5072 Children_Permission (C); 4173 Children_Permission (C);
5073 4174
5074 begin 4175 begin
5075 -- We change the current node from Entire_Object to 4176 -- We change the current node from Entire_Object to
5090 Children_Permission => ChildrenPerm) 4191 Children_Permission => ChildrenPerm)
5091 )); 4192 ));
5092 4193
5093 -- We fill the hash table with all sons of the record, 4194 -- We fill the hash table with all sons of the record,
5094 -- with basic Entire_Objects nodes. 4195 -- with basic Entire_Objects nodes.
4196
5095 Elem := First_Component_Or_Discriminant 4197 Elem := First_Component_Or_Discriminant
5096 (Etype (Prefix (N))); 4198 (Etype (Prefix (N)));
5097 4199
5098 while Present (Elem) loop 4200 while Present (Elem) loop
5099 Son := new Perm_Tree_Wrapper' 4201 Son := new Perm_Tree_Wrapper'
5100 (Tree => 4202 (Tree =>
5101 (Kind => Entire_Object, 4203 (Kind => Entire_Object,
5102 Is_Node_Deep => Is_Deep (Etype (Elem)), 4204 Is_Node_Deep => Is_Deep (Etype (Elem)),
5103 Permission => ChildrenPerm, 4205 Permission => ChildrenPerm,
5104 Children_Permission => ChildrenPerm)); 4206 Children_Permission => ChildrenPerm));
5105 4207 Perm_Tree_Maps.Set (C.all.Tree.Component, Elem, Son);
5106 Perm_Tree_Maps.Set
5107 (C.all.Tree.Component, Elem, Son);
5108
5109 Next_Component_Or_Discriminant (Elem); 4208 Next_Component_Or_Discriminant (Elem);
5110 end loop; 4209 end loop;
5111 4210
5112 -- Now we set the right field to No_Access, and then we 4211 -- Now we set the right field to Borrowed, and then we
5113 -- return the tree to the sons, so that the recursion can 4212 -- return the tree to the sons, so that the recursion can
5114 -- continue. 4213 -- continue.
5115 4214
5116 declare 4215 declare
5117 Selected_Component : constant Entity_Id := 4216 Selected_Component : constant Entity_Id :=
5118 Entity (Selector_Name (N)); 4217 Entity (Selector_Name (N));
5119 4218 Selected_C : Perm_Tree_Access := Perm_Tree_Maps.Get
5120 Selected_C : Perm_Tree_Access := 4219 (Component (C), Selected_Component);
5121 Perm_Tree_Maps.Get
5122 (Component (C), Selected_Component);
5123 4220
5124 begin 4221 begin
5125 if Selected_C = null then 4222 if Selected_C = null then
5126 Selected_C := Other_Components (C); 4223 Selected_C := Other_Components (C);
5127 end if; 4224 end if;
5128 4225
5129 pragma Assert (Selected_C /= null); 4226 pragma Assert (Selected_C /= null);
5130 4227 Selected_C.all.Tree.Permission := Borrowed;
5131 Selected_C.all.Tree.Permission := No_Access;
5132
5133 return Selected_C; 4228 return Selected_C;
5134 end; 4229 end;
5135 end; 4230 end;
4231
5136 else 4232 else
5137 raise Program_Error; 4233 raise Program_Error;
5138 end if; 4234 end if;
5139 end; 4235 end;
5140 4236
5146 when N_Indexed_Component 4242 when N_Indexed_Component
5147 | N_Slice 4243 | N_Slice
5148 => 4244 =>
5149 declare 4245 declare
5150 C : constant Perm_Tree_Access := 4246 C : constant Perm_Tree_Access :=
5151 Set_Perm_Prefixes_Borrow_Out (Prefix (N)); 4247 Set_Perm_Prefixes_Borrow (Prefix (N));
5152 4248
5153 begin 4249 begin
5154 if C = null then 4250 if C = null then
4251
5155 -- We went through a function call, do nothing 4252 -- We went through a function call, do nothing
5156 4253
5157 return null; 4254 return null;
5158 end if; 4255 end if;
5159 4256
5160 -- The permission of the returned node should be either W 4257 pragma Assert (Permission (C) = Borrowed);
5161 -- (because the recursive call sets <= Write_Only) or No
5162 -- (if another path has been moved with 'Access).
5163
5164 pragma Assert (Permission (C) = No_Access);
5165
5166 pragma Assert (Kind (C) = Entire_Object 4258 pragma Assert (Kind (C) = Entire_Object
5167 or else Kind (C) = Array_Component); 4259 or else Kind (C) = Array_Component);
5168 4260
5169 if Kind (C) = Array_Component then 4261 if Kind (C) = Array_Component then
4262
5170 -- The tree is unfolded. We just modify the permission and 4263 -- The tree is unfolded. We just modify the permission and
5171 -- return the elem subtree. 4264 -- return the elem subtree.
5172 4265
5173 pragma Assert (Get_Elem (C) /= null); 4266 pragma Assert (Get_Elem (C) /= null);
5174 4267 C.all.Tree.Get_Elem.all.Tree.Permission := Borrowed;
5175 C.all.Tree.Get_Elem.all.Tree.Permission := No_Access;
5176
5177 return Get_Elem (C); 4268 return Get_Elem (C);
4269
5178 elsif Kind (C) = Entire_Object then 4270 elsif Kind (C) = Entire_Object then
5179 declare 4271 declare
5180 -- Expand the tree. Replace node with Array_Component. 4272 -- Expand the tree. Replace node with Array_Component.
5181 4273
5182 Son : Perm_Tree_Access; 4274 Son : Perm_Tree_Access;
5184 begin 4276 begin
5185 Son := new Perm_Tree_Wrapper' 4277 Son := new Perm_Tree_Wrapper'
5186 (Tree => 4278 (Tree =>
5187 (Kind => Entire_Object, 4279 (Kind => Entire_Object,
5188 Is_Node_Deep => Is_Node_Deep (C), 4280 Is_Node_Deep => Is_Node_Deep (C),
5189 Permission => No_Access, 4281 Permission => Borrowed,
5190 Children_Permission => Children_Permission (C))); 4282 Children_Permission => Children_Permission (C)));
5191 4283
5192 -- We change the current node from Entire_Object 4284 -- We change the current node from Entire_Object
5193 -- to Array_Component with same permission and the 4285 -- to Array_Component with same permission and the
5194 -- previously defined son. 4286 -- previously defined son.
5195 4287
5196 C.all.Tree := (Kind => Array_Component, 4288 C.all.Tree := (Kind => Array_Component,
5197 Is_Node_Deep => Is_Node_Deep (C), 4289 Is_Node_Deep => Is_Node_Deep (C),
5198 Permission => No_Access, 4290 Permission => Borrowed,
5199 Get_Elem => Son); 4291 Get_Elem => Son);
5200
5201 return Get_Elem (C); 4292 return Get_Elem (C);
5202 end; 4293 end;
4294
5203 else 4295 else
5204 raise Program_Error; 4296 raise Program_Error;
5205 end if; 4297 end if;
5206 end; 4298 end;
5207 4299
5211 -- at one step. 4303 -- at one step.
5212 4304
5213 when N_Explicit_Dereference => 4305 when N_Explicit_Dereference =>
5214 declare 4306 declare
5215 C : constant Perm_Tree_Access := 4307 C : constant Perm_Tree_Access :=
5216 Set_Perm_Prefixes_Borrow_Out (Prefix (N)); 4308 Set_Perm_Prefixes_Borrow (Prefix (N));
5217 4309
5218 begin 4310 begin
5219 if C = null then 4311 if C = null then
4312
5220 -- We went through a function call. Do nothing. 4313 -- We went through a function call. Do nothing.
5221 4314
5222 return null; 4315 return null;
5223 end if; 4316 end if;
5224 4317
5225 -- The permission of the returned node should be No 4318 -- The permission of the returned node should be No
5226 4319
5227 pragma Assert (Permission (C) = No_Access); 4320 pragma Assert (Permission (C) = Borrowed);
5228 pragma Assert (Kind (C) = Entire_Object 4321 pragma Assert (Kind (C) = Entire_Object
5229 or else Kind (C) = Reference); 4322 or else Kind (C) = Reference);
5230 4323
5231 if Kind (C) = Reference then 4324 if Kind (C) = Reference then
4325
5232 -- The tree is unfolded. We just modify the permission and 4326 -- The tree is unfolded. We just modify the permission and
5233 -- return the elem subtree. 4327 -- return the elem subtree.
5234 4328
5235 pragma Assert (Get_All (C) /= null); 4329 pragma Assert (Get_All (C) /= null);
5236 4330 C.all.Tree.Get_All.all.Tree.Permission := Borrowed;
5237 C.all.Tree.Get_All.all.Tree.Permission := No_Access;
5238
5239 return Get_All (C); 4331 return Get_All (C);
4332
5240 elsif Kind (C) = Entire_Object then 4333 elsif Kind (C) = Entire_Object then
5241 declare 4334 declare
5242 -- Expand the tree. Replace the node with Reference. 4335 -- Expand the tree. Replace the node with Reference.
5243 4336
5244 Son : Perm_Tree_Access; 4337 Son : Perm_Tree_Access;
5246 begin 4339 begin
5247 Son := new Perm_Tree_Wrapper' 4340 Son := new Perm_Tree_Wrapper'
5248 (Tree => 4341 (Tree =>
5249 (Kind => Entire_Object, 4342 (Kind => Entire_Object,
5250 Is_Node_Deep => Is_Deep (Etype (N)), 4343 Is_Node_Deep => Is_Deep (Etype (N)),
5251 Permission => No_Access, 4344 Permission => Borrowed,
5252 Children_Permission => Children_Permission (C))); 4345 Children_Permission => Children_Permission (C)));
5253 4346
5254 -- We change the current node from Entire_Object to 4347 -- We change the current node from Entire_Object to
5255 -- Reference with No_Access and the previous son. 4348 -- Reference with Borrowed and the previous son.
5256 4349
5257 pragma Assert (Is_Node_Deep (C)); 4350 pragma Assert (Is_Node_Deep (C));
5258
5259 C.all.Tree := (Kind => Reference, 4351 C.all.Tree := (Kind => Reference,
5260 Is_Node_Deep => Is_Node_Deep (C), 4352 Is_Node_Deep => Is_Node_Deep (C),
5261 Permission => No_Access, 4353 Permission => Borrowed,
5262 Get_All => Son); 4354 Get_All => Son);
5263
5264 return Get_All (C); 4355 return Get_All (C);
5265 end; 4356 end;
4357
5266 else 4358 else
5267 raise Program_Error; 4359 raise Program_Error;
5268 end if; 4360 end if;
5269 end; 4361 end;
5270 4362
5272 return null; 4364 return null;
5273 4365
5274 when others => 4366 when others =>
5275 raise Program_Error; 4367 raise Program_Error;
5276 end case; 4368 end case;
5277 end Set_Perm_Prefixes_Borrow_Out; 4369 end Set_Perm_Prefixes_Borrow;
5278
5279 ----------------------------
5280 -- Set_Perm_Prefixes_Move --
5281 ----------------------------
5282
5283 function Set_Perm_Prefixes_Move
5284 (N : Node_Id; Mode : Checking_Mode)
5285 return Perm_Tree_Access
5286 is
5287 begin
5288 case Nkind (N) is
5289
5290 -- Base identifier. Set permission to W or No depending on Mode.
5291
5292 when N_Identifier
5293 | N_Expanded_Name
5294 =>
5295 declare
5296 P : constant Node_Id := Entity (N);
5297 C : constant Perm_Tree_Access :=
5298 Get (Current_Perm_Env, Unique_Entity (P));
5299
5300 begin
5301 -- The base tree can be RW (first move from this base path) or
5302 -- W (already some extensions values moved), or even No_Access
5303 -- (extensions moved with 'Access). But it cannot be Read_Only
5304 -- (we get an error).
5305
5306 if Permission (C) = Read_Only then
5307 raise Unrecoverable_Error;
5308 end if;
5309
5310 -- Setting the initialization map to True, so that this
5311 -- variable cannot be ignored anymore when looking at end
5312 -- of elaboration of package.
5313
5314 Set (Current_Initialization_Map, Unique_Entity (P), True);
5315
5316 if C = null then
5317 -- No null possible here, there are no parents for the path.
5318 -- This means we are using a global variable without adding
5319 -- it in environment with a global aspect.
5320
5321 Illegal_Global_Usage (N);
5322 end if;
5323
5324 if Mode = Super_Move then
5325 C.all.Tree.Permission := No_Access;
5326 else
5327 C.all.Tree.Permission := Glb (Write_Only, Permission (C));
5328 end if;
5329
5330 return C;
5331 end;
5332
5333 when N_Type_Conversion
5334 | N_Unchecked_Type_Conversion
5335 | N_Qualified_Expression
5336 =>
5337 return Set_Perm_Prefixes_Move (Expression (N), Mode);
5338
5339 when N_Parameter_Specification
5340 | N_Defining_Identifier
5341 =>
5342 raise Program_Error;
5343
5344 -- We set the permission tree of its prefix, and then we extract
5345 -- from the returned pointer our subtree and assign an adequate
5346 -- permission to it, if unfolded. If folded, we unroll the tree
5347 -- at one step.
5348
5349 when N_Selected_Component =>
5350 declare
5351 C : constant Perm_Tree_Access :=
5352 Set_Perm_Prefixes_Move (Prefix (N), Mode);
5353
5354 begin
5355 if C = null then
5356 -- We went through a function call, do nothing
5357
5358 return null;
5359 end if;
5360
5361 -- The permission of the returned node should be either W
5362 -- (because the recursive call sets <= Write_Only) or No
5363 -- (if another path has been moved with 'Access).
5364
5365 pragma Assert (Permission (C) = No_Access
5366 or else Permission (C) = Write_Only);
5367
5368 if Mode = Super_Move then
5369 -- The permission of the returned node should be No (thanks
5370 -- to the recursion).
5371
5372 pragma Assert (Permission (C) = No_Access);
5373 null;
5374 end if;
5375
5376 pragma Assert (Kind (C) = Entire_Object
5377 or else Kind (C) = Record_Component);
5378
5379 if Kind (C) = Record_Component then
5380 -- The tree is unfolded. We just modify the permission and
5381 -- return the record subtree.
5382
5383 declare
5384 Selected_Component : constant Entity_Id :=
5385 Entity (Selector_Name (N));
5386
5387 Selected_C : Perm_Tree_Access :=
5388 Perm_Tree_Maps.Get
5389 (Component (C), Selected_Component);
5390
5391 begin
5392 if Selected_C = null then
5393 -- If the hash table returns no element, then we fall
5394 -- into the part of Other_Components.
5395 pragma Assert (Is_Tagged_Type (Etype (Prefix (N))));
5396
5397 Selected_C := Other_Components (C);
5398 end if;
5399
5400 pragma Assert (Selected_C /= null);
5401
5402 -- The Selected_C can have permissions:
5403 -- RW : first move in this path
5404 -- W : Already other moves in this path
5405 -- No : Already other moves with 'Access
5406
5407 pragma Assert (Permission (Selected_C) /= Read_Only);
5408 if Mode = Super_Move then
5409 Selected_C.all.Tree.Permission := No_Access;
5410 else
5411 Selected_C.all.Tree.Permission :=
5412 Glb (Write_Only, Permission (Selected_C));
5413
5414 end if;
5415
5416 return Selected_C;
5417 end;
5418 elsif Kind (C) = Entire_Object then
5419 declare
5420 -- Expand the tree. Replace the node with
5421 -- Record_Component.
5422
5423 Elem : Node_Id;
5424
5425 -- Create an empty hash table
5426
5427 Hashtbl : Perm_Tree_Maps.Instance;
5428
5429 -- We are in Move or Super_Move mode, hence we can assume
5430 -- that the Children_permission is RW, given that there
5431 -- are no other paths that could have been moved.
5432
5433 pragma Assert (Children_Permission (C) = Read_Write);
5434
5435 -- We create the unrolled nodes, that will all have RW
5436 -- permission given that we are in move mode. We will
5437 -- then set the right node to W.
5438
5439 Son : Perm_Tree_Access;
5440
5441 begin
5442 -- We change the current node from Entire_Object to
5443 -- Record_Component with same permission and an empty
5444 -- hash table as component list.
5445
5446 C.all.Tree :=
5447 (Kind => Record_Component,
5448 Is_Node_Deep => Is_Node_Deep (C),
5449 Permission => Permission (C),
5450 Component => Hashtbl,
5451 Other_Components =>
5452 new Perm_Tree_Wrapper'
5453 (Tree =>
5454 (Kind => Entire_Object,
5455 Is_Node_Deep => True,
5456 Permission => Read_Write,
5457 Children_Permission => Read_Write)
5458 ));
5459
5460 -- We fill the hash table with all sons of the record,
5461 -- with basic Entire_Objects nodes.
5462 Elem := First_Component_Or_Discriminant
5463 (Etype (Prefix (N)));
5464
5465 while Present (Elem) loop
5466 Son := new Perm_Tree_Wrapper'
5467 (Tree =>
5468 (Kind => Entire_Object,
5469 Is_Node_Deep => Is_Deep (Etype (Elem)),
5470 Permission => Read_Write,
5471 Children_Permission => Read_Write));
5472
5473 Perm_Tree_Maps.Set
5474 (C.all.Tree.Component, Elem, Son);
5475
5476 Next_Component_Or_Discriminant (Elem);
5477 end loop;
5478
5479 -- Now we set the right field to Write_Only or No_Access
5480 -- depending on mode, and then we return the tree to the
5481 -- sons, so that the recursion can continue.
5482
5483 declare
5484 Selected_Component : constant Entity_Id :=
5485 Entity (Selector_Name (N));
5486
5487 Selected_C : Perm_Tree_Access :=
5488 Perm_Tree_Maps.Get
5489 (Component (C), Selected_Component);
5490
5491 begin
5492 if Selected_C = null then
5493 Selected_C := Other_Components (C);
5494 end if;
5495
5496 pragma Assert (Selected_C /= null);
5497
5498 -- Given that this is a newly created Select_C, we can
5499 -- safely assume that its permission is Read_Write.
5500
5501 pragma Assert (Permission (Selected_C) =
5502 Read_Write);
5503
5504 if Mode = Super_Move then
5505 Selected_C.all.Tree.Permission := No_Access;
5506 else
5507 Selected_C.all.Tree.Permission := Write_Only;
5508 end if;
5509
5510 return Selected_C;
5511 end;
5512 end;
5513 else
5514 raise Program_Error;
5515 end if;
5516 end;
5517
5518 -- We set the permission tree of its prefix, and then we extract
5519 -- from the returned pointer the subtree and assign an adequate
5520 -- permission to it, if unfolded. If folded, we unroll the tree
5521 -- at one step.
5522
5523 when N_Indexed_Component
5524 | N_Slice
5525 =>
5526 declare
5527 C : constant Perm_Tree_Access :=
5528 Set_Perm_Prefixes_Move (Prefix (N), Mode);
5529
5530 begin
5531 if C = null then
5532 -- We went through a function call, do nothing
5533
5534 return null;
5535 end if;
5536
5537 -- The permission of the returned node should be either
5538 -- W (because the recursive call sets <= Write_Only)
5539 -- or No (if another path has been moved with 'Access)
5540
5541 if Mode = Super_Move then
5542 pragma Assert (Permission (C) = No_Access);
5543 null;
5544 else
5545 pragma Assert (Permission (C) = Write_Only
5546 or else Permission (C) = No_Access);
5547 null;
5548 end if;
5549
5550 pragma Assert (Kind (C) = Entire_Object
5551 or else Kind (C) = Array_Component);
5552
5553 if Kind (C) = Array_Component then
5554 -- The tree is unfolded. We just modify the permission and
5555 -- return the elem subtree.
5556
5557 if Get_Elem (C) = null then
5558 -- Hash_Table_Error
5559 raise Program_Error;
5560 end if;
5561
5562 -- The Get_Elem can have permissions :
5563 -- RW : first move in this path
5564 -- W : Already other moves in this path
5565 -- No : Already other moves with 'Access
5566
5567 pragma Assert (Permission (Get_Elem (C)) /= Read_Only);
5568
5569 if Mode = Super_Move then
5570 C.all.Tree.Get_Elem.all.Tree.Permission := No_Access;
5571 else
5572 C.all.Tree.Get_Elem.all.Tree.Permission :=
5573 Glb (Write_Only, Permission (Get_Elem (C)));
5574 end if;
5575
5576 return Get_Elem (C);
5577 elsif Kind (C) = Entire_Object then
5578 declare
5579 -- Expand the tree. Replace node with Array_Component.
5580
5581 -- We are in move mode, hence we can assume that the
5582 -- Children_permission is RW.
5583
5584 pragma Assert (Children_Permission (C) = Read_Write);
5585
5586 Son : Perm_Tree_Access;
5587
5588 begin
5589 Son := new Perm_Tree_Wrapper'
5590 (Tree =>
5591 (Kind => Entire_Object,
5592 Is_Node_Deep => Is_Node_Deep (C),
5593 Permission => Read_Write,
5594 Children_Permission => Read_Write));
5595
5596 if Mode = Super_Move then
5597 Son.all.Tree.Permission := No_Access;
5598 else
5599 Son.all.Tree.Permission := Write_Only;
5600 end if;
5601
5602 -- We change the current node from Entire_Object
5603 -- to Array_Component with same permission and the
5604 -- previously defined son.
5605
5606 C.all.Tree := (Kind => Array_Component,
5607 Is_Node_Deep => Is_Node_Deep (C),
5608 Permission => Permission (C),
5609 Get_Elem => Son);
5610
5611 return Get_Elem (C);
5612 end;
5613 else
5614 raise Program_Error;
5615 end if;
5616 end;
5617
5618 -- We set the permission tree of its prefix, and then we extract
5619 -- from the returned pointer the subtree and assign an adequate
5620 -- permission to it, if unfolded. If folded, we unroll the tree
5621 -- at one step.
5622
5623 when N_Explicit_Dereference =>
5624 declare
5625 C : constant Perm_Tree_Access :=
5626 Set_Perm_Prefixes_Move (Prefix (N), Move);
5627
5628 begin
5629 if C = null then
5630 -- We went through a function call: do nothing
5631
5632 return null;
5633 end if;
5634
5635 -- The permission of the returned node should be only
5636 -- W (because the recursive call sets <= Write_Only)
5637 -- No is NOT POSSIBLE here
5638
5639 pragma Assert (Permission (C) = Write_Only);
5640
5641 pragma Assert (Kind (C) = Entire_Object
5642 or else Kind (C) = Reference);
5643
5644 if Kind (C) = Reference then
5645 -- The tree is unfolded. We just modify the permission and
5646 -- return the elem subtree.
5647
5648 if Get_All (C) = null then
5649 -- Hash_Table_Error
5650 raise Program_Error;
5651 end if;
5652
5653 -- The Get_All can have permissions :
5654 -- RW : first move in this path
5655 -- W : Already other moves in this path
5656 -- No : Already other moves with 'Access
5657
5658 pragma Assert (Permission (Get_All (C)) /= Read_Only);
5659
5660 if Mode = Super_Move then
5661 C.all.Tree.Get_All.all.Tree.Permission := No_Access;
5662 else
5663 Get_All (C).all.Tree.Permission :=
5664 Glb (Write_Only, Permission (Get_All (C)));
5665 end if;
5666 return Get_All (C);
5667 elsif Kind (C) = Entire_Object then
5668 declare
5669 -- Expand the tree. Replace the node with Reference.
5670
5671 -- We are in Move or Super_Move mode, hence we can assume
5672 -- that the Children_permission is RW.
5673
5674 pragma Assert (Children_Permission (C) = Read_Write);
5675
5676 Son : Perm_Tree_Access;
5677
5678 begin
5679 Son := new Perm_Tree_Wrapper'
5680 (Tree =>
5681 (Kind => Entire_Object,
5682 Is_Node_Deep => Is_Deep (Etype (N)),
5683 Permission => Read_Write,
5684 Children_Permission => Read_Write));
5685
5686 if Mode = Super_Move then
5687 Son.all.Tree.Permission := No_Access;
5688 else
5689 Son.all.Tree.Permission := Write_Only;
5690 end if;
5691
5692 -- We change the current node from Entire_Object to
5693 -- Reference with Write_Only and the previous son.
5694
5695 pragma Assert (Is_Node_Deep (C));
5696
5697 C.all.Tree := (Kind => Reference,
5698 Is_Node_Deep => Is_Node_Deep (C),
5699 Permission => Write_Only,
5700 -- Write_only is equal to C.Permission
5701 Get_All => Son);
5702
5703 return Get_All (C);
5704 end;
5705 else
5706 raise Program_Error;
5707 end if;
5708 end;
5709
5710 when N_Function_Call =>
5711 return null;
5712
5713 when others =>
5714 raise Program_Error;
5715 end case;
5716
5717 end Set_Perm_Prefixes_Move;
5718
5719 -------------------------------
5720 -- Set_Perm_Prefixes_Observe --
5721 -------------------------------
5722
5723 function Set_Perm_Prefixes_Observe
5724 (N : Node_Id)
5725 return Perm_Tree_Access
5726 is
5727 begin
5728 pragma Assert (Current_Checking_Mode = Observe);
5729
5730 case Nkind (N) is
5731 -- Base identifier. Set permission to R.
5732
5733 when N_Identifier
5734 | N_Expanded_Name
5735 | N_Defining_Identifier
5736 =>
5737 declare
5738 P : Node_Id;
5739 C : Perm_Tree_Access;
5740
5741 begin
5742 if Nkind (N) = N_Defining_Identifier then
5743 P := N;
5744 else
5745 P := Entity (N);
5746 end if;
5747
5748 C := Get (Current_Perm_Env, Unique_Entity (P));
5749 -- Setting the initialization map to True, so that this
5750 -- variable cannot be ignored anymore when looking at end
5751 -- of elaboration of package.
5752
5753 Set (Current_Initialization_Map, Unique_Entity (P), True);
5754
5755 if C = null then
5756 -- No null possible here, there are no parents for the path.
5757 -- This means we are using a global variable without adding
5758 -- it in environment with a global aspect.
5759
5760 Illegal_Global_Usage (N);
5761 end if;
5762
5763 C.all.Tree.Permission := Glb (Read_Only, Permission (C));
5764
5765 return C;
5766 end;
5767
5768 when N_Type_Conversion
5769 | N_Unchecked_Type_Conversion
5770 | N_Qualified_Expression
5771 =>
5772 return Set_Perm_Prefixes_Observe (Expression (N));
5773
5774 when N_Parameter_Specification =>
5775 raise Program_Error;
5776
5777 -- We set the permission tree of its prefix, and then we extract
5778 -- from the returned pointer our subtree and assign an adequate
5779 -- permission to it, if unfolded. If folded, we unroll the tree
5780 -- at one step.
5781
5782 when N_Selected_Component =>
5783 declare
5784 C : constant Perm_Tree_Access :=
5785 Set_Perm_Prefixes_Observe (Prefix (N));
5786
5787 begin
5788 if C = null then
5789 -- We went through a function call, do nothing
5790
5791 return null;
5792 end if;
5793
5794 pragma Assert (Kind (C) = Entire_Object
5795 or else Kind (C) = Record_Component);
5796
5797 if Kind (C) = Record_Component then
5798 -- The tree is unfolded. We just modify the permission and
5799 -- return the record subtree. We put the permission to the
5800 -- glb of read_only and its current permission, to consider
5801 -- the case of observing x.y while x.z has been moved. Then
5802 -- x should be No_Access.
5803
5804 declare
5805 Selected_Component : constant Entity_Id :=
5806 Entity (Selector_Name (N));
5807
5808 Selected_C : Perm_Tree_Access :=
5809 Perm_Tree_Maps.Get
5810 (Component (C), Selected_Component);
5811
5812 begin
5813 if Selected_C = null then
5814 Selected_C := Other_Components (C);
5815 end if;
5816
5817 pragma Assert (Selected_C /= null);
5818
5819 Selected_C.all.Tree.Permission :=
5820 Glb (Read_Only, Permission (Selected_C));
5821
5822 return Selected_C;
5823 end;
5824 elsif Kind (C) = Entire_Object then
5825 declare
5826 -- Expand the tree. Replace the node with
5827 -- Record_Component.
5828
5829 Elem : Node_Id;
5830
5831 -- Create an empty hash table
5832
5833 Hashtbl : Perm_Tree_Maps.Instance;
5834
5835 -- We create the unrolled nodes, that will all have RW
5836 -- permission given that we are in move mode. We will
5837 -- then set the right node to W.
5838
5839 Son : Perm_Tree_Access;
5840
5841 Child_Perm : constant Perm_Kind :=
5842 Children_Permission (C);
5843
5844 begin
5845 -- We change the current node from Entire_Object to
5846 -- Record_Component with same permission and an empty
5847 -- hash table as component list.
5848
5849 C.all.Tree :=
5850 (Kind => Record_Component,
5851 Is_Node_Deep => Is_Node_Deep (C),
5852 Permission => Permission (C),
5853 Component => Hashtbl,
5854 Other_Components =>
5855 new Perm_Tree_Wrapper'
5856 (Tree =>
5857 (Kind => Entire_Object,
5858 Is_Node_Deep => True,
5859 Permission => Child_Perm,
5860 Children_Permission => Child_Perm)
5861 ));
5862
5863 -- We fill the hash table with all sons of the record,
5864 -- with basic Entire_Objects nodes.
5865 Elem := First_Component_Or_Discriminant
5866 (Etype (Prefix (N)));
5867
5868 while Present (Elem) loop
5869 Son := new Perm_Tree_Wrapper'
5870 (Tree =>
5871 (Kind => Entire_Object,
5872 Is_Node_Deep => Is_Deep (Etype (Elem)),
5873 Permission => Child_Perm,
5874 Children_Permission => Child_Perm));
5875
5876 Perm_Tree_Maps.Set
5877 (C.all.Tree.Component, Elem, Son);
5878
5879 Next_Component_Or_Discriminant (Elem);
5880 end loop;
5881
5882 -- Now we set the right field to Read_Only. and then we
5883 -- return the tree to the sons, so that the recursion can
5884 -- continue.
5885
5886 declare
5887 Selected_Component : constant Entity_Id :=
5888 Entity (Selector_Name (N));
5889
5890 Selected_C : Perm_Tree_Access :=
5891 Perm_Tree_Maps.Get
5892 (Component (C), Selected_Component);
5893
5894 begin
5895 if Selected_C = null then
5896 Selected_C := Other_Components (C);
5897 end if;
5898
5899 pragma Assert (Selected_C /= null);
5900
5901 Selected_C.all.Tree.Permission :=
5902 Glb (Read_Only, Child_Perm);
5903
5904 return Selected_C;
5905 end;
5906 end;
5907 else
5908 raise Program_Error;
5909 end if;
5910 end;
5911
5912 -- We set the permission tree of its prefix, and then we extract from
5913 -- the returned pointer the subtree and assign an adequate permission
5914 -- to it, if unfolded. If folded, we unroll the tree at one step.
5915
5916 when N_Indexed_Component
5917 | N_Slice
5918 =>
5919 declare
5920 C : constant Perm_Tree_Access :=
5921 Set_Perm_Prefixes_Observe (Prefix (N));
5922
5923 begin
5924 if C = null then
5925 -- We went through a function call, do nothing
5926
5927 return null;
5928 end if;
5929
5930 pragma Assert (Kind (C) = Entire_Object
5931 or else Kind (C) = Array_Component);
5932
5933 if Kind (C) = Array_Component then
5934 -- The tree is unfolded. We just modify the permission and
5935 -- return the elem subtree.
5936
5937 pragma Assert (Get_Elem (C) /= null);
5938
5939 C.all.Tree.Get_Elem.all.Tree.Permission :=
5940 Glb (Read_Only, Permission (Get_Elem (C)));
5941
5942 return Get_Elem (C);
5943 elsif Kind (C) = Entire_Object then
5944 declare
5945 -- Expand the tree. Replace node with Array_Component.
5946
5947 Son : Perm_Tree_Access;
5948
5949 Child_Perm : constant Perm_Kind :=
5950 Glb (Read_Only, Children_Permission (C));
5951
5952 begin
5953 Son := new Perm_Tree_Wrapper'
5954 (Tree =>
5955 (Kind => Entire_Object,
5956 Is_Node_Deep => Is_Node_Deep (C),
5957 Permission => Child_Perm,
5958 Children_Permission => Child_Perm));
5959
5960 -- We change the current node from Entire_Object
5961 -- to Array_Component with same permission and the
5962 -- previously defined son.
5963
5964 C.all.Tree := (Kind => Array_Component,
5965 Is_Node_Deep => Is_Node_Deep (C),
5966 Permission => Child_Perm,
5967 Get_Elem => Son);
5968
5969 return Get_Elem (C);
5970 end;
5971
5972 else
5973 raise Program_Error;
5974 end if;
5975 end;
5976
5977 -- We set the permission tree of its prefix, and then we extract from
5978 -- the returned pointer the subtree and assign an adequate permission
5979 -- to it, if unfolded. If folded, we unroll the tree at one step.
5980
5981 when N_Explicit_Dereference =>
5982 declare
5983 C : constant Perm_Tree_Access :=
5984 Set_Perm_Prefixes_Observe (Prefix (N));
5985
5986 begin
5987 if C = null then
5988 -- We went through a function call, do nothing
5989
5990 return null;
5991 end if;
5992
5993 pragma Assert (Kind (C) = Entire_Object
5994 or else Kind (C) = Reference);
5995
5996 if Kind (C) = Reference then
5997 -- The tree is unfolded. We just modify the permission and
5998 -- return the elem subtree.
5999
6000 pragma Assert (Get_All (C) /= null);
6001
6002 C.all.Tree.Get_All.all.Tree.Permission :=
6003 Glb (Read_Only, Permission (Get_All (C)));
6004
6005 return Get_All (C);
6006 elsif Kind (C) = Entire_Object then
6007 declare
6008 -- Expand the tree. Replace the node with Reference.
6009
6010 Son : Perm_Tree_Access;
6011
6012 Child_Perm : constant Perm_Kind :=
6013 Glb (Read_Only, Children_Permission (C));
6014
6015 begin
6016 Son := new Perm_Tree_Wrapper'
6017 (Tree =>
6018 (Kind => Entire_Object,
6019 Is_Node_Deep => Is_Deep (Etype (N)),
6020 Permission => Child_Perm,
6021 Children_Permission => Child_Perm));
6022
6023 -- We change the current node from Entire_Object to
6024 -- Reference with Write_Only and the previous son.
6025
6026 pragma Assert (Is_Node_Deep (C));
6027
6028 C.all.Tree := (Kind => Reference,
6029 Is_Node_Deep => Is_Node_Deep (C),
6030 Permission => Child_Perm,
6031 Get_All => Son);
6032
6033 return Get_All (C);
6034 end;
6035 else
6036 raise Program_Error;
6037 end if;
6038 end;
6039
6040 when N_Function_Call =>
6041 return null;
6042
6043 when others =>
6044 raise Program_Error;
6045
6046 end case;
6047 end Set_Perm_Prefixes_Observe;
6048 4370
6049 ------------------- 4371 -------------------
6050 -- Setup_Globals -- 4372 -- Setup_Globals --
6051 ------------------- 4373 -------------------
6052 4374
6053 procedure Setup_Globals (Subp : Entity_Id) is 4375 procedure Setup_Globals (Subp : Entity_Id) is
6054
6055 procedure Setup_Globals_From_List 4376 procedure Setup_Globals_From_List
6056 (First_Item : Node_Id; 4377 (First_Item : Node_Id;
6057 Kind : Formal_Kind); 4378 Kind : Formal_Kind);
6058 -- Set up global items from the list starting at Item 4379 -- Set up global items from the list starting at Item
6059 4380
6078 -- Ignore abstract states, which play no role in pointer aliasing 4399 -- Ignore abstract states, which play no role in pointer aliasing
6079 4400
6080 if Ekind (E) = E_Abstract_State then 4401 if Ekind (E) = E_Abstract_State then
6081 null; 4402 null;
6082 else 4403 else
6083 Setup_Parameter_Or_Global (E, Kind); 4404 Setup_Parameter_Or_Global (E, Kind, Global_Var => True);
6084 end if; 4405 end if;
6085 Next_Global (Item); 4406 Next_Global (Item);
6086 end loop; 4407 end loop;
6087 end Setup_Globals_From_List; 4408 end Setup_Globals_From_List;
6088 4409
6093 procedure Setup_Globals_Of_Mode (Global_Mode : Name_Id) is 4414 procedure Setup_Globals_Of_Mode (Global_Mode : Name_Id) is
6094 Kind : Formal_Kind; 4415 Kind : Formal_Kind;
6095 4416
6096 begin 4417 begin
6097 case Global_Mode is 4418 case Global_Mode is
6098 when Name_Input | Name_Proof_In => 4419 when Name_Input
4420 | Name_Proof_In
4421 =>
6099 Kind := E_In_Parameter; 4422 Kind := E_In_Parameter;
4423
6100 when Name_Output => 4424 when Name_Output =>
6101 Kind := E_Out_Parameter; 4425 Kind := E_Out_Parameter;
4426
6102 when Name_In_Out => 4427 when Name_In_Out =>
6103 Kind := E_In_Out_Parameter; 4428 Kind := E_In_Out_Parameter;
4429
6104 when others => 4430 when others =>
6105 raise Program_Error; 4431 raise Program_Error;
6106 end case; 4432 end case;
6107 4433
6108 -- Set up both global items from Global and Refined_Global pragmas 4434 -- Set up both global items from Global and Refined_Global pragmas
6124 ------------------------------- 4450 -------------------------------
6125 -- Setup_Parameter_Or_Global -- 4451 -- Setup_Parameter_Or_Global --
6126 ------------------------------- 4452 -------------------------------
6127 4453
6128 procedure Setup_Parameter_Or_Global 4454 procedure Setup_Parameter_Or_Global
6129 (Id : Entity_Id; 4455 (Id : Entity_Id;
6130 Mode : Formal_Kind) 4456 Mode : Formal_Kind;
4457 Global_Var : Boolean)
6131 is 4458 is
6132 Elem : Perm_Tree_Access; 4459 Elem : Perm_Tree_Access;
4460 View_Typ : Entity_Id;
6133 4461
6134 begin 4462 begin
4463 if Present (Full_View (Etype (Id))) then
4464 View_Typ := Full_View (Etype (Id));
4465 else
4466 View_Typ := Etype (Id);
4467 end if;
4468
6135 Elem := new Perm_Tree_Wrapper' 4469 Elem := new Perm_Tree_Wrapper'
6136 (Tree => 4470 (Tree =>
6137 (Kind => Entire_Object, 4471 (Kind => Entire_Object,
6138 Is_Node_Deep => Is_Deep (Etype (Id)), 4472 Is_Node_Deep => Is_Deep (Etype (Id)),
6139 Permission => Read_Write, 4473 Permission => Unrestricted,
6140 Children_Permission => Read_Write)); 4474 Children_Permission => Unrestricted));
6141 4475
6142 case Mode is 4476 case Mode is
4477
4478 -- All out and in out parameters are considered to be unrestricted.
4479 -- They are whether borrowed or moved. Ada Rules would restrict
4480 -- these permissions further. For example an in parameter cannot
4481 -- be written.
4482
4483 -- In the following we deal with in parameters that can be observed.
4484 -- We only consider the observing cases.
4485
6143 when E_In_Parameter => 4486 when E_In_Parameter =>
6144 4487
6145 -- Borrowed IN: RW for everybody 4488 -- Handling global variables as IN parameters here.
6146 4489 -- Remove the following condition once it's decided how globals
6147 if Is_Borrowed_In (Id) then 4490 -- should be considered. ???
6148 Elem.all.Tree.Permission := Read_Write; 4491 --
6149 Elem.all.Tree.Children_Permission := Read_Write; 4492 -- In SPARK, IN access-to-variable is an observe operation for
6150 4493 -- a function, and a borrow operation for a procedure.
6151 -- Observed IN: R for everybody 4494
4495 if not Global_Var then
4496 if (Is_Access_Type (View_Typ)
4497 and then Is_Access_Constant (View_Typ)
4498 and then Is_Anonymous_Access_Type (View_Typ))
4499 or else
4500 (Is_Access_Type (View_Typ)
4501 and then Ekind (Scope (Id)) = E_Function)
4502 or else
4503 (not Is_Access_Type (View_Typ)
4504 and then Is_Deep (View_Typ)
4505 and then not Is_Anonymous_Access_Type (View_Typ))
4506 then
4507 Elem.all.Tree.Permission := Observed;
4508 Elem.all.Tree.Children_Permission := Observed;
4509
4510 else
4511 Elem.all.Tree.Permission := Unrestricted;
4512 Elem.all.Tree.Children_Permission := Unrestricted;
4513 end if;
6152 4514
6153 else 4515 else
6154 Elem.all.Tree.Permission := Read_Only; 4516 Elem.all.Tree.Permission := Observed;
6155 Elem.all.Tree.Children_Permission := Read_Only; 4517 Elem.all.Tree.Children_Permission := Observed;
6156 end if; 4518 end if;
6157 4519
6158 -- OUT: borrow, but callee has W only 4520 -- When out or in/out formal or global parameters, we set them to
6159 4521 -- the Unrestricted state. "We want to be able to assume that all
6160 when E_Out_Parameter => 4522 -- relevant writable globals are unrestricted when a subprogram
6161 Elem.all.Tree.Permission := Write_Only; 4523 -- starts executing". Formal parameters of mode out or in/out
6162 Elem.all.Tree.Children_Permission := Write_Only; 4524 -- are whether Borrowers or the targets of a move operation:
6163 4525 -- they start theirs lives in the subprogram as Unrestricted.
6164 -- IN OUT: borrow and callee has RW 4526
6165 4527 when others =>
6166 when E_In_Out_Parameter => 4528 Elem.all.Tree.Permission := Unrestricted;
6167 Elem.all.Tree.Permission := Read_Write; 4529 Elem.all.Tree.Children_Permission := Unrestricted;
6168 Elem.all.Tree.Children_Permission := Read_Write;
6169 end case; 4530 end case;
6170 4531
6171 Set (Current_Perm_Env, Id, Elem); 4532 Set (Current_Perm_Env, Id, Elem);
6172 end Setup_Parameter_Or_Global; 4533 end Setup_Parameter_Or_Global;
6173 4534
6174 ---------------------- 4535 ----------------------
6175 -- Setup_Parameters -- 4536 -- Setup_Parameters --
6176 ---------------------- 4537 ----------------------
6177 4538
6178 procedure Setup_Parameters (Subp : Entity_Id) is 4539 procedure Setup_Parameters (Subp : Entity_Id) is Formal : Entity_Id;
6179 Formal : Entity_Id;
6180
6181 begin 4540 begin
6182 Formal := First_Formal (Subp); 4541 Formal := First_Formal (Subp);
6183 while Present (Formal) loop 4542 while Present (Formal) loop
6184 Setup_Parameter_Or_Global (Formal, Ekind (Formal)); 4543 Setup_Parameter_Or_Global
4544 (Formal, Ekind (Formal), Global_Var => False);
6185 Next_Formal (Formal); 4545 Next_Formal (Formal);
6186 end loop; 4546 end loop;
6187 end Setup_Parameters; 4547 end Setup_Parameters;
6188 4548
4549 -------------------------------
4550 -- Has_Ownership_Aspect_True --
4551 -------------------------------
4552
4553 function Has_Ownership_Aspect_True
4554 (N : Entity_Id;
4555 Msg : String)
4556 return Boolean
4557 is
4558 begin
4559 case Ekind (Etype (N)) is
4560 when Access_Kind =>
4561 if Ekind (Etype (N)) = E_General_Access_Type then
4562 Error_Msg_NE (Msg & " & not allowed " &
4563 "(Named General Access type)", N, N);
4564 return False;
4565
4566 else
4567 return True;
4568 end if;
4569
4570 when E_Array_Type
4571 | E_Array_Subtype
4572 =>
4573 declare
4574 Com_Ty : constant Node_Id := Component_Type (Etype (N));
4575 Ret : Boolean := Has_Ownership_Aspect_True (Com_Ty, "");
4576
4577 begin
4578 if Nkind (Parent (N)) = N_Full_Type_Declaration and
4579 Is_Anonymous_Access_Type (Com_Ty)
4580 then
4581 Ret := False;
4582 end if;
4583
4584 if not Ret then
4585 Error_Msg_NE (Msg & " & not allowed "
4586 & "(Components of Named General Access type or"
4587 & " Anonymous type)", N, N);
4588 end if;
4589 return Ret;
4590 end;
4591
4592 -- ??? What about hidden components
4593
4594 when E_Record_Type
4595 | E_Record_Subtype
4596 =>
4597 declare
4598 Elmt : Entity_Id;
4599 Elmt_T_Perm : Boolean := True;
4600 Elmt_Perm, Elmt_Anonym : Boolean;
4601
4602 begin
4603 Elmt := First_Component_Or_Discriminant (Etype (N));
4604 while Present (Elmt) loop
4605 Elmt_Perm := Has_Ownership_Aspect_True (Elmt,
4606 "type of component");
4607 Elmt_Anonym := Is_Anonymous_Access_Type (Etype (Elmt));
4608 if Elmt_Anonym then
4609 Error_Msg_NE
4610 ("type of component & not allowed"
4611 & " (Components of Anonymous type)", Elmt, Elmt);
4612 end if;
4613 Elmt_T_Perm := Elmt_T_Perm and Elmt_Perm and not Elmt_Anonym;
4614 Next_Component_Or_Discriminant (Elmt);
4615 end loop;
4616 if not Elmt_T_Perm then
4617 Error_Msg_NE
4618 (Msg & " & not allowed (One or "
4619 & "more components have Ownership Aspect False)",
4620 N, N);
4621 end if;
4622 return Elmt_T_Perm;
4623 end;
4624
4625 when others =>
4626 return True;
4627 end case;
4628
4629 end Has_Ownership_Aspect_True;
6189 end Sem_SPARK; 4630 end Sem_SPARK;