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