OSDN Git Service

2005-03-08 Geert Bosch <bosch@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / exp_tss.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT COMPILER COMPONENTS                         --
4 --                                                                          --
5 --                              E X P _ T S S                               --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --          Copyright (C) 1992-2005 Free Software Foundation, Inc.          --
10 --                                                                          --
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.                                                      --
21 --                                                                          --
22 -- GNAT was originally developed  by the GNAT team at  New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
24 --                                                                          --
25 ------------------------------------------------------------------------------
26
27 with Atree;    use Atree;
28 with Einfo;    use Einfo;
29 with Elists;   use Elists;
30 with Exp_Util; use Exp_Util;
31 with Lib;      use Lib;
32 with Namet;    use Namet;
33 with Sem_Util; use Sem_Util;
34 with Sinfo;    use Sinfo;
35
36 package body Exp_Tss is
37
38    --------------------
39    -- Base_Init_Proc --
40    --------------------
41
42    function Base_Init_Proc (Typ : Entity_Id) return Entity_Id is
43       Full_Type : E;
44       Proc      : Entity_Id;
45
46    begin
47       pragma Assert (Ekind (Typ) in Type_Kind);
48
49       if Is_Private_Type (Typ) then
50          Full_Type := Underlying_Type (Base_Type (Typ));
51       else
52          Full_Type := Typ;
53       end if;
54
55       if No (Full_Type) then
56          return Empty;
57       elsif Is_Concurrent_Type (Full_Type)
58         and then Present (Corresponding_Record_Type (Base_Type (Full_Type)))
59       then
60          return Init_Proc (Corresponding_Record_Type (Base_Type (Full_Type)));
61
62       else
63          Proc := Init_Proc (Base_Type (Full_Type));
64
65          if No (Proc)
66            and then Is_Composite_Type (Full_Type)
67            and then Is_Derived_Type (Full_Type)
68          then
69             return Init_Proc (Root_Type (Full_Type));
70          else
71             return Proc;
72          end if;
73       end if;
74    end Base_Init_Proc;
75
76    --------------
77    -- Copy_TSS --
78    --------------
79
80    --  Note: internally this routine is also used to initially set up
81    --  a TSS entry for a new type (case of being called from Set_TSS)
82
83    procedure Copy_TSS (TSS : Entity_Id; Typ : Entity_Id) is
84       FN : Node_Id;
85
86    begin
87       Ensure_Freeze_Node (Typ);
88       FN := Freeze_Node (Typ);
89
90       if No (TSS_Elist (FN)) then
91          Set_TSS_Elist (FN, New_Elmt_List);
92       end if;
93
94       --  We prepend here, so that a second call overrides the first, it
95       --  is not clear that this is required, but it seems reasonable.
96
97       Prepend_Elmt (TSS, TSS_Elist (FN));
98    end Copy_TSS;
99
100    ------------------------
101    -- Find_Inherited_TSS --
102    ------------------------
103
104    function Find_Inherited_TSS
105      (Typ : Entity_Id;
106       Nam : TSS_Name_Type) return Entity_Id
107    is
108       Btyp : Entity_Id := Typ;
109       Proc : Entity_Id;
110
111    begin
112       loop
113          Btyp := Base_Type (Btyp);
114          Proc :=  TSS (Btyp, Nam);
115
116          exit when Present (Proc)
117            or else not Is_Derived_Type (Btyp);
118
119          --  If Typ is a derived type, it may inherit attributes from some
120          --  ancestor.
121
122          Btyp := Etype (Btyp);
123       end loop;
124
125       if No (Proc) then
126
127          --  If nothing else, use the TSS of the root type
128
129          Proc := TSS (Base_Type (Underlying_Type (Typ)), Nam);
130       end if;
131
132       return Proc;
133    end Find_Inherited_TSS;
134
135    -----------------------
136    -- Get_TSS_Name_Type --
137    -----------------------
138
139    function Get_TSS_Name (E : Entity_Id) return TSS_Name_Type is
140       C1 : Character;
141       C2 : Character;
142       Nm : TSS_Name_Type;
143
144    begin
145       Get_Last_Two_Chars (Chars (E), C1, C2);
146
147       if C1 in 'A' .. 'Z' and then C2 in 'A' .. 'Z' then
148          Nm := (C1, C2);
149
150          for J in TSS_Names'Range loop
151             if Nm = TSS_Names (J) then
152                return Nm;
153             end if;
154          end loop;
155       end if;
156
157       return TSS_Null;
158    end Get_TSS_Name;
159
160    ---------------------------------
161    -- Has_Non_Null_Base_Init_Proc --
162    ---------------------------------
163
164    function Has_Non_Null_Base_Init_Proc (Typ : Entity_Id) return Boolean is
165       BIP : constant Entity_Id := Base_Init_Proc (Typ);
166
167    begin
168       return Present (BIP) and then not Is_Null_Init_Proc (BIP);
169    end Has_Non_Null_Base_Init_Proc;
170
171    ---------------
172    -- Init_Proc --
173    ---------------
174
175    function Init_Proc (Typ : Entity_Id) return Entity_Id is
176       FN   : constant Node_Id := Freeze_Node (Typ);
177       Elmt : Elmt_Id;
178
179    begin
180       if No (FN) then
181          return Empty;
182
183       elsif No (TSS_Elist (FN)) then
184          return Empty;
185
186       else
187          Elmt := First_Elmt (TSS_Elist (FN));
188          while Present (Elmt) loop
189             if Is_Init_Proc (Node (Elmt)) then
190                return Node (Elmt);
191             end if;
192
193             Next_Elmt (Elmt);
194          end loop;
195       end if;
196
197       return Empty;
198    end Init_Proc;
199
200    ------------------
201    -- Is_Init_Proc --
202    ------------------
203
204    function Is_Init_Proc (E : Entity_Id) return Boolean is
205       C1 : Character;
206       C2 : Character;
207    begin
208       Get_Last_Two_Chars (Chars (E), C1, C2);
209       return C1 = TSS_Init_Proc (1) and then C2 = TSS_Init_Proc (2);
210    end Is_Init_Proc;
211
212    ------------
213    -- Is_TSS --
214    ------------
215
216    function Is_TSS (E : Entity_Id; Nam : TSS_Name_Type) return Boolean is
217       C1 : Character;
218       C2 : Character;
219    begin
220       Get_Last_Two_Chars (Chars (E), C1, C2);
221       return C1 = Nam (1) and then C2 = Nam (2);
222    end Is_TSS;
223
224    function Is_TSS (N : Name_Id; Nam : TSS_Name_Type) return Boolean is
225       C1 : Character;
226       C2 : Character;
227    begin
228       Get_Last_Two_Chars (N, C1, C2);
229       return C1 = Nam (1) and then C2 = Nam (2);
230    end Is_TSS;
231
232    -------------------------
233    -- Make_Init_Proc_Name --
234    -------------------------
235
236    function Make_Init_Proc_Name (Typ : Entity_Id) return Name_Id is
237    begin
238       Get_Name_String (Chars (Typ));
239       Name_Len := Name_Len + 2;
240       Name_Buffer (Name_Len - 1) := TSS_Init_Proc (1);
241       Name_Buffer (Name_Len)     := TSS_Init_Proc (2);
242       return Name_Find;
243    end Make_Init_Proc_Name;
244
245    -------------------------
246    -- Make_TSS_Name_Local --
247    -------------------------
248
249    function Make_TSS_Name_Local
250      (Typ : Entity_Id;
251       Nam : TSS_Name_Type) return Name_Id
252    is
253    begin
254       Get_Name_String (Chars (Typ));
255       Add_Char_To_Name_Buffer (Nam (1));
256       Add_Char_To_Name_Buffer (Nam (2));
257       Add_Char_To_Name_Buffer ('_');
258       Add_Nat_To_Name_Buffer (Increment_Serial_Number);
259       return Name_Find;
260    end Make_TSS_Name_Local;
261
262    -------------------
263    -- Make_TSS_Name --
264    -------------------
265
266    function Make_TSS_Name
267      (Typ : Entity_Id;
268       Nam : TSS_Name_Type) return Name_Id
269    is
270    begin
271       Get_Name_String (Chars (Typ));
272       Add_Char_To_Name_Buffer (Nam (1));
273       Add_Char_To_Name_Buffer (Nam (2));
274       return Name_Find;
275    end Make_TSS_Name;
276
277    --------------
278    -- Same_TSS --
279    --------------
280
281    function Same_TSS (E1, E2 : Entity_Id) return Boolean is
282       E1C1 : Character;
283       E1C2 : Character;
284       E2C1 : Character;
285       E2C2 : Character;
286
287    begin
288       Get_Last_Two_Chars (Chars (E1), E1C1, E1C2);
289       Get_Last_Two_Chars (Chars (E2), E2C1, E2C2);
290
291       return
292         E1C1 = E2C1
293           and then
294         E1C2 = E2C2
295           and then
296         E1C1 in 'A' .. 'Z'
297           and then
298         E1C2 in 'A' .. 'Z';
299    end Same_TSS;
300
301    -------------------
302    -- Set_Init_Proc --
303    -------------------
304
305    procedure Set_Init_Proc (Typ : Entity_Id; Init : Entity_Id) is
306    begin
307       Set_TSS (Typ, Init);
308    end Set_Init_Proc;
309
310    -------------
311    -- Set_TSS --
312    -------------
313
314    procedure Set_TSS (Typ : Entity_Id; TSS : Entity_Id) is
315       Subprog_Body : constant Node_Id := Unit_Declaration_Node (TSS);
316
317    begin
318       --  Case of insertion location is in unit defining the type
319
320       if In_Same_Code_Unit (Typ, TSS) then
321          Append_Freeze_Action (Typ, Subprog_Body);
322
323       --  Otherwise, we are using an already existing TSS in another unit
324
325       else
326          null;
327       end if;
328
329       Copy_TSS (TSS, Typ);
330    end Set_TSS;
331
332    ---------
333    -- TSS --
334    ---------
335
336    function TSS (Typ : Entity_Id; Nam : TSS_Name_Type) return Entity_Id is
337       FN   : constant Node_Id := Freeze_Node (Typ);
338       Elmt : Elmt_Id;
339       Subp : Entity_Id;
340
341    begin
342       if No (FN) then
343          return Empty;
344
345       elsif No (TSS_Elist (FN)) then
346          return Empty;
347
348       else
349          Elmt := First_Elmt (TSS_Elist (FN));
350          while Present (Elmt) loop
351             if Is_TSS (Node (Elmt), Nam) then
352                Subp := Node (Elmt);
353
354                --  For stream subprograms, the TSS entity may be a renaming-
355                --  as-body of an already generated entity. Use that one rather
356                --  the one introduced by the renaming, which is an artifact of
357                --  current stream handling.
358
359                if Nkind (Parent (Parent (Subp))) =
360                                            N_Subprogram_Renaming_Declaration
361                  and then
362                    Present (Corresponding_Spec (Parent (Parent (Subp))))
363                then
364                   return Corresponding_Spec (Parent (Parent (Subp)));
365                else
366                   return Subp;
367                end if;
368
369             else
370                Next_Elmt (Elmt);
371             end if;
372          end loop;
373       end if;
374
375       return Empty;
376    end TSS;
377
378    function TSS (Typ : Entity_Id; Nam : Name_Id) return Entity_Id is
379       FN   : constant Node_Id := Freeze_Node (Typ);
380       Elmt : Elmt_Id;
381       Subp : Entity_Id;
382
383    begin
384       if No (FN) then
385          return Empty;
386
387       elsif No (TSS_Elist (FN)) then
388          return Empty;
389
390       else
391          Elmt := First_Elmt (TSS_Elist (FN));
392          while Present (Elmt) loop
393             if Chars (Node (Elmt)) =  Nam then
394                Subp := Node (Elmt);
395
396                --  For stream subprograms, the TSS entity may be a renaming-
397                --  as-body of an already generated entity. Use that one rather
398                --  the one introduced by the renaming, which is an artifact of
399                --  current stream handling.
400
401                if Nkind (Parent (Parent (Subp))) =
402                                            N_Subprogram_Renaming_Declaration
403                  and then
404                    Present (Corresponding_Spec (Parent (Parent (Subp))))
405                then
406                   return Corresponding_Spec (Parent (Parent (Subp)));
407                else
408                   return Subp;
409                end if;
410
411             else
412                Next_Elmt (Elmt);
413             end if;
414          end loop;
415       end if;
416
417       return Empty;
418    end TSS;
419
420 end Exp_Tss;