OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [tags/] [gnu-src/] [gcc-4.5.1/] [gcc-4.5.1-or32-1.0rc1/] [gcc/] [ada/] [sem_elim.adb] - Blame information for rev 338

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 281 jeremybenn
------------------------------------------------------------------------------
2
--                                                                          --
3
--                         GNAT COMPILER COMPONENTS                         --
4
--                                                                          --
5
--                             S E M _ E L I M                              --
6
--                                                                          --
7
--                                 B o d y                                  --
8
--                                                                          --
9
--          Copyright (C) 1997-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 Atree;    use Atree;
27
with Einfo;    use Einfo;
28
with Errout;   use Errout;
29
with Lib;      use Lib;
30
with Namet;    use Namet;
31
with Nlists;   use Nlists;
32
with Sem;      use Sem;
33
with Sem_Prag; use Sem_Prag;
34
with Sem_Util; use Sem_Util;
35
with Sinput;   use Sinput;
36
with Sinfo;    use Sinfo;
37
with Snames;   use Snames;
38
with Stand;    use Stand;
39
with Stringt;  use Stringt;
40
with Table;
41
 
42
with GNAT.HTable; use GNAT.HTable;
43
 
44
package body Sem_Elim is
45
 
46
   No_Elimination : Boolean;
47
   --  Set True if no Eliminate pragmas active
48
 
49
   ---------------------
50
   -- Data Structures --
51
   ---------------------
52
 
53
   --  A single pragma Eliminate is represented by the following record
54
 
55
   type Elim_Data;
56
   type Access_Elim_Data is access Elim_Data;
57
 
58
   type Names is array (Nat range <>) of Name_Id;
59
   --  Type used to represent set of names. Used for names in Unit_Name
60
   --  and also the set of names in Argument_Types.
61
 
62
   type Access_Names is access Names;
63
 
64
   type Elim_Data is record
65
 
66
      Unit_Name : Access_Names;
67
      --  Unit name, broken down into a set of names (e.g. A.B.C is
68
      --  represented as Name_Id values for A, B, C in sequence).
69
 
70
      Entity_Name : Name_Id;
71
      --  Entity name if Entity parameter if present. If no Entity parameter
72
      --  was supplied, then Entity_Node is set to Empty, and the Entity_Name
73
      --  field contains the last identifier name in the Unit_Name.
74
 
75
      Entity_Scope : Access_Names;
76
      --  Static scope of the entity within the compilation unit represented by
77
      --  Unit_Name.
78
 
79
      Entity_Node : Node_Id;
80
      --  Save node of entity argument, for posting error messages. Set
81
      --  to Empty if there is no entity argument.
82
 
83
      Parameter_Types : Access_Names;
84
      --  Set to set of names given for parameter types. If no parameter
85
      --  types argument is present, this argument is set to null.
86
 
87
      Result_Type : Name_Id;
88
      --  Result type name if Result_Types parameter present, No_Name if not
89
 
90
      Source_Location : Name_Id;
91
      --  String describing the source location of subprogram defining name if
92
      --  Source_Location parameter present, No_Name if not
93
 
94
      Hash_Link : Access_Elim_Data;
95
      --  Link for hash table use
96
 
97
      Homonym : Access_Elim_Data;
98
      --  Pointer to next entry with same key
99
 
100
      Prag : Node_Id;
101
      --  Node_Id for Eliminate pragma
102
 
103
   end record;
104
 
105
   ----------------
106
   -- Hash_Table --
107
   ----------------
108
 
109
   --  Setup hash table using the Entity_Name field as the hash key
110
 
111
   subtype Element is Elim_Data;
112
   subtype Elmt_Ptr is Access_Elim_Data;
113
 
114
   subtype Key is Name_Id;
115
 
116
   type Header_Num is range 0 .. 1023;
117
 
118
   Null_Ptr : constant Elmt_Ptr := null;
119
 
120
   ----------------------
121
   -- Hash_Subprograms --
122
   ----------------------
123
 
124
   package Hash_Subprograms is
125
 
126
      function Equal (F1, F2 : Key) return Boolean;
127
      pragma Inline (Equal);
128
 
129
      function Get_Key (E : Elmt_Ptr) return Key;
130
      pragma Inline (Get_Key);
131
 
132
      function Hash (F : Key) return Header_Num;
133
      pragma Inline (Hash);
134
 
