2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / gcc / ada / par-labl.adb
blob835be36e337ce49434e74ed0eca2a70fa925acfb
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- P A R . L A B L --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 1992-2003, Free Software Foundation, Inc. --
10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 2, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
20 -- MA 02111-1307, USA. --
21 -- --
22 -- GNAT was originally developed by the GNAT team at New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 -- --
25 ------------------------------------------------------------------------------
27 separate (Par)
28 procedure Labl is
29 Enclosing_Body_Or_Block : Node_Id;
30 -- Innermost enclosing body or block statement
32 Label_Decl_Node : Node_Id;
33 -- Implicit label declaration node
35 Defining_Ident_Node : Node_Id;
36 -- Defining identifier node for implicit label declaration
38 Next_Label_Elmt : Elmt_Id;
39 -- Next element on label element list
41 Label_Node : Node_Id;
42 -- Next label node to process
44 function Find_Enclosing_Body_Or_Block (N : Node_Id) return Node_Id;
45 -- Find the innermost body or block that encloses N.
47 function Find_Enclosing_Body (N : Node_Id) return Node_Id;
48 -- Find the innermost body that encloses N.
50 procedure Check_Distinct_Labels;
51 -- Checks the rule in RM-5.1(11), which requires distinct identifiers
52 -- for all the labels in a given body.
54 ---------------------------
55 -- Check_Distinct_Labels --
56 ---------------------------
58 procedure Check_Distinct_Labels is
59 Label_Id : constant Node_Id := Identifier (Label_Node);
61 Enclosing_Body : constant Node_Id :=
62 Find_Enclosing_Body (Enclosing_Body_Or_Block);
63 -- Innermost enclosing body
65 Next_Other_Label_Elmt : Elmt_Id := First_Elmt (Label_List);
66 -- Next element on label element list
68 Other_Label : Node_Id;
69 -- Next label node to process
71 begin
72 -- Loop through all the labels, and if we find some other label
73 -- (i.e. not Label_Node) that has the same identifier,
74 -- and whose innermost enclosing body is the same,
75 -- then we have an error.
77 -- Note that in the worst case, this is quadratic in the number
78 -- of labels. However, labels are not all that common, and this
79 -- is only called for explicit labels.
80 -- ???Nonetheless, the efficiency could be improved. For example,
81 -- call Labl for each body, rather than once per compilation.
83 while Present (Next_Other_Label_Elmt) loop
84 Other_Label := Node (Next_Other_Label_Elmt);
86 exit when Label_Node = Other_Label;
88 if Chars (Label_Id) = Chars (Identifier (Other_Label))
89 and then Enclosing_Body = Find_Enclosing_Body (Other_Label)
90 then
91 Error_Msg_Sloc := Sloc (Other_Label);
92 Error_Msg_N ("& conflicts with label#", Label_Id);
93 exit;
94 end if;
96 Next_Elmt (Next_Other_Label_Elmt);
97 end loop;
98 end Check_Distinct_Labels;
100 -------------------------
101 -- Find_Enclosing_Body --
102 -------------------------
104 function Find_Enclosing_Body (N : Node_Id) return Node_Id is
105 Result : Node_Id := N;
107 begin
108 -- This is the same as Find_Enclosing_Body_Or_Block, except
109 -- that we skip block statements and accept statements, instead
110 -- of stopping at them.
112 while Present (Result)
113 and then Nkind (Result) /= N_Entry_Body
114 and then Nkind (Result) /= N_Task_Body
115 and then Nkind (Result) /= N_Package_Body
116 and then Nkind (Result) /= N_Subprogram_Body
117 loop
118 Result := Parent (Result);
119 end loop;
121 return Result;
122 end Find_Enclosing_Body;
124 ----------------------------------
125 -- Find_Enclosing_Body_Or_Block --
126 ----------------------------------
128 function Find_Enclosing_Body_Or_Block (N : Node_Id) return Node_Id is
129 Result : Node_Id := Parent (N);
131 begin
132 -- Climb up the parent chain until we find a body or block.
134 while Present (Result)
135 and then Nkind (Result) /= N_Accept_Statement
136 and then Nkind (Result) /= N_Entry_Body
137 and then Nkind (Result) /= N_Task_Body
138 and then Nkind (Result) /= N_Package_Body
139 and then Nkind (Result) /= N_Subprogram_Body
140 and then Nkind (Result) /= N_Block_Statement
141 loop
142 Result := Parent (Result);
143 end loop;
145 return Result;
146 end Find_Enclosing_Body_Or_Block;
148 -- Start of processing for Par.Labl
150 begin
151 Next_Label_Elmt := First_Elmt (Label_List);
153 while Present (Next_Label_Elmt) loop
154 Label_Node := Node (Next_Label_Elmt);
156 if not Comes_From_Source (Label_Node) then
157 goto Next_Label;
158 end if;
160 -- Find the innermost enclosing body or block, which is where
161 -- we need to implicitly declare this label
163 Enclosing_Body_Or_Block := Find_Enclosing_Body_Or_Block (Label_Node);
165 -- If we didn't find a parent, then the label in question never got
166 -- hooked into a reasonable declarative part. This happens only in
167 -- error situations, and we simply ignore the entry (we aren't going
168 -- to get into the semantics in any case given the error).
170 if Present (Enclosing_Body_Or_Block) then
171 Check_Distinct_Labels;
173 -- Now create the implicit label declaration node and its
174 -- corresponding defining identifier. Note that the defining
175 -- occurrence of a label is the implicit label declaration that
176 -- we are creating. The label itself is an applied occurrence.
178 Label_Decl_Node :=
179 New_Node (N_Implicit_Label_Declaration, Sloc (Label_Node));
180 Defining_Ident_Node :=
181 New_Entity (N_Defining_Identifier, Sloc (Identifier (Label_Node)));
182 Set_Chars (Defining_Ident_Node, Chars (Identifier (Label_Node)));
183 Set_Defining_Identifier (Label_Decl_Node, Defining_Ident_Node);
184 Set_Label_Construct (Label_Decl_Node, Label_Node);
186 -- The following makes sure that Comes_From_Source is appropriately
187 -- set for the entity, depending on whether the label appeared in
188 -- the source explicitly or not.
190 Set_Comes_From_Source
191 (Defining_Ident_Node, Comes_From_Source (Identifier (Label_Node)));
193 -- Now attach the implicit label declaration to the appropriate
194 -- declarative region, creating a declaration list if none exists
196 if not Present (Declarations (Enclosing_Body_Or_Block)) then
197 Set_Declarations (Enclosing_Body_Or_Block, New_List);
198 end if;
200 Append (Label_Decl_Node, Declarations (Enclosing_Body_Or_Block));
201 end if;
203 <<Next_Label>>
204 Next_Elmt (Next_Label_Elmt);
205 end loop;
207 end Labl;