OSDN Git Service

2010-06-17 Robert Dewar <dewar@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / sem_scil.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT COMPILER COMPONENTS                         --
4 --                                                                          --
5 --                             S E M _ S C I L                              --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --             Copyright (C) 2009, 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
26 with Einfo;    use Einfo;
27 with Namet;    use Namet;
28 with Nlists;   use Nlists;
29 with Opt;      use Opt;
30 with Rtsfind;  use Rtsfind;
31 with Sem;      use Sem;
32 with Sem_Aux;  use Sem_Aux;
33 with Sem_Util; use Sem_Util;
34 with Sinfo;    use Sinfo;
35 with Snames;   use Snames;
36 with Stand;    use Stand;
37
38 package body Sem_SCIL is
39
40    ----------------------
41    -- Adjust_SCIL_Node --
42    ----------------------
43
44    procedure Adjust_SCIL_Node (Old_Node : Node_Id; New_Node : Node_Id) is
45       SCIL_Node : Node_Id;
46
47    begin
48       pragma Assert (Generate_SCIL);
49
50       --  Check cases in which no action is required. Currently the only SCIL
51       --  nodes that may require adjustment are those of dispatching calls
52       --  internally generated by the frontend.
53
54       if Comes_From_Source (Old_Node)
55         or else not
56           Nkind_In (New_Node, N_Function_Call, N_Procedure_Call_Statement)
57       then
58          return;
59
60       --  Conditional expression associated with equality operator. Old_Node
61       --  may be part of the expansion of the predefined equality operator of
62       --  a tagged type and hence we need to check if it has a SCIL dispatching
63       --  node that needs adjustment.
64
65       elsif Nkind (Old_Node) = N_Conditional_Expression
66         and then (Nkind (Original_Node (Old_Node)) = N_Op_Eq
67                     or else
68                       (Nkind (Original_Node (Old_Node)) = N_Function_Call
69                         and then Chars (Name (Original_Node (Old_Node))) =
70                                                                  Name_Op_Eq))
71       then
72          null;
73
74       --  Type conversions may involve dispatching calls to functions whose
75       --  associated SCIL dispatching node needs adjustment.
76
77       elsif Nkind_In (Old_Node, N_Type_Conversion,
78                                 N_Unchecked_Type_Conversion)
79       then
80          null;
81
82       --  Relocated subprogram call
83
84       elsif Nkind (Old_Node) = Nkind (New_Node)
85         and then Original_Node (Old_Node) = Original_Node (New_Node)
86       then
87          null;
88
89       else
90          return;
91       end if;
92
93       --  Search for the SCIL node and update it (if found)
94
95       SCIL_Node := Find_SCIL_Node (Old_Node);
96
97       if Present (SCIL_Node) then
98          Set_SCIL_Related_Node (SCIL_Node, New_Node);
99       end if;
100    end Adjust_SCIL_Node;
101
102    ---------------------
103    -- Check_SCIL_Node --
104    ---------------------
105
106    function Check_SCIL_Node (N : Node_Id) return Traverse_Result is
107       Ctrl_Tag : Node_Id;
108       Ctrl_Typ : Entity_Id;
109
110    begin
111       if Nkind (N) = N_SCIL_Membership_Test then
112
113          --  Check contents of the boolean expression associated with the
114          --  membership test.
115
116          pragma Assert (Nkind (SCIL_Related_Node (N)) = N_Identifier
117            and then Etype (SCIL_Related_Node (N)) = Standard_Boolean);
118
119          --  Check the entity identifier of the associated tagged type (that
120          --  is, in testing for membership in T'Class, the entity id of the
121          --  specific type T).
122
123          --  Note: When the SCIL node is generated the private and full-view
124          --    of the tagged types may have been swapped and hence the node
125          --    referenced by attribute SCIL_Entity may be the private view.
126          --    Therefore, in order to uniformily locate the full-view we use
127          --    attribute Underlying_Type.
128
129          pragma Assert (Is_Tagged_Type (Underlying_Type (SCIL_Entity (N))));
130
131          --  Interface types are unsupported
132
133          pragma Assert (not Is_Interface (Underlying_Type (SCIL_Entity (N))));
134
135          --  Check the decoration of the expression that denotes the tag value
136          --  being tested
137
138          Ctrl_Tag := SCIL_Tag_Value (N);
139
140          case Nkind (Ctrl_Tag) is
141
142             --  For class-wide membership tests the SCIL tag value is the tag
143             --  of the tested object (i.e. Obj.Tag).
144
145             when N_Selected_Component =>
146                pragma Assert (Etype (Ctrl_Tag) = RTE (RE_Tag));
147                null;
148
149             when others =>
150                pragma Assert (False);
151                null;
152          end case;
153
154          return Skip;
155
156       elsif Nkind (N) = N_SCIL_Dispatching_Call then
157          Ctrl_Tag := SCIL_Controlling_Tag (N);
158
159          --  SCIL_Related_Node of SCIL dispatching call nodes MUST reference
160          --  subprogram calls.
161
162          if not Nkind_In (SCIL_Related_Node (N), N_Function_Call,
163                                                  N_Procedure_Call_Statement)
164          then
165             pragma Assert (False);
166             raise Program_Error;
167
168          --  In simple cases the controlling tag is the tag of the controlling
169          --  argument (i.e. Obj.Tag).
170
171          elsif Nkind (Ctrl_Tag) = N_Selected_Component then
172             Ctrl_Typ := Etype (Ctrl_Tag);
173
174             --  Interface types are unsupported
175
176             if Is_Interface (Ctrl_Typ)
177               or else (RTE_Available (RE_Interface_Tag)
178                          and then Ctrl_Typ = RTE (RE_Interface_Tag))
179             then
180                null;
181
182             else
183                pragma Assert (Ctrl_Typ = RTE (RE_Tag));
184                null;
185             end if;
186
187          --  When the controlling tag of a dispatching call is an identifier
188          --  the SCIL_Controlling_Tag attribute references the corresponding
189          --  object or parameter declaration. Interface types are still
190          --  unsupported.
191
192          elsif Nkind_In (Ctrl_Tag, N_Object_Declaration,
193                                    N_Parameter_Specification)
194          then
195             Ctrl_Typ := Etype (Defining_Identifier (Ctrl_Tag));
196
197             --  Interface types are unsupported.
198
199             if Is_Interface (Ctrl_Typ)
200               or else (RTE_Available (RE_Interface_Tag)
201                         and then Ctrl_Typ = RTE (RE_Interface_Tag))
202               or else (Is_Access_Type (Ctrl_Typ)
203                         and then
204                           Is_Interface
205                             (Available_View
206                               (Base_Type (Designated_Type (Ctrl_Typ)))))
207             then
208                null;
209
210             else
211                pragma Assert
212                  (Ctrl_Typ = RTE (RE_Tag)
213                     or else
214                       (Is_Access_Type (Ctrl_Typ)
215                         and then Available_View
216                                   (Base_Type (Designated_Type (Ctrl_Typ))) =
217                                                                 RTE (RE_Tag)));
218                null;
219             end if;
220
221          --  Interface types are unsupported
222
223          elsif Is_Interface (Etype (Ctrl_Tag)) then
224             null;
225
226          else
227             pragma Assert (False);
228             raise Program_Error;
229          end if;
230
231          return Skip;
232
233       --  Node is not N_SCIL_Dispatching_Call
234
235       else
236          return OK;
237       end if;
238    end Check_SCIL_Node;
239
240    --------------------
241    -- Find_SCIL_Node --
242    --------------------
243
244    function Find_SCIL_Node (Node : Node_Id) return Node_Id is
245       Found_Node : Node_Id;
246       --  This variable stores the last node found by the nested subprogram
247       --  Find_SCIL_Node.
248
249       function Find_SCIL_Node (L : List_Id) return Boolean;
250       --  Searches in list L for a SCIL node associated with a dispatching call
251       --  whose SCIL_Related_Node is Node. If found returns true and stores the
252       --  SCIL node in Found_Node; otherwise returns False and sets Found_Node
253       --  to Empty.
254
255       --------------------
256       -- Find_SCIL_Node --
257       --------------------
258
259       function Find_SCIL_Node (L : List_Id) return Boolean is
260          N : Node_Id;
261
262       begin
263          N := First (L);
264          while Present (N) loop
265             if Nkind (N) in N_SCIL_Node
266               and then SCIL_Related_Node (N) = Node
267             then
268                Found_Node := N;
269                return True;
270             end if;
271
272             Next (N);
273          end loop;
274
275          Found_Node := Empty;
276          return False;
277       end Find_SCIL_Node;
278
279       --  Local variables
280
281       P : Node_Id;
282
283    --  Start of processing for Find_SCIL_Node
284
285    begin
286       pragma Assert (Generate_SCIL);
287
288       --  Search for the SCIL node in list associated with a transient scope
289
290       if Scope_Is_Transient then
291          declare
292             SE : Scope_Stack_Entry
293                    renames Scope_Stack.Table (Scope_Stack.Last);
294          begin
295             if SE.Is_Transient
296               and then Present (SE.Actions_To_Be_Wrapped_Before)
297               and then Find_SCIL_Node (SE.Actions_To_Be_Wrapped_Before)
298             then
299                return Found_Node;
300             end if;
301          end;
302       end if;
303
304       --  Otherwise climb up the tree searching for the SCIL node analyzing
305       --  all the lists in which Insert_Actions may have inserted it
306
307       P := Node;
308       while Present (P) loop
309          case Nkind (P) is
310
311             --  Actions associated with AND THEN or OR ELSE
312
313             when N_Short_Circuit =>
314                if Present (Actions (P))
315                  and then Find_SCIL_Node (Actions (P))
316                then
317                   return Found_Node;
318                end if;
319
320             --  Actions of conditional expressions
321
322             when N_Conditional_Expression =>
323                if (Present (Then_Actions (P))
324                     and then Find_SCIL_Node (Actions (P)))
325                  or else
326                   (Present (Else_Actions (P))
327                     and then Find_SCIL_Node (Else_Actions (P)))
328                then
329                   return Found_Node;
330                end if;
331
332             --  Actions in handled sequence of statements
333
334             when
335                N_Handled_Sequence_Of_Statements =>
336                   if Find_SCIL_Node (Statements (P)) then
337                      return Found_Node;
338                   end if;
339
340             --  Conditions of while expression or elsif.
341
342             when N_Iteration_Scheme |
343                  N_Elsif_Part
344             =>
345                if Present (Condition_Actions (P))
346                  and then Find_SCIL_Node (Condition_Actions (P))
347                then
348                   return Found_Node;
349                end if;
350
351             --  Statements, declarations, pragmas, representation clauses
352
353             when
354                --  Statements
355
356                N_Procedure_Call_Statement               |
357                N_Statement_Other_Than_Procedure_Call    |
358
359                --  Pragmas
360
361                N_Pragma                                 |
362
363                --  Representation_Clause
364
365                N_At_Clause                              |
366                N_Attribute_Definition_Clause            |
367                N_Enumeration_Representation_Clause      |
368                N_Record_Representation_Clause           |
369
370                --  Declarations
371
372                N_Abstract_Subprogram_Declaration        |
373                N_Entry_Body                             |
374                N_Exception_Declaration                  |
375                N_Exception_Renaming_Declaration         |
376                N_Formal_Abstract_Subprogram_Declaration |
377                N_Formal_Concrete_Subprogram_Declaration |
378                N_Formal_Object_Declaration              |
379                N_Formal_Type_Declaration                |
380                N_Full_Type_Declaration                  |
381                N_Function_Instantiation                 |
382                N_Generic_Function_Renaming_Declaration  |
383                N_Generic_Package_Declaration            |
384                N_Generic_Package_Renaming_Declaration   |
385                N_Generic_Procedure_Renaming_Declaration |
386                N_Generic_Subprogram_Declaration         |
387                N_Implicit_Label_Declaration             |
388                N_Incomplete_Type_Declaration            |
389                N_Number_Declaration                     |
390                N_Object_Declaration                     |
391                N_Object_Renaming_Declaration            |
392                N_Package_Body                           |
393                N_Package_Body_Stub                      |
394                N_Package_Declaration                    |
395                N_Package_Instantiation                  |
396                N_Package_Renaming_Declaration           |
397                N_Private_Extension_Declaration          |
398                N_Private_Type_Declaration               |
399                N_Procedure_Instantiation                |
400                N_Protected_Body                         |
401                N_Protected_Body_Stub                    |
402                N_Protected_Type_Declaration             |
403                N_Single_Task_Declaration                |
404                N_Subprogram_Body                        |
405                N_Subprogram_Body_Stub                   |
406                N_Subprogram_Declaration                 |
407                N_Subprogram_Renaming_Declaration        |
408                N_Subtype_Declaration                    |
409                N_Task_Body                              |
410                N_Task_Body_Stub                         |
411                N_Task_Type_Declaration                  |
412
413                --  Freeze entity behaves like a declaration or statement
414
415                N_Freeze_Entity
416             =>
417                --  Do not search here if the item is not a list member
418
419                if not Is_List_Member (P) then
420                   null;
421
422                --  Do not search if parent of P is an N_Component_Association
423                --  node (i.e. we are in the context of an N_Aggregate or
424                --  N_Extension_Aggregate node). In this case the node should
425                --  have been added before the entire aggregate.
426
427                elsif Nkind (Parent (P)) = N_Component_Association then
428                   null;
429
430                --  Do not search if the parent of P is either an N_Variant
431                --  node or an N_Record_Definition node. In this case the node
432                --  should have been added before the entire record.
433
434                elsif Nkind (Parent (P)) = N_Variant
435                  or else Nkind (Parent (P)) = N_Record_Definition
436                then
437                   null;
438
439                --  Otherwise search it in the list containing this node
440
441                elsif Find_SCIL_Node (List_Containing (P)) then
442                   return Found_Node;
443                end if;
444
445             --  A special case, N_Raise_xxx_Error can act either as a statement
446             --  or a subexpression. We diferentiate them by looking at the
447             --  Etype. It is set to Standard_Void_Type in the statement case.
448
449             when
450                N_Raise_xxx_Error =>
451                   if Etype (P) = Standard_Void_Type then
452                      if Is_List_Member (P)
453                        and then Find_SCIL_Node (List_Containing (P))
454                      then
455                         return Found_Node;
456                      end if;
457
458                   --  In the subexpression case, keep climbing
459
460                   else
461                      null;
462                   end if;
463
464             --  If a component association appears within a loop created for
465             --  an array aggregate, check if the SCIL node was added to the
466             --  the list of nodes attached to the association.
467
468             when
469                N_Component_Association =>
470                   if Nkind (Parent (P)) = N_Aggregate
471                     and then Present (Loop_Actions (P))
472                     and then Find_SCIL_Node (Loop_Actions (P))
473                   then
474                      return Found_Node;
475                   end if;
476
477             --  Another special case, an attribute denoting a procedure call
478
479             when
480                N_Attribute_Reference =>
481                   if Is_Procedure_Attribute_Name (Attribute_Name (P))
482                     and then Find_SCIL_Node (List_Containing (P))
483                   then
484                      return Found_Node;
485
486                   --  In the subexpression case keep climbing
487
488                   else
489                      null;
490                   end if;
491
492             --  SCIL nodes do not have subtrees and hence they can never be
493             --  found climbing tree
494
495             when
496                N_SCIL_Dispatch_Table_Object_Init        |
497                N_SCIL_Dispatch_Table_Tag_Init           |
498                N_SCIL_Dispatching_Call                  |
499                N_SCIL_Membership_Test                   |
500                N_SCIL_Tag_Init
501             =>
502                pragma Assert (False);
503                raise Program_Error;
504
505             --  For all other node types, keep climbing tree
506
507             when
508                N_Abortable_Part                         |
509                N_Accept_Alternative                     |
510                N_Access_Definition                      |
511                N_Access_Function_Definition             |
512                N_Access_Procedure_Definition            |
513                N_Access_To_Object_Definition            |
514                N_Aggregate                              |
515                N_Allocator                              |
516                N_Case_Statement_Alternative             |
517                N_Character_Literal                      |
518                N_Compilation_Unit                       |
519                N_Compilation_Unit_Aux                   |
520                N_Component_Clause                       |
521                N_Component_Declaration                  |
522                N_Component_Definition                   |
523                N_Component_List                         |
524                N_Constrained_Array_Definition           |
525                N_Decimal_Fixed_Point_Definition         |
526                N_Defining_Character_Literal             |
527                N_Defining_Identifier                    |
528                N_Defining_Operator_Symbol               |
529                N_Defining_Program_Unit_Name             |
530                N_Delay_Alternative                      |
531                N_Delta_Constraint                       |
532                N_Derived_Type_Definition                |
533                N_Designator                             |
534                N_Digits_Constraint                      |
535                N_Discriminant_Association               |
536                N_Discriminant_Specification             |
537                N_Empty                                  |
538                N_Entry_Body_Formal_Part                 |
539                N_Entry_Call_Alternative                 |
540                N_Entry_Declaration                      |
541                N_Entry_Index_Specification              |
542                N_Enumeration_Type_Definition            |
543                N_Error                                  |
544                N_Exception_Handler                      |
545                N_Expanded_Name                          |
546                N_Explicit_Dereference                   |
547                N_Expression_With_Actions                |
548                N_Extension_Aggregate                    |
549                N_Floating_Point_Definition              |
550                N_Formal_Decimal_Fixed_Point_Definition  |
551                N_Formal_Derived_Type_Definition         |
552                N_Formal_Discrete_Type_Definition        |
553                N_Formal_Floating_Point_Definition       |
554                N_Formal_Modular_Type_Definition         |
555                N_Formal_Ordinary_Fixed_Point_Definition |
556                N_Formal_Package_Declaration             |
557                N_Formal_Private_Type_Definition         |
558                N_Formal_Signed_Integer_Type_Definition  |
559                N_Function_Call                          |
560                N_Function_Specification                 |
561                N_Generic_Association                    |
562                N_Identifier                             |
563                N_In                                     |
564                N_Index_Or_Discriminant_Constraint       |
565                N_Indexed_Component                      |
566                N_Integer_Literal                        |
567                N_Itype_Reference                        |
568                N_Label                                  |
569                N_Loop_Parameter_Specification           |
570                N_Mod_Clause                             |
571                N_Modular_Type_Definition                |
572                N_Not_In                                 |
573                N_Null                                   |
574                N_Op_Abs                                 |
575                N_Op_Add                                 |
576                N_Op_And                                 |
577                N_Op_Concat                              |
578                N_Op_Divide                              |
579                N_Op_Eq                                  |
580                N_Op_Expon                               |
581                N_Op_Ge                                  |
582                N_Op_Gt                                  |
583                N_Op_Le                                  |
584                N_Op_Lt                                  |
585                N_Op_Minus                               |
586                N_Op_Mod                                 |
587                N_Op_Multiply                            |
588                N_Op_Ne                                  |
589                N_Op_Not                                 |
590                N_Op_Or                                  |
591                N_Op_Plus                                |
592                N_Op_Rem                                 |
593                N_Op_Rotate_Left                         |
594                N_Op_Rotate_Right                        |
595                N_Op_Shift_Left                          |
596                N_Op_Shift_Right                         |
597                N_Op_Shift_Right_Arithmetic              |
598                N_Op_Subtract                            |
599                N_Op_Xor                                 |
600                N_Operator_Symbol                        |
601                N_Ordinary_Fixed_Point_Definition        |
602                N_Others_Choice                          |
603                N_Package_Specification                  |
604                N_Parameter_Association                  |
605                N_Parameter_Specification                |
606                N_Pop_Constraint_Error_Label             |
607                N_Pop_Program_Error_Label                |
608                N_Pop_Storage_Error_Label                |
609                N_Pragma_Argument_Association            |
610                N_Procedure_Specification                |
611                N_Protected_Definition                   |
612                N_Push_Constraint_Error_Label            |
613                N_Push_Program_Error_Label               |
614                N_Push_Storage_Error_Label               |
615                N_Qualified_Expression                   |
616                N_Range                                  |
617                N_Range_Constraint                       |
618                N_Real_Literal                           |
619                N_Real_Range_Specification               |
620                N_Record_Definition                      |
621                N_Reference                              |
622                N_Selected_Component                     |
623                N_Signed_Integer_Type_Definition         |
624                N_Single_Protected_Declaration           |
625                N_Slice                                  |
626                N_String_Literal                         |
627                N_Subprogram_Info                        |
628                N_Subtype_Indication                     |
629                N_Subunit                                |
630                N_Task_Definition                        |
631                N_Terminate_Alternative                  |
632                N_Triggering_Alternative                 |
633                N_Type_Conversion                        |
634                N_Unchecked_Expression                   |
635                N_Unchecked_Type_Conversion              |
636                N_Unconstrained_Array_Definition         |
637                N_Unused_At_End                          |
638                N_Unused_At_Start                        |
639                N_Use_Package_Clause                     |
640                N_Use_Type_Clause                        |
641                N_Variant                                |
642                N_Variant_Part                           |
643                N_Validate_Unchecked_Conversion          |
644                N_With_Clause
645             =>
646                null;
647
648          end case;
649
650          --  If we fall through above tests keep climbing tree
651
652          if Nkind (Parent (P)) = N_Subunit then
653
654             --  This is the proper body corresponding to a stub. Insertion done
655             --  at the point of the stub, which is in the declarative part of
656             --  the parent unit.
657
658             P := Corresponding_Stub (Parent (P));
659
660          else
661             P := Parent (P);
662          end if;
663       end loop;
664
665       --  SCIL node not found
666
667       return Empty;
668    end Find_SCIL_Node;
669
670    -------------------------
671    -- First_Non_SCIL_Node --
672    -------------------------
673
674    function First_Non_SCIL_Node (L : List_Id) return Node_Id is
675       N : Node_Id;
676
677    begin
678       N := First (L);
679       while Nkind (N) in N_SCIL_Node loop
680          Next (N);
681       end loop;
682
683       return N;
684    end First_Non_SCIL_Node;
685
686    ------------------------
687    -- Next_Non_SCIL_Node --
688    ------------------------
689
690    function Next_Non_SCIL_Node (N : Node_Id) return Node_Id is
691       Aux_N : Node_Id;
692
693    begin
694       Aux_N := Next (N);
695       while Nkind (Aux_N) in N_SCIL_Node loop
696          Next (Aux_N);
697       end loop;
698
699       return Aux_N;
700    end Next_Non_SCIL_Node;
701
702 end Sem_SCIL;