1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1992-2003 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 (No_Abort_Statements)
63 and then Restriction_Parameters (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 (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);
113 R_Id : Restriction_Id;
116 if not Is_Predefined_File_Name (Fnam) then
119 -- Ada child unit spec, needs checking against list
122 -- Pad name to 8 characters with blanks
124 Get_Name_String (Fnam);
125 Name_Len := Name_Len - 4;
127 while Name_Len < 8 loop
128 Name_Len := Name_Len + 1;
129 Name_Buffer (Name_Len) := ' ';
132 for J in Unit_Array'Range loop
134 and then Name_Buffer (1 .. 8) = Unit_Array (J).Filenm
136 R_Id := Unit_Array (J).Res_Id;
137 Violations (R_Id) := True;
139 if Restrictions (R_Id) then
141 S : constant String := Restriction_Id'Image (R_Id);
144 Error_Msg_Unit_1 := U;
147 ("|dependence on $ not allowed,", N);
149 Name_Buffer (1 .. S'Last) := S;
150 Name_Len := S'Length;
151 Set_Casing (All_Lower_Case);
152 Error_Msg_Name_1 := Name_Enter;
153 Error_Msg_Sloc := Restrictions_Loc (R_Id);
156 ("\|violates pragma Restriction (%) #", N);
165 end Check_Restricted_Unit;
167 -----------------------
168 -- Check_Restriction --
169 -----------------------
171 -- Case of simple identifier (no parameter)
173 procedure Check_Restriction (R : Restriction_Id; N : Node_Id) is
174 Rimage : constant String := Restriction_Id'Image (R);
177 Violations (R) := True;
179 if (Restrictions (R) or Restriction_Warnings (R))
180 and then not Suppress_Restriction_Message (N)
182 -- Output proper message. If this is just a case of
183 -- a restriction warning, then we output a warning msg
185 if not Restrictions (R) then
187 ("?violation of restriction %", Rimage, N);
189 -- If this is a real restriction violation, then generate
190 -- a non-serious message with appropriate location.
193 Error_Msg_Sloc := Restrictions_Loc (R);
195 -- If we have a location for the Restrictions pragma, output it
197 if Error_Msg_Sloc > No_Location
198 or else Error_Msg_Sloc = System_Location
201 ("|violation of restriction %#", Rimage, N);
203 -- Otherwise restriction was implicit (e.g. set by another pragma)
207 ("|violation of implicit restriction %", Rimage, N);
211 end Check_Restriction;
213 -- Case where a parameter is present, with a count
215 procedure Check_Restriction
216 (R : Restriction_Parameter_Id;
221 if Restriction_Parameters (R) /= No_Uint
222 and then V > Restriction_Parameters (R)
223 and then not Suppress_Restriction_Message (N)
226 S : constant String := Restriction_Parameter_Id'Image (R);
228 Name_Buffer (1 .. S'Last) := S;
229 Name_Len := S'Length;
230 Set_Casing (All_Lower_Case);
231 Error_Msg_Name_1 := Name_Enter;
232 Error_Msg_Sloc := Restriction_Parameters_Loc (R);
233 Error_Msg_N ("|maximum value exceeded for restriction %#", N);
236 end Check_Restriction;
238 -- Case where a parameter is present, no count given
240 procedure Check_Restriction
241 (R : Restriction_Parameter_Id;
245 if Restriction_Parameters (R) = Uint_0
246 and then not Suppress_Restriction_Message (N)
249 S : constant String := Restriction_Parameter_Id'Image (R);
251 Name_Buffer (1 .. S'Last) := S;
252 Name_Len := S'Length;
253 Set_Casing (All_Lower_Case);
254 Error_Msg_Name_1 := Name_Enter;
255 Error_Msg_Sloc := Restriction_Parameters_Loc (R);
256 Error_Msg_N ("|maximum value exceeded for restriction %#", N);
259 end Check_Restriction;
261 -------------------------------------------
262 -- Compilation_Unit_Restrictions_Restore --
263 -------------------------------------------
265 procedure Compilation_Unit_Restrictions_Restore
266 (R : Save_Compilation_Unit_Restrictions)
269 for J in Compilation_Unit_Restrictions loop
270 Restrictions (J) := R (J);
272 end Compilation_Unit_Restrictions_Restore;
274 ----------------------------------------
275 -- Compilation_Unit_Restrictions_Save --
276 ----------------------------------------
278 function Compilation_Unit_Restrictions_Save
279 return Save_Compilation_Unit_Restrictions
281 R : Save_Compilation_Unit_Restrictions;
284 for J in Compilation_Unit_Restrictions loop
285 R (J) := Restrictions (J);
286 Restrictions (J) := False;
290 end Compilation_Unit_Restrictions_Save;
292 ------------------------
293 -- Get_Restriction_Id --
294 ------------------------
296 function Get_Restriction_Id
298 return Restriction_Id
304 Set_Casing (All_Upper_Case);
306 J := Restriction_Id'First;
307 while J /= Not_A_Restriction_Id loop
309 S : constant String := Restriction_Id'Image (J);
312 exit when S = Name_Buffer (1 .. Name_Len);
315 J := Restriction_Id'Succ (J);
319 end Get_Restriction_Id;
321 ----------------------------------
322 -- Get_Restriction_Parameter_Id --
323 ----------------------------------
325 function Get_Restriction_Parameter_Id
327 return Restriction_Parameter_Id
329 J : Restriction_Parameter_Id;
333 Set_Casing (All_Upper_Case);
335 J := Restriction_Parameter_Id'First;
336 while J /= Not_A_Restriction_Parameter_Id loop
338 S : constant String := Restriction_Parameter_Id'Image (J);
341 exit when S = Name_Buffer (1 .. Name_Len);
344 J := Restriction_Parameter_Id'Succ (J);
348 end Get_Restriction_Parameter_Id;
350 -------------------------------
351 -- No_Exception_Handlers_Set --
352 -------------------------------
354 function No_Exception_Handlers_Set return Boolean is
356 return Restrictions (No_Exception_Handlers);
357 end No_Exception_Handlers_Set;
359 ------------------------
360 -- Restricted_Profile --
361 ------------------------
363 -- This implementation must be coordinated with Set_Restricted_Profile
365 function Restricted_Profile return Boolean is
367 return Restrictions (No_Abort_Statements)
368 and then Restrictions (No_Asynchronous_Control)
369 and then Restrictions (No_Entry_Queue)
370 and then Restrictions (No_Task_Hierarchy)
371 and then Restrictions (No_Task_Allocators)
372 and then Restrictions (No_Dynamic_Priorities)
373 and then Restrictions (No_Terminate_Alternatives)
374 and then Restrictions (No_Dynamic_Interrupts)
375 and then Restrictions (No_Protected_Type_Allocators)
376 and then Restrictions (No_Local_Protected_Objects)
377 and then Restrictions (No_Requeue)
378 and then Restrictions (No_Task_Attributes)
379 and then Restriction_Parameters (Max_Asynchronous_Select_Nesting) = 0
380 and then Restriction_Parameters (Max_Task_Entries) = 0
381 and then Restriction_Parameters (Max_Protected_Entries) <= 1
382 and then Restriction_Parameters (Max_Select_Alternatives) = 0;
383 end Restricted_Profile;
385 ---------------------
386 -- Restriction_Msg --
387 ---------------------
389 procedure Restriction_Msg (Msg : String; R : String; N : Node_Id) is
390 B : String (1 .. Msg'Length + 2 * R'Length + 1);
394 Name_Buffer (1 .. R'Last) := R;
395 Name_Len := R'Length;
396 Set_Casing (Identifier_Casing (Get_Source_File_Index (Sloc (N))));
399 for J in Msg'Range loop
400 if Msg (J) = '%' then
404 -- Put characters of image in message, quoting upper case letters
406 for J in 1 .. Name_Len loop
407 if Name_Buffer (J) in 'A' .. 'Z' then
413 B (P) := Name_Buffer (J);
425 Error_Msg_N (B (1 .. P), N);
432 procedure Set_Ravenscar (N : Node_Id) is
433 Loc : constant Source_Ptr := Sloc (N);
436 Set_Restricted_Profile (N);
437 Restrictions (Boolean_Entry_Barriers) := True;
438 Restrictions (No_Select_Statements) := True;
439 Restrictions (No_Calendar) := True;
440 Restrictions (No_Entry_Queue) := True;
441 Restrictions (No_Relative_Delay) := True;
442 Restrictions (No_Task_Termination) := True;
443 Restrictions (No_Implicit_Heap_Allocations) := True;
445 Restrictions_Loc (Boolean_Entry_Barriers) := Loc;
446 Restrictions_Loc (No_Select_Statements) := Loc;
447 Restrictions_Loc (No_Calendar) := Loc;
448 Restrictions_Loc (No_Entry_Queue) := Loc;
449 Restrictions_Loc (No_Relative_Delay) := Loc;
450 Restrictions_Loc (No_Task_Termination) := Loc;
451 Restrictions_Loc (No_Implicit_Heap_Allocations) := Loc;
454 ----------------------------
455 -- Set_Restricted_Profile --
456 ----------------------------
458 -- This must be coordinated with Restricted_Profile
460 procedure Set_Restricted_Profile (N : Node_Id) is
461 Loc : constant Source_Ptr := Sloc (N);
464 Restrictions (No_Abort_Statements) := True;
465 Restrictions (No_Asynchronous_Control) := True;
466 Restrictions (No_Entry_Queue) := True;
467 Restrictions (No_Task_Hierarchy) := True;
468 Restrictions (No_Task_Allocators) := True;
469 Restrictions (No_Dynamic_Priorities) := True;
470 Restrictions (No_Terminate_Alternatives) := True;
471 Restrictions (No_Dynamic_Interrupts) := True;
472 Restrictions (No_Protected_Type_Allocators) := True;
473 Restrictions (No_Local_Protected_Objects) := True;
474 Restrictions (No_Requeue) := True;
475 Restrictions (No_Task_Attributes) := True;
477 Restrictions_Loc (No_Abort_Statements) := Loc;
478 Restrictions_Loc (No_Asynchronous_Control) := Loc;
479 Restrictions_Loc (No_Entry_Queue) := Loc;
480 Restrictions_Loc (No_Task_Hierarchy) := Loc;
481 Restrictions_Loc (No_Task_Allocators) := Loc;
482 Restrictions_Loc (No_Dynamic_Priorities) := Loc;
483 Restrictions_Loc (No_Terminate_Alternatives) := Loc;
484 Restrictions_Loc (No_Dynamic_Interrupts) := Loc;
485 Restrictions_Loc (No_Protected_Type_Allocators) := Loc;
486 Restrictions_Loc (No_Local_Protected_Objects) := Loc;
487 Restrictions_Loc (No_Requeue) := Loc;
488 Restrictions_Loc (No_Task_Attributes) := Loc;
490 Restriction_Parameters (Max_Asynchronous_Select_Nesting) := Uint_0;
491 Restriction_Parameters (Max_Task_Entries) := Uint_0;
492 Restriction_Parameters (Max_Select_Alternatives) := Uint_0;
494 if Restriction_Parameters (Max_Protected_Entries) /= Uint_0 then
495 Restriction_Parameters (Max_Protected_Entries) := Uint_1;
497 end Set_Restricted_Profile;
499 ----------------------------------
500 -- Suppress_Restriction_Message --
501 ----------------------------------
503 function Suppress_Restriction_Message (N : Node_Id) return Boolean is
505 -- We only output messages for the extended main source unit
507 if In_Extended_Main_Source_Unit (N) then
510 -- If loaded by rtsfind, then suppress message
512 elsif Sloc (N) <= No_Location then
515 -- Otherwise suppress message if internal file
518 return Is_Internal_File_Name (Unit_File_Name (Get_Source_Unit (N)));
520 end Suppress_Restriction_Message;
522 ---------------------
523 -- Tasking_Allowed --
524 ---------------------
526 function Tasking_Allowed return Boolean is
528 return Restriction_Parameters (Max_Tasks) /= 0
529 and then not Restrictions (No_Tasking);