1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2021-2024, 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 3, 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 COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
26 -- Package containing utility procedures related to Stack Scrubbing
28 with Atree
; use Atree
;
29 with Einfo
; use Einfo
;
30 with Einfo
.Entities
; use Einfo
.Entities
;
31 with Errout
; use Errout
;
32 with Namet
; use Namet
;
33 with Nlists
; use Nlists
;
34 with Sem_Eval
; use Sem_Eval
;
35 with Sinfo
; use Sinfo
;
36 with Sinfo
.Nodes
; use Sinfo
.Nodes
;
37 with Sinfo
.Utils
; use Sinfo
.Utils
;
38 with Snames
; use Snames
;
39 with Stringt
; use Stringt
;
42 -----------------------
43 -- Local Subprograms --
44 -----------------------
46 function Find_Explicit_Strub_Pragma
(Id
: Entity_Id
) return Node_Id
;
47 -- Return a pragma Machine_Attribute (Id, "strub"[, "mode"]) node
50 function Strub_Pragma_Arg
(Item
: Node_Id
) return Node_Id
is
52 (Next
(Next
(First
(Pragma_Argument_Associations
(Item
))))));
53 -- Return the pragma argument holding the strub mode associated
54 -- with Item, a subprogram, variable, constant, or type. Bear in
55 -- mind that strub pragmas with an explicit strub mode argument,
56 -- naming access-to-subprogram types, are applied to the
57 -- designated subprogram type.
59 function Strub_Pragma_Arg_To_String
(Item
: Node_Id
) return String is
60 (To_String
(Strval
(Expr_Value_S
(Item
))));
61 -- Extract and return as a String the strub mode held in a node
62 -- returned by Strub_Pragma_Arg.
64 function Strub_Pragma_Mode
66 Item
: Node_Id
) return Strub_Mode
;
67 -- Return the strub mode associated with Item expressed in Id.
68 -- Strub_Pragma_P (Id) must hold.
70 ---------------------------
71 -- Check_Same_Strub_Mode --
72 ---------------------------
74 procedure Check_Same_Strub_Mode
75 (Dest
, Src
: Entity_Id
;
76 Report
: Boolean := True)
78 Src_Strub_Mode
: constant Strub_Mode
:= Explicit_Strub_Mode
(Src
);
79 Dest_Strub_Mode
: constant Strub_Mode
:= Explicit_Strub_Mode
(Dest
);
82 if Dest_Strub_Mode
= Src_Strub_Mode
then
86 -- Internal is not part of the interface, it's an *internal*
87 -- implementation detail, so consider it equivalent to unspecified here.
88 -- ??? -fstrub=relaxed|strict makes them interface-equivalent to
89 -- Callable or Disabled, respectively, but we don't look at that flag in
90 -- the front-end, and it seems undesirable for that flag to affect
91 -- whether specifications are conformant. Maybe there should be some
92 -- means to specify Callable or Disabled along with Internal?
94 if Dest_Strub_Mode
in Unspecified | Internal
95 and then Src_Strub_Mode
in Unspecified | Internal
104 if Src_Strub_Mode
/= Unspecified
then
105 Error_Msg_Sloc
:= Sloc
(Find_Explicit_Strub_Pragma
(Src
));
107 Error_Msg_Sloc
:= Sloc
(Src
);
109 Error_Msg_Node_2
:= Src
;
110 Error_Msg_NE
("& requires the same `strub` mode as &#",
111 (if Dest_Strub_Mode
/= Unspecified
112 then Find_Explicit_Strub_Pragma
(Dest
)
115 end Check_Same_Strub_Mode
;
117 ----------------------------
118 -- Compatible_Strub_Modes --
119 ----------------------------
121 function Compatible_Strub_Modes
122 (Dest
, Src
: Entity_Id
) return Boolean
124 Src_Strub_Mode
: constant Strub_Mode
:= Explicit_Strub_Mode
(Src
);
125 Dest_Strub_Mode
: constant Strub_Mode
:= Explicit_Strub_Mode
(Dest
);
128 return Src_Strub_Mode
= Dest_Strub_Mode
129 or else At_Calls
not in Src_Strub_Mode | Dest_Strub_Mode
;
130 end Compatible_Strub_Modes
;
132 ---------------------
133 -- Copy_Strub_Mode --
134 ---------------------
136 procedure Copy_Strub_Mode
(Dest
, Src
: Entity_Id
) is
137 Strub
: Node_Id
:= Find_Explicit_Strub_Pragma
(Src
);
138 Src_Strub_Mode
: constant Strub_Mode
:= Strub_Pragma_Mode
(Src
, Strub
);
141 pragma Assert
(Explicit_Strub_Mode
(Dest
) = Unspecified
);
143 -- Refrain from copying Internal to subprogram types.
144 -- It affects code generation for the subprogram,
145 -- but it has no effect on its type or interface.
147 if Src_Strub_Mode
= Unspecified
148 or else (Ekind
(Dest
) = E_Subprogram_Type
149 and then Src_Strub_Mode
= Internal
)
154 Strub
:= New_Copy
(Strub
);
155 Set_Next_Rep_Item
(Strub
, First_Rep_Item
(Dest
));
156 Set_First_Rep_Item
(Dest
, Strub
);
157 Set_Has_Gigi_Rep_Item
(Dest
);
160 -------------------------
161 -- Explicit_Strub_Mode --
162 -------------------------
164 function Explicit_Strub_Mode
(Id
: Entity_Id
) return Strub_Mode
is
165 Item
: constant Node_Id
:= Find_Explicit_Strub_Pragma
(Id
);
168 return Strub_Pragma_Mode
(Id
, Item
);
169 end Explicit_Strub_Mode
;
171 --------------------------------
172 -- Find_Explicit_Strub_Pragma --
173 --------------------------------
175 function Find_Explicit_Strub_Pragma
(Id
: Entity_Id
) return Node_Id
is
179 if not Has_Gigi_Rep_Item
(Id
) then
183 Item
:= First_Rep_Item
(Id
);
184 while Present
(Item
) loop
185 if Strub_Pragma_P
(Item
) then
188 Item
:= Next_Rep_Item
(Item
);
192 end Find_Explicit_Strub_Pragma
;
194 -----------------------
195 -- Strub_Pragma_Mode --
196 -----------------------
198 function Strub_Pragma_Mode
200 Item
: Node_Id
) return Strub_Mode
202 Arg
: Node_Id
:= Empty
;
205 -- ??? Enumeration literals, despite being conceptually functions, have
206 -- neither bodies nor stack frames, and it's not clear whether it would
207 -- make more sense to treat them as subprograms or as constants, but
208 -- they can be renamed as functions. Should we require all literals of
209 -- a type to have the same strub mode? Rule out their annotation?
211 if Ekind
(Id
) in E_Subprogram_Type
213 | Generic_Subprogram_Kind
219 Arg
:= Strub_Pragma_Arg
(Item
);
225 Str
: constant String := Strub_Pragma_Arg_To_String
(Arg
);
227 if Str
'Length /= 8 then
231 case Str
(Str
'First) is
233 if Str
= "at-calls" then
238 if Str
= "internal" then
243 if Str
= "callable" then
248 if Str
= "disabled" then
258 -- Access-to-subprogram types and variables can be treated just like
259 -- other access types, because the pragma logic has already promoted to
260 -- subprogram types any annotations applicable to them.
262 elsif Ekind
(Id
) in Type_Kind
-- except E_Subprogram_Type, covered above
271 Arg
:= Strub_Pragma_Arg
(Item
);
273 -- A strub parameter is not applicable to variables,
274 -- and will be ignored.
282 pragma Assert
(Item
= Empty
);
283 return Not_Applicable
;
285 end Strub_Pragma_Mode
;
291 function Strub_Pragma_P
292 (Item
: Node_Id
) return Boolean is
293 (Nkind
(Item
) = N_Pragma
294 and then Pragma_Name
(Item
) = Name_Machine_Attribute
296 Strub_Pragma_Arg_To_String
298 (Next
(First
(Pragma_Argument_Associations
(Item
)))))