135
      function Next (E : Elmt_Ptr) return Elmt_Ptr;
136
      pragma Inline (Next);
137
 
138
      procedure Set_Next (E : Elmt_Ptr; Next : Elmt_Ptr);
139
      pragma Inline (Set_Next);
140
 
141
   end Hash_Subprograms;
142
 
143
   package body Hash_Subprograms is
144
 
145
      -----------
146
      -- Equal --
147
      -----------
148
 
149
      function Equal (F1, F2 : Key) return Boolean is
150
      begin
151
         return F1 = F2;
152
      end Equal;
153
 
154
      -------------
155
      -- Get_Key --
156
      -------------
157
 
158
      function Get_Key (E : Elmt_Ptr) return Key is
159
      begin
160
         return E.Entity_Name;
161
      end Get_Key;
162
 
163
      ----------
164
      -- Hash --
165
      ----------
166
 
167
      function Hash (F : Key) return Header_Num is
168
      begin
169
         return Header_Num (Int (F) mod 1024);
170
      end Hash;
171
 
172
      ----------
173
      -- Next --
174
      ----------
175
 
176
      function Next (E : Elmt_Ptr) return Elmt_Ptr is
177
      begin
178
         return E.Hash_Link;
179
      end Next;
180
 
181
      --------------
182
      -- Set_Next --
183
      --------------
184
 
185
      procedure Set_Next (E : Elmt_Ptr; Next : Elmt_Ptr) is
186
      begin
187
         E.Hash_Link := Next;
188
      end Set_Next;
189
   end Hash_Subprograms;
190
 
191
   ------------
192
   -- Tables --
193
   ------------
194
 
195
   --  The following table records the data for each pragmas, using the
196
   --  entity name as the hash key for retrieval. Entries in this table
197
   --  are set by Process_Eliminate_Pragma and read by Check_Eliminated.
198
 
199
   package Elim_Hash_Table is new Static_HTable (
200
      Header_Num => Header_Num,
201
      Element    => Element,
202
      Elmt_Ptr   => Elmt_Ptr,
203
      Null_Ptr   => Null_Ptr,
204
      Set_Next   => Hash_Subprograms.Set_Next,
205
      Next       => Hash_Subprograms.Next,
206
      Key        => Key,
207
      Get_Key    => Hash_Subprograms.Get_Key,
208
      Hash       => Hash_Subprograms.Hash,
209
      Equal      => Hash_Subprograms.Equal);
210
 
211
   --  The following table records entities for subprograms that are
212
   --  eliminated, and corresponding eliminate pragmas that caused the
213
   --  elimination. Entries in this table are set by Check_Eliminated
214
   --  and read by Eliminate_Error_Msg.
215
 
216
   type Elim_Entity_Entry is record
217
      Prag : Node_Id;
218
      Subp : Entity_Id;
219
   end record;
220
 
221
   package Elim_Entities is new Table.Table (
222
     Table_Component_Type => Elim_Entity_Entry,
223
     Table_Index_Type     => Name_Id'Base,
224
     Table_Low_Bound      => First_Name_Id,
225
     Table_Initial        => 50,
226
     Table_Increment      => 200,
227
     Table_Name           => "Elim_Entries");
228
 
229
   ----------------------
230
   -- Check_Eliminated --
231
   ----------------------
232
 
233
   procedure Check_Eliminated (E : Entity_Id) is
234
      Elmt : Access_Elim_Data;
235
      Scop : Entity_Id;
236
      Form : Entity_Id;
237
 
238
   begin
239
      if No_Elimination then
240
         return;
241
 
242
      --  Elimination of objects and types is not implemented yet
243
 
244
      elsif Ekind (E) not in Subprogram_Kind then
245
         return;
246
      end if;
247
 
248
      --  Loop through homonyms for this key
249
 
250
      Elmt := Elim_Hash_Table.Get (Chars (E));
251
      while Elmt /= null loop
252
         Check_Homonyms : declare
253
            procedure Set_Eliminated;
254
            --  Set current subprogram entity as eliminated
255
 
256
            --------------------
257
            -- Set_Eliminated --
258
            --------------------
259
 
260
            procedure Set_Eliminated is
261
            begin
262
               if Is_Dispatching_Operation (E) then
263
 
264
                  --  If an overriding dispatching primitive is eliminated then
265
                  --  its parent must have been eliminated.
266
 
