OSDN Git Service

2006-10-31 Javier Miranda <miranda@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,  51  Franklin  Street,  Fifth  Floor, --
20 -- Boston, MA 02110-1301, 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       return Make_TSS_Name (Typ, TSS_Init_Proc);
239    end Make_Init_Proc_Name;
240
241    -------------------------
242    -- Make_TSS_Name_Local --
243    -------------------------
244
245    function Make_TSS_Name_Local
246      (Typ : Entity_Id;
247       Nam : TSS_Name_Type) return Name_Id
248    is
249    begin
250       Get_Name_String (Chars (Typ));
251       Add_Char_To_Name_Buffer ('_');
252       Add_Nat_To_Name_Buffer (Increment_Serial_Number);
253       Add_Char_To_Name_Buffer (Nam (1));
254       Add_Char_To_Name_Buffer (Nam (2));
255       return Name_Find;
256    end Make_TSS_Name_Local;
257
258    -------------------
259    -- Make_TSS_Name --
260    -------------------
261
262    function Make_TSS_Name
263      (Typ : Entity_Id;
264       Nam : TSS_Name_Type) return Name_Id
265    is
266    begin
267       Get_Name_String (Chars (Typ));
268       Add_Char_To_Name_Buffer (Nam (1));
269       Add_Char_To_Name_Buffer (Nam (2));
270       return Name_Find;
271    end Make_TSS_Name;
272
273    --------------
274    -- Same_TSS --
275    --------------
276
277    function Same_TSS (E1, E2 : Entity_Id) return Boolean is
278       E1C1 : Character;
279       E1C2 : Character;
280       E2C1 : Character;
281       E2C2 : Character;
282
283    begin
284       Get_Last_Two_Chars (Chars (E1), E1C1, E1C2);
285       Get_Last_Two_Chars (Chars (E2), E2C1, E2C2);
286
287       return
288         E1C1 = E2C1
289           and then
290         E1C2 = E2C2
291           and then
292         E1C1 in 'A' .. 'Z'
293           and then
294         E1C2 in 'A' .. 'Z';
295    end Same_TSS;
296
297    -------------------
298    -- Set_Init_Proc --
299    -------------------
300
301    procedure Set_Init_Proc (Typ : Entity_Id; Init : Entity_Id) is
302    begin
303       Set_TSS (Typ, Init);
304    end Set_Init_Proc;
305
306    -------------
307    -- Set_TSS --
308    -------------
309
310    procedure Set_TSS (Typ : Entity_Id; TSS : Entity_Id) is
311       Subprog_Body : constant Node_Id := Unit_Declaration_Node (TSS);
312
313    begin
314       --  Case of insertion location is in unit defining the type
315
316       if In_Same_Code_Unit (Typ, TSS) then
317          Append_Freeze_Action (Typ, Subprog_Body);
318
319       --  Otherwise, we are using an already existing TSS in another unit
320
321       else
322          null;
323       end if;
324
325       Copy_TSS (TSS, Typ);
326    end Set_TSS;
327
328    ---------
329    -- TSS --
330    ---------
331
332    function TSS (Typ : Entity_Id; Nam : TSS_Name_Type) return Entity_Id is
333       FN   : constant Node_Id := Freeze_Node (Typ);
334       Elmt : Elmt_Id;
335       Subp : Entity_Id;
336
337    begin
338       if No (FN) then
339          return Empty;
340
341       elsif No (TSS_Elist (FN)) then
342          return Empty;
343
344       else
345          Elmt := First_Elmt (TSS_Elist (FN));
346          while Present (Elmt) loop
347             if Is_TSS (Node (Elmt), Nam) then
348                Subp := Node (Elmt);
349
350                --  For stream subprograms, the TSS entity may be a renaming-
351                --  as-body of an already generated entity. Use that one rather
352                --  the one introduced by the renaming, which is an artifact of
353                --  current stream handling.
354
355                if Nkind (Parent (Parent (Subp))) =
356                                            N_Subprogram_Renaming_Declaration
357                  and then
358                    Present (Corresponding_Spec (Parent (Parent (Subp))))
359                then
360                   return Corresponding_Spec (Parent (Parent (Subp)));
361                else
362                   return Subp;
363                end if;
364
365             else
366                Next_Elmt (Elmt);
367             end if;
368          end loop;
369       end if;
370
371       return Empty;
372    end TSS;
373
374    function TSS (Typ : Entity_Id; Nam : Name_Id) return Entity_Id is
375       FN   : constant Node_Id := Freeze_Node (Typ);
376       Elmt : Elmt_Id;
377       Subp : Entity_Id;
378
379    begin
380       if No (FN) then
381          return Empty;
382
383       elsif No (TSS_Elist (FN)) then
384          return Empty;
385
386       else
387          Elmt := First_Elmt (TSS_Elist (FN));
388          while Present (Elmt) loop
389             if Chars (Node (Elmt)) =  Nam then
390                Subp := Node (Elmt);
391
392                --  For stream subprograms, the TSS entity may be a renaming-
393                --  as-body of an already generated entity. Use that one rather
394                --  the one introduced by the renaming, which is an artifact of
395                --  current stream handling.
396
397                if Nkind (Parent (Parent (Subp))) =
398                                            N_Subprogram_Renaming_Declaration
399                  and then
400                    Present (Corresponding_Spec (Parent (Parent (Subp))))
401                then
402                   return Corresponding_Spec (Parent (Parent (Subp)));
403                else
404                   return Subp;
405                end if;
406
407             else
408                Next_Elmt (Elmt);
409             end if;
410          end loop;
411       end if;
412
413       return Empty;
414    end TSS;
415
416 end Exp_Tss;