1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1992-2003, Free Software Foundation, Inc. --
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. --
22 -- GNAT was originally developed by the GNAT team at New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc. --
25 ------------------------------------------------------------------------------
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
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
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
)
91 Error_Msg_Sloc
:= Sloc
(Other_Label
);
92 Error_Msg_N
("& conflicts with label#", Label_Id
);
96 Next_Elmt
(Next_Other_Label_Elmt
);
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
;
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
118 Result
:= Parent
(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
);
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
142 Result
:= Parent
(Result
);
146 end Find_Enclosing_Body_Or_Block
;
148 -- Start of processing for Par.Labl
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
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.
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
);
200 Append
(Label_Decl_Node
, Declarations
(Enclosing_Body_Or_Block
));
204 Next_Elmt
(Next_Label_Elmt
);