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-2013, 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 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.          --
20--                                                                          --
21-- GNAT was originally developed  by the GNAT team at  New York University. --
22-- Extensive contributions were provided by Ada Core Technologies Inc.      --
23--                                                                          --
24------------------------------------------------------------------------------
25
26with Atree;    use Atree;
27with Einfo;    use Einfo;
28with Elists;   use Elists;
29with Exp_Util; use Exp_Util;
30with Nlists;   use Nlists;
31with Lib;      use Lib;
32with Restrict; use Restrict;
33with Rident;   use Rident;
34with Sem_Aux;  use Sem_Aux;
35with Sem_Util; use Sem_Util;
36with Sinfo;    use Sinfo;
37
38package body Exp_Tss is
39
40   --------------------
41   -- Base_Init_Proc --
42   --------------------
43
44   function Base_Init_Proc
45     (Typ : Entity_Id;
46      Ref : Entity_Id := Empty) return Entity_Id
47   is
48      Full_Type : E;
49      Proc      : Entity_Id;
50
51   begin
52      pragma Assert (Is_Type (Typ));
53
54      if Is_Private_Type (Typ) then
55         Full_Type := Underlying_Type (Base_Type (Typ));
56      else
57         Full_Type := Typ;
58      end if;
59
60      if No (Full_Type) then
61         return Empty;
62
63      elsif Is_Concurrent_Type (Full_Type)
64        and then Present (Corresponding_Record_Type (Base_Type (Full_Type)))
65      then
66         --  The initialization routine to be called is that of the base type
67         --  of the corresponding record type, which may itself be a subtype
68         --  and possibly an itype.
69
70         return Init_Proc
71           (Base_Type (Corresponding_Record_Type (Base_Type (Full_Type))),
72            Ref);
73
74      else
75         Proc := Init_Proc (Base_Type (Full_Type), Ref);
76
77         if No (Proc)
78           and then Is_Composite_Type (Full_Type)
79           and then Is_Derived_Type (Full_Type)
80         then
81            return Init_Proc (Root_Type (Full_Type), Ref);
82         else
83            return Proc;
84         end if;
85      end if;
86   end Base_Init_Proc;
87
88   --------------
89   -- Copy_TSS --
90   --------------
91
92   --  Note: internally this routine is also used to initially set up
93   --  a TSS entry for a new type (case of being called from Set_TSS)
94
95   procedure Copy_TSS (TSS : Entity_Id; Typ : Entity_Id) is
96      FN : Node_Id;
97
98   begin
99      Ensure_Freeze_Node (Typ);
100      FN := Freeze_Node (Typ);
101
102      if No (TSS_Elist (FN)) then
103         Set_TSS_Elist (FN, New_Elmt_List);
104      end if;
105
106      --  We prepend here, so that a second call overrides the first, it
107      --  is not clear that this is required, but it seems reasonable.
108
109      Prepend_Elmt (TSS, TSS_Elist (FN));
110   end Copy_TSS;
111
112   -------------------
113   -- CPP_Init_Proc --
114   -------------------
115
116   function CPP_Init_Proc (Typ  : Entity_Id) return Entity_Id is
117      FN   : constant Node_Id := Freeze_Node (Typ);
118      Elmt : Elmt_Id;
119
120   begin
121      if not Is_CPP_Class (Root_Type (Typ))
122        or else No (FN)
123        or else No (TSS_Elist (FN))
124      then
125         return Empty;
126
127      else
128         Elmt := First_Elmt (TSS_Elist (FN));
129         while Present (Elmt) loop
130            if Is_CPP_Init_Proc (Node (Elmt)) then
131               return Node (Elmt);
132            end if;
133
134            Next_Elmt (Elmt);
135         end loop;
136      end if;
137
138      return Empty;
139   end CPP_Init_Proc;
140
141   ------------------------
142   -- Find_Inherited_TSS --
143   ------------------------
144
145   function Find_Inherited_TSS
146     (Typ : Entity_Id;
147      Nam : TSS_Name_Type) return Entity_Id
148   is
149      Btyp : Entity_Id := Typ;
150      Proc : Entity_Id;
151
152   begin
153      loop
154         Btyp := Base_Type (Btyp);
155         Proc :=  TSS (Btyp, Nam);
156
157         exit when Present (Proc)
158           or else not Is_Derived_Type (Btyp);
159
160         --  If Typ is a derived type, it may inherit attributes from some
161         --  ancestor.
162
163         Btyp := Etype (Btyp);
164      end loop;
165
166      if No (Proc) then
167
168         --  If nothing else, use the TSS of the root type
169
170         Proc := TSS (Base_Type (Underlying_Type (Typ)), Nam);
171      end if;
172
173      return Proc;
174   end Find_Inherited_TSS;
175
176   -----------------------
177   -- Get_TSS_Name_Type --
178   -----------------------
179
180   function Get_TSS_Name (E : Entity_Id) return TSS_Name_Type is
181      C1 : Character;
182      C2 : Character;
183      Nm : TSS_Name_Type;
184
185   begin
186      Get_Last_Two_Chars (Chars (E), C1, C2);
187
188      if C1 in 'A' .. 'Z' and then C2 in 'A' .. 'Z' then
189         Nm := (C1, C2);
190
191         for J in TSS_Names'Range loop
192            if Nm = TSS_Names (J) then
193               return Nm;
194            end if;
195         end loop;
196      end if;
197
198      return TSS_Null;
199   end Get_TSS_Name;
200
201   ---------------------------------
202   -- Has_Non_Null_Base_Init_Proc --
203   ---------------------------------
204
205   --  Note: if a base Init_Proc is present, and No_Default_Initialization is
206   --  present, then we must avoid testing for a null init proc, since there
207   --  is no init proc present in this case.
208
209   function Has_Non_Null_Base_Init_Proc (Typ : Entity_Id) return Boolean is
210      BIP : constant Entity_Id := Base_Init_Proc (Typ);
211   begin
212      return Present (BIP)
213        and then (Restriction_Active (No_Default_Initialization)
214                   or else not Is_Null_Init_Proc (BIP));
215   end Has_Non_Null_Base_Init_Proc;
216
217   ---------------
218   -- Init_Proc --
219   ---------------
220
221   function Init_Proc
222     (Typ  : Entity_Id;
223      Ref  : Entity_Id := Empty) return Entity_Id
224   is
225      FN   : constant Node_Id := Freeze_Node (Typ);
226      Elmt : Elmt_Id;
227      E1   : Entity_Id;
228      E2   : Entity_Id;
229
230   begin
231      if No (FN) then
232         return Empty;
233
234      elsif No (TSS_Elist (FN)) then
235         return Empty;
236
237      elsif No (Ref) then
238         Elmt := First_Elmt (TSS_Elist (FN));
239         while Present (Elmt) loop
240            if Is_Init_Proc (Node (Elmt)) then
241               if not Is_CPP_Class (Typ) then
242                  return Node (Elmt);
243
244               --  For CPP classes, we are looking for the default constructor,
245               --  and so we must skip any non-default constructor.
246
247               elsif
248                 No (Next
249                      (First
250                        (Parameter_Specifications (Parent (Node (Elmt))))))
251               then
252                  return Node (Elmt);
253               end if;
254            end if;
255
256            Next_Elmt (Elmt);
257         end loop;
258
259      --  Non-default constructors are currently supported only in the context
260      --  of interfacing with C++.
261
262      else pragma Assert (Is_CPP_Class (Typ));
263
264         --  Use the referenced function to locate the init_proc matching
265         --  the C++ constructor.
266
267         Elmt := First_Elmt (TSS_Elist (FN));
268         while Present (Elmt) loop
269            if Is_Init_Proc (Node (Elmt)) then
270               E1 := Next_Formal (First_Formal (Node (Elmt)));
271               E2 := First_Formal (Ref);
272               while Present (E1) and then Present (E2) loop
273                  if Chars (E1) /= Chars (E2)
274                    or else Ekind (E1) /= Ekind (E2)
275                  then
276                     exit;
277
278                  elsif Ekind (Etype (E1)) /= E_Anonymous_Access_Type
279                    and then Ekind (Etype (E2)) /= E_Anonymous_Access_Type
280                    and then Etype (E1) /= Etype (E2)
281                  then
282                     exit;
283
284                  elsif Ekind (Etype (E1)) = E_Anonymous_Access_Type
285                    and then Ekind (Etype (E2)) = E_Anonymous_Access_Type
286                    and then Directly_Designated_Type (Etype (E1))
287                               /= Directly_Designated_Type (Etype (E2))
288                  then
289                     exit;
290                  end if;
291
292                  E1 := Next_Formal (E1);
293                  E2 := Next_Formal (E2);
294               end loop;
295
296               if No (E1) and then No (E2) then
297                  return Node (Elmt);
298               end if;
299            end if;
300
301            Next_Elmt (Elmt);
302         end loop;
303      end if;
304
305      return Empty;
306   end Init_Proc;
307
308   ----------------------
309   -- Is_CPP_Init_Proc --
310   ----------------------
311
312   function Is_CPP_Init_Proc (E : Entity_Id) return Boolean is
313      C1 : Character;
314      C2 : Character;
315   begin
316      Get_Last_Two_Chars (Chars (E), C1, C2);
317      return C1 = TSS_CPP_Init_Proc (1) and then C2 = TSS_CPP_Init_Proc (2);
318   end Is_CPP_Init_Proc;
319
320   ------------------
321   -- Is_Init_Proc --
322   ------------------
323
324   function Is_Init_Proc (E : Entity_Id) return Boolean is
325      C1 : Character;
326      C2 : Character;
327   begin
328      Get_Last_Two_Chars (Chars (E), C1, C2);
329      return C1 = TSS_Init_Proc (1) and then C2 = TSS_Init_Proc (2);
330   end Is_Init_Proc;
331
332   ------------
333   -- Is_TSS --
334   ------------
335
336   function Is_TSS (E : Entity_Id; Nam : TSS_Name_Type) return Boolean is
337      C1 : Character;
338      C2 : Character;
339   begin
340      Get_Last_Two_Chars (Chars (E), C1, C2);
341      return C1 = Nam (1) and then C2 = Nam (2);
342   end Is_TSS;
343
344   function Is_TSS (N : Name_Id; Nam : TSS_Name_Type) return Boolean is
345      C1 : Character;
346      C2 : Character;
347   begin
348      Get_Last_Two_Chars (N, C1, C2);
349      return C1 = Nam (1) and then C2 = Nam (2);
350   end Is_TSS;
351
352   -------------------------
353   -- Make_Init_Proc_Name --
354   -------------------------
355
356   function Make_Init_Proc_Name (Typ : Entity_Id) return Name_Id is
357   begin
358      return Make_TSS_Name (Typ, TSS_Init_Proc);
359   end Make_Init_Proc_Name;
360
361   -------------------
362   -- Make_TSS_Name --
363   -------------------
364
365   function Make_TSS_Name
366     (Typ : Entity_Id;
367      Nam : TSS_Name_Type) return Name_Id
368   is
369   begin
370      Get_Name_String (Chars (Typ));
371      Add_Char_To_Name_Buffer (Nam (1));
372      Add_Char_To_Name_Buffer (Nam (2));
373      return Name_Find;
374   end Make_TSS_Name;
375
376   -------------------------
377   -- Make_TSS_Name_Local --
378   -------------------------
379
380   function Make_TSS_Name_Local
381     (Typ : Entity_Id;
382      Nam : TSS_Name_Type) return Name_Id
383   is
384   begin
385      Get_Name_String (Chars (Typ));
386      Add_Char_To_Name_Buffer ('_');
387      Add_Nat_To_Name_Buffer (Increment_Serial_Number);
388      Add_Char_To_Name_Buffer (Nam (1));
389      Add_Char_To_Name_Buffer (Nam (2));
390      return Name_Find;
391   end Make_TSS_Name_Local;
392
393   --------------
394   -- Same_TSS --
395   --------------
396
397   function Same_TSS (E1, E2 : Entity_Id) return Boolean is
398      E1C1 : Character;
399      E1C2 : Character;
400      E2C1 : Character;
401      E2C2 : Character;
402
403   begin
404      Get_Last_Two_Chars (Chars (E1), E1C1, E1C2);
405      Get_Last_Two_Chars (Chars (E2), E2C1, E2C2);
406
407      return
408        E1C1 = E2C1
409          and then
410        E1C2 = E2C2
411          and then
412        E1C1 in 'A' .. 'Z'
413          and then
414        E1C2 in 'A' .. 'Z';
415   end Same_TSS;
416
417   -------------------
418   -- Set_Init_Proc --
419   -------------------
420
421   procedure Set_Init_Proc (Typ : Entity_Id; Init : Entity_Id) is
422   begin
423      Set_TSS (Typ, Init);
424   end Set_Init_Proc;
425
426   -------------
427   -- Set_TSS --
428   -------------
429
430   procedure Set_TSS (Typ : Entity_Id; TSS : Entity_Id) is
431   begin
432      --  Make sure body of subprogram is frozen
433
434      --  Skip this for Init_Proc with No_Default_Initialization, since the
435      --  Init proc is a dummy void entity in this case to be ignored.
436
437      if (Is_Init_Proc (TSS) or else Is_CPP_Init_Proc (TSS))
438        and then Restriction_Active (No_Default_Initialization)
439      then
440         null;
441
442      --  Skip this if not in the same code unit (since it means we are using
443      --  an already existing TSS in another unit)
444
445      elsif not In_Same_Code_Unit (Typ, TSS) then
446         null;
447
448      --  Otherwise make sure body is frozen
449
450      else
451         Append_Freeze_Action (Typ, Unit_Declaration_Node (TSS));
452      end if;
453
454      --  Set TSS entry
455
456      Copy_TSS (TSS, Typ);
457   end Set_TSS;
458
459   ---------
460   -- TSS --
461   ---------
462
463   function TSS (Typ : Entity_Id; Nam : TSS_Name_Type) return Entity_Id is
464      FN   : constant Node_Id := Freeze_Node (Typ);
465      Elmt : Elmt_Id;
466      Subp : Entity_Id;
467
468   begin
469      if No (FN) then
470         return Empty;
471
472      elsif No (TSS_Elist (FN)) then
473         return Empty;
474
475      else
476         Elmt := First_Elmt (TSS_Elist (FN));
477         while Present (Elmt) loop
478            if Is_TSS (Node (Elmt), Nam) then
479               Subp := Node (Elmt);
480
481               --  For stream subprograms, the TSS entity may be a renaming-
482               --  as-body of an already generated entity. Use that one rather
483               --  the one introduced by the renaming, which is an artifact of
484               --  current stream handling.
485
486               if Nkind (Parent (Parent (Subp))) =
487                                           N_Subprogram_Renaming_Declaration
488                 and then
489                   Present (Corresponding_Spec (Parent (Parent (Subp))))
490               then
491                  return Corresponding_Spec (Parent (Parent (Subp)));
492               else
493                  return Subp;
494               end if;
495
496            else
497               Next_Elmt (Elmt);
498            end if;
499         end loop;
500      end if;
501
502      return Empty;
503   end TSS;
504
505   function TSS (Typ : Entity_Id; Nam : Name_Id) return Entity_Id is
506      FN   : constant Node_Id := Freeze_Node (Typ);
507      Elmt : Elmt_Id;
508      Subp : Entity_Id;
509
510   begin
511      if No (FN) then
512         return Empty;
513
514      elsif No (TSS_Elist (FN)) then
515         return Empty;
516
517      else
518         Elmt := First_Elmt (TSS_Elist (FN));
519         while Present (Elmt) loop
520            if Chars (Node (Elmt)) =  Nam then
521               Subp := Node (Elmt);
522
523               --  For stream subprograms, the TSS entity may be a renaming-
524               --  as-body of an already generated entity. Use that one rather
525               --  the one introduced by the renaming, which is an artifact of
526               --  current stream handling.
527
528               if Nkind (Parent (Parent (Subp))) =
529                                           N_Subprogram_Renaming_Declaration
530                 and then
531                   Present (Corresponding_Spec (Parent (Parent (Subp))))
532               then
533                  return Corresponding_Spec (Parent (Parent (Subp)));
534               else
535                  return Subp;
536               end if;
537
538            else
539               Next_Elmt (Elmt);
540            end if;
541         end loop;
542      end if;
543
544      return Empty;
545   end TSS;
546
547end Exp_Tss;
548