267
                  if Is_Overriding_Operation (E)
268
                    and then not Is_Eliminated (Overridden_Operation (E))
269
                  then
270
                     Error_Msg_Name_1 := Chars (E);
271
                     Error_Msg_N ("cannot eliminate subprogram %", E);
272
                     return;
273
                  end if;
274
               end if;
275
 
276
               Set_Is_Eliminated (E);
277
               Elim_Entities.Append ((Prag => Elmt.Prag, Subp => E));
278
            end Set_Eliminated;
279
 
280
         --  Start of processing for Check_Homonyms
281
 
282
         begin
283
            --  First we check that the name of the entity matches
284
 
285
            if Elmt.Entity_Name /= Chars (E) then
286
               goto Continue;
287
            end if;
288
 
289
            --  Find enclosing unit
290
 
291
            Scop := Cunit_Entity (Current_Sem_Unit);
292
 
293
            --  Now see if compilation unit matches
294
 
295
            for J in reverse Elmt.Unit_Name'Range loop
296
               if Elmt.Unit_Name (J) /= Chars (Scop) then
297
                  goto Continue;
298
               end if;
299
 
300
               Scop := Scope (Scop);
301
               while Ekind (Scop) = E_Block loop
302
                  Scop := Scope (Scop);
303
               end loop;
304
 
305
               if Scop /= Standard_Standard and then J = 1 then
306
                  goto Continue;
307
               end if;
308
            end loop;
309
 
310
            if Scop /= Standard_Standard then
311
               goto Continue;
312
            end if;
313
 
314
            --  Check for case of given entity is a library level subprogram
315
            --  and we have the single parameter Eliminate case, a match!
316
 
317
            if Is_Compilation_Unit (E)
318
              and then Is_Subprogram (E)
319
              and then No (Elmt.Entity_Node)
320
            then
321
               Set_Eliminated;
322
               return;
323
 
324
               --  Check for case of type or object with two parameter case
325
 
326
            elsif (Is_Type (E) or else Is_Object (E))
327
              and then Elmt.Result_Type = No_Name
328
              and then Elmt.Parameter_Types = null
329
            then
330
               Set_Eliminated;
331
               return;
332
 
333
            --  Check for case of subprogram
334
 
335
            elsif Ekind (E) = E_Function
336
              or else Ekind (E) = E_Procedure
337
            then
338
               --  If Source_Location present, then see if it matches
339
 
340
               if Elmt.Source_Location /= No_Name then
341
                  Get_Name_String (Elmt.Source_Location);
342
 
343
                  declare
344
                     Sloc_Trace : constant String :=
345
                                    Name_Buffer (1 .. Name_Len);
346
 
347
                     Idx : Natural := Sloc_Trace'First;
348
                     --  Index in Sloc_Trace, if equals to 0, then we have
349
                     --  completely traversed Sloc_Trace
350
 
351
                     Last : constant Natural := Sloc_Trace'Last;
352
 
353
                     P      : Source_Ptr;
354
                     Sindex : Source_File_Index;
355
 
356
                     function File_Name_Match return Boolean;
357
                     --  This function is supposed to be called when Idx points
358
                     --  to the beginning of the new file name, and Name_Buffer
359
                     --  is set to contain the name of the proper source file
360
                     --  from the chain corresponding to the Sloc of E. First
361
                     --  it checks that these two files have the same name. If
362
                     --  this check is successful, moves Idx to point to the
363
                     --  beginning of the column number.
364
 
365
                     function Line_Num_Match return Boolean;
366
                     --  This function is supposed to be called when Idx points
367
                     --  to the beginning of the column number, and P is
368
                     --  set to point to the proper Sloc the chain
369
                     --  corresponding to the Sloc of E. First it checks that
370
                     --  the line number Idx points on and the line number
371
                     --  corresponding to P are the same. If this check is
372
                     --  successful, moves Idx to point to the beginning of
373
                     --  the next file name in Sloc_Trace. If there is no file
374
                     --  name any more, Idx is set to 0.
375
 
376
                     function Different_Trace_Lengths return Boolean;
377
                     --  From Idx and P, defines if there are in both traces
378
                     --  more element(s) in the instantiation chains. Returns
379
                     --  False if one trace contains more element(s), but
380
                     --  another does not. If both traces contains more
381
                     --  elements (that is, the function returns False), moves
382
                     --  P ahead in the chain corresponding to E, recomputes
