Mercurial > hg > CbC > CbC_gcc
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; |