1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1992-2004 Free Software Foundation, Inc. --
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- --
13 -- ware Foundation; either version 2, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
20 -- MA 02111-1307, USA. --
22 -- GNAT was originally developed by the GNAT team at New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc. --
25 ------------------------------------------------------------------------------
27 with Atree
; use Atree
;
28 with Casing
; use Casing
;
29 with Errout
; use Errout
;
30 with Fname
; use Fname
;
31 with Fname
.UF
; use Fname
.UF
;
33 with Namet
; use Namet
;
34 with Sinput
; use Sinput
;
35 with Uname
; use Uname
;
37 package body Restrict
is
39 -----------------------
40 -- Local Subprograms --
41 -----------------------
43 procedure Restriction_Msg
(Msg
: String; R
: String; N
: Node_Id
);
44 -- Output error message at node N with given text, replacing the
45 -- '%' in the message with the name of the restriction given as R,
46 -- cased according to the current identifier casing. We do not use
47 -- the normal insertion mechanism, since this requires an entry
48 -- in the Names table, and this table will be locked if we are
49 -- generating a message from gigi.
51 function Suppress_Restriction_Message
(N
: Node_Id
) return Boolean;
52 -- N is the node for a possible restriction violation message, but
53 -- the message is to be suppressed if this is an internal file and
54 -- this file is not the main unit.
60 function Abort_Allowed
return Boolean is
62 if Restrictions
.Set
(No_Abort_Statements
)
63 and then Restrictions
.Set
(Max_Asynchronous_Select_Nesting
)
64 and then Restrictions
.Value
(Max_Asynchronous_Select_Nesting
) = 0
72 ------------------------------------
73 -- Check_Elaboration_Code_Allowed --
74 ------------------------------------
76 procedure Check_Elaboration_Code_Allowed
(N
: Node_Id
) is
78 -- Avoid calling Namet.Unlock/Lock except when there is an error.
79 -- Even in the error case it is a bit dubious, either gigi needs
80 -- the table locked or it does not! ???
82 if Restrictions
.Set
(No_Elaboration_Code
)
83 and then not Suppress_Restriction_Message
(N
)
86 Check_Restriction
(Restriction_Id
'(No_Elaboration_Code), N);
89 end Check_Elaboration_Code_Allowed;
91 ----------------------------------
92 -- Check_No_Implicit_Heap_Alloc --
93 ----------------------------------
95 procedure Check_No_Implicit_Heap_Alloc (N : Node_Id) is
97 Check_Restriction (Restriction_Id'(No_Implicit_Heap_Allocations
), N
);
98 end Check_No_Implicit_Heap_Alloc
;
100 ---------------------------
101 -- Check_Restricted_Unit --
102 ---------------------------
104 procedure Check_Restricted_Unit
(U
: Unit_Name_Type
; N
: Node_Id
) is
106 if Suppress_Restriction_Message
(N
) then
109 elsif Is_Spec_Name
(U
) then
111 Fnam
: constant File_Name_Type
:=
112 Get_File_Name
(U
, Subunit
=> False);
115 if not Is_Predefined_File_Name
(Fnam
) then
118 -- Predefined spec, needs checking against list
121 -- Pad name to 8 characters with blanks
123 Get_Name_String
(Fnam
);
124 Name_Len
:= Name_Len
- 4;
126 while Name_Len
< 8 loop
127 Name_Len
:= Name_Len
+ 1;
128 Name_Buffer
(Name_Len
) := ' ';
131 for J
in Unit_Array
'Range loop
133 and then Name_Buffer
(1 .. 8) = Unit_Array
(J
).Filenm
135 Check_Restriction
(Unit_Array
(J
).Res_Id
, N
);
141 end Check_Restricted_Unit
;
143 -----------------------
144 -- Check_Restriction --
145 -----------------------
147 procedure Check_Restriction
150 V
: Uint
:= Uint_Minus_1
)
152 Rimage
: constant String := Restriction_Id
'Image (R
);
155 -- V converted to integer form. If V is greater than Integer'Last,
156 -- it is reset to minus 1 (unknown value).
158 procedure Update_Restrictions
(Info
: in out Restrictions_Info
);
159 -- Update violation information in Info.Violated and Info.Count
161 -------------------------
162 -- Update_Restrictions --
163 -------------------------
165 procedure Update_Restrictions
(Info
: in out Restrictions_Info
) is
167 -- If not violated, set as violated now
169 if not Info
.Violated
(R
) then
170 Info
.Violated
(R
) := True;
172 if R
in All_Parameter_Restrictions
then
174 Info
.Unknown
(R
) := True;
177 Info
.Count
(R
) := VV
;
181 -- Otherwise if violated already and a parameter restriction,
182 -- update count by maximizing or summing depending on restriction.
184 elsif R
in All_Parameter_Restrictions
then
186 -- If new value is unknown, result is unknown
189 Info
.Unknown
(R
) := True;
191 -- If checked by maximization, do maximization
193 elsif R
in Checked_Max_Parameter_Restrictions
then
194 Info
.Count
(R
) := Integer'Max (Info
.Count
(R
), VV
);
196 -- If checked by adding, do add, checking for overflow
198 elsif R
in Checked_Add_Parameter_Restrictions
then
200 pragma Unsuppress
(Overflow_Check
);
202 Info
.Count
(R
) := Info
.Count
(R
) + VV
;
204 when Constraint_Error
=>
205 Info
.Count
(R
) := Integer'Last;
206 Info
.Unknown
(R
) := True;
209 -- Should not be able to come here, known counts should only
210 -- occur for restrictions that are Checked_max or Checked_Sum.
216 end Update_Restrictions
;
218 -- Start of processing for Check_Restriction
221 if UI_Is_In_Int_Range
(V
) then
222 VV
:= Integer (UI_To_Int
(V
));
227 -- Count can only be specified in the checked val parameter case
229 pragma Assert
(VV
< 0 or else R
in Checked_Val_Parameter_Restrictions
);
231 -- Nothing to do if value of zero specified for parameter restriction
237 -- Update current restrictions
239 Update_Restrictions
(Restrictions
);
241 -- If in main extended unit, update main restrictions as well
243 if Current_Sem_Unit
= Main_Unit
244 or else In_Extended_Main_Source_Unit
(N
)
246 Update_Restrictions
(Main_Restrictions
);
249 -- Nothing to do if restriction message suppressed
251 if Suppress_Restriction_Message
(N
) then
254 -- If restriction not set, nothing to do
256 elsif not Restrictions
.Set
(R
) then
259 -- Here if restriction set, check for violation (either this is a
260 -- Boolean restriction, or a parameter restriction with a value of
261 -- zero and an unknown count, or a parameter restriction with a
262 -- known value that exceeds the restriction count).
264 elsif R
in All_Boolean_Restrictions
265 or else (Restrictions
.Unknown
(R
)
266 and then Restrictions
.Value
(R
) = 0)
267 or else Restrictions
.Count
(R
) > Restrictions
.Value
(R
)
269 Error_Msg_Sloc
:= Restrictions_Loc
(R
);
271 -- If we have a location for the Restrictions pragma, output it
273 if Error_Msg_Sloc
> No_Location
274 or else Error_Msg_Sloc
= System_Location
276 if Restriction_Warnings
(R
) then
277 Restriction_Msg
("|violation of restriction %#?", Rimage
, N
);
279 Restriction_Msg
("|violation of restriction %#", Rimage
, N
);
282 -- Otherwise we have the case of an implicit restriction
283 -- (e.g. a restriction implicitly set by another pragma)
287 ("|violation of implicit restriction %", Rimage
, N
);
290 end Check_Restriction
;
292 ----------------------------------------
293 -- Cunit_Boolean_Restrictions_Restore --
294 ----------------------------------------
296 procedure Cunit_Boolean_Restrictions_Restore
297 (R
: Save_Cunit_Boolean_Restrictions
)
300 for J
in Cunit_Boolean_Restrictions
loop
301 Restrictions
.Set
(J
) := R
(J
);
303 end Cunit_Boolean_Restrictions_Restore
;
305 -------------------------------------
306 -- Cunit_Boolean_Restrictions_Save --
307 -------------------------------------
309 function Cunit_Boolean_Restrictions_Save
310 return Save_Cunit_Boolean_Restrictions
312 R
: Save_Cunit_Boolean_Restrictions
;
315 for J
in Cunit_Boolean_Restrictions
loop
316 R
(J
) := Restrictions
.Set
(J
);
317 Restrictions
.Set
(J
) := False;
321 end Cunit_Boolean_Restrictions_Save
;
323 ------------------------
324 -- Get_Restriction_Id --
325 ------------------------
327 function Get_Restriction_Id
328 (N
: Name_Id
) return Restriction_Id
332 Set_Casing
(All_Upper_Case
);
334 for J
in All_Restrictions
loop
336 S
: constant String := Restriction_Id
'Image (J
);
338 if S
= Name_Buffer
(1 .. Name_Len
) then
344 return Not_A_Restriction_Id
;
345 end Get_Restriction_Id
;
347 -------------------------------
348 -- No_Exception_Handlers_Set --
349 -------------------------------
351 function No_Exception_Handlers_Set
return Boolean is
353 return Restrictions
.Set
(No_Exception_Handlers
);
354 end No_Exception_Handlers_Set
;
356 ------------------------
357 -- Restricted_Profile --
358 ------------------------
360 -- This implementation must be coordinated with Set_Restricted_Profile
362 function Restricted_Profile
return Boolean is
364 return Restrictions
.Set
(No_Abort_Statements
)
365 and then Restrictions
.Set
(No_Asynchronous_Control
)
366 and then Restrictions
.Set
(No_Entry_Queue
)
367 and then Restrictions
.Set
(No_Task_Hierarchy
)
368 and then Restrictions
.Set
(No_Task_Allocators
)
369 and then Restrictions
.Set
(No_Dynamic_Priorities
)
370 and then Restrictions
.Set
(No_Terminate_Alternatives
)
371 and then Restrictions
.Set
(No_Dynamic_Attachment
)
372 and then Restrictions
.Set
(No_Protected_Type_Allocators
)
373 and then Restrictions
.Set
(No_Local_Protected_Objects
)
374 and then Restrictions
.Set
(No_Requeue_Statements
)
375 and then Restrictions
.Set
(No_Task_Attributes_Package
)
376 and then Restrictions
.Set
(Max_Asynchronous_Select_Nesting
)
377 and then Restrictions
.Set
(Max_Task_Entries
)
378 and then Restrictions
.Set
(Max_Protected_Entries
)
379 and then Restrictions
.Set
(Max_Select_Alternatives
)
380 and then Restrictions
.Value
(Max_Asynchronous_Select_Nesting
) = 0
381 and then Restrictions
.Value
(Max_Task_Entries
) = 0
382 and then Restrictions
.Value
(Max_Protected_Entries
) <= 1
383 and then Restrictions
.Value
(Max_Select_Alternatives
) = 0;
384 end Restricted_Profile
;
386 ------------------------
387 -- Restriction_Active --
388 ------------------------
390 function Restriction_Active
(R
: All_Restrictions
) return Boolean is
392 return Restrictions
.Set
(R
);
393 end Restriction_Active
;
395 ---------------------
396 -- Restriction_Msg --
397 ---------------------
399 procedure Restriction_Msg
(Msg
: String; R
: String; N
: Node_Id
) is
400 B
: String (1 .. Msg
'Length + 2 * R
'Length + 1);
404 Name_Buffer
(1 .. R
'Last) := R
;
405 Name_Len
:= R
'Length;
406 Set_Casing
(Identifier_Casing
(Get_Source_File_Index
(Sloc
(N
))));
409 for J
in Msg
'Range loop
410 if Msg
(J
) = '%' then
414 -- Put characters of image in message, quoting upper case letters
416 for J
in 1 .. Name_Len
loop
417 if Name_Buffer
(J
) in 'A' .. 'Z' then
423 B
(P
) := Name_Buffer
(J
);
435 Error_Msg_N
(B
(1 .. P
), N
);
442 procedure Set_Ravenscar
(N
: Node_Id
) is
444 Set_Restricted_Profile
(N
);
445 Set_Restriction
(Simple_Barriers
, N
);
446 Set_Restriction
(No_Select_Statements
, N
);
447 Set_Restriction
(No_Calendar
, N
);
448 Set_Restriction
(No_Entry_Queue
, N
);
449 Set_Restriction
(No_Relative_Delay
, N
);
450 Set_Restriction
(No_Task_Termination
, N
);
451 Set_Restriction
(No_Implicit_Heap_Allocations
, N
);
454 ----------------------------
455 -- Set_Restricted_Profile --
456 ----------------------------
458 -- This must be coordinated with Restricted_Profile
460 procedure Set_Restricted_Profile
(N
: Node_Id
) is
462 -- Set Boolean restrictions for Restricted Profile
464 Set_Restriction
(No_Abort_Statements
, N
);
465 Set_Restriction
(No_Asynchronous_Control
, N
);
466 Set_Restriction
(No_Entry_Queue
, N
);
467 Set_Restriction
(No_Task_Hierarchy
, N
);
468 Set_Restriction
(No_Task_Allocators
, N
);
469 Set_Restriction
(No_Dynamic_Priorities
, N
);
470 Set_Restriction
(No_Terminate_Alternatives
, N
);
471 Set_Restriction
(No_Dynamic_Attachment
, N
);
472 Set_Restriction
(No_Protected_Type_Allocators
, N
);
473 Set_Restriction
(No_Local_Protected_Objects
, N
);
474 Set_Restriction
(No_Requeue_Statements
, N
);
475 Set_Restriction
(No_Task_Attributes_Package
, N
);
477 -- Set parameter restrictions
479 Set_Restriction
(Max_Asynchronous_Select_Nesting
, N
, 0);
480 Set_Restriction
(Max_Task_Entries
, N
, 0);
481 Set_Restriction
(Max_Select_Alternatives
, N
, 0);
482 Set_Restriction
(Max_Protected_Entries
, N
, 1);
483 end Set_Restricted_Profile
;
485 ---------------------
486 -- Set_Restriction --
487 ---------------------
489 -- Case of Boolean restriction
491 procedure Set_Restriction
492 (R
: All_Boolean_Restrictions
;
496 Restrictions
.Set
(R
) := True;
498 -- Set location, but preserve location of system
499 -- restriction for nice error msg with run time name
501 if Restrictions_Loc
(R
) /= System_Location
then
502 Restrictions_Loc
(R
) := Sloc
(N
);
505 -- Record the restriction if we are in the main unit,
506 -- or in the extended main unit. The reason that we
507 -- test separately for Main_Unit is that gnat.adc is
508 -- processed with Current_Sem_Unit = Main_Unit, but
509 -- nodes in gnat.adc do not appear to be the extended
510 -- main source unit (they probably should do ???)
512 if Current_Sem_Unit
= Main_Unit
513 or else In_Extended_Main_Source_Unit
(N
)
515 if not Restriction_Warnings
(R
) then
516 Main_Restrictions
.Set
(R
) := True;
521 -- Case of parameter restriction
523 procedure Set_Restriction
524 (R
: All_Parameter_Restrictions
;
529 if Restrictions
.Set
(R
) then
530 if V
< Restrictions
.Value
(R
) then
531 Restrictions
.Value
(R
) := V
;
532 Restrictions_Loc
(R
) := Sloc
(N
);
536 Restrictions
.Set
(R
) := True;
537 Restrictions
.Value
(R
) := V
;
538 Restrictions_Loc
(R
) := Sloc
(N
);
541 -- Record the restriction if we are in the main unit,
542 -- or in the extended main unit. The reason that we
543 -- test separately for Main_Unit is that gnat.adc is
544 -- processed with Current_Sem_Unit = Main_Unit, but
545 -- nodes in gnat.adc do not appear to be the extended
546 -- main source unit (they probably should do ???)
548 if Current_Sem_Unit
= Main_Unit
549 or else In_Extended_Main_Source_Unit
(N
)
551 if Main_Restrictions
.Set
(R
) then
552 if V
< Main_Restrictions
.Value
(R
) then
553 Main_Restrictions
.Value
(R
) := V
;
556 elsif not Restriction_Warnings
(R
) then
557 Main_Restrictions
.Set
(R
) := True;
558 Main_Restrictions
.Value
(R
) := V
;
563 ----------------------------------
564 -- Suppress_Restriction_Message --
565 ----------------------------------
567 function Suppress_Restriction_Message
(N
: Node_Id
) return Boolean is
569 -- We only output messages for the extended main source unit
571 if In_Extended_Main_Source_Unit
(N
) then
574 -- If loaded by rtsfind, then suppress message
576 elsif Sloc
(N
) <= No_Location
then
579 -- Otherwise suppress message if internal file
582 return Is_Internal_File_Name
(Unit_File_Name
(Get_Source_Unit
(N
)));
584 end Suppress_Restriction_Message
;
586 ---------------------
587 -- Tasking_Allowed --
588 ---------------------
590 function Tasking_Allowed
return Boolean is
592 return not Restrictions
.Set
(No_Tasking
)
593 and then (not Restrictions
.Set
(Max_Tasks
)
594 or else Restrictions
.Value
(Max_Tasks
) > 0);