383
                     --  Sindex and sets the name of the corresponding file in
384
                     --  Name_Buffer
385
 
386
                     function Skip_Spaces return Natural;
387
                     --  If Sloc_Trace (Idx) is not space character, returns
388
                     --  Idx. Otherwise returns the index of the nearest
389
                     --  non-space character in Sloc_Trace to the right of Idx.
390
                     --  Returns 0 if there is no such character.
391
 
392
                     -----------------------------
393
                     -- Different_Trace_Lengths --
394
                     -----------------------------
395
 
396
                     function Different_Trace_Lengths return Boolean is
397
                     begin
398
                        P := Instantiation (Sindex);
399
 
400
                        if (P = No_Location and then Idx /= 0)
401
                          or else
402
                           (P /= No_Location and then Idx = 0)
403
                        then
404
                           return True;
405
 
406
                        else
407
                           if P /= No_Location then
408
                              Sindex := Get_Source_File_Index (P);
409
                              Get_Name_String (File_Name (Sindex));
410
                           end if;
411
 
412
                           return False;
413
                        end if;
414
                     end Different_Trace_Lengths;
415
 
416
                     ---------------------
417
                     -- File_Name_Match --
418
                     ---------------------
419
 
420
                     function File_Name_Match return Boolean is
421
                        Tmp_Idx : Natural;
422
                        End_Idx : Natural;
423
 
424
                     begin
425
                        if Idx = 0 then
426
                           return False;
427
                        end if;
428
 
429
                        --  Find first colon. If no colon, then return False.
430
                        --  If there is a colon, Tmp_Idx is set to point just
431
                        --  before the colon.
432
 
433
                        Tmp_Idx := Idx - 1;
434
                        loop
435
                           if Tmp_Idx >= Last then
436
                              return False;
437
                           elsif Sloc_Trace (Tmp_Idx + 1) = ':' then
438
                              exit;
439
                           else
440
                              Tmp_Idx := Tmp_Idx + 1;
441
                           end if;
442
                        end loop;
443
 
444
                        --  Find last non-space before this colon. If there is
445
                        --  no space character before this colon, then return
446
                        --  False. Otherwise, End_Idx is set to point to this
447
                        --  non-space character.
448
 
449
                        End_Idx := Tmp_Idx;
450
                        loop
451
                           if End_Idx < Idx then
452
                              return False;
453
 
454
                           elsif Sloc_Trace (End_Idx) /= ' ' then
455
                              exit;
456
 
457
                           else
458
                              End_Idx := End_Idx - 1;
459
                           end if;
460
                        end loop;
461
 
462
                        --  Now see if file name matches what is in Name_Buffer
463
                        --  and if so, step Idx past it and return True. If the
464
                        --  name does not match, return False.
465
 
466
                        if Sloc_Trace (Idx .. End_Idx) =
467
                           Name_Buffer (1 .. Name_Len)
468
                        then
469
                           Idx := Tmp_Idx + 2;
470
                           Idx := Skip_Spaces;
471
                           return True;
472
                        else
473
                           return False;
474
                        end if;
475
                     end File_Name_Match;
476
 
477
                     --------------------
478
                     -- Line_Num_Match --
479
                     --------------------
480
 
481
                     function Line_Num_Match return Boolean is
482
                        N : Int := 0;
483
 
484
                     begin
485
                        if Idx = 0 then
486
                           return False;
487
                        end if;
488
 
489
                        while Idx <= Last
490
                           and then Sloc_Trace (Idx) in '0' .. '9'
491
                        loop
492
                           N := N * 10 +
493
                            (Character'Pos (Sloc_Trace (Idx)) -
494
                             Character'Pos ('0'));
495
                           Idx := Idx + 1;
496
                        end loop;
497
 
498
                        if Get_Physical_Line_Number (P) =
499
                           Physical_Line_Number (N)
500
                        then
501
                           while Idx <= Last and then
502
                              Sloc_Trace (Idx) /= '['
503
                           loop
504
                              Idx := Idx + 1;
505
                           end loop;
506
 
507
                           if Idx <= Last and then
508
                             Sloc_Trace (Idx) = '['
509
                           then
510
                              Idx := Idx + 1;
511
                              Idx := Skip_Spaces;
512
                           else
513
                              Idx := 0;
514
                           end if;
515
 
516
                           return True;
517
 
518
                        else
519
                           return False;
520
                        end if;
521
                     end Line_Num_Match;
522
 
523
                     -----------------
524
                     -- Skip_Spaces --
525
                     -----------------
526
 
527
                     function Skip_Spaces return Natural is
528
                        Res : Natural;
529
 
530
                     begin
531
                        Res := Idx;
532
                        while Sloc_Trace (Res) = ' ' loop
533
                           Res := Res + 1;
534
 
535
                           if Res > Last then
536
                              Res := 0;
537
                              exit;
538
                           end if;
539
                        end loop;
540
 
541
                        return Res;
542
                     end Skip_Spaces;
543
 
544
                  begin
545
                     P := Sloc (E);
546
                     Sindex := Get_Source_File_Index (P);
547
                     Get_Name_String (File_Name (Sindex));
548
 
549
                     Idx := Skip_Spaces;
550
                     while Idx > 0 loop
551
                        if not File_Name_Match then
552
                           goto Continue;
553
                        elsif not Line_Num_Match then
554
                           goto Continue;
555
                        end if;
556
 
557
                        if Different_Trace_Lengths then
558
                           goto Continue;
559
                        end if;
560
                     end loop;
561
                  end;
562
               end if;
563
 
564
               --  If we have a Result_Type, then we must have a function with
565
               --  the proper result type.
566
 
567
               if Elmt.Result_Type /= No_Name then
568
                  if Ekind (E) /= E_Function
569
                    or else Chars (Etype (E)) /= Elmt.Result_Type
570
                  then
571
                     goto Continue;
572
                  end if;
573
               end if;
574
 
575
               --  If we have Parameter_Types, they must match
576
 
577
               if Elmt.Parameter_Types /= null then
578
                  Form := First_Formal (E);
579
 
580
                  if No (Form)
581
                    and then Elmt.Parameter_Types'Length = 1
582
                    and then Elmt.Parameter_Types (1) = No_Name
583
                  then
584
                     --  Parameterless procedure matches
585
 
586
                     null;
587
 
588
                  elsif Elmt.Parameter_Types = null then
589
                     goto Continue;
590
 
591
                  else
592
                     for J in Elmt.Parameter_Types'Range loop
593
                        if No (Form)
594
                          or else
595
                            Chars (Etype (Form)) /= Elmt.Parameter_Types (J)
596
                        then
597
                           goto Continue;
598
                        else
599
                           Next_Formal (Form);
600
                        end if;
601
                     end loop;
602
 
603
                     if Present (Form) then
604
                        goto Continue;
605
                     end if;
606
                  end if;
607
               end if;
608
 
609
               --  If we fall through, this is match
610
 
611
               Set_Eliminated;
612
               return;
613
            end if;
614
         end Check_Homonyms;
615
 
616
      <<Continue>>
617
         Elmt := Elmt.Homonym;
618
      end loop;
619
 
620
      return;
621
   end Check_Eliminated;
622
 
623
   -------------------------------------
624
   -- Check_For_Eliminated_Subprogram --
625
   -------------------------------------
626
 
627
   procedure Check_For_Eliminated_Subprogram (N : Node_Id; S : Entity_Id) is
628
      Ultimate_Subp  : constant Entity_Id := Ultimate_Alias (S);
629
      Enclosing_Subp : Entity_Id;
630
 
631
   begin
632
      if Is_Eliminated (Ultimate_Subp)
633
        and then not Inside_A_Generic
634
        and then not Is_Generic_Unit (Cunit_Entity (Current_Sem_Unit))
635
      then
636
         Enclosing_Subp := Current_Subprogram;
637
         while Present (Enclosing_Subp) loop
638
            if Is_Eliminated (Enclosing_Subp) then
639
               return;
640
            end if;
641
 
642
            Enclosing_Subp := Enclosing_Subprogram (Enclosing_Subp);
643
         end loop;
644
 
645
         Eliminate_Error_Msg (N, Ultimate_Subp);
646
      end if;
647
   end Check_For_Eliminated_Subprogram;
648
 
649
   -------------------------
650
   -- Eliminate_Error_Msg --
651
   -------------------------
652
 
653
   procedure Eliminate_Error_Msg (N : Node_Id; E : Entity_Id) is
654
   begin
655
      for J in Elim_Entities.First .. Elim_Entities.Last loop
656
         if E = Elim_Entities.Table (J).Subp then
657
            Error_Msg_Sloc := Sloc (Elim_Entities.Table (J).Prag);
658
            Error_Msg_NE ("cannot reference subprogram & eliminated #", N, E);
659
            return;
660
         end if;
661
      end loop;
662
 
663
      --  If this is an internal operation generated for a protected operation,
664
      --  its name does not match the source name, so just report the error.
665
 
666
      if not Comes_From_Source (E)
667
        and then Present (First_Entity (E))
668
        and then Is_Concurrent_Record_Type (Etype (First_Entity (E)))
669
      then
670
         Error_Msg_NE
671
           ("cannot reference eliminated protected subprogram", N, E);
672
 
673
      --  Otherwise should not fall through, entry should be in table
674
 
675
      else
676
         raise Program_Error;
677
      end if;
678
   end Eliminate_Error_Msg;
679
 
680
   ----------------
681
   -- Initialize --
682
   ----------------
683
 
684
   procedure Initialize is
685
   begin
686
      Elim_Hash_Table.Reset;
687
      Elim_Entities.Init;
688
      No_Elimination := True;
689
   end Initialize;
690
 
691
   ------------------------------
692
   -- Process_Eliminate_Pragma --
693
   ------------------------------
694
 
695
   procedure Process_Eliminate_Pragma
696
     (Pragma_Node         : Node_Id;
697
      Arg_Unit_Name       : Node_Id;
698
      Arg_Entity          : Node_Id;
699
      Arg_Parameter_Types : Node_Id;
700
      Arg_Result_Type     : Node_Id;
701
      Arg_Source_Location : Node_Id)
702
   is
703
      Data : constant Access_Elim_Data := new Elim_Data;
704
      --  Build result data here
705
 
706
      Elmt : Access_Elim_Data;
707
 
708
      Num_Names : Nat := 0;
709
      --  Number of names in unit name
710
 
711
      Lit       : Node_Id;
712
      Arg_Ent   : Entity_Id;
713
      Arg_Uname : Node_Id;
714
 
715
      function OK_Selected_Component (N : Node_Id) return Boolean;
716
      --  Test if N is a selected component with all identifiers, or a
717
      --  selected component whose selector is an operator symbol. As a
718
      --  side effect if result is True, sets Num_Names to the number
719
      --  of names present (identifiers and operator if any).
720
 
721
      ---------------------------
722
      -- OK_Selected_Component --
723
      ---------------------------
724
 
725
      function OK_Selected_Component (N : Node_Id) return Boolean is
726
      begin
727
         if Nkind (N) = N_Identifier
728
           or else Nkind (N) = N_Operator_Symbol
729
         then
730
            Num_Names := Num_Names + 1;
731
            return True;
732
 
733
         elsif Nkind (N) = N_Selected_Component then
734
            return OK_Selected_Component (Prefix (N))
735
              and then OK_Selected_Component (Selector_Name (N));
736
 
737
         else
738
            return False;
739
         end if;
740
      end OK_Selected_Component;
741
 
742
   --  Start of processing for Process_Eliminate_Pragma
743
 
744
   begin
745
      Data.Prag := Pragma_Node;
746
      Error_Msg_Name_1 := Name_Eliminate;
747
 
748
      --  Process Unit_Name argument
749
 
750
      if Nkind (Arg_Unit_Name) = N_Identifier then
751
         Data.Unit_Name := new Names'(1 => Chars (Arg_Unit_Name));
752
         Num_Names := 1;
753
 
754
      elsif OK_Selected_Component (Arg_Unit_Name) then
755
         Data.Unit_Name := new Names (1 .. Num_Names);
756
 
757
         Arg_Uname := Arg_Unit_Name;
758
         for J in reverse 2 .. Num_Names loop
759
            Data.Unit_Name (J) := Chars (Selector_Name (Arg_Uname));
760
            Arg_Uname := Prefix (Arg_Uname);
761
         end loop;
762
 
763
         Data.Unit_Name (1) := Chars (Arg_Uname);
764
 
765
      else
766
         Error_Msg_N
767
           ("wrong form for Unit_Name parameter of pragma%", Arg_Unit_Name);
768
         return;
769
      end if;
770
 
771
      --  Process Entity argument
772
 
773
      if Present (Arg_Entity) then
774
         Num_Names := 0;
775
 
776
         if Nkind (Arg_Entity) = N_Identifier
777
           or else Nkind (Arg_Entity) = N_Operator_Symbol
778
         then
779
            Data.Entity_Name  := Chars (Arg_Entity);
780
            Data.Entity_Node  := Arg_Entity;
781
            Data.Entity_Scope := null;
782
 
783
         elsif OK_Selected_Component (Arg_Entity) then
784
            Data.Entity_Scope := new Names (1 .. Num_Names - 1);
785
            Data.Entity_Name  := Chars (Selector_Name (Arg_Entity));
786
            Data.Entity_Node  := Arg_Entity;
787
 
788
            Arg_Ent := Prefix (Arg_Entity);
789
            for J in reverse 2 .. Num_Names - 1 loop
790
               Data.Entity_Scope (J) := Chars (Selector_Name (Arg_Ent));
791
               Arg_Ent := Prefix (Arg_Ent);
792
            end loop;
793
 
794
            Data.Entity_Scope (1) := Chars (Arg_Ent);
795
 
796
         elsif Is_Config_Static_String (Arg_Entity) then
797
            Data.Entity_Name := Name_Find;
798
            Data.Entity_Node := Arg_Entity;
799
 
800
         else
801
            return;
802
         end if;
803
      else
804
         Data.Entity_Node := Empty;
805
         Data.Entity_Name := Data.Unit_Name (Num_Names);
806
      end if;
807
 
808
      --  Process Parameter_Types argument
809
 
810
      if Present (Arg_Parameter_Types) then
811
 
812
         --  Here for aggregate case
813
 
814
         if Nkind (Arg_Parameter_Types) = N_Aggregate then
815
            Data.Parameter_Types :=
816
              new Names
817
                (1 .. List_Length (Expressions (Arg_Parameter_Types)));
818
 
819
            Lit := First (Expressions (Arg_Parameter_Types));
820
            for J in Data.Parameter_Types'Range loop
821
               if Is_Config_Static_String (Lit) then
822
                  Data.Parameter_Types (J) := Name_Find;
823
                  Next (Lit);
824
               else
825
                  return;
826
               end if;
827
            end loop;
828
 
829
         --  Otherwise we must have case of one name, which looks like a
830
         --  parenthesized literal rather than an aggregate.
831
 
832
         elsif Paren_Count (Arg_Parameter_Types) /= 1 then
833
            Error_Msg_N
834
              ("wrong form for argument of pragma Eliminate",
835
               Arg_Parameter_Types);
836
            return;
837
 
838
         elsif Is_Config_Static_String (Arg_Parameter_Types) then
839
            String_To_Name_Buffer (Strval (Arg_Parameter_Types));
840
 
841
            if Name_Len = 0 then
842
 
843
               --  Parameterless procedure
844
 
845
               Data.Parameter_Types := new Names'(1 => No_Name);
846
 
847
            else
848
               Data.Parameter_Types := new Names'(1 => Name_Find);
849
            end if;
850
 
851
         else
852
            return;
853
         end if;
854
      end if;
855
 
856
      --  Process Result_Types argument
857
 
858
      if Present (Arg_Result_Type) then
859
         if Is_Config_Static_String (Arg_Result_Type) then
860
            Data.Result_Type := Name_Find;
861
         else
862
            return;
863
         end if;
864
 
865
      --  Here if no Result_Types argument
866
 
867
      else
868
         Data.Result_Type := No_Name;
869
      end if;
870
 
871
      --  Process Source_Location argument
872
 
873
      if Present (Arg_Source_Location) then
874
         if Is_Config_Static_String (Arg_Source_Location) then
875
            Data.Source_Location := Name_Find;
876
         else
877
            return;
878
         end if;
879
      else
880
         Data.Source_Location := No_Name;
881
      end if;
882
 
883
      Elmt := Elim_Hash_Table.Get (Hash_Subprograms.Get_Key (Data));
884
 
885
      --  If we already have an entry with this same key, then link
886
      --  it into the chain of entries for this key.
887
 
888
      if Elmt /= null then
889
         Data.Homonym := Elmt.Homonym;
890
         Elmt.Homonym := Data;
891
 
892
      --  Otherwise create a new entry
893
 
894
      else
895
         Elim_Hash_Table.Set (Data);
896
      end if;
897
 
898
      No_Elimination := False;
899
   end Process_Eliminate_Pragma;
900
 
901
end Sem_Elim;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.