1 |
706 |
jeremybenn |
------------------------------------------------------------------------------
|
2 |
|
|
-- --
|
3 |
|
|
-- GNAT COMPILER COMPONENTS --
|
4 |
|
|
-- --
|
5 |
|
|
-- S E M _ W A R N --
|
6 |
|
|
-- --
|
7 |
|
|
-- B o d y --
|
8 |
|
|
-- --
|
9 |
|
|
-- Copyright (C) 1999-2011, 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 Debug; use Debug;
|
28 |
|
|
with Einfo; use Einfo;
|
29 |
|
|
with Errout; use Errout;
|
30 |
|
|
with Exp_Code; use Exp_Code;
|
31 |
|
|
with Fname; use Fname;
|
32 |
|
|
with Lib; use Lib;
|
33 |
|
|
with Namet; use Namet;
|
34 |
|
|
with Nlists; use Nlists;
|
35 |
|
|
with Opt; use Opt;
|
36 |
|
|
with Par_SCO; use Par_SCO;
|
37 |
|
|
with Rtsfind; use Rtsfind;
|
38 |
|
|
with Sem; use Sem;
|
39 |
|
|
with Sem_Ch8; use Sem_Ch8;
|
40 |
|
|
with Sem_Aux; use Sem_Aux;
|
41 |
|
|
with Sem_Eval; use Sem_Eval;
|
42 |
|
|
with Sem_Util; use Sem_Util;
|
43 |
|
|
with Sinfo; use Sinfo;
|
44 |
|
|
with Sinput; use Sinput;
|
45 |
|
|
with Snames; use Snames;
|
46 |
|
|
with Stand; use Stand;
|
47 |
|
|
with Stringt; use Stringt;
|
48 |
|
|
with Uintp; use Uintp;
|
49 |
|
|
|
50 |
|
|
package body Sem_Warn is
|
51 |
|
|
|
52 |
|
|
-- The following table collects Id's of entities that are potentially
|
53 |
|
|
-- unreferenced. See Check_Unset_Reference for further details.
|
54 |
|
|
-- ??? Check_Unset_Reference has zero information about this table.
|
55 |
|
|
|
56 |
|
|
package Unreferenced_Entities is new Table.Table (
|
57 |
|
|
Table_Component_Type => Entity_Id,
|
58 |
|
|
Table_Index_Type => Nat,
|
59 |
|
|
Table_Low_Bound => 1,
|
60 |
|
|
Table_Initial => Alloc.Unreferenced_Entities_Initial,
|
61 |
|
|
Table_Increment => Alloc.Unreferenced_Entities_Increment,
|
62 |
|
|
Table_Name => "Unreferenced_Entities");
|
63 |
|
|
|
64 |
|
|
-- The following table collects potential warnings for IN OUT parameters
|
65 |
|
|
-- that are referenced but not modified. These warnings are processed when
|
66 |
|
|
-- the front end calls the procedure Output_Non_Modified_In_Out_Warnings.
|
67 |
|
|
-- The reason that we defer output of these messages is that we want to
|
68 |
|
|
-- detect the case where the relevant procedure is used as a generic actual
|
69 |
|
|
-- in an instantiation, since we suppress the warnings in this case. The
|
70 |
|
|
-- flag Used_As_Generic_Actual will be set in this case, but only at the
|
71 |
|
|
-- point of usage. Similarly, we suppress the message if the address of the
|
72 |
|
|
-- procedure is taken, where the flag Address_Taken may be set later.
|
73 |
|
|
|
74 |
|
|
package In_Out_Warnings is new Table.Table (
|
75 |
|
|
Table_Component_Type => Entity_Id,
|
76 |
|
|
Table_Index_Type => Nat,
|
77 |
|
|
Table_Low_Bound => 1,
|
78 |
|
|
Table_Initial => Alloc.In_Out_Warnings_Initial,
|
79 |
|
|
Table_Increment => Alloc.In_Out_Warnings_Increment,
|
80 |
|
|
Table_Name => "In_Out_Warnings");
|
81 |
|
|
|
82 |
|
|
--------------------------------------------------------
|
83 |
|
|
-- Handling of Warnings Off, Unmodified, Unreferenced --
|
84 |
|
|
--------------------------------------------------------
|
85 |
|
|
|
86 |
|
|
-- The functions Has_Warnings_Off, Has_Unmodified, Has_Unreferenced must
|
87 |
|
|
-- generally be used instead of Warnings_Off, Has_Pragma_Unmodified and
|
88 |
|
|
-- Has_Pragma_Unreferenced, as noted in the specs in Einfo.
|
89 |
|
|
|
90 |
|
|
-- In order to avoid losing warnings in -gnatw.w (warn on unnecessary
|
91 |
|
|
-- warnings off pragma) mode, i.e. to avoid false negatives, the code
|
92 |
|
|
-- must follow some important rules.
|
93 |
|
|
|
94 |
|
|
-- Call these functions as late as possible, after completing all other
|
95 |
|
|
-- tests, just before the warnings is given. For example, don't write:
|
96 |
|
|
|
97 |
|
|
-- if not Has_Warnings_Off (E)
|
98 |
|
|
-- and then some-other-predicate-on-E then ..
|
99 |
|
|
|
100 |
|
|
-- Instead the following is preferred
|
101 |
|
|
|
102 |
|
|
-- if some-other-predicate-on-E
|
103 |
|
|
-- and then Has_Warnings_Off (E)
|
104 |
|
|
|
105 |
|
|
-- This way if some-other-predicate is false, we avoid a false indication
|
106 |
|
|
-- that a Warnings (Off,E) pragma was useful in preventing a warning.
|
107 |
|
|
|
108 |
|
|
-- The second rule is that if both Has_Unmodified and Has_Warnings_Off, or
|
109 |
|
|
-- Has_Unreferenced and Has_Warnings_Off are called, make sure that the
|
110 |
|
|
-- call to Has_Unmodified/Has_Unreferenced comes first, this way we record
|
111 |
|
|
-- that the Warnings (Off) could have been Unreferenced or Unmodified. In
|
112 |
|
|
-- fact Has_Unmodified/Has_Unreferenced includes a test for Warnings Off,
|
113 |
|
|
-- and so a subsequent test is not needed anyway (though it is harmless).
|
114 |
|
|
|
115 |
|
|
-----------------------
|
116 |
|
|
-- Local Subprograms --
|
117 |
|
|
-----------------------
|
118 |
|
|
|
119 |
|
|
function Generic_Package_Spec_Entity (E : Entity_Id) return Boolean;
|
120 |
|
|
-- This returns true if the entity E is declared within a generic package.
|
121 |
|
|
-- The point of this is to detect variables which are not assigned within
|
122 |
|
|
-- the generic, but might be assigned outside the package for any given
|
123 |
|
|
-- instance. These are cases where we leave the warnings to be posted for
|
124 |
|
|
-- the instance, when we will know more.
|
125 |
|
|
|
126 |
|
|
function Goto_Spec_Entity (E : Entity_Id) return Entity_Id;
|
127 |
|
|
-- If E is a parameter entity for a subprogram body, then this function
|
128 |
|
|
-- returns the corresponding spec entity, if not, E is returned unchanged.
|
129 |
|
|
|
130 |
|
|
function Has_Pragma_Unmodified_Check_Spec (E : Entity_Id) return Boolean;
|
131 |
|
|
-- Tests Has_Pragma_Unmodified flag for entity E. If E is not a formal,
|
132 |
|
|
-- this is simply the setting of the flag Has_Pragma_Unmodified. If E is
|
133 |
|
|
-- a body formal, the setting of the flag in the corresponding spec is
|
134 |
|
|
-- also checked (and True returned if either flag is True).
|
135 |
|
|
|
136 |
|
|
function Has_Pragma_Unreferenced_Check_Spec (E : Entity_Id) return Boolean;
|
137 |
|
|
-- Tests Has_Pragma_Unreferenced flag for entity E. If E is not a formal,
|
138 |
|
|
-- this is simply the setting of the flag Has_Pragma_Unreferenced. If E is
|
139 |
|
|
-- a body formal, the setting of the flag in the corresponding spec is
|
140 |
|
|
-- also checked (and True returned if either flag is True).
|
141 |
|
|
|
142 |
|
|
function Never_Set_In_Source_Check_Spec (E : Entity_Id) return Boolean;
|
143 |
|
|
-- Tests Never_Set_In_Source status for entity E. If E is not a formal,
|
144 |
|
|
-- this is simply the setting of the flag Never_Set_In_Source. If E is
|
145 |
|
|
-- a body formal, the setting of the flag in the corresponding spec is
|
146 |
|
|
-- also checked (and False returned if either flag is False).
|
147 |
|
|
|
148 |
|
|
function Operand_Has_Warnings_Suppressed (N : Node_Id) return Boolean;
|
149 |
|
|
-- This function traverses the expression tree represented by the node N
|
150 |
|
|
-- and determines if any sub-operand is a reference to an entity for which
|
151 |
|
|
-- the Warnings_Off flag is set. True is returned if such an entity is
|
152 |
|
|
-- encountered, and False otherwise.
|
153 |
|
|
|
154 |
|
|
function Referenced_Check_Spec (E : Entity_Id) return Boolean;
|
155 |
|
|
-- Tests Referenced status for entity E. If E is not a formal, this is
|
156 |
|
|
-- simply the setting of the flag Referenced. If E is a body formal, the
|
157 |
|
|
-- setting of the flag in the corresponding spec is also checked (and True
|
158 |
|
|
-- returned if either flag is True).
|
159 |
|
|
|
160 |
|
|
function Referenced_As_LHS_Check_Spec (E : Entity_Id) return Boolean;
|
161 |
|
|
-- Tests Referenced_As_LHS status for entity E. If E is not a formal, this
|
162 |
|
|
-- is simply the setting of the flag Referenced_As_LHS. If E is a body
|
163 |
|
|
-- formal, the setting of the flag in the corresponding spec is also
|
164 |
|
|
-- checked (and True returned if either flag is True).
|
165 |
|
|
|
166 |
|
|
function Referenced_As_Out_Parameter_Check_Spec
|
167 |
|
|
(E : Entity_Id) return Boolean;
|
168 |
|
|
-- Tests Referenced_As_Out_Parameter status for entity E. If E is not a
|
169 |
|
|
-- formal, this is simply the setting of Referenced_As_Out_Parameter. If E
|
170 |
|
|
-- is a body formal, the setting of the flag in the corresponding spec is
|
171 |
|
|
-- also checked (and True returned if either flag is True).
|
172 |
|
|
|
173 |
|
|
procedure Warn_On_Unreferenced_Entity
|
174 |
|
|
(Spec_E : Entity_Id;
|
175 |
|
|
Body_E : Entity_Id := Empty);
|
176 |
|
|
-- Output warnings for unreferenced entity E. For the case of an entry
|
177 |
|
|
-- formal, Body_E is the corresponding body entity for a particular
|
178 |
|
|
-- accept statement, and the message is posted on Body_E. In all other
|
179 |
|
|
-- cases, Body_E is ignored and must be Empty.
|
180 |
|
|
|
181 |
|
|
function Warnings_Off_Check_Spec (E : Entity_Id) return Boolean;
|
182 |
|
|
-- Returns True if Warnings_Off is set for the entity E or (in the case
|
183 |
|
|
-- where there is a Spec_Entity), Warnings_Off is set for the Spec_Entity.
|
184 |
|
|
|
185 |
|
|
--------------------------
|
186 |
|
|
-- Check_Code_Statement --
|
187 |
|
|
--------------------------
|
188 |
|
|
|
189 |
|
|
procedure Check_Code_Statement (N : Node_Id) is
|
190 |
|
|
begin
|
191 |
|
|
-- If volatile, nothing to worry about
|
192 |
|
|
|
193 |
|
|
if Is_Asm_Volatile (N) then
|
194 |
|
|
return;
|
195 |
|
|
end if;
|
196 |
|
|
|
197 |
|
|
-- Warn if no input or no output
|
198 |
|
|
|
199 |
|
|
Setup_Asm_Inputs (N);
|
200 |
|
|
|
201 |
|
|
if No (Asm_Input_Value) then
|
202 |
|
|
Error_Msg_F
|
203 |
|
|
("?code statement with no inputs should usually be Volatile!", N);
|
204 |
|
|
return;
|
205 |
|
|
end if;
|
206 |
|
|
|
207 |
|
|
Setup_Asm_Outputs (N);
|
208 |
|
|
|
209 |
|
|
if No (Asm_Output_Variable) then
|
210 |
|
|
Error_Msg_F
|
211 |
|
|
("?code statement with no outputs should usually be Volatile!", N);
|
212 |
|
|
return;
|
213 |
|
|
end if;
|
214 |
|
|
end Check_Code_Statement;
|
215 |
|
|
|
216 |
|
|
---------------------------------
|
217 |
|
|
-- Check_Infinite_Loop_Warning --
|
218 |
|
|
---------------------------------
|
219 |
|
|
|
220 |
|
|
-- The case we look for is a while loop which tests a local variable, where
|
221 |
|
|
-- there is no obvious direct or possible indirect update of the variable
|
222 |
|
|
-- within the body of the loop.
|
223 |
|
|
|
224 |
|
|
procedure Check_Infinite_Loop_Warning (Loop_Statement : Node_Id) is
|
225 |
|
|
Expression : Node_Id := Empty;
|
226 |
|
|
-- Set to WHILE or EXIT WHEN condition to be tested
|
227 |
|
|
|
228 |
|
|
Ref : Node_Id := Empty;
|
229 |
|
|
-- Reference in Expression to variable that might not be modified
|
230 |
|
|
-- in loop, indicating a possible infinite loop.
|
231 |
|
|
|
232 |
|
|
Var : Entity_Id := Empty;
|
233 |
|
|
-- Corresponding entity (entity of Ref)
|
234 |
|
|
|
235 |
|
|
Function_Call_Found : Boolean := False;
|
236 |
|
|
-- True if Find_Var found a function call in the condition
|
237 |
|
|
|
238 |
|
|
procedure Find_Var (N : Node_Id);
|
239 |
|
|
-- Inspect condition to see if it depends on a single entity reference.
|
240 |
|
|
-- If so, Ref is set to point to the reference node, and Var is set to
|
241 |
|
|
-- the referenced Entity.
|
242 |
|
|
|
243 |
|
|
function Has_Indirection (T : Entity_Id) return Boolean;
|
244 |
|
|
-- If the controlling variable is an access type, or is a record type
|
245 |
|
|
-- with access components, assume that it is changed indirectly and
|
246 |
|
|
-- suppress the warning. As a concession to low-level programming, in
|
247 |
|
|
-- particular within Declib, we also suppress warnings on a record
|
248 |
|
|
-- type that contains components of type Address or Short_Address.
|
249 |
|
|
|
250 |
|
|
function Is_Suspicious_Function_Name (E : Entity_Id) return Boolean;
|
251 |
|
|
-- Given an entity name, see if the name appears to have something to
|
252 |
|
|
-- do with I/O or network stuff, and if so, return True. Used to kill
|
253 |
|
|
-- some false positives on a heuristic basis that such functions will
|
254 |
|
|
-- likely have some strange side effect dependencies. A rather funny
|
255 |
|
|
-- kludge, but warning messages are in the heuristics business.
|
256 |
|
|
|
257 |
|
|
function Test_Ref (N : Node_Id) return Traverse_Result;
|
258 |
|
|
-- Test for reference to variable in question. Returns Abandon if
|
259 |
|
|
-- matching reference found. Used in instantiation of No_Ref_Found.
|
260 |
|
|
|
261 |
|
|
function No_Ref_Found is new Traverse_Func (Test_Ref);
|
262 |
|
|
-- Function to traverse body of procedure. Returns Abandon if matching
|
263 |
|
|
-- reference found.
|
264 |
|
|
|
265 |
|
|
--------------
|
266 |
|
|
-- Find_Var --
|
267 |
|
|
--------------
|
268 |
|
|
|
269 |
|
|
procedure Find_Var (N : Node_Id) is
|
270 |
|
|
begin
|
271 |
|
|
-- Condition is a direct variable reference
|
272 |
|
|
|
273 |
|
|
if Is_Entity_Name (N) then
|
274 |
|
|
Ref := N;
|
275 |
|
|
Var := Entity (Ref);
|
276 |
|
|
|
277 |
|
|
-- Case of condition is a comparison with compile time known value
|
278 |
|
|
|
279 |
|
|
elsif Nkind (N) in N_Op_Compare then
|
280 |
|
|
if Compile_Time_Known_Value (Right_Opnd (N)) then
|
281 |
|
|
Find_Var (Left_Opnd (N));
|
282 |
|
|
|
283 |
|
|
elsif Compile_Time_Known_Value (Left_Opnd (N)) then
|
284 |
|
|
Find_Var (Right_Opnd (N));
|
285 |
|
|
|
286 |
|
|
-- Ignore any other comparison
|
287 |
|
|
|
288 |
|
|
else
|
289 |
|
|
return;
|
290 |
|
|
end if;
|
291 |
|
|
|
292 |
|
|
-- If condition is a negation, check its operand
|
293 |
|
|
|
294 |
|
|
elsif Nkind (N) = N_Op_Not then
|
295 |
|
|
Find_Var (Right_Opnd (N));
|
296 |
|
|
|
297 |
|
|
-- Case of condition is function call
|
298 |
|
|
|
299 |
|
|
elsif Nkind (N) = N_Function_Call then
|
300 |
|
|
|
301 |
|
|
Function_Call_Found := True;
|
302 |
|
|
|
303 |
|
|
-- Forget it if function name is not entity, who knows what
|
304 |
|
|
-- we might be calling?
|
305 |
|
|
|
306 |
|
|
if not Is_Entity_Name (Name (N)) then
|
307 |
|
|
return;
|
308 |
|
|
|
309 |
|
|
-- Forget it if function name is suspicious. A strange test
|
310 |
|
|
-- but warning generation is in the heuristics business!
|
311 |
|
|
|
312 |
|
|
elsif Is_Suspicious_Function_Name (Entity (Name (N))) then
|
313 |
|
|
return;
|
314 |
|
|
|
315 |
|
|
-- Forget it if warnings are suppressed on function entity
|
316 |
|
|
|
317 |
|
|
elsif Has_Warnings_Off (Entity (Name (N))) then
|
318 |
|
|
return;
|
319 |
|
|
end if;
|
320 |
|
|
|
321 |
|
|
-- OK, see if we have one argument
|
322 |
|
|
|
323 |
|
|
declare
|
324 |
|
|
PA : constant List_Id := Parameter_Associations (N);
|
325 |
|
|
|
326 |
|
|
begin
|
327 |
|
|
-- One argument, so check the argument
|
328 |
|
|
|
329 |
|
|
if Present (PA)
|
330 |
|
|
and then List_Length (PA) = 1
|
331 |
|
|
then
|
332 |
|
|
if Nkind (First (PA)) = N_Parameter_Association then
|
333 |
|
|
Find_Var (Explicit_Actual_Parameter (First (PA)));
|
334 |
|
|
else
|
335 |
|
|
Find_Var (First (PA));
|
336 |
|
|
end if;
|
337 |
|
|
|
338 |
|
|
-- Not one argument
|
339 |
|
|
|
340 |
|
|
else
|
341 |
|
|
return;
|
342 |
|
|
end if;
|
343 |
|
|
end;
|
344 |
|
|
|
345 |
|
|
-- Any other kind of node is not something we warn for
|
346 |
|
|
|
347 |
|
|
else
|
348 |
|
|
return;
|
349 |
|
|
end if;
|
350 |
|
|
end Find_Var;
|
351 |
|
|
|
352 |
|
|
---------------------
|
353 |
|
|
-- Has_Indirection --
|
354 |
|
|
---------------------
|
355 |
|
|
|
356 |
|
|
function Has_Indirection (T : Entity_Id) return Boolean is
|
357 |
|
|
Comp : Entity_Id;
|
358 |
|
|
Rec : Entity_Id;
|
359 |
|
|
|
360 |
|
|
begin
|
361 |
|
|
if Is_Access_Type (T) then
|
362 |
|
|
return True;
|
363 |
|
|
|
364 |
|
|
elsif Is_Private_Type (T)
|
365 |
|
|
and then Present (Full_View (T))
|
366 |
|
|
and then Is_Access_Type (Full_View (T))
|
367 |
|
|
then
|
368 |
|
|
return True;
|
369 |
|
|
|
370 |
|
|
elsif Is_Record_Type (T) then
|
371 |
|
|
Rec := T;
|
372 |
|
|
|
373 |
|
|
elsif Is_Private_Type (T)
|
374 |
|
|
and then Present (Full_View (T))
|
375 |
|
|
and then Is_Record_Type (Full_View (T))
|
376 |
|
|
then
|
377 |
|
|
Rec := Full_View (T);
|
378 |
|
|
else
|
379 |
|
|
return False;
|
380 |
|
|
end if;
|
381 |
|
|
|
382 |
|
|
Comp := First_Component (Rec);
|
383 |
|
|
while Present (Comp) loop
|
384 |
|
|
if Is_Access_Type (Etype (Comp))
|
385 |
|
|
or else Is_Descendent_Of_Address (Etype (Comp))
|
386 |
|
|
then
|
387 |
|
|
return True;
|
388 |
|
|
end if;
|
389 |
|
|
|
390 |
|
|
Next_Component (Comp);
|
391 |
|
|
end loop;
|
392 |
|
|
|
393 |
|
|
return False;
|
394 |
|
|
end Has_Indirection;
|
395 |
|
|
|
396 |
|
|
---------------------------------
|
397 |
|
|
-- Is_Suspicious_Function_Name --
|
398 |
|
|
---------------------------------
|
399 |
|
|
|
400 |
|
|
function Is_Suspicious_Function_Name (E : Entity_Id) return Boolean is
|
401 |
|
|
S : Entity_Id;
|
402 |
|
|
|
403 |
|
|
function Substring_Present (S : String) return Boolean;
|
404 |
|
|
-- Returns True if name buffer has given string delimited by non-
|
405 |
|
|
-- alphabetic characters or by end of string. S is lower case.
|
406 |
|
|
|
407 |
|
|
-----------------------
|
408 |
|
|
-- Substring_Present --
|
409 |
|
|
-----------------------
|
410 |
|
|
|
411 |
|
|
function Substring_Present (S : String) return Boolean is
|
412 |
|
|
Len : constant Natural := S'Length;
|
413 |
|
|
|
414 |
|
|
begin
|
415 |
|
|
for J in 1 .. Name_Len - (Len - 1) loop
|
416 |
|
|
if Name_Buffer (J .. J + (Len - 1)) = S
|
417 |
|
|
and then
|
418 |
|
|
(J = 1
|
419 |
|
|
or else Name_Buffer (J - 1) not in 'a' .. 'z')
|
420 |
|
|
and then
|
421 |
|
|
(J + Len > Name_Len
|
422 |
|
|
or else Name_Buffer (J + Len) not in 'a' .. 'z')
|
423 |
|
|
then
|
424 |
|
|
return True;
|
425 |
|
|
end if;
|
426 |
|
|
end loop;
|
427 |
|
|
|
428 |
|
|
return False;
|
429 |
|
|
end Substring_Present;
|
430 |
|
|
|
431 |
|
|
-- Start of processing for Is_Suspicious_Function_Name
|
432 |
|
|
|
433 |
|
|
begin
|
434 |
|
|
S := E;
|
435 |
|
|
while Present (S) and then S /= Standard_Standard loop
|
436 |
|
|
Get_Name_String (Chars (S));
|
437 |
|
|
|
438 |
|
|
if Substring_Present ("io")
|
439 |
|
|
or else Substring_Present ("file")
|
440 |
|
|
or else Substring_Present ("network")
|
441 |
|
|
then
|
442 |
|
|
return True;
|
443 |
|
|
else
|
444 |
|
|
S := Scope (S);
|
445 |
|
|
end if;
|
446 |
|
|
end loop;
|
447 |
|
|
|
448 |
|
|
return False;
|
449 |
|
|
end Is_Suspicious_Function_Name;
|
450 |
|
|
|
451 |
|
|
--------------
|
452 |
|
|
-- Test_Ref --
|
453 |
|
|
--------------
|
454 |
|
|
|
455 |
|
|
function Test_Ref (N : Node_Id) return Traverse_Result is
|
456 |
|
|
begin
|
457 |
|
|
-- Waste of time to look at the expression we are testing
|
458 |
|
|
|
459 |
|
|
if N = Expression then
|
460 |
|
|
return Skip;
|
461 |
|
|
|
462 |
|
|
-- Direct reference to variable in question
|
463 |
|
|
|
464 |
|
|
elsif Is_Entity_Name (N)
|
465 |
|
|
and then Present (Entity (N))
|
466 |
|
|
and then Entity (N) = Var
|
467 |
|
|
then
|
468 |
|
|
-- If this is an lvalue, then definitely abandon, since
|
469 |
|
|
-- this could be a direct modification of the variable.
|
470 |
|
|
|
471 |
|
|
if May_Be_Lvalue (N) then
|
472 |
|
|
return Abandon;
|
473 |
|
|
end if;
|
474 |
|
|
|
475 |
|
|
-- If we appear in the context of a procedure call, then also
|
476 |
|
|
-- abandon, since there may be issues of non-visible side
|
477 |
|
|
-- effects going on in the call.
|
478 |
|
|
|
479 |
|
|
declare
|
480 |
|
|
P : Node_Id;
|
481 |
|
|
|
482 |
|
|
begin
|
483 |
|
|
P := N;
|
484 |
|
|
loop
|
485 |
|
|
P := Parent (P);
|
486 |
|
|
exit when P = Loop_Statement;
|
487 |
|
|
|
488 |
|
|
-- Abandon if at procedure call, or something strange is
|
489 |
|
|
-- going on (perhaps a node with no parent that should
|
490 |
|
|
-- have one but does not?) As always, for a warning we
|
491 |
|
|
-- prefer to just abandon the warning than get into the
|
492 |
|
|
-- business of complaining about the tree structure here!
|
493 |
|
|
|
494 |
|
|
if No (P) or else Nkind (P) = N_Procedure_Call_Statement then
|
495 |
|
|
return Abandon;
|
496 |
|
|
end if;
|
497 |
|
|
end loop;
|
498 |
|
|
end;
|
499 |
|
|
|
500 |
|
|
-- Reference to variable renaming variable in question
|
501 |
|
|
|
502 |
|
|
elsif Is_Entity_Name (N)
|
503 |
|
|
and then Present (Entity (N))
|
504 |
|
|
and then Ekind (Entity (N)) = E_Variable
|
505 |
|
|
and then Present (Renamed_Object (Entity (N)))
|
506 |
|
|
and then Is_Entity_Name (Renamed_Object (Entity (N)))
|
507 |
|
|
and then Entity (Renamed_Object (Entity (N))) = Var
|
508 |
|
|
and then May_Be_Lvalue (N)
|
509 |
|
|
then
|
510 |
|
|
return Abandon;
|
511 |
|
|
|
512 |
|
|
-- Call to subprogram
|
513 |
|
|
|
514 |
|
|
elsif Nkind (N) = N_Procedure_Call_Statement
|
515 |
|
|
or else Nkind (N) = N_Function_Call
|
516 |
|
|
then
|
517 |
|
|
-- If subprogram is within the scope of the entity we are dealing
|
518 |
|
|
-- with as the loop variable, then it could modify this parameter,
|
519 |
|
|
-- so we abandon in this case. In the case of a subprogram that is
|
520 |
|
|
-- not an entity we also abandon. The check for no entity being
|
521 |
|
|
-- present is a defense against previous errors.
|
522 |
|
|
|
523 |
|
|
if not Is_Entity_Name (Name (N))
|
524 |
|
|
or else No (Entity (Name (N)))
|
525 |
|
|
or else Scope_Within (Entity (Name (N)), Scope (Var))
|
526 |
|
|
then
|
527 |
|
|
return Abandon;
|
528 |
|
|
end if;
|
529 |
|
|
|
530 |
|
|
-- If any of the arguments are of type access to subprogram, then
|
531 |
|
|
-- we may have funny side effects, so no warning in this case.
|
532 |
|
|
|
533 |
|
|
declare
|
534 |
|
|
Actual : Node_Id;
|
535 |
|
|
begin
|
536 |
|
|
Actual := First_Actual (N);
|
537 |
|
|
while Present (Actual) loop
|
538 |
|
|
if Is_Access_Subprogram_Type (Etype (Actual)) then
|
539 |
|
|
return Abandon;
|
540 |
|
|
else
|
541 |
|
|
Next_Actual (Actual);
|
542 |
|
|
end if;
|
543 |
|
|
end loop;
|
544 |
|
|
end;
|
545 |
|
|
|
546 |
|
|
-- Declaration of the variable in question
|
547 |
|
|
|
548 |
|
|
elsif Nkind (N) = N_Object_Declaration
|
549 |
|
|
and then Defining_Identifier (N) = Var
|
550 |
|
|
then
|
551 |
|
|
return Abandon;
|
552 |
|
|
end if;
|
553 |
|
|
|
554 |
|
|
-- All OK, continue scan
|
555 |
|
|
|
556 |
|
|
return OK;
|
557 |
|
|
end Test_Ref;
|
558 |
|
|
|
559 |
|
|
-- Start of processing for Check_Infinite_Loop_Warning
|
560 |
|
|
|
561 |
|
|
begin
|
562 |
|
|
-- Skip processing if debug flag gnatd.w is set
|
563 |
|
|
|
564 |
|
|
if Debug_Flag_Dot_W then
|
565 |
|
|
return;
|
566 |
|
|
end if;
|
567 |
|
|
|
568 |
|
|
-- Deal with Iteration scheme present
|
569 |
|
|
|
570 |
|
|
declare
|
571 |
|
|
Iter : constant Node_Id := Iteration_Scheme (Loop_Statement);
|
572 |
|
|
|
573 |
|
|
begin
|
574 |
|
|
if Present (Iter) then
|
575 |
|
|
|
576 |
|
|
-- While iteration
|
577 |
|
|
|
578 |
|
|
if Present (Condition (Iter)) then
|
579 |
|
|
|
580 |
|
|
-- Skip processing for while iteration with conditions actions,
|
581 |
|
|
-- since they make it too complicated to get the warning right.
|
582 |
|
|
|
583 |
|
|
if Present (Condition_Actions (Iter)) then
|
584 |
|
|
return;
|
585 |
|
|
end if;
|
586 |
|
|
|
587 |
|
|
-- Capture WHILE condition
|
588 |
|
|
|
589 |
|
|
Expression := Condition (Iter);
|
590 |
|
|
|
591 |
|
|
-- For iteration, do not process, since loop will always terminate
|
592 |
|
|
|
593 |
|
|
elsif Present (Loop_Parameter_Specification (Iter)) then
|
594 |
|
|
return;
|
595 |
|
|
end if;
|
596 |
|
|
end if;
|
597 |
|
|
end;
|
598 |
|
|
|
599 |
|
|
-- Check chain of EXIT statements, we only process loops that have a
|
600 |
|
|
-- single exit condition (either a single EXIT WHEN statement, or a
|
601 |
|
|
-- WHILE loop not containing any EXIT WHEN statements).
|
602 |
|
|
|
603 |
|
|
declare
|
604 |
|
|
Ident : constant Node_Id := Identifier (Loop_Statement);
|
605 |
|
|
Exit_Stmt : Node_Id;
|
606 |
|
|
|
607 |
|
|
begin
|
608 |
|
|
-- If we don't have a proper chain set, ignore call entirely. This
|
609 |
|
|
-- happens because of previous errors.
|
610 |
|
|
|
611 |
|
|
if No (Entity (Ident))
|
612 |
|
|
or else Ekind (Entity (Ident)) /= E_Loop
|
613 |
|
|
then
|
614 |
|
|
return;
|
615 |
|
|
end if;
|
616 |
|
|
|
617 |
|
|
-- Otherwise prepare to scan list of EXIT statements
|
618 |
|
|
|
619 |
|
|
Exit_Stmt := First_Exit_Statement (Entity (Ident));
|
620 |
|
|
while Present (Exit_Stmt) loop
|
621 |
|
|
|
622 |
|
|
-- Check for EXIT WHEN
|
623 |
|
|
|
624 |
|
|
if Present (Condition (Exit_Stmt)) then
|
625 |
|
|
|
626 |
|
|
-- Quit processing if EXIT WHEN in WHILE loop, or more than
|
627 |
|
|
-- one EXIT WHEN statement present in the loop.
|
628 |
|
|
|
629 |
|
|
if Present (Expression) then
|
630 |
|
|
return;
|
631 |
|
|
|
632 |
|
|
-- Otherwise capture condition from EXIT WHEN statement
|
633 |
|
|
|
634 |
|
|
else
|
635 |
|
|
Expression := Condition (Exit_Stmt);
|
636 |
|
|
end if;
|
637 |
|
|
end if;
|
638 |
|
|
|
639 |
|
|
Exit_Stmt := Next_Exit_Statement (Exit_Stmt);
|
640 |
|
|
end loop;
|
641 |
|
|
end;
|
642 |
|
|
|
643 |
|
|
-- Return if no condition to test
|
644 |
|
|
|
645 |
|
|
if No (Expression) then
|
646 |
|
|
return;
|
647 |
|
|
end if;
|
648 |
|
|
|
649 |
|
|
-- Initial conditions met, see if condition is of right form
|
650 |
|
|
|
651 |
|
|
Find_Var (Expression);
|
652 |
|
|
|
653 |
|
|
-- Nothing to do if local variable from source not found. If it's a
|
654 |
|
|
-- renaming, it is probably renaming something too complicated to deal
|
655 |
|
|
-- with here.
|
656 |
|
|
|
657 |
|
|
if No (Var)
|
658 |
|
|
or else Ekind (Var) /= E_Variable
|
659 |
|
|
or else Is_Library_Level_Entity (Var)
|
660 |
|
|
or else not Comes_From_Source (Var)
|
661 |
|
|
or else Nkind (Parent (Var)) = N_Object_Renaming_Declaration
|
662 |
|
|
then
|
663 |
|
|
return;
|
664 |
|
|
|
665 |
|
|
-- Nothing to do if there is some indirection involved (assume that the
|
666 |
|
|
-- designated variable might be modified in some way we don't see).
|
667 |
|
|
-- However, if no function call was found, then we don't care about
|
668 |
|
|
-- indirections, because the condition must be something like "while X
|
669 |
|
|
-- /= null loop", so we don't care if X.all is modified in the loop.
|
670 |
|
|
|
671 |
|
|
elsif Function_Call_Found and then Has_Indirection (Etype (Var)) then
|
672 |
|
|
return;
|
673 |
|
|
|
674 |
|
|
-- Same sort of thing for volatile variable, might be modified by
|
675 |
|
|
-- some other task or by the operating system in some way.
|
676 |
|
|
|
677 |
|
|
elsif Is_Volatile (Var) then
|
678 |
|
|
return;
|
679 |
|
|
end if;
|
680 |
|
|
|
681 |
|
|
-- Filter out case of original statement sequence starting with delay.
|
682 |
|
|
-- We assume this is a multi-tasking program and that the condition
|
683 |
|
|
-- is affected by other threads (some kind of busy wait).
|
684 |
|
|
|
685 |
|
|
declare
|
686 |
|
|
Fstm : constant Node_Id :=
|
687 |
|
|
Original_Node (First (Statements (Loop_Statement)));
|
688 |
|
|
begin
|
689 |
|
|
if Nkind (Fstm) = N_Delay_Relative_Statement
|
690 |
|
|
or else Nkind (Fstm) = N_Delay_Until_Statement
|
691 |
|
|
then
|
692 |
|
|
return;
|
693 |
|
|
end if;
|
694 |
|
|
end;
|
695 |
|
|
|
696 |
|
|
-- We have a variable reference of the right form, now we scan the loop
|
697 |
|
|
-- body to see if it looks like it might not be modified
|
698 |
|
|
|
699 |
|
|
if No_Ref_Found (Loop_Statement) = OK then
|
700 |
|
|
Error_Msg_NE
|
701 |
|
|
("?variable& is not modified in loop body!", Ref, Var);
|
702 |
|
|
Error_Msg_N
|
703 |
|
|
("\?possible infinite loop!", Ref);
|
704 |
|
|
end if;
|
705 |
|
|
end Check_Infinite_Loop_Warning;
|
706 |
|
|
|
707 |
|
|
----------------------------
|
708 |
|
|
-- Check_Low_Bound_Tested --
|
709 |
|
|
----------------------------
|
710 |
|
|
|
711 |
|
|
procedure Check_Low_Bound_Tested (Expr : Node_Id) is
|
712 |
|
|
begin
|
713 |
|
|
if Comes_From_Source (Expr) then
|
714 |
|
|
declare
|
715 |
|
|
L : constant Node_Id := Left_Opnd (Expr);
|
716 |
|
|
R : constant Node_Id := Right_Opnd (Expr);
|
717 |
|
|
begin
|
718 |
|
|
if Nkind (L) = N_Attribute_Reference
|
719 |
|
|
and then Attribute_Name (L) = Name_First
|
720 |
|
|
and then Is_Entity_Name (Prefix (L))
|
721 |
|
|
and then Is_Formal (Entity (Prefix (L)))
|
722 |
|
|
then
|
723 |
|
|
Set_Low_Bound_Tested (Entity (Prefix (L)));
|
724 |
|
|
end if;
|
725 |
|
|
|
726 |
|
|
if Nkind (R) = N_Attribute_Reference
|
727 |
|
|
and then Attribute_Name (R) = Name_First
|
728 |
|
|
and then Is_Entity_Name (Prefix (R))
|
729 |
|
|
and then Is_Formal (Entity (Prefix (R)))
|
730 |
|
|
then
|
731 |
|
|
Set_Low_Bound_Tested (Entity (Prefix (R)));
|
732 |
|
|
end if;
|
733 |
|
|
end;
|
734 |
|
|
end if;
|
735 |
|
|
end Check_Low_Bound_Tested;
|
736 |
|
|
|
737 |
|
|
----------------------
|
738 |
|
|
-- Check_References --
|
739 |
|
|
----------------------
|
740 |
|
|
|
741 |
|
|
procedure Check_References (E : Entity_Id; Anod : Node_Id := Empty) is
|
742 |
|
|
E1 : Entity_Id;
|
743 |
|
|
E1T : Entity_Id;
|
744 |
|
|
UR : Node_Id;
|
745 |
|
|
|
746 |
|
|
function Body_Formal
|
747 |
|
|
(E : Entity_Id;
|
748 |
|
|
Accept_Statement : Node_Id) return Entity_Id;
|
749 |
|
|
-- For an entry formal entity from an entry declaration, find the
|
750 |
|
|
-- corresponding body formal from the given accept statement.
|
751 |
|
|
|
752 |
|
|
function Missing_Subunits return Boolean;
|
753 |
|
|
-- We suppress warnings when there are missing subunits, because this
|
754 |
|
|
-- may generate too many false positives: entities in a parent may only
|
755 |
|
|
-- be referenced in one of the subunits. We make an exception for
|
756 |
|
|
-- subunits that contain no other stubs.
|
757 |
|
|
|
758 |
|
|
procedure Output_Reference_Error (M : String);
|
759 |
|
|
-- Used to output an error message. Deals with posting the error on the
|
760 |
|
|
-- body formal in the accept case.
|
761 |
|
|
|
762 |
|
|
function Publicly_Referenceable (Ent : Entity_Id) return Boolean;
|
763 |
|
|
-- This is true if the entity in question is potentially referenceable
|
764 |
|
|
-- from another unit. This is true for entities in packages that are at
|
765 |
|
|
-- the library level.
|
766 |
|
|
|
767 |
|
|
function Warnings_Off_E1 return Boolean;
|
768 |
|
|
-- Return True if Warnings_Off is set for E1, or for its Etype (E1T),
|
769 |
|
|
-- or for the base type of E1T.
|
770 |
|
|
|
771 |
|
|
-----------------
|
772 |
|
|
-- Body_Formal --
|
773 |
|
|
-----------------
|
774 |
|
|
|
775 |
|
|
function Body_Formal
|
776 |
|
|
(E : Entity_Id;
|
777 |
|
|
Accept_Statement : Node_Id) return Entity_Id
|
778 |
|
|
is
|
779 |
|
|
Body_Param : Node_Id;
|
780 |
|
|
Body_E : Entity_Id;
|
781 |
|
|
|
782 |
|
|
begin
|
783 |
|
|
-- Loop to find matching parameter in accept statement
|
784 |
|
|
|
785 |
|
|
Body_Param := First (Parameter_Specifications (Accept_Statement));
|
786 |
|
|
while Present (Body_Param) loop
|
787 |
|
|
Body_E := Defining_Identifier (Body_Param);
|
788 |
|
|
|
789 |
|
|
if Chars (Body_E) = Chars (E) then
|
790 |
|
|
return Body_E;
|
791 |
|
|
end if;
|
792 |
|
|
|
793 |
|
|
Next (Body_Param);
|
794 |
|
|
end loop;
|
795 |
|
|
|
796 |
|
|
-- Should never fall through, should always find a match
|
797 |
|
|
|
798 |
|
|
raise Program_Error;
|
799 |
|
|
end Body_Formal;
|
800 |
|
|
|
801 |
|
|
----------------------
|
802 |
|
|
-- Missing_Subunits --
|
803 |
|
|
----------------------
|
804 |
|
|
|
805 |
|
|
function Missing_Subunits return Boolean is
|
806 |
|
|
D : Node_Id;
|
807 |
|
|
|
808 |
|
|
begin
|
809 |
|
|
if not Unloaded_Subunits then
|
810 |
|
|
|
811 |
|
|
-- Normal compilation, all subunits are present
|
812 |
|
|
|
813 |
|
|
return False;
|
814 |
|
|
|
815 |
|
|
elsif E /= Main_Unit_Entity then
|
816 |
|
|
|
817 |
|
|
-- No warnings on a stub that is not the main unit
|
818 |
|
|
|
819 |
|
|
return True;
|
820 |
|
|
|
821 |
|
|
elsif Nkind (Unit_Declaration_Node (E)) in N_Proper_Body then
|
822 |
|
|
D := First (Declarations (Unit_Declaration_Node (E)));
|
823 |
|
|
while Present (D) loop
|
824 |
|
|
|
825 |
|
|
-- No warnings if the proper body contains nested stubs
|
826 |
|
|
|
827 |
|
|
if Nkind (D) in N_Body_Stub then
|
828 |
|
|
return True;
|
829 |
|
|
end if;
|
830 |
|
|
|
831 |
|
|
Next (D);
|
832 |
|
|
end loop;
|
833 |
|
|
|
834 |
|
|
return False;
|
835 |
|
|
|
836 |
|
|
else
|
837 |
|
|
-- Missing stubs elsewhere
|
838 |
|
|
|
839 |
|
|
return True;
|
840 |
|
|
end if;
|
841 |
|
|
end Missing_Subunits;
|
842 |
|
|
|
843 |
|
|
----------------------------
|
844 |
|
|
-- Output_Reference_Error --
|
845 |
|
|
----------------------------
|
846 |
|
|
|
847 |
|
|
procedure Output_Reference_Error (M : String) is
|
848 |
|
|
begin
|
849 |
|
|
-- Never issue messages for internal names, nor for renamings
|
850 |
|
|
|
851 |
|
|
if Is_Internal_Name (Chars (E1))
|
852 |
|
|
or else Nkind (Parent (E1)) = N_Object_Renaming_Declaration
|
853 |
|
|
then
|
854 |
|
|
return;
|
855 |
|
|
end if;
|
856 |
|
|
|
857 |
|
|
-- Don't output message for IN OUT formal unless we have the warning
|
858 |
|
|
-- flag specifically set. It is a bit odd to distinguish IN OUT
|
859 |
|
|
-- formals from other cases. This distinction is historical in
|
860 |
|
|
-- nature. Warnings for IN OUT formals were added fairly late.
|
861 |
|
|
|
862 |
|
|
if Ekind (E1) = E_In_Out_Parameter
|
863 |
|
|
and then not Check_Unreferenced_Formals
|
864 |
|
|
then
|
865 |
|
|
return;
|
866 |
|
|
end if;
|
867 |
|
|
|
868 |
|
|
-- Other than accept case, post error on defining identifier
|
869 |
|
|
|
870 |
|
|
if No (Anod) then
|
871 |
|
|
Error_Msg_N (M, E1);
|
872 |
|
|
|
873 |
|
|
-- Accept case, find body formal to post the message
|
874 |
|
|
|
875 |
|
|
else
|
876 |
|
|
Error_Msg_NE (M, Body_Formal (E1, Accept_Statement => Anod), E1);
|
877 |
|
|
|
878 |
|
|
end if;
|
879 |
|
|
end Output_Reference_Error;
|
880 |
|
|
|
881 |
|
|
----------------------------
|
882 |
|
|
-- Publicly_Referenceable --
|
883 |
|
|
----------------------------
|
884 |
|
|
|
885 |
|
|
function Publicly_Referenceable (Ent : Entity_Id) return Boolean is
|
886 |
|
|
P : Node_Id;
|
887 |
|
|
Prev : Node_Id;
|
888 |
|
|
|
889 |
|
|
begin
|
890 |
|
|
-- A formal parameter is never referenceable outside the body of its
|
891 |
|
|
-- subprogram or entry.
|
892 |
|
|
|
893 |
|
|
if Is_Formal (Ent) then
|
894 |
|
|
return False;
|
895 |
|
|
end if;
|
896 |
|
|
|
897 |
|
|
-- Examine parents to look for a library level package spec. But if
|
898 |
|
|
-- we find a body or block or other similar construct along the way,
|
899 |
|
|
-- we cannot be referenced.
|
900 |
|
|
|
901 |
|
|
Prev := Ent;
|
902 |
|
|
P := Parent (Ent);
|
903 |
|
|
loop
|
904 |
|
|
case Nkind (P) is
|
905 |
|
|
|
906 |
|
|
-- If we get to top of tree, then publicly referenceable
|
907 |
|
|
|
908 |
|
|
when N_Empty =>
|
909 |
|
|
return True;
|
910 |
|
|
|
911 |
|
|
-- If we reach a generic package declaration, then always
|
912 |
|
|
-- consider this referenceable, since any instantiation will
|
913 |
|
|
-- have access to the entities in the generic package. Note
|
914 |
|
|
-- that the package itself may not be instantiated, but then
|
915 |
|
|
-- we will get a warning for the package entity.
|
916 |
|
|
|
917 |
|
|
-- Note that generic formal parameters are themselves not
|
918 |
|
|
-- publicly referenceable in an instance, and warnings on them
|
919 |
|
|
-- are useful.
|
920 |
|
|
|
921 |
|
|
when N_Generic_Package_Declaration =>
|
922 |
|
|
return
|
923 |
|
|
not Is_List_Member (Prev)
|
924 |
|
|
or else List_Containing (Prev)
|
925 |
|
|
/= Generic_Formal_Declarations (P);
|
926 |
|
|
|
927 |
|
|
-- Similarly, the generic formals of a generic subprogram are
|
928 |
|
|
-- not accessible.
|
929 |
|
|
|
930 |
|
|
when N_Generic_Subprogram_Declaration =>
|
931 |
|
|
if Is_List_Member (Prev)
|
932 |
|
|
and then List_Containing (Prev) =
|
933 |
|
|
Generic_Formal_Declarations (P)
|
934 |
|
|
then
|
935 |
|
|
return False;
|
936 |
|
|
else
|
937 |
|
|
P := Parent (P);
|
938 |
|
|
end if;
|
939 |
|
|
|
940 |
|
|
-- If we reach a subprogram body, entity is not referenceable
|
941 |
|
|
-- unless it is the defining entity of the body. This will
|
942 |
|
|
-- happen, e.g. when a function is an attribute renaming that
|
943 |
|
|
-- is rewritten as a body.
|
944 |
|
|
|
945 |
|
|
when N_Subprogram_Body =>
|
946 |
|
|
if Ent /= Defining_Entity (P) then
|
947 |
|
|
return False;
|
948 |
|
|
else
|
949 |
|
|
P := Parent (P);
|
950 |
|
|
end if;
|
951 |
|
|
|
952 |
|
|
-- If we reach any other body, definitely not referenceable
|
953 |
|
|
|
954 |
|
|
when N_Package_Body |
|
955 |
|
|
N_Task_Body |
|
956 |
|
|
N_Entry_Body |
|
957 |
|
|
N_Protected_Body |
|
958 |
|
|
N_Block_Statement |
|
959 |
|
|
N_Subunit =>
|
960 |
|
|
return False;
|
961 |
|
|
|
962 |
|
|
-- For all other cases, keep looking up tree
|
963 |
|
|
|
964 |
|
|
when others =>
|
965 |
|
|
Prev := P;
|
966 |
|
|
P := Parent (P);
|
967 |
|
|
end case;
|
968 |
|
|
end loop;
|
969 |
|
|
end Publicly_Referenceable;
|
970 |
|
|
|
971 |
|
|
---------------------
|
972 |
|
|
-- Warnings_Off_E1 --
|
973 |
|
|
---------------------
|
974 |
|
|
|
975 |
|
|
function Warnings_Off_E1 return Boolean is
|
976 |
|
|
begin
|
977 |
|
|
return Has_Warnings_Off (E1T)
|
978 |
|
|
or else Has_Warnings_Off (Base_Type (E1T))
|
979 |
|
|
or else Warnings_Off_Check_Spec (E1);
|
980 |
|
|
end Warnings_Off_E1;
|
981 |
|
|
|
982 |
|
|
-- Start of processing for Check_References
|
983 |
|
|
|
984 |
|
|
begin
|
985 |
|
|
-- No messages if warnings are suppressed, or if we have detected any
|
986 |
|
|
-- real errors so far (this last check avoids junk messages resulting
|
987 |
|
|
-- from errors, e.g. a subunit that is not loaded).
|
988 |
|
|
|
989 |
|
|
if Warning_Mode = Suppress
|
990 |
|
|
or else Serious_Errors_Detected /= 0
|
991 |
|
|
then
|
992 |
|
|
return;
|
993 |
|
|
end if;
|
994 |
|
|
|
995 |
|
|
-- We also skip the messages if any subunits were not loaded (see
|
996 |
|
|
-- comment in Sem_Ch10 to understand how this is set, and why it is
|
997 |
|
|
-- necessary to suppress the warnings in this case).
|
998 |
|
|
|
999 |
|
|
if Missing_Subunits then
|
1000 |
|
|
return;
|
1001 |
|
|
end if;
|
1002 |
|
|
|
1003 |
|
|
-- Otherwise loop through entities, looking for suspicious stuff
|
1004 |
|
|
|
1005 |
|
|
E1 := First_Entity (E);
|
1006 |
|
|
while Present (E1) loop
|
1007 |
|
|
E1T := Etype (E1);
|
1008 |
|
|
|
1009 |
|
|
-- We are only interested in source entities. We also don't issue
|
1010 |
|
|
-- warnings within instances, since the proper place for such
|
1011 |
|
|
-- warnings is on the template when it is compiled.
|
1012 |
|
|
|
1013 |
|
|
if Comes_From_Source (E1)
|
1014 |
|
|
and then Instantiation_Location (Sloc (E1)) = No_Location
|
1015 |
|
|
then
|
1016 |
|
|
-- We are interested in variables and out/in-out parameters, but
|
1017 |
|
|
-- we exclude protected types, too complicated to worry about.
|
1018 |
|
|
|
1019 |
|
|
if Ekind (E1) = E_Variable
|
1020 |
|
|
or else
|
1021 |
|
|
(Ekind_In (E1, E_Out_Parameter, E_In_Out_Parameter)
|
1022 |
|
|
and then not Is_Protected_Type (Current_Scope))
|
1023 |
|
|
then
|
1024 |
|
|
-- Case of an unassigned variable
|
1025 |
|
|
|
1026 |
|
|
-- First gather any Unset_Reference indication for E1. In the
|
1027 |
|
|
-- case of a parameter, it is the Spec_Entity that is relevant.
|
1028 |
|
|
|
1029 |
|
|
if Ekind (E1) = E_Out_Parameter
|
1030 |
|
|
and then Present (Spec_Entity (E1))
|
1031 |
|
|
then
|
1032 |
|
|
UR := Unset_Reference (Spec_Entity (E1));
|
1033 |
|
|
else
|
1034 |
|
|
UR := Unset_Reference (E1);
|
1035 |
|
|
end if;
|
1036 |
|
|
|
1037 |
|
|
-- Special processing for access types
|
1038 |
|
|
|
1039 |
|
|
if Present (UR)
|
1040 |
|
|
and then Is_Access_Type (E1T)
|
1041 |
|
|
then
|
1042 |
|
|
-- For access types, the only time we made a UR entry was
|
1043 |
|
|
-- for a dereference, and so we post the appropriate warning
|
1044 |
|
|
-- here (note that the dereference may not be explicit in
|
1045 |
|
|
-- the source, for example in the case of a dispatching call
|
1046 |
|
|
-- with an anonymous access controlling formal, or of an
|
1047 |
|
|
-- assignment of a pointer involving discriminant check on
|
1048 |
|
|
-- the designated object).
|
1049 |
|
|
|
1050 |
|
|
if not Warnings_Off_E1 then
|
1051 |
|
|
Error_Msg_NE ("?& may be null!", UR, E1);
|
1052 |
|
|
end if;
|
1053 |
|
|
|
1054 |
|
|
goto Continue;
|
1055 |
|
|
|
1056 |
|
|
-- Case of variable that could be a constant. Note that we
|
1057 |
|
|
-- never signal such messages for generic package entities,
|
1058 |
|
|
-- since a given instance could have modifications outside
|
1059 |
|
|
-- the package.
|
1060 |
|
|
|
1061 |
|
|
elsif Warn_On_Constant
|
1062 |
|
|
and then (Ekind (E1) = E_Variable
|
1063 |
|
|
and then Has_Initial_Value (E1))
|
1064 |
|
|
and then Never_Set_In_Source_Check_Spec (E1)
|
1065 |
|
|
and then not Address_Taken (E1)
|
1066 |
|
|
and then not Generic_Package_Spec_Entity (E1)
|
1067 |
|
|
then
|
1068 |
|
|
-- A special case, if this variable is volatile and not
|
1069 |
|
|
-- imported, it is not helpful to tell the programmer
|
1070 |
|
|
-- to mark the variable as constant, since this would be
|
1071 |
|
|
-- illegal by virtue of RM C.6(13).
|
1072 |
|
|
|
1073 |
|
|
if (Is_Volatile (E1) or else Has_Volatile_Components (E1))
|
1074 |
|
|
and then not Is_Imported (E1)
|
1075 |
|
|
then
|
1076 |
|
|
Error_Msg_N
|
1077 |
|
|
("?& is not modified, volatile has no effect!", E1);
|
1078 |
|
|
|
1079 |
|
|
-- Another special case, Exception_Occurrence, this catches
|
1080 |
|
|
-- the case of exception choice (and a bit more too, but not
|
1081 |
|
|
-- worth doing more investigation here).
|
1082 |
|
|
|
1083 |
|
|
elsif Is_RTE (E1T, RE_Exception_Occurrence) then
|
1084 |
|
|
null;
|
1085 |
|
|
|
1086 |
|
|
-- Here we give the warning if referenced and no pragma
|
1087 |
|
|
-- Unreferenced or Unmodified is present.
|
1088 |
|
|
|
1089 |
|
|
else
|
1090 |
|
|
-- Variable case
|
1091 |
|
|
|
1092 |
|
|
if Ekind (E1) = E_Variable then
|
1093 |
|
|
if Referenced_Check_Spec (E1)
|
1094 |
|
|
and then not Has_Pragma_Unreferenced_Check_Spec (E1)
|
1095 |
|
|
and then not Has_Pragma_Unmodified_Check_Spec (E1)
|
1096 |
|
|
then
|
1097 |
|
|
if not Warnings_Off_E1 then
|
1098 |
|
|
Error_Msg_N -- CODEFIX
|
1099 |
|
|
("?& is not modified, "
|
1100 |
|
|
& "could be declared constant!",
|
1101 |
|
|
E1);
|
1102 |
|
|
end if;
|
1103 |
|
|
end if;
|
1104 |
|
|
end if;
|
1105 |
|
|
end if;
|
1106 |
|
|
|
1107 |
|
|
-- Other cases of a variable or parameter never set in source
|
1108 |
|
|
|
1109 |
|
|
elsif Never_Set_In_Source_Check_Spec (E1)
|
1110 |
|
|
|
1111 |
|
|
-- No warning if warning for this case turned off
|
1112 |
|
|
|
1113 |
|
|
and then Warn_On_No_Value_Assigned
|
1114 |
|
|
|
1115 |
|
|
-- No warning if address taken somewhere
|
1116 |
|
|
|
1117 |
|
|
and then not Address_Taken (E1)
|
1118 |
|
|
|
1119 |
|
|
-- No warning if explicit initial value
|
1120 |
|
|
|
1121 |
|
|
and then not Has_Initial_Value (E1)
|
1122 |
|
|
|
1123 |
|
|
-- No warning for generic package spec entities, since we
|
1124 |
|
|
-- might set them in a child unit or something like that
|
1125 |
|
|
|
1126 |
|
|
and then not Generic_Package_Spec_Entity (E1)
|
1127 |
|
|
|
1128 |
|
|
-- No warning if fully initialized type, except that for
|
1129 |
|
|
-- this purpose we do not consider access types to qualify
|
1130 |
|
|
-- as fully initialized types (relying on an access type
|
1131 |
|
|
-- variable being null when it is never set is a bit odd!)
|
1132 |
|
|
|
1133 |
|
|
-- Also we generate warning for an out parameter that is
|
1134 |
|
|
-- never referenced, since again it seems odd to rely on
|
1135 |
|
|
-- default initialization to set an out parameter value.
|
1136 |
|
|
|
1137 |
|
|
and then (Is_Access_Type (E1T)
|
1138 |
|
|
or else Ekind (E1) = E_Out_Parameter
|
1139 |
|
|
or else not Is_Fully_Initialized_Type (E1T))
|
1140 |
|
|
then
|
1141 |
|
|
-- Do not output complaint about never being assigned a
|
1142 |
|
|
-- value if a pragma Unmodified applies to the variable
|
1143 |
|
|
-- we are examining, or if it is a parameter, if there is
|
1144 |
|
|
-- a pragma Unreferenced for the corresponding spec, or
|
1145 |
|
|
-- if the type is marked as having unreferenced objects.
|
1146 |
|
|
-- The last is a little peculiar, but better too few than
|
1147 |
|
|
-- too many warnings in this situation.
|
1148 |
|
|
|
1149 |
|
|
if Has_Pragma_Unreferenced_Objects (E1T)
|
1150 |
|
|
or else Has_Pragma_Unmodified_Check_Spec (E1)
|
1151 |
|
|
then
|
1152 |
|
|
null;
|
1153 |
|
|
|
1154 |
|
|
-- IN OUT parameter case where parameter is referenced. We
|
1155 |
|
|
-- separate this out, since this is the case where we delay
|
1156 |
|
|
-- output of the warning until more information is available
|
1157 |
|
|
-- (about use in an instantiation or address being taken).
|
1158 |
|
|
|
1159 |
|
|
elsif Ekind (E1) = E_In_Out_Parameter
|
1160 |
|
|
and then Referenced_Check_Spec (E1)
|
1161 |
|
|
then
|
1162 |
|
|
-- Suppress warning if private type, and the procedure
|
1163 |
|
|
-- has a separate declaration in a different unit. This
|
1164 |
|
|
-- is the case where the client of a package sees only
|
1165 |
|
|
-- the private type, and it may be quite reasonable
|
1166 |
|
|
-- for the logical view to be IN OUT, even if the
|
1167 |
|
|
-- implementation ends up using access types or some
|
1168 |
|
|
-- other method to achieve the local effect of a
|
1169 |
|
|
-- modification. On the other hand if the spec and body
|
1170 |
|
|
-- are in the same unit, we are in the package body and
|
1171 |
|
|
-- there we have less excuse for a junk IN OUT parameter.
|
1172 |
|
|
|
1173 |
|
|
if Has_Private_Declaration (E1T)
|
1174 |
|
|
and then Present (Spec_Entity (E1))
|
1175 |
|
|
and then not In_Same_Source_Unit (E1, Spec_Entity (E1))
|
1176 |
|
|
then
|
1177 |
|
|
null;
|
1178 |
|
|
|
1179 |
|
|
-- Suppress warning for any parameter of a dispatching
|
1180 |
|
|
-- operation, since it is quite reasonable to have an
|
1181 |
|
|
-- operation that is overridden, and for some subclasses
|
1182 |
|
|
-- needs the formal to be IN OUT and for others happens
|
1183 |
|
|
-- not to assign it.
|
1184 |
|
|
|
1185 |
|
|
elsif Is_Dispatching_Operation
|
1186 |
|
|
(Scope (Goto_Spec_Entity (E1)))
|
1187 |
|
|
then
|
1188 |
|
|
null;
|
1189 |
|
|
|
1190 |
|
|
-- Suppress warning if composite type contains any access
|
1191 |
|
|
-- component, since the logical effect of modifying a
|
1192 |
|
|
-- parameter may be achieved by modifying a referenced
|
1193 |
|
|
-- object.
|
1194 |
|
|
|
1195 |
|
|
elsif Is_Composite_Type (E1T)
|
1196 |
|
|
and then Has_Access_Values (E1T)
|
1197 |
|
|
then
|
1198 |
|
|
null;
|
1199 |
|
|
|
1200 |
|
|
-- Suppress warning on formals of an entry body. All
|
1201 |
|
|
-- references are attached to the formal in the entry
|
1202 |
|
|
-- declaration, which are marked Is_Entry_Formal.
|
1203 |
|
|
|
1204 |
|
|
elsif Ekind (Scope (E1)) = E_Entry
|
1205 |
|
|
and then not Is_Entry_Formal (E1)
|
1206 |
|
|
then
|
1207 |
|
|
null;
|
1208 |
|
|
|
1209 |
|
|
-- OK, looks like warning for an IN OUT parameter that
|
1210 |
|
|
-- could be IN makes sense, but we delay the output of
|
1211 |
|
|
-- the warning, pending possibly finding out later on
|
1212 |
|
|
-- that the associated subprogram is used as a generic
|
1213 |
|
|
-- actual, or its address/access is taken. In these two
|
1214 |
|
|
-- cases, we suppress the warning because the context may
|
1215 |
|
|
-- force use of IN OUT, even if in this particular case
|
1216 |
|
|
-- the formal is not modified.
|
1217 |
|
|
|
1218 |
|
|
else
|
1219 |
|
|
In_Out_Warnings.Append (E1);
|
1220 |
|
|
end if;
|
1221 |
|
|
|
1222 |
|
|
-- Other cases of formals
|
1223 |
|
|
|
1224 |
|
|
elsif Is_Formal (E1) then
|
1225 |
|
|
if not Is_Trivial_Subprogram (Scope (E1)) then
|
1226 |
|
|
if Referenced_Check_Spec (E1) then
|
1227 |
|
|
if not Has_Pragma_Unmodified_Check_Spec (E1)
|
1228 |
|
|
and then not Warnings_Off_E1
|
1229 |
|
|
then
|
1230 |
|
|
Output_Reference_Error
|
1231 |
|
|
("?formal parameter& is read but "
|
1232 |
|
|
& "never assigned!");
|
1233 |
|
|
end if;
|
1234 |
|
|
|
1235 |
|
|
elsif not Has_Pragma_Unreferenced_Check_Spec (E1)
|
1236 |
|
|
and then not Warnings_Off_E1
|
1237 |
|
|
then
|
1238 |
|
|
Output_Reference_Error
|
1239 |
|
|
("?formal parameter& is not referenced!");
|
1240 |
|
|
end if;
|
1241 |
|
|
end if;
|
1242 |
|
|
|
1243 |
|
|
-- Case of variable
|
1244 |
|
|
|
1245 |
|
|
else
|
1246 |
|
|
if Referenced (E1) then
|
1247 |
|
|
if not Has_Unmodified (E1)
|
1248 |
|
|
and then not Warnings_Off_E1
|
1249 |
|
|
then
|
1250 |
|
|
Output_Reference_Error
|
1251 |
|
|
("?variable& is read but never assigned!");
|
1252 |
|
|
end if;
|
1253 |
|
|
|
1254 |
|
|
elsif not Has_Unreferenced (E1)
|
1255 |
|
|
and then not Warnings_Off_E1
|
1256 |
|
|
then
|
1257 |
|
|
Output_Reference_Error -- CODEFIX
|
1258 |
|
|
("?variable& is never read and never assigned!");
|
1259 |
|
|
end if;
|
1260 |
|
|
|
1261 |
|
|
-- Deal with special case where this variable is hidden
|
1262 |
|
|
-- by a loop variable.
|
1263 |
|
|
|
1264 |
|
|
if Ekind (E1) = E_Variable
|
1265 |
|
|
and then Present (Hiding_Loop_Variable (E1))
|
1266 |
|
|
and then not Warnings_Off_E1
|
1267 |
|
|
then
|
1268 |
|
|
Error_Msg_N
|
1269 |
|
|
("?for loop implicitly declares loop variable!",
|
1270 |
|
|
Hiding_Loop_Variable (E1));
|
1271 |
|
|
|
1272 |
|
|
Error_Msg_Sloc := Sloc (E1);
|
1273 |
|
|
Error_Msg_N
|
1274 |
|
|
("\?declaration hides & declared#!",
|
1275 |
|
|
Hiding_Loop_Variable (E1));
|
1276 |
|
|
end if;
|
1277 |
|
|
end if;
|
1278 |
|
|
|
1279 |
|
|
goto Continue;
|
1280 |
|
|
end if;
|
1281 |
|
|
|
1282 |
|
|
-- Check for unset reference
|
1283 |
|
|
|
1284 |
|
|
if Warn_On_No_Value_Assigned and then Present (UR) then
|
1285 |
|
|
|
1286 |
|
|
-- For other than access type, go back to original node to
|
1287 |
|
|
-- deal with case where original unset reference has been
|
1288 |
|
|
-- rewritten during expansion.
|
1289 |
|
|
|
1290 |
|
|
-- In some cases, the original node may be a type conversion
|
1291 |
|
|
-- or qualification, and in this case we want the object
|
1292 |
|
|
-- entity inside.
|
1293 |
|
|
|
1294 |
|
|
UR := Original_Node (UR);
|
1295 |
|
|
while Nkind (UR) = N_Type_Conversion
|
1296 |
|
|
or else Nkind (UR) = N_Qualified_Expression
|
1297 |
|
|
loop
|
1298 |
|
|
UR := Expression (UR);
|
1299 |
|
|
end loop;
|
1300 |
|
|
|
1301 |
|
|
-- Here we issue the warning, all checks completed
|
1302 |
|
|
|
1303 |
|
|
-- If we have a return statement, this was a case of an OUT
|
1304 |
|
|
-- parameter not being set at the time of the return. (Note:
|
1305 |
|
|
-- it can't be N_Extended_Return_Statement, because those
|
1306 |
|
|
-- are only for functions, and functions do not allow OUT
|
1307 |
|
|
-- parameters.)
|
1308 |
|
|
|
1309 |
|
|
if not Is_Trivial_Subprogram (Scope (E1)) then
|
1310 |
|
|
if Nkind (UR) = N_Simple_Return_Statement
|
1311 |
|
|
and then not Has_Pragma_Unmodified_Check_Spec (E1)
|
1312 |
|
|
then
|
1313 |
|
|
if not Warnings_Off_E1 then
|
1314 |
|
|
Error_Msg_NE
|
1315 |
|
|
("?OUT parameter& not set before return", UR, E1);
|
1316 |
|
|
end if;
|
1317 |
|
|
|
1318 |
|
|
-- If the unset reference is a selected component
|
1319 |
|
|
-- prefix from source, mention the component as well.
|
1320 |
|
|
-- If the selected component comes from expansion, all
|
1321 |
|
|
-- we know is that the entity is not fully initialized
|
1322 |
|
|
-- at the point of the reference. Locate a random
|
1323 |
|
|
-- uninitialized component to get a better message.
|
1324 |
|
|
|
1325 |
|
|
elsif Nkind (Parent (UR)) = N_Selected_Component then
|
1326 |
|
|
Error_Msg_Node_2 := Selector_Name (Parent (UR));
|
1327 |
|
|
|
1328 |
|
|
if not Comes_From_Source (Parent (UR)) then
|
1329 |
|
|
declare
|
1330 |
|
|
Comp : Entity_Id;
|
1331 |
|
|
|
1332 |
|
|
begin
|
1333 |
|
|
Comp := First_Entity (E1T);
|
1334 |
|
|
while Present (Comp) loop
|
1335 |
|
|
if Ekind (Comp) = E_Component
|
1336 |
|
|
and then Nkind (Parent (Comp)) =
|
1337 |
|
|
N_Component_Declaration
|
1338 |
|
|
and then No (Expression (Parent (Comp)))
|
1339 |
|
|
then
|
1340 |
|
|
Error_Msg_Node_2 := Comp;
|
1341 |
|
|
exit;
|
1342 |
|
|
end if;
|
1343 |
|
|
|
1344 |
|
|
Next_Entity (Comp);
|
1345 |
|
|
end loop;
|
1346 |
|
|
end;
|
1347 |
|
|
end if;
|
1348 |
|
|
|
1349 |
|
|
-- Issue proper warning. This is a case of referencing
|
1350 |
|
|
-- a variable before it has been explicitly assigned.
|
1351 |
|
|
-- For access types, UR was only set for dereferences,
|
1352 |
|
|
-- so the issue is that the value may be null.
|
1353 |
|
|
|
1354 |
|
|
if not Is_Trivial_Subprogram (Scope (E1)) then
|
1355 |
|
|
if not Warnings_Off_E1 then
|
1356 |
|
|
if Is_Access_Type (Etype (Parent (UR))) then
|
1357 |
|
|
Error_Msg_N ("?`&.&` may be null!", UR);
|
1358 |
|
|
else
|
1359 |
|
|
Error_Msg_N
|
1360 |
|
|
("?`&.&` may be referenced before "
|
1361 |
|
|
& "it has a value!", UR);
|
1362 |
|
|
end if;
|
1363 |
|
|
end if;
|
1364 |
|
|
end if;
|
1365 |
|
|
|
1366 |
|
|
-- All other cases of unset reference active
|
1367 |
|
|
|
1368 |
|
|
elsif not Warnings_Off_E1 then
|
1369 |
|
|
Error_Msg_N
|
1370 |
|
|
("?& may be referenced before it has a value!",
|
1371 |
|
|
UR);
|
1372 |
|
|
end if;
|
1373 |
|
|
end if;
|
1374 |
|
|
|
1375 |
|
|
goto Continue;
|
1376 |
|
|
end if;
|
1377 |
|
|
end if;
|
1378 |
|
|
|
1379 |
|
|
-- Then check for unreferenced entities. Note that we are only
|
1380 |
|
|
-- interested in entities whose Referenced flag is not set.
|
1381 |
|
|
|
1382 |
|
|
if not Referenced_Check_Spec (E1)
|
1383 |
|
|
|
1384 |
|
|
-- If Referenced_As_LHS is set, then that's still interesting
|
1385 |
|
|
-- (potential "assigned but never read" case), but not if we
|
1386 |
|
|
-- have pragma Unreferenced, which cancels this warning.
|
1387 |
|
|
|
1388 |
|
|
and then (not Referenced_As_LHS_Check_Spec (E1)
|
1389 |
|
|
or else not Has_Unreferenced (E1))
|
1390 |
|
|
|
1391 |
|
|
-- Check that warnings on unreferenced entities are enabled
|
1392 |
|
|
|
1393 |
|
|
and then
|
1394 |
|
|
((Check_Unreferenced and then not Is_Formal (E1))
|
1395 |
|
|
|
1396 |
|
|
-- Case of warning on unreferenced formal
|
1397 |
|
|
|
1398 |
|
|
or else
|
1399 |
|
|
(Check_Unreferenced_Formals and then Is_Formal (E1))
|
1400 |
|
|
|
1401 |
|
|
-- Case of warning on unread variables modified by an
|
1402 |
|
|
-- assignment, or an OUT parameter if it is the only one.
|
1403 |
|
|
|
1404 |
|
|
or else
|
1405 |
|
|
(Warn_On_Modified_Unread
|
1406 |
|
|
and then Referenced_As_LHS_Check_Spec (E1))
|
1407 |
|
|
|
1408 |
|
|
-- Case of warning on any unread OUT parameter (note
|
1409 |
|
|
-- such indications are only set if the appropriate
|
1410 |
|
|
-- warning options were set, so no need to recheck here.)
|
1411 |
|
|
|
1412 |
|
|
or else
|
1413 |
|
|
Referenced_As_Out_Parameter_Check_Spec (E1))
|
1414 |
|
|
|
1415 |
|
|
-- All other entities, including local packages that cannot be
|
1416 |
|
|
-- referenced from elsewhere, including those declared within a
|
1417 |
|
|
-- package body.
|
1418 |
|
|
|
1419 |
|
|
and then (Is_Object (E1)
|
1420 |
|
|
or else
|
1421 |
|
|
Is_Type (E1)
|
1422 |
|
|
or else
|
1423 |
|
|
Ekind (E1) = E_Label
|
1424 |
|
|
or else
|
1425 |
|
|
Ekind (E1) = E_Exception
|
1426 |
|
|
or else
|
1427 |
|
|
Ekind (E1) = E_Named_Integer
|
1428 |
|
|
or else
|
1429 |
|
|
Ekind (E1) = E_Named_Real
|
1430 |
|
|
or else
|
1431 |
|
|
Is_Overloadable (E1)
|
1432 |
|
|
|
1433 |
|
|
-- Package case, if the main unit is a package spec
|
1434 |
|
|
-- or generic package spec, then there may be a
|
1435 |
|
|
-- corresponding body that references this package
|
1436 |
|
|
-- in some other file. Otherwise we can be sure
|
1437 |
|
|
-- that there is no other reference.
|
1438 |
|
|
|
1439 |
|
|
or else
|
1440 |
|
|
(Ekind (E1) = E_Package
|
1441 |
|
|
and then
|
1442 |
|
|
not Is_Package_Or_Generic_Package
|
1443 |
|
|
(Cunit_Entity (Current_Sem_Unit))))
|
1444 |
|
|
|
1445 |
|
|
-- Exclude instantiations, since there is no reason why every
|
1446 |
|
|
-- entity in an instantiation should be referenced.
|
1447 |
|
|
|
1448 |
|
|
and then Instantiation_Location (Sloc (E1)) = No_Location
|
1449 |
|
|
|
1450 |
|
|
-- Exclude formal parameters from bodies if the corresponding
|
1451 |
|
|
-- spec entity has been referenced in the case where there is
|
1452 |
|
|
-- a separate spec.
|
1453 |
|
|
|
1454 |
|
|
and then not (Is_Formal (E1)
|
1455 |
|
|
and then Ekind (Scope (E1)) = E_Subprogram_Body
|
1456 |
|
|
and then Present (Spec_Entity (E1))
|
1457 |
|
|
and then Referenced (Spec_Entity (E1)))
|
1458 |
|
|
|
1459 |
|
|
-- Consider private type referenced if full view is referenced.
|
1460 |
|
|
-- If there is not full view, this is a generic type on which
|
1461 |
|
|
-- warnings are also useful.
|
1462 |
|
|
|
1463 |
|
|
and then
|
1464 |
|
|
not (Is_Private_Type (E1)
|
1465 |
|
|
and then Present (Full_View (E1))
|
1466 |
|
|
and then Referenced (Full_View (E1)))
|
1467 |
|
|
|
1468 |
|
|
-- Don't worry about full view, only about private type
|
1469 |
|
|
|
1470 |
|
|
and then not Has_Private_Declaration (E1)
|
1471 |
|
|
|
1472 |
|
|
-- Eliminate dispatching operations from consideration, we
|
1473 |
|
|
-- cannot tell if these are referenced or not in any easy
|
1474 |
|
|
-- manner (note this also catches Adjust/Finalize/Initialize).
|
1475 |
|
|
|
1476 |
|
|
and then not Is_Dispatching_Operation (E1)
|
1477 |
|
|
|
1478 |
|
|
-- Check entity that can be publicly referenced (we do not give
|
1479 |
|
|
-- messages for such entities, since there could be other
|
1480 |
|
|
-- units, not involved in this compilation, that contain
|
1481 |
|
|
-- relevant references.
|
1482 |
|
|
|
1483 |
|
|
and then not Publicly_Referenceable (E1)
|
1484 |
|
|
|
1485 |
|
|
-- Class wide types are marked as source entities, but they are
|
1486 |
|
|
-- not really source entities, and are always created, so we do
|
1487 |
|
|
-- not care if they are not referenced.
|
1488 |
|
|
|
1489 |
|
|
and then Ekind (E1) /= E_Class_Wide_Type
|
1490 |
|
|
|
1491 |
|
|
-- Objects other than parameters of task types are allowed to
|
1492 |
|
|
-- be non-referenced, since they start up tasks!
|
1493 |
|
|
|
1494 |
|
|
and then ((Ekind (E1) /= E_Variable
|
1495 |
|
|
and then Ekind (E1) /= E_Constant
|
1496 |
|
|
and then Ekind (E1) /= E_Component)
|
1497 |
|
|
or else not Is_Task_Type (E1T))
|
1498 |
|
|
|
1499 |
|
|
-- For subunits, only place warnings on the main unit itself,
|
1500 |
|
|
-- since parent units are not completely compiled.
|
1501 |
|
|
|
1502 |
|
|
and then (Nkind (Unit (Cunit (Main_Unit))) /= N_Subunit
|
1503 |
|
|
or else Get_Source_Unit (E1) = Main_Unit)
|
1504 |
|
|
|
1505 |
|
|
-- No warning on a return object, because these are often
|
1506 |
|
|
-- created with a single expression and an implicit return.
|
1507 |
|
|
-- If the object is a variable there will be a warning
|
1508 |
|
|
-- indicating that it could be declared constant.
|
1509 |
|
|
|
1510 |
|
|
and then not
|
1511 |
|
|
(Ekind (E1) = E_Constant and then Is_Return_Object (E1))
|
1512 |
|
|
then
|
1513 |
|
|
-- Suppress warnings in internal units if not in -gnatg mode
|
1514 |
|
|
-- (these would be junk warnings for an applications program,
|
1515 |
|
|
-- since they refer to problems in internal units).
|
1516 |
|
|
|
1517 |
|
|
if GNAT_Mode
|
1518 |
|
|
or else not Is_Internal_File_Name
|
1519 |
|
|
(Unit_File_Name (Get_Source_Unit (E1)))
|
1520 |
|
|
then
|
1521 |
|
|
-- We do not immediately flag the error. This is because we
|
1522 |
|
|
-- have not expanded generic bodies yet, and they may have
|
1523 |
|
|
-- the missing reference. So instead we park the entity on a
|
1524 |
|
|
-- list, for later processing. However for the case of an
|
1525 |
|
|
-- accept statement we want to output messages now, since
|
1526 |
|
|
-- we know we already have all information at hand, and we
|
1527 |
|
|
-- also want to have separate warnings for each accept
|
1528 |
|
|
-- statement for the same entry.
|
1529 |
|
|
|
1530 |
|
|
if Present (Anod) then
|
1531 |
|
|
pragma Assert (Is_Formal (E1));
|
1532 |
|
|
|
1533 |
|
|
-- The unreferenced entity is E1, but post the warning
|
1534 |
|
|
-- on the body entity for this accept statement.
|
1535 |
|
|
|
1536 |
|
|
if not Warnings_Off_E1 then
|
1537 |
|
|
Warn_On_Unreferenced_Entity
|
1538 |
|
|
(E1, Body_Formal (E1, Accept_Statement => Anod));
|
1539 |
|
|
end if;
|
1540 |
|
|
|
1541 |
|
|
elsif not Warnings_Off_E1 then
|
1542 |
|
|
Unreferenced_Entities.Append (E1);
|
1543 |
|
|
end if;
|
1544 |
|
|
end if;
|
1545 |
|
|
|
1546 |
|
|
-- Generic units are referenced in the generic body, but if they
|
1547 |
|
|
-- are not public and never instantiated we want to force a
|
1548 |
|
|
-- warning on them. We treat them as redundant constructs to
|
1549 |
|
|
-- minimize noise.
|
1550 |
|
|
|
1551 |
|
|
elsif Is_Generic_Subprogram (E1)
|
1552 |
|
|
and then not Is_Instantiated (E1)
|
1553 |
|
|
and then not Publicly_Referenceable (E1)
|
1554 |
|
|
and then Instantiation_Depth (Sloc (E1)) = 0
|
1555 |
|
|
and then Warn_On_Redundant_Constructs
|
1556 |
|
|
then
|
1557 |
|
|
if not Warnings_Off_E1 then
|
1558 |
|
|
Unreferenced_Entities.Append (E1);
|
1559 |
|
|
|
1560 |
|
|
-- Force warning on entity
|
1561 |
|
|
|
1562 |
|
|
Set_Referenced (E1, False);
|
1563 |
|
|
end if;
|
1564 |
|
|
end if;
|
1565 |
|
|
end if;
|
1566 |
|
|
|
1567 |
|
|
-- Recurse into nested package or block. Do not recurse into a formal
|
1568 |
|
|
-- package, because the corresponding body is not analyzed.
|
1569 |
|
|
|
1570 |
|
|
<<Continue>>
|
1571 |
|
|
if (Is_Package_Or_Generic_Package (E1)
|
1572 |
|
|
and then Nkind (Parent (E1)) = N_Package_Specification
|
1573 |
|
|
and then
|
1574 |
|
|
Nkind (Original_Node (Unit_Declaration_Node (E1)))
|
1575 |
|
|
/= N_Formal_Package_Declaration)
|
1576 |
|
|
|
1577 |
|
|
or else Ekind (E1) = E_Block
|
1578 |
|
|
then
|
1579 |
|
|
Check_References (E1);
|
1580 |
|
|
end if;
|
1581 |
|
|
|
1582 |
|
|
Next_Entity (E1);
|
1583 |
|
|
end loop;
|
1584 |
|
|
end Check_References;
|
1585 |
|
|
|
1586 |
|
|
---------------------------
|
1587 |
|
|
-- Check_Unset_Reference --
|
1588 |
|
|
---------------------------
|
1589 |
|
|
|
1590 |
|
|
procedure Check_Unset_Reference (N : Node_Id) is
|
1591 |
|
|
Typ : constant Entity_Id := Etype (N);
|
1592 |
|
|
|
1593 |
|
|
function Is_OK_Fully_Initialized return Boolean;
|
1594 |
|
|
-- This function returns true if the given node N is fully initialized
|
1595 |
|
|
-- so that the reference is safe as far as this routine is concerned.
|
1596 |
|
|
-- Safe generally means that the type of N is a fully initialized type.
|
1597 |
|
|
-- The one special case is that for access types, which are always fully
|
1598 |
|
|
-- initialized, we don't consider a dereference OK since it will surely
|
1599 |
|
|
-- be dereferencing a null value, which won't do.
|
1600 |
|
|
|
1601 |
|
|
function Prefix_Has_Dereference (Pref : Node_Id) return Boolean;
|
1602 |
|
|
-- Used to test indexed or selected component or slice to see if the
|
1603 |
|
|
-- evaluation of the prefix depends on a dereference, and if so, returns
|
1604 |
|
|
-- True, in which case we always check the prefix, even if we know that
|
1605 |
|
|
-- the referenced component is initialized. Pref is the prefix to test.
|
1606 |
|
|
|
1607 |
|
|
-----------------------------
|
1608 |
|
|
-- Is_OK_Fully_Initialized --
|
1609 |
|
|
-----------------------------
|
1610 |
|
|
|
1611 |
|
|
function Is_OK_Fully_Initialized return Boolean is
|
1612 |
|
|
begin
|
1613 |
|
|
if Is_Access_Type (Typ) and then Is_Dereferenced (N) then
|
1614 |
|
|
return False;
|
1615 |
|
|
else
|
1616 |
|
|
return Is_Fully_Initialized_Type (Typ);
|
1617 |
|
|
end if;
|
1618 |
|
|
end Is_OK_Fully_Initialized;
|
1619 |
|
|
|
1620 |
|
|
----------------------------
|
1621 |
|
|
-- Prefix_Has_Dereference --
|
1622 |
|
|
----------------------------
|
1623 |
|
|
|
1624 |
|
|
function Prefix_Has_Dereference (Pref : Node_Id) return Boolean is
|
1625 |
|
|
begin
|
1626 |
|
|
-- If prefix is of an access type, it certainly needs a dereference
|
1627 |
|
|
|
1628 |
|
|
if Is_Access_Type (Etype (Pref)) then
|
1629 |
|
|
return True;
|
1630 |
|
|
|
1631 |
|
|
-- If prefix is explicit dereference, that's a dereference for sure
|
1632 |
|
|
|
1633 |
|
|
elsif Nkind (Pref) = N_Explicit_Dereference then
|
1634 |
|
|
return True;
|
1635 |
|
|
|
1636 |
|
|
-- If prefix is itself a component reference or slice check prefix
|
1637 |
|
|
|
1638 |
|
|
elsif Nkind (Pref) = N_Slice
|
1639 |
|
|
or else Nkind (Pref) = N_Indexed_Component
|
1640 |
|
|
or else Nkind (Pref) = N_Selected_Component
|
1641 |
|
|
then
|
1642 |
|
|
return Prefix_Has_Dereference (Prefix (Pref));
|
1643 |
|
|
|
1644 |
|
|
-- All other cases do not involve a dereference
|
1645 |
|
|
|
1646 |
|
|
else
|
1647 |
|
|
return False;
|
1648 |
|
|
end if;
|
1649 |
|
|
end Prefix_Has_Dereference;
|
1650 |
|
|
|
1651 |
|
|
-- Start of processing for Check_Unset_Reference
|
1652 |
|
|
|
1653 |
|
|
begin
|
1654 |
|
|
-- Nothing to do if warnings suppressed
|
1655 |
|
|
|
1656 |
|
|
if Warning_Mode = Suppress then
|
1657 |
|
|
return;
|
1658 |
|
|
end if;
|
1659 |
|
|
|
1660 |
|
|
-- Ignore reference unless it comes from source. Almost always if we
|
1661 |
|
|
-- have a reference from generated code, it is bogus (e.g. calls to init
|
1662 |
|
|
-- procs to set default discriminant values).
|
1663 |
|
|
|
1664 |
|
|
if not Comes_From_Source (N) then
|
1665 |
|
|
return;
|
1666 |
|
|
end if;
|
1667 |
|
|
|
1668 |
|
|
-- Otherwise see what kind of node we have. If the entity already has an
|
1669 |
|
|
-- unset reference, it is not necessarily the earliest in the text,
|
1670 |
|
|
-- because resolution of the prefix of selected components is completed
|
1671 |
|
|
-- before the resolution of the selected component itself. As a result,
|
1672 |
|
|
-- given (R /= null and then R.X > 0), the occurrences of R are examined
|
1673 |
|
|
-- in right-to-left order. If there is already an unset reference, we
|
1674 |
|
|
-- check whether N is earlier before proceeding.
|
1675 |
|
|
|
1676 |
|
|
case Nkind (N) is
|
1677 |
|
|
|
1678 |
|
|
-- For identifier or expanded name, examine the entity involved
|
1679 |
|
|
|
1680 |
|
|
when N_Identifier | N_Expanded_Name =>
|
1681 |
|
|
declare
|
1682 |
|
|
E : constant Entity_Id := Entity (N);
|
1683 |
|
|
|
1684 |
|
|
begin
|
1685 |
|
|
if (Ekind (E) = E_Variable
|
1686 |
|
|
or else
|
1687 |
|
|
Ekind (E) = E_Out_Parameter)
|
1688 |
|
|
and then Never_Set_In_Source_Check_Spec (E)
|
1689 |
|
|
and then not Has_Initial_Value (E)
|
1690 |
|
|
and then (No (Unset_Reference (E))
|
1691 |
|
|
or else
|
1692 |
|
|
Earlier_In_Extended_Unit
|
1693 |
|
|
(Sloc (N), Sloc (Unset_Reference (E))))
|
1694 |
|
|
and then not Has_Pragma_Unmodified_Check_Spec (E)
|
1695 |
|
|
and then not Warnings_Off_Check_Spec (E)
|
1696 |
|
|
then
|
1697 |
|
|
-- We may have an unset reference. The first test is whether
|
1698 |
|
|
-- this is an access to a discriminant of a record or a
|
1699 |
|
|
-- component with default initialization. Both of these
|
1700 |
|
|
-- cases can be ignored, since the actual object that is
|
1701 |
|
|
-- referenced is definitely initialized. Note that this
|
1702 |
|
|
-- covers the case of reading discriminants of an OUT
|
1703 |
|
|
-- parameter, which is OK even in Ada 83.
|
1704 |
|
|
|
1705 |
|
|
-- Note that we are only interested in a direct reference to
|
1706 |
|
|
-- a record component here. If the reference is through an
|
1707 |
|
|
-- access type, then the access object is being referenced,
|
1708 |
|
|
-- not the record, and still deserves an unset reference.
|
1709 |
|
|
|
1710 |
|
|
if Nkind (Parent (N)) = N_Selected_Component
|
1711 |
|
|
and not Is_Access_Type (Typ)
|
1712 |
|
|
then
|
1713 |
|
|
declare
|
1714 |
|
|
ES : constant Entity_Id :=
|
1715 |
|
|
Entity (Selector_Name (Parent (N)));
|
1716 |
|
|
begin
|
1717 |
|
|
if Ekind (ES) = E_Discriminant
|
1718 |
|
|
or else
|
1719 |
|
|
(Present (Declaration_Node (ES))
|
1720 |
|
|
and then
|
1721 |
|
|
Present (Expression (Declaration_Node (ES))))
|
1722 |
|
|
then
|
1723 |
|
|
return;
|
1724 |
|
|
end if;
|
1725 |
|
|
end;
|
1726 |
|
|
end if;
|
1727 |
|
|
|
1728 |
|
|
-- Exclude fully initialized types
|
1729 |
|
|
|
1730 |
|
|
if Is_OK_Fully_Initialized then
|
1731 |
|
|
return;
|
1732 |
|
|
end if;
|
1733 |
|
|
|
1734 |
|
|
-- Here we have a potential unset reference. But before we
|
1735 |
|
|
-- get worried about it, we have to make sure that the
|
1736 |
|
|
-- entity declaration is in the same procedure as the
|
1737 |
|
|
-- reference, since if they are in separate procedures, then
|
1738 |
|
|
-- we have no idea about sequential execution.
|
1739 |
|
|
|
1740 |
|
|
-- The tests in the loop below catch all such cases, but do
|
1741 |
|
|
-- allow the reference to appear in a loop, block, or
|
1742 |
|
|
-- package spec that is nested within the declaring scope.
|
1743 |
|
|
-- As always, it is possible to construct cases where the
|
1744 |
|
|
-- warning is wrong, that is why it is a warning!
|
1745 |
|
|
|
1746 |
|
|
Potential_Unset_Reference : declare
|
1747 |
|
|
SR : Entity_Id;
|
1748 |
|
|
SE : constant Entity_Id := Scope (E);
|
1749 |
|
|
|
1750 |
|
|
function Within_Postcondition return Boolean;
|
1751 |
|
|
-- Returns True iff N is within a Postcondition or
|
1752 |
|
|
-- Ensures component in a Test_Case.
|
1753 |
|
|
|
1754 |
|
|
--------------------------
|
1755 |
|
|
-- Within_Postcondition --
|
1756 |
|
|
--------------------------
|
1757 |
|
|
|
1758 |
|
|
function Within_Postcondition return Boolean is
|
1759 |
|
|
Nod, P : Node_Id;
|
1760 |
|
|
|
1761 |
|
|
begin
|
1762 |
|
|
Nod := Parent (N);
|
1763 |
|
|
while Present (Nod) loop
|
1764 |
|
|
if Nkind (Nod) = N_Pragma
|
1765 |
|
|
and then Pragma_Name (Nod) = Name_Postcondition
|
1766 |
|
|
then
|
1767 |
|
|
return True;
|
1768 |
|
|
|
1769 |
|
|
elsif Present (Parent (Nod)) then
|
1770 |
|
|
P := Parent (Nod);
|
1771 |
|
|
|
1772 |
|
|
if Nkind (P) = N_Pragma
|
1773 |
|
|
and then Pragma_Name (P) = Name_Test_Case
|
1774 |
|
|
and then
|
1775 |
|
|
Nod = Get_Ensures_From_Test_Case_Pragma (P)
|
1776 |
|
|
then
|
1777 |
|
|
return True;
|
1778 |
|
|
end if;
|
1779 |
|
|
end if;
|
1780 |
|
|
|
1781 |
|
|
Nod := Parent (Nod);
|
1782 |
|
|
end loop;
|
1783 |
|
|
|
1784 |
|
|
return False;
|
1785 |
|
|
end Within_Postcondition;
|
1786 |
|
|
|
1787 |
|
|
-- Start of processing for Potential_Unset_Reference
|
1788 |
|
|
|
1789 |
|
|
begin
|
1790 |
|
|
SR := Current_Scope;
|
1791 |
|
|
while SR /= SE loop
|
1792 |
|
|
if SR = Standard_Standard
|
1793 |
|
|
or else Is_Subprogram (SR)
|
1794 |
|
|
or else Is_Concurrent_Body (SR)
|
1795 |
|
|
or else Is_Concurrent_Type (SR)
|
1796 |
|
|
then
|
1797 |
|
|
return;
|
1798 |
|
|
end if;
|
1799 |
|
|
|
1800 |
|
|
SR := Scope (SR);
|
1801 |
|
|
end loop;
|
1802 |
|
|
|
1803 |
|
|
-- Case of reference has an access type. This is a
|
1804 |
|
|
-- special case since access types are always set to null
|
1805 |
|
|
-- so cannot be truly uninitialized, but we still want to
|
1806 |
|
|
-- warn about cases of obvious null dereference.
|
1807 |
|
|
|
1808 |
|
|
if Is_Access_Type (Typ) then
|
1809 |
|
|
Access_Type_Case : declare
|
1810 |
|
|
P : Node_Id;
|
1811 |
|
|
|
1812 |
|
|
function Process
|
1813 |
|
|
(N : Node_Id) return Traverse_Result;
|
1814 |
|
|
-- Process function for instantiation of Traverse
|
1815 |
|
|
-- below. Checks if N contains reference to E other
|
1816 |
|
|
-- than a dereference.
|
1817 |
|
|
|
1818 |
|
|
function Ref_In (Nod : Node_Id) return Boolean;
|
1819 |
|
|
-- Determines whether Nod contains a reference to
|
1820 |
|
|
-- the entity E that is not a dereference.
|
1821 |
|
|
|
1822 |
|
|
-------------
|
1823 |
|
|
-- Process --
|
1824 |
|
|
-------------
|
1825 |
|
|
|
1826 |
|
|
function Process
|
1827 |
|
|
(N : Node_Id) return Traverse_Result
|
1828 |
|
|
is
|
1829 |
|
|
begin
|
1830 |
|
|
if Is_Entity_Name (N)
|
1831 |
|
|
and then Entity (N) = E
|
1832 |
|
|
and then not Is_Dereferenced (N)
|
1833 |
|
|
then
|
1834 |
|
|
return Abandon;
|
1835 |
|
|
else
|
1836 |
|
|
return OK;
|
1837 |
|
|
end if;
|
1838 |
|
|
end Process;
|
1839 |
|
|
|
1840 |
|
|
------------
|
1841 |
|
|
-- Ref_In --
|
1842 |
|
|
------------
|
1843 |
|
|
|
1844 |
|
|
function Ref_In (Nod : Node_Id) return Boolean is
|
1845 |
|
|
function Traverse is new Traverse_Func (Process);
|
1846 |
|
|
begin
|
1847 |
|
|
return Traverse (Nod) = Abandon;
|
1848 |
|
|
end Ref_In;
|
1849 |
|
|
|
1850 |
|
|
-- Start of processing for Access_Type_Case
|
1851 |
|
|
|
1852 |
|
|
begin
|
1853 |
|
|
-- Don't bother if we are inside an instance, since
|
1854 |
|
|
-- the compilation of the generic template is where
|
1855 |
|
|
-- the warning should be issued.
|
1856 |
|
|
|
1857 |
|
|
if In_Instance then
|
1858 |
|
|
return;
|
1859 |
|
|
end if;
|
1860 |
|
|
|
1861 |
|
|
-- Don't bother if this is not the main unit. If we
|
1862 |
|
|
-- try to give this warning for with'ed units, we
|
1863 |
|
|
-- get some false positives, since we do not record
|
1864 |
|
|
-- references in other units.
|
1865 |
|
|
|
1866 |
|
|
if not In_Extended_Main_Source_Unit (E)
|
1867 |
|
|
or else
|
1868 |
|
|
not In_Extended_Main_Source_Unit (N)
|
1869 |
|
|
then
|
1870 |
|
|
return;
|
1871 |
|
|
end if;
|
1872 |
|
|
|
1873 |
|
|
-- We are only interested in dereferences
|
1874 |
|
|
|
1875 |
|
|
if not Is_Dereferenced (N) then
|
1876 |
|
|
return;
|
1877 |
|
|
end if;
|
1878 |
|
|
|
1879 |
|
|
-- One more check, don't bother with references
|
1880 |
|
|
-- that are inside conditional statements or WHILE
|
1881 |
|
|
-- loops if the condition references the entity in
|
1882 |
|
|
-- question. This avoids most false positives.
|
1883 |
|
|
|
1884 |
|
|
P := Parent (N);
|
1885 |
|
|
loop
|
1886 |
|
|
P := Parent (P);
|
1887 |
|
|
exit when No (P);
|
1888 |
|
|
|
1889 |
|
|
if (Nkind (P) = N_If_Statement
|
1890 |
|
|
or else
|
1891 |
|
|
Nkind (P) = N_Elsif_Part)
|
1892 |
|
|
and then Ref_In (Condition (P))
|
1893 |
|
|
then
|
1894 |
|
|
return;
|
1895 |
|
|
|
1896 |
|
|
elsif Nkind (P) = N_Loop_Statement
|
1897 |
|
|
and then Present (Iteration_Scheme (P))
|
1898 |
|
|
and then
|
1899 |
|
|
Ref_In (Condition (Iteration_Scheme (P)))
|
1900 |
|
|
then
|
1901 |
|
|
return;
|
1902 |
|
|
end if;
|
1903 |
|
|
end loop;
|
1904 |
|
|
end Access_Type_Case;
|
1905 |
|
|
end if;
|
1906 |
|
|
|
1907 |
|
|
-- One more check, don't bother if we are within a
|
1908 |
|
|
-- postcondition, since the expression occurs in a
|
1909 |
|
|
-- place unrelated to the actual test.
|
1910 |
|
|
|
1911 |
|
|
if not Within_Postcondition then
|
1912 |
|
|
|
1913 |
|
|
-- Here we definitely have a case for giving a warning
|
1914 |
|
|
-- for a reference to an unset value. But we don't
|
1915 |
|
|
-- give the warning now. Instead set Unset_Reference
|
1916 |
|
|
-- in the identifier involved. The reason for this is
|
1917 |
|
|
-- that if we find the variable is never ever assigned
|
1918 |
|
|
-- a value then that warning is more important and
|
1919 |
|
|
-- there is no point in giving the reference warning.
|
1920 |
|
|
|
1921 |
|
|
-- If this is an identifier, set the field directly
|
1922 |
|
|
|
1923 |
|
|
if Nkind (N) = N_Identifier then
|
1924 |
|
|
Set_Unset_Reference (E, N);
|
1925 |
|
|
|
1926 |
|
|
-- Otherwise it is an expanded name, so set the field
|
1927 |
|
|
-- of the actual identifier for the reference.
|
1928 |
|
|
|
1929 |
|
|
else
|
1930 |
|
|
Set_Unset_Reference (E, Selector_Name (N));
|
1931 |
|
|
end if;
|
1932 |
|
|
end if;
|
1933 |
|
|
end Potential_Unset_Reference;
|
1934 |
|
|
end if;
|
1935 |
|
|
end;
|
1936 |
|
|
|
1937 |
|
|
-- Indexed component or slice
|
1938 |
|
|
|
1939 |
|
|
when N_Indexed_Component | N_Slice =>
|
1940 |
|
|
|
1941 |
|
|
-- If prefix does not involve dereferencing an access type, then
|
1942 |
|
|
-- we know we are OK if the component type is fully initialized,
|
1943 |
|
|
-- since the component will have been set as part of the default
|
1944 |
|
|
-- initialization.
|
1945 |
|
|
|
1946 |
|
|
if not Prefix_Has_Dereference (Prefix (N))
|
1947 |
|
|
and then Is_OK_Fully_Initialized
|
1948 |
|
|
then
|
1949 |
|
|
return;
|
1950 |
|
|
|
1951 |
|
|
-- Look at prefix in access type case, or if the component is not
|
1952 |
|
|
-- fully initialized.
|
1953 |
|
|
|
1954 |
|
|
else
|
1955 |
|
|
Check_Unset_Reference (Prefix (N));
|
1956 |
|
|
end if;
|
1957 |
|
|
|
1958 |
|
|
-- Record component
|
1959 |
|
|
|
1960 |
|
|
when N_Selected_Component =>
|
1961 |
|
|
declare
|
1962 |
|
|
Pref : constant Node_Id := Prefix (N);
|
1963 |
|
|
Ent : constant Entity_Id := Entity (Selector_Name (N));
|
1964 |
|
|
|
1965 |
|
|
begin
|
1966 |
|
|
-- If prefix involves dereferencing an access type, always
|
1967 |
|
|
-- check the prefix, since the issue then is whether this
|
1968 |
|
|
-- access value is null.
|
1969 |
|
|
|
1970 |
|
|
if Prefix_Has_Dereference (Pref) then
|
1971 |
|
|
null;
|
1972 |
|
|
|
1973 |
|
|
-- Always go to prefix if no selector entity is set. Can this
|
1974 |
|
|
-- happen in the normal case? Not clear, but it definitely can
|
1975 |
|
|
-- happen in error cases.
|
1976 |
|
|
|
1977 |
|
|
elsif No (Ent) then
|
1978 |
|
|
null;
|
1979 |
|
|
|
1980 |
|
|
-- For a record component, check some cases where we have
|
1981 |
|
|
-- reasonable cause to consider that the component is known to
|
1982 |
|
|
-- be or probably is initialized. In this case, we don't care
|
1983 |
|
|
-- if the prefix itself was explicitly initialized.
|
1984 |
|
|
|
1985 |
|
|
-- Discriminants are always considered initialized
|
1986 |
|
|
|
1987 |
|
|
elsif Ekind (Ent) = E_Discriminant then
|
1988 |
|
|
return;
|
1989 |
|
|
|
1990 |
|
|
-- An explicitly initialized component is certainly initialized
|
1991 |
|
|
|
1992 |
|
|
elsif Nkind (Parent (Ent)) = N_Component_Declaration
|
1993 |
|
|
and then Present (Expression (Parent (Ent)))
|
1994 |
|
|
then
|
1995 |
|
|
return;
|
1996 |
|
|
|
1997 |
|
|
-- A fully initialized component is initialized
|
1998 |
|
|
|
1999 |
|
|
elsif Is_OK_Fully_Initialized then
|
2000 |
|
|
return;
|
2001 |
|
|
end if;
|
2002 |
|
|
|
2003 |
|
|
-- If none of those cases apply, check the record type prefix
|
2004 |
|
|
|
2005 |
|
|
Check_Unset_Reference (Pref);
|
2006 |
|
|
end;
|
2007 |
|
|
|
2008 |
|
|
-- For type conversions or qualifications examine the expression
|
2009 |
|
|
|
2010 |
|
|
when N_Type_Conversion | N_Qualified_Expression =>
|
2011 |
|
|
Check_Unset_Reference (Expression (N));
|
2012 |
|
|
|
2013 |
|
|
-- For explicit dereference, always check prefix, which will generate
|
2014 |
|
|
-- an unset reference (since this is a case of dereferencing null).
|
2015 |
|
|
|
2016 |
|
|
when N_Explicit_Dereference =>
|
2017 |
|
|
Check_Unset_Reference (Prefix (N));
|
2018 |
|
|
|
2019 |
|
|
-- All other cases are not cases of an unset reference
|
2020 |
|
|
|
2021 |
|
|
when others =>
|
2022 |
|
|
null;
|
2023 |
|
|
|
2024 |
|
|
end case;
|
2025 |
|
|
end Check_Unset_Reference;
|
2026 |
|
|
|
2027 |
|
|
------------------------
|
2028 |
|
|
-- Check_Unused_Withs --
|
2029 |
|
|
------------------------
|
2030 |
|
|
|
2031 |
|
|
procedure Check_Unused_Withs (Spec_Unit : Unit_Number_Type := No_Unit) is
|
2032 |
|
|
Cnode : Node_Id;
|
2033 |
|
|
Item : Node_Id;
|
2034 |
|
|
Lunit : Node_Id;
|
2035 |
|
|
Ent : Entity_Id;
|
2036 |
|
|
|
2037 |
|
|
Munite : constant Entity_Id := Cunit_Entity (Main_Unit);
|
2038 |
|
|
-- This is needed for checking the special renaming case
|
2039 |
|
|
|
2040 |
|
|
procedure Check_One_Unit (Unit : Unit_Number_Type);
|
2041 |
|
|
-- Subsidiary procedure, performs checks for specified unit
|
2042 |
|
|
|
2043 |
|
|
--------------------
|
2044 |
|
|
-- Check_One_Unit --
|
2045 |
|
|
--------------------
|
2046 |
|
|
|
2047 |
|
|
procedure Check_One_Unit (Unit : Unit_Number_Type) is
|
2048 |
|
|
Is_Visible_Renaming : Boolean := False;
|
2049 |
|
|
Pack : Entity_Id;
|
2050 |
|
|
|
2051 |
|
|
procedure Check_Inner_Package (Pack : Entity_Id);
|
2052 |
|
|
-- Pack is a package local to a unit in a with_clause. Both the unit
|
2053 |
|
|
-- and Pack are referenced. If none of the entities in Pack are
|
2054 |
|
|
-- referenced, then the only occurrence of Pack is in a USE clause
|
2055 |
|
|
-- or a pragma, and a warning is worthwhile as well.
|
2056 |
|
|
|
2057 |
|
|
function Check_System_Aux return Boolean;
|
2058 |
|
|
-- Before giving a warning on a with_clause for System, check whether
|
2059 |
|
|
-- a system extension is present.
|
2060 |
|
|
|
2061 |
|
|
function Find_Package_Renaming
|
2062 |
|
|
(P : Entity_Id;
|
2063 |
|
|
L : Entity_Id) return Entity_Id;
|
2064 |
|
|
-- The only reference to a context unit may be in a renaming
|
2065 |
|
|
-- declaration. If this renaming declares a visible entity, do not
|
2066 |
|
|
-- warn that the context clause could be moved to the body, because
|
2067 |
|
|
-- the renaming may be intended to re-export the unit.
|
2068 |
|
|
|
2069 |
|
|
function Has_Visible_Entities (P : Entity_Id) return Boolean;
|
2070 |
|
|
-- This function determines if a package has any visible entities.
|
2071 |
|
|
-- True is returned if there is at least one declared visible entity,
|
2072 |
|
|
-- otherwise False is returned (e.g. case of only pragmas present).
|
2073 |
|
|
|
2074 |
|
|
-------------------------
|
2075 |
|
|
-- Check_Inner_Package --
|
2076 |
|
|
-------------------------
|
2077 |
|
|
|
2078 |
|
|
procedure Check_Inner_Package (Pack : Entity_Id) is
|
2079 |
|
|
E : Entity_Id;
|
2080 |
|
|
Un : constant Node_Id := Sinfo.Unit (Cnode);
|
2081 |
|
|
|
2082 |
|
|
function Check_Use_Clause (N : Node_Id) return Traverse_Result;
|
2083 |
|
|
-- If N is a use_clause for Pack, emit warning
|
2084 |
|
|
|
2085 |
|
|
procedure Check_Use_Clauses is new
|
2086 |
|
|
Traverse_Proc (Check_Use_Clause);
|
2087 |
|
|
|
2088 |
|
|
----------------------
|
2089 |
|
|
-- Check_Use_Clause --
|
2090 |
|
|
----------------------
|
2091 |
|
|
|
2092 |
|
|
function Check_Use_Clause (N : Node_Id) return Traverse_Result is
|
2093 |
|
|
Nam : Node_Id;
|
2094 |
|
|
|
2095 |
|
|
begin
|
2096 |
|
|
if Nkind (N) = N_Use_Package_Clause then
|
2097 |
|
|
Nam := First (Names (N));
|
2098 |
|
|
while Present (Nam) loop
|
2099 |
|
|
if Entity (Nam) = Pack then
|
2100 |
|
|
Error_Msg_Qual_Level := 1;
|
2101 |
|
|
Error_Msg_NE -- CODEFIX
|
2102 |
|
|
("?no entities of package& are referenced!",
|
2103 |
|
|
Nam, Pack);
|
2104 |
|
|
Error_Msg_Qual_Level := 0;
|
2105 |
|
|
end if;
|
2106 |
|
|
|
2107 |
|
|
Next (Nam);
|
2108 |
|
|
end loop;
|
2109 |
|
|
end if;
|
2110 |
|
|
|
2111 |
|
|
return OK;
|
2112 |
|
|
end Check_Use_Clause;
|
2113 |
|
|
|
2114 |
|
|
-- Start of processing for Check_Inner_Package
|
2115 |
|
|
|
2116 |
|
|
begin
|
2117 |
|
|
E := First_Entity (Pack);
|
2118 |
|
|
while Present (E) loop
|
2119 |
|
|
if Referenced_Check_Spec (E) then
|
2120 |
|
|
return;
|
2121 |
|
|
end if;
|
2122 |
|
|
|
2123 |
|
|
Next_Entity (E);
|
2124 |
|
|
end loop;
|
2125 |
|
|
|
2126 |
|
|
-- No entities of the package are referenced. Check whether the
|
2127 |
|
|
-- reference to the package itself is a use clause, and if so
|
2128 |
|
|
-- place a warning on it.
|
2129 |
|
|
|
2130 |
|
|
Check_Use_Clauses (Un);
|
2131 |
|
|
end Check_Inner_Package;
|
2132 |
|
|
|
2133 |
|
|
----------------------
|
2134 |
|
|
-- Check_System_Aux --
|
2135 |
|
|
----------------------
|
2136 |
|
|
|
2137 |
|
|
function Check_System_Aux return Boolean is
|
2138 |
|
|
Ent : Entity_Id;
|
2139 |
|
|
|
2140 |
|
|
begin
|
2141 |
|
|
if Chars (Lunit) = Name_System
|
2142 |
|
|
and then Scope (Lunit) = Standard_Standard
|
2143 |
|
|
and then Present_System_Aux
|
2144 |
|
|
then
|
2145 |
|
|
Ent := First_Entity (System_Aux_Id);
|
2146 |
|
|
while Present (Ent) loop
|
2147 |
|
|
if Referenced_Check_Spec (Ent) then
|
2148 |
|
|
return True;
|
2149 |
|
|
end if;
|
2150 |
|
|
|
2151 |
|
|
Next_Entity (Ent);
|
2152 |
|
|
end loop;
|
2153 |
|
|
end if;
|
2154 |
|
|
|
2155 |
|
|
return False;
|
2156 |
|
|
end Check_System_Aux;
|
2157 |
|
|
|
2158 |
|
|
---------------------------
|
2159 |
|
|
-- Find_Package_Renaming --
|
2160 |
|
|
---------------------------
|
2161 |
|
|
|
2162 |
|
|
function Find_Package_Renaming
|
2163 |
|
|
(P : Entity_Id;
|
2164 |
|
|
L : Entity_Id) return Entity_Id
|
2165 |
|
|
is
|
2166 |
|
|
E1 : Entity_Id;
|
2167 |
|
|
R : Entity_Id;
|
2168 |
|
|
|
2169 |
|
|
begin
|
2170 |
|
|
Is_Visible_Renaming := False;
|
2171 |
|
|
|
2172 |
|
|
E1 := First_Entity (P);
|
2173 |
|
|
while Present (E1) loop
|
2174 |
|
|
if Ekind (E1) = E_Package
|
2175 |
|
|
and then Renamed_Object (E1) = L
|
2176 |
|
|
then
|
2177 |
|
|
Is_Visible_Renaming := not Is_Hidden (E1);
|
2178 |
|
|
return E1;
|
2179 |
|
|
|
2180 |
|
|
elsif Ekind (E1) = E_Package
|
2181 |
|
|
and then No (Renamed_Object (E1))
|
2182 |
|
|
and then not Is_Generic_Instance (E1)
|
2183 |
|
|
then
|
2184 |
|
|
R := Find_Package_Renaming (E1, L);
|
2185 |
|
|
|
2186 |
|
|
if Present (R) then
|
2187 |
|
|
Is_Visible_Renaming := not Is_Hidden (R);
|
2188 |
|
|
return R;
|
2189 |
|
|
end if;
|
2190 |
|
|
end if;
|
2191 |
|
|
|
2192 |
|
|
Next_Entity (E1);
|
2193 |
|
|
end loop;
|
2194 |
|
|
|
2195 |
|
|
return Empty;
|
2196 |
|
|
end Find_Package_Renaming;
|
2197 |
|
|
|
2198 |
|
|
--------------------------
|
2199 |
|
|
-- Has_Visible_Entities --
|
2200 |
|
|
--------------------------
|
2201 |
|
|
|
2202 |
|
|
function Has_Visible_Entities (P : Entity_Id) return Boolean is
|
2203 |
|
|
E : Entity_Id;
|
2204 |
|
|
|
2205 |
|
|
begin
|
2206 |
|
|
-- If unit in context is not a package, it is a subprogram that
|
2207 |
|
|
-- is not called or a generic unit that is not instantiated
|
2208 |
|
|
-- in the current unit, and warning is appropriate.
|
2209 |
|
|
|
2210 |
|
|
if Ekind (P) /= E_Package then
|
2211 |
|
|
return True;
|
2212 |
|
|
end if;
|
2213 |
|
|
|
2214 |
|
|
-- If unit comes from a limited_with clause, look for declaration
|
2215 |
|
|
-- of shadow entities.
|
2216 |
|
|
|
2217 |
|
|
if Present (Limited_View (P)) then
|
2218 |
|
|
E := First_Entity (Limited_View (P));
|
2219 |
|
|
else
|
2220 |
|
|
E := First_Entity (P);
|
2221 |
|
|
end if;
|
2222 |
|
|
|
2223 |
|
|
while Present (E)
|
2224 |
|
|
and then E /= First_Private_Entity (P)
|
2225 |
|
|
loop
|
2226 |
|
|
if Comes_From_Source (E)
|
2227 |
|
|
or else Present (Limited_View (P))
|
2228 |
|
|
then
|
2229 |
|
|
return True;
|
2230 |
|
|
end if;
|
2231 |
|
|
|
2232 |
|
|
Next_Entity (E);
|
2233 |
|
|
end loop;
|
2234 |
|
|
|
2235 |
|
|
return False;
|
2236 |
|
|
end Has_Visible_Entities;
|
2237 |
|
|
|
2238 |
|
|
-- Start of processing for Check_One_Unit
|
2239 |
|
|
|
2240 |
|
|
begin
|
2241 |
|
|
Cnode := Cunit (Unit);
|
2242 |
|
|
|
2243 |
|
|
-- Only do check in units that are part of the extended main unit.
|
2244 |
|
|
-- This is actually a necessary restriction, because in the case of
|
2245 |
|
|
-- subprogram acting as its own specification, there can be with's in
|
2246 |
|
|
-- subunits that we will not see.
|
2247 |
|
|
|
2248 |
|
|
if not In_Extended_Main_Source_Unit (Cnode) then
|
2249 |
|
|
return;
|
2250 |
|
|
|
2251 |
|
|
-- In configurable run time mode, we remove the bodies of non-inlined
|
2252 |
|
|
-- subprograms, which may lead to spurious warnings, which are
|
2253 |
|
|
-- clearly undesirable.
|
2254 |
|
|
|
2255 |
|
|
elsif Configurable_Run_Time_Mode
|
2256 |
|
|
and then Is_Predefined_File_Name (Unit_File_Name (Unit))
|
2257 |
|
|
then
|
2258 |
|
|
return;
|
2259 |
|
|
end if;
|
2260 |
|
|
|
2261 |
|
|
-- Loop through context items in this unit
|
2262 |
|
|
|
2263 |
|
|
Item := First (Context_Items (Cnode));
|
2264 |
|
|
while Present (Item) loop
|
2265 |
|
|
if Nkind (Item) = N_With_Clause
|
2266 |
|
|
and then not Implicit_With (Item)
|
2267 |
|
|
and then In_Extended_Main_Source_Unit (Item)
|
2268 |
|
|
then
|
2269 |
|
|
Lunit := Entity (Name (Item));
|
2270 |
|
|
|
2271 |
|
|
-- Check if this unit is referenced (skip the check if this
|
2272 |
|
|
-- is explicitly marked by a pragma Unreferenced).
|
2273 |
|
|
|
2274 |
|
|
if not Referenced (Lunit)
|
2275 |
|
|
and then not Has_Unreferenced (Lunit)
|
2276 |
|
|
then
|
2277 |
|
|
-- Suppress warnings in internal units if not in -gnatg mode
|
2278 |
|
|
-- (these would be junk warnings for an application program,
|
2279 |
|
|
-- since they refer to problems in internal units).
|
2280 |
|
|
|
2281 |
|
|
if GNAT_Mode
|
2282 |
|
|
or else not Is_Internal_File_Name (Unit_File_Name (Unit))
|
2283 |
|
|
then
|
2284 |
|
|
-- Here we definitely have a non-referenced unit. If it
|
2285 |
|
|
-- is the special call for a spec unit, then just set the
|
2286 |
|
|
-- flag to be read later.
|
2287 |
|
|
|
2288 |
|
|
if Unit = Spec_Unit then
|
2289 |
|
|
Set_Unreferenced_In_Spec (Item);
|
2290 |
|
|
|
2291 |
|
|
-- Otherwise simple unreferenced message, but skip this
|
2292 |
|
|
-- if no visible entities, because that is most likely a
|
2293 |
|
|
-- case where warning would be false positive (e.g. a
|
2294 |
|
|
-- package with only a linker options pragma and nothing
|
2295 |
|
|
-- else or a pragma elaborate with a body library task).
|
2296 |
|
|
|
2297 |
|
|
elsif Has_Visible_Entities (Entity (Name (Item))) then
|
2298 |
|
|
Error_Msg_N -- CODEFIX
|
2299 |
|
|
("?unit& is not referenced!", Name (Item));
|
2300 |
|
|
end if;
|
2301 |
|
|
end if;
|
2302 |
|
|
|
2303 |
|
|
-- If main unit is a renaming of this unit, then we consider
|
2304 |
|
|
-- the with to be OK (obviously it is needed in this case!)
|
2305 |
|
|
-- This may be transitive: the unit in the with_clause may
|
2306 |
|
|
-- itself be a renaming, in which case both it and the main
|
2307 |
|
|
-- unit rename the same ultimate package.
|
2308 |
|
|
|
2309 |
|
|
elsif Present (Renamed_Entity (Munite))
|
2310 |
|
|
and then
|
2311 |
|
|
(Renamed_Entity (Munite) = Lunit
|
2312 |
|
|
or else Renamed_Entity (Munite) = Renamed_Entity (Lunit))
|
2313 |
|
|
then
|
2314 |
|
|
null;
|
2315 |
|
|
|
2316 |
|
|
-- If this unit is referenced, and it is a package, we do
|
2317 |
|
|
-- another test, to see if any of the entities in the package
|
2318 |
|
|
-- are referenced. If none of the entities are referenced, we
|
2319 |
|
|
-- still post a warning. This occurs if the only use of the
|
2320 |
|
|
-- package is in a use clause, or in a package renaming
|
2321 |
|
|
-- declaration. This check is skipped for packages that are
|
2322 |
|
|
-- renamed in a spec, since the entities in such a package are
|
2323 |
|
|
-- visible to clients via the renaming.
|
2324 |
|
|
|
2325 |
|
|
elsif Ekind (Lunit) = E_Package
|
2326 |
|
|
and then not Renamed_In_Spec (Lunit)
|
2327 |
|
|
then
|
2328 |
|
|
-- If Is_Instantiated is set, it means that the package is
|
2329 |
|
|
-- implicitly instantiated (this is the case of parent
|
2330 |
|
|
-- instance or an actual for a generic package formal), and
|
2331 |
|
|
-- this counts as a reference.
|
2332 |
|
|
|
2333 |
|
|
if Is_Instantiated (Lunit) then
|
2334 |
|
|
null;
|
2335 |
|
|
|
2336 |
|
|
-- If no entities in package, and there is a pragma
|
2337 |
|
|
-- Elaborate_Body present, then assume that this with is
|
2338 |
|
|
-- done for purposes of this elaboration.
|
2339 |
|
|
|
2340 |
|
|
elsif No (First_Entity (Lunit))
|
2341 |
|
|
and then Has_Pragma_Elaborate_Body (Lunit)
|
2342 |
|
|
then
|
2343 |
|
|
null;
|
2344 |
|
|
|
2345 |
|
|
-- Otherwise see if any entities have been referenced
|
2346 |
|
|
|
2347 |
|
|
else
|
2348 |
|
|
if Limited_Present (Item) then
|
2349 |
|
|
Ent := First_Entity (Limited_View (Lunit));
|
2350 |
|
|
else
|
2351 |
|
|
Ent := First_Entity (Lunit);
|
2352 |
|
|
end if;
|
2353 |
|
|
|
2354 |
|
|
loop
|
2355 |
|
|
-- No more entities, and we did not find one that was
|
2356 |
|
|
-- referenced. Means we have a definite case of a with
|
2357 |
|
|
-- none of whose entities was referenced.
|
2358 |
|
|
|
2359 |
|
|
if No (Ent) then
|
2360 |
|
|
|
2361 |
|
|
-- If in spec, just set the flag
|
2362 |
|
|
|
2363 |
|
|
if Unit = Spec_Unit then
|
2364 |
|
|
Set_No_Entities_Ref_In_Spec (Item);
|
2365 |
|
|
|
2366 |
|
|
elsif Check_System_Aux then
|
2367 |
|
|
null;
|
2368 |
|
|
|
2369 |
|
|
-- Else give the warning
|
2370 |
|
|
|
2371 |
|
|
else
|
2372 |
|
|
if not
|
2373 |
|
|
Has_Unreferenced (Entity (Name (Item)))
|
2374 |
|
|
then
|
2375 |
|
|
Error_Msg_N -- CODEFIX
|
2376 |
|
|
("?no entities of & are referenced!",
|
2377 |
|
|
Name (Item));
|
2378 |
|
|
end if;
|
2379 |
|
|
|
2380 |
|
|
-- Look for renamings of this package, and flag
|
2381 |
|
|
-- them as well. If the original package has
|
2382 |
|
|
-- warnings off, we suppress the warning on the
|
2383 |
|
|
-- renaming as well.
|
2384 |
|
|
|
2385 |
|
|
Pack := Find_Package_Renaming (Munite, Lunit);
|
2386 |
|
|
|
2387 |
|
|
if Present (Pack)
|
2388 |
|
|
and then not Has_Warnings_Off (Lunit)
|
2389 |
|
|
and then not Has_Unreferenced (Pack)
|
2390 |
|
|
then
|
2391 |
|
|
Error_Msg_NE -- CODEFIX
|
2392 |
|
|
("?no entities of & are referenced!",
|
2393 |
|
|
Unit_Declaration_Node (Pack),
|
2394 |
|
|
Pack);
|
2395 |
|
|
end if;
|
2396 |
|
|
end if;
|
2397 |
|
|
|
2398 |
|
|
exit;
|
2399 |
|
|
|
2400 |
|
|
-- Case of entity being referenced. The reference may
|
2401 |
|
|
-- come from a limited_with_clause, in which case the
|
2402 |
|
|
-- limited view of the entity carries the flag.
|
2403 |
|
|
|
2404 |
|
|
elsif Referenced_Check_Spec (Ent)
|
2405 |
|
|
or else Referenced_As_LHS_Check_Spec (Ent)
|
2406 |
|
|
or else Referenced_As_Out_Parameter_Check_Spec (Ent)
|
2407 |
|
|
or else
|
2408 |
|
|
(From_With_Type (Ent)
|
2409 |
|
|
and then Is_Incomplete_Type (Ent)
|
2410 |
|
|
and then Present (Non_Limited_View (Ent))
|
2411 |
|
|
and then Referenced (Non_Limited_View (Ent)))
|
2412 |
|
|
then
|
2413 |
|
|
-- This means that the with is indeed fine, in that
|
2414 |
|
|
-- it is definitely needed somewhere, and we can
|
2415 |
|
|
-- quit worrying about this one...
|
2416 |
|
|
|
2417 |
|
|
-- Except for one little detail: if either of the
|
2418 |
|
|
-- flags was set during spec processing, this is
|
2419 |
|
|
-- where we complain that the with could be moved
|
2420 |
|
|
-- from the spec. If the spec contains a visible
|
2421 |
|
|
-- renaming of the package, inhibit warning to move
|
2422 |
|
|
-- with_clause to body.
|
2423 |
|
|
|
2424 |
|
|
if Ekind (Munite) = E_Package_Body then
|
2425 |
|
|
Pack :=
|
2426 |
|
|
Find_Package_Renaming
|
2427 |
|
|
(Spec_Entity (Munite), Lunit);
|
2428 |
|
|
else
|
2429 |
|
|
Pack := Empty;
|
2430 |
|
|
end if;
|
2431 |
|
|
|
2432 |
|
|
-- If a renaming is present in the spec do not warn
|
2433 |
|
|
-- because the body or child unit may depend on it.
|
2434 |
|
|
|
2435 |
|
|
if Present (Pack)
|
2436 |
|
|
and then Renamed_Entity (Pack) = Lunit
|
2437 |
|
|
then
|
2438 |
|
|
exit;
|
2439 |
|
|
|
2440 |
|
|
elsif Unreferenced_In_Spec (Item) then
|
2441 |
|
|
Error_Msg_N -- CODEFIX
|
2442 |
|
|
("?unit& is not referenced in spec!",
|
2443 |
|
|
Name (Item));
|
2444 |
|
|
|
2445 |
|
|
elsif No_Entities_Ref_In_Spec (Item) then
|
2446 |
|
|
Error_Msg_N -- CODEFIX
|
2447 |
|
|
("?no entities of & are referenced in spec!",
|
2448 |
|
|
Name (Item));
|
2449 |
|
|
|
2450 |
|
|
else
|
2451 |
|
|
if Ekind (Ent) = E_Package then
|
2452 |
|
|
Check_Inner_Package (Ent);
|
2453 |
|
|
end if;
|
2454 |
|
|
|
2455 |
|
|
exit;
|
2456 |
|
|
end if;
|
2457 |
|
|
|
2458 |
|
|
if not Is_Visible_Renaming then
|
2459 |
|
|
Error_Msg_N -- CODEFIX
|
2460 |
|
|
("\?with clause might be moved to body!",
|
2461 |
|
|
Name (Item));
|
2462 |
|
|
end if;
|
2463 |
|
|
|
2464 |
|
|
exit;
|
2465 |
|
|
|
2466 |
|
|
-- Move to next entity to continue search
|
2467 |
|
|
|
2468 |
|
|
else
|
2469 |
|
|
Next_Entity (Ent);
|
2470 |
|
|
end if;
|
2471 |
|
|
end loop;
|
2472 |
|
|
end if;
|
2473 |
|
|
|
2474 |
|
|
-- For a generic package, the only interesting kind of
|
2475 |
|
|
-- reference is an instantiation, since entities cannot be
|
2476 |
|
|
-- referenced directly.
|
2477 |
|
|
|
2478 |
|
|
elsif Is_Generic_Unit (Lunit) then
|
2479 |
|
|
|
2480 |
|
|
-- Unit was never instantiated, set flag for case of spec
|
2481 |
|
|
-- call, or give warning for normal call.
|
2482 |
|
|
|
2483 |
|
|
if not Is_Instantiated (Lunit) then
|
2484 |
|
|
if Unit = Spec_Unit then
|
2485 |
|
|
Set_Unreferenced_In_Spec (Item);
|
2486 |
|
|
else
|
2487 |
|
|
Error_Msg_N -- CODEFIX
|
2488 |
|
|
("?unit& is never instantiated!", Name (Item));
|
2489 |
|
|
end if;
|
2490 |
|
|
|
2491 |
|
|
-- If unit was indeed instantiated, make sure that flag is
|
2492 |
|
|
-- not set showing it was uninstantiated in the spec, and if
|
2493 |
|
|
-- so, give warning.
|
2494 |
|
|
|
2495 |
|
|
elsif Unreferenced_In_Spec (Item) then
|
2496 |
|
|
Error_Msg_N
|
2497 |
|
|
("?unit& is not instantiated in spec!", Name (Item));
|
2498 |
|
|
Error_Msg_N -- CODEFIX
|
2499 |
|
|
("\?with clause can be moved to body!", Name (Item));
|
2500 |
|
|
end if;
|
2501 |
|
|
end if;
|
2502 |
|
|
end if;
|
2503 |
|
|
|
2504 |
|
|
Next (Item);
|
2505 |
|
|
end loop;
|
2506 |
|
|
end Check_One_Unit;
|
2507 |
|
|
|
2508 |
|
|
-- Start of processing for Check_Unused_Withs
|
2509 |
|
|
|
2510 |
|
|
begin
|
2511 |
|
|
if not Opt.Check_Withs
|
2512 |
|
|
or else Operating_Mode = Check_Syntax
|
2513 |
|
|
then
|
2514 |
|
|
return;
|
2515 |
|
|
end if;
|
2516 |
|
|
|
2517 |
|
|
-- Flag any unused with clauses, but skip this step if we are compiling
|
2518 |
|
|
-- a subunit on its own, since we do not have enough information to
|
2519 |
|
|
-- determine whether with's are used. We will get the relevant warnings
|
2520 |
|
|
-- when we compile the parent. This is the normal style of GNAT
|
2521 |
|
|
-- compilation in any case.
|
2522 |
|
|
|
2523 |
|
|
if Nkind (Unit (Cunit (Main_Unit))) = N_Subunit then
|
2524 |
|
|
return;
|
2525 |
|
|
end if;
|
2526 |
|
|
|
2527 |
|
|
-- Process specified units
|
2528 |
|
|
|
2529 |
|
|
if Spec_Unit = No_Unit then
|
2530 |
|
|
|
2531 |
|
|
-- For main call, check all units
|
2532 |
|
|
|
2533 |
|
|
for Unit in Main_Unit .. Last_Unit loop
|
2534 |
|
|
Check_One_Unit (Unit);
|
2535 |
|
|
end loop;
|
2536 |
|
|
|
2537 |
|
|
else
|
2538 |
|
|
-- For call for spec, check only the spec
|
2539 |
|
|
|
2540 |
|
|
Check_One_Unit (Spec_Unit);
|
2541 |
|
|
end if;
|
2542 |
|
|
end Check_Unused_Withs;
|
2543 |
|
|
|
2544 |
|
|
---------------------------------
|
2545 |
|
|
-- Generic_Package_Spec_Entity --
|
2546 |
|
|
---------------------------------
|
2547 |
|
|
|
2548 |
|
|
function Generic_Package_Spec_Entity (E : Entity_Id) return Boolean is
|
2549 |
|
|
S : Entity_Id;
|
2550 |
|
|
|
2551 |
|
|
begin
|
2552 |
|
|
if Is_Package_Body_Entity (E) then
|
2553 |
|
|
return False;
|
2554 |
|
|
|
2555 |
|
|
else
|
2556 |
|
|
S := Scope (E);
|
2557 |
|
|
loop
|
2558 |
|
|
if S = Standard_Standard then
|
2559 |
|
|
return False;
|
2560 |
|
|
|
2561 |
|
|
elsif Ekind (S) = E_Generic_Package then
|
2562 |
|
|
return True;
|
2563 |
|
|
|
2564 |
|
|
elsif Ekind (S) = E_Package then
|
2565 |
|
|
S := Scope (S);
|
2566 |
|
|
|
2567 |
|
|
else
|
2568 |
|
|
return False;
|
2569 |
|
|
end if;
|
2570 |
|
|
end loop;
|
2571 |
|
|
end if;
|
2572 |
|
|
end Generic_Package_Spec_Entity;
|
2573 |
|
|
|
2574 |
|
|
----------------------
|
2575 |
|
|
-- Goto_Spec_Entity --
|
2576 |
|
|
----------------------
|
2577 |
|
|
|
2578 |
|
|
function Goto_Spec_Entity (E : Entity_Id) return Entity_Id is
|
2579 |
|
|
begin
|
2580 |
|
|
if Is_Formal (E)
|
2581 |
|
|
and then Present (Spec_Entity (E))
|
2582 |
|
|
then
|
2583 |
|
|
return Spec_Entity (E);
|
2584 |
|
|
else
|
2585 |
|
|
return E;
|
2586 |
|
|
end if;
|
2587 |
|
|
end Goto_Spec_Entity;
|
2588 |
|
|
|
2589 |
|
|
--------------------------------------
|
2590 |
|
|
-- Has_Pragma_Unmodified_Check_Spec --
|
2591 |
|
|
--------------------------------------
|
2592 |
|
|
|
2593 |
|
|
function Has_Pragma_Unmodified_Check_Spec
|
2594 |
|
|
(E : Entity_Id) return Boolean
|
2595 |
|
|
is
|
2596 |
|
|
begin
|
2597 |
|
|
if Is_Formal (E) and then Present (Spec_Entity (E)) then
|
2598 |
|
|
|
2599 |
|
|
-- Note: use of OR instead of OR ELSE here is deliberate, we want
|
2600 |
|
|
-- to mess with Unmodified flags on both body and spec entities.
|
2601 |
|
|
|
2602 |
|
|
return Has_Unmodified (E)
|
2603 |
|
|
or
|
2604 |
|
|
Has_Unmodified (Spec_Entity (E));
|
2605 |
|
|
|
2606 |
|
|
else
|
2607 |
|
|
return Has_Unmodified (E);
|
2608 |
|
|
end if;
|
2609 |
|
|
end Has_Pragma_Unmodified_Check_Spec;
|
2610 |
|
|
|
2611 |
|
|
----------------------------------------
|
2612 |
|
|
-- Has_Pragma_Unreferenced_Check_Spec --
|
2613 |
|
|
----------------------------------------
|
2614 |
|
|
|
2615 |
|
|
function Has_Pragma_Unreferenced_Check_Spec
|
2616 |
|
|
(E : Entity_Id) return Boolean
|
2617 |
|
|
is
|
2618 |
|
|
begin
|
2619 |
|
|
if Is_Formal (E) and then Present (Spec_Entity (E)) then
|
2620 |
|
|
|
2621 |
|
|
-- Note: use of OR here instead of OR ELSE is deliberate, we want
|
2622 |
|
|
-- to mess with flags on both entities.
|
2623 |
|
|
|
2624 |
|
|
return Has_Unreferenced (E)
|
2625 |
|
|
or
|
2626 |
|
|
Has_Unreferenced (Spec_Entity (E));
|
2627 |
|
|
|
2628 |
|
|
else
|
2629 |
|
|
return Has_Unreferenced (E);
|
2630 |
|
|
end if;
|
2631 |
|
|
end Has_Pragma_Unreferenced_Check_Spec;
|
2632 |
|
|
|
2633 |
|
|
----------------
|
2634 |
|
|
-- Initialize --
|
2635 |
|
|
----------------
|
2636 |
|
|
|
2637 |
|
|
procedure Initialize is
|
2638 |
|
|
begin
|
2639 |
|
|
Warnings_Off_Pragmas.Init;
|
2640 |
|
|
Unreferenced_Entities.Init;
|
2641 |
|
|
In_Out_Warnings.Init;
|
2642 |
|
|
end Initialize;
|
2643 |
|
|
|
2644 |
|
|
------------------------------------
|
2645 |
|
|
-- Never_Set_In_Source_Check_Spec --
|
2646 |
|
|
------------------------------------
|
2647 |
|
|
|
2648 |
|
|
function Never_Set_In_Source_Check_Spec (E : Entity_Id) return Boolean is
|
2649 |
|
|
begin
|
2650 |
|
|
if Is_Formal (E) and then Present (Spec_Entity (E)) then
|
2651 |
|
|
return Never_Set_In_Source (E)
|
2652 |
|
|
and then
|
2653 |
|
|
Never_Set_In_Source (Spec_Entity (E));
|
2654 |
|
|
else
|
2655 |
|
|
return Never_Set_In_Source (E);
|
2656 |
|
|
end if;
|
2657 |
|
|
end Never_Set_In_Source_Check_Spec;
|
2658 |
|
|
|
2659 |
|
|
-------------------------------------
|
2660 |
|
|
-- Operand_Has_Warnings_Suppressed --
|
2661 |
|
|
-------------------------------------
|
2662 |
|
|
|
2663 |
|
|
function Operand_Has_Warnings_Suppressed (N : Node_Id) return Boolean is
|
2664 |
|
|
|
2665 |
|
|
function Check_For_Warnings (N : Node_Id) return Traverse_Result;
|
2666 |
|
|
-- Function used to check one node to see if it is or was originally
|
2667 |
|
|
-- a reference to an entity for which Warnings are off. If so, Abandon
|
2668 |
|
|
-- is returned, otherwise OK_Orig is returned to continue the traversal
|
2669 |
|
|
-- of the original expression.
|
2670 |
|
|
|
2671 |
|
|
function Traverse is new Traverse_Func (Check_For_Warnings);
|
2672 |
|
|
-- Function used to traverse tree looking for warnings
|
2673 |
|
|
|
2674 |
|
|
------------------------
|
2675 |
|
|
-- Check_For_Warnings --
|
2676 |
|
|
------------------------
|
2677 |
|
|
|
2678 |
|
|
function Check_For_Warnings (N : Node_Id) return Traverse_Result is
|
2679 |
|
|
R : constant Node_Id := Original_Node (N);
|
2680 |
|
|
|
2681 |
|
|
begin
|
2682 |
|
|
if Nkind (R) in N_Has_Entity
|
2683 |
|
|
and then Present (Entity (R))
|
2684 |
|
|
and then Has_Warnings_Off (Entity (R))
|
2685 |
|
|
then
|
2686 |
|
|
return Abandon;
|
2687 |
|
|
else
|
2688 |
|
|
return OK_Orig;
|
2689 |
|
|
end if;
|
2690 |
|
|
end Check_For_Warnings;
|
2691 |
|
|
|
2692 |
|
|
-- Start of processing for Operand_Has_Warnings_Suppressed
|
2693 |
|
|
|
2694 |
|
|
begin
|
2695 |
|
|
return Traverse (N) = Abandon;
|
2696 |
|
|
|
2697 |
|
|
-- If any exception occurs, then something has gone wrong, and this is
|
2698 |
|
|
-- only a minor aesthetic issue anyway, so just say we did not find what
|
2699 |
|
|
-- we are looking for, rather than blow up.
|
2700 |
|
|
|
2701 |
|
|
exception
|
2702 |
|
|
when others =>
|
2703 |
|
|
return False;
|
2704 |
|
|
end Operand_Has_Warnings_Suppressed;
|
2705 |
|
|
|
2706 |
|
|
-----------------------------------------
|
2707 |
|
|
-- Output_Non_Modified_In_Out_Warnings --
|
2708 |
|
|
-----------------------------------------
|
2709 |
|
|
|
2710 |
|
|
procedure Output_Non_Modified_In_Out_Warnings is
|
2711 |
|
|
|
2712 |
|
|
function No_Warn_On_In_Out (E : Entity_Id) return Boolean;
|
2713 |
|
|
-- Given a formal parameter entity E, determines if there is a reason to
|
2714 |
|
|
-- suppress IN OUT warnings (not modified, could be IN) for formals of
|
2715 |
|
|
-- the subprogram. We suppress these warnings if Warnings Off is set, or
|
2716 |
|
|
-- if we have seen the address of the subprogram being taken, or if the
|
2717 |
|
|
-- subprogram is used as a generic actual (in the latter cases the
|
2718 |
|
|
-- context may force use of IN OUT, even if the parameter is not
|
2719 |
|
|
-- modifies for this particular case.
|
2720 |
|
|
|
2721 |
|
|
-----------------------
|
2722 |
|
|
-- No_Warn_On_In_Out --
|
2723 |
|
|
-----------------------
|
2724 |
|
|
|
2725 |
|
|
function No_Warn_On_In_Out (E : Entity_Id) return Boolean is
|
2726 |
|
|
S : constant Entity_Id := Scope (E);
|
2727 |
|
|
SE : constant Entity_Id := Spec_Entity (E);
|
2728 |
|
|
|
2729 |
|
|
begin
|
2730 |
|
|
-- Do not warn if address is taken, since funny business may be going
|
2731 |
|
|
-- on in treating the parameter indirectly as IN OUT.
|
2732 |
|
|
|
2733 |
|
|
if Address_Taken (S)
|
2734 |
|
|
or else (Present (SE) and then Address_Taken (Scope (SE)))
|
2735 |
|
|
then
|
2736 |
|
|
return True;
|
2737 |
|
|
|
2738 |
|
|
-- Do not warn if used as a generic actual, since the generic may be
|
2739 |
|
|
-- what is forcing the use of an "unnecessary" IN OUT.
|
2740 |
|
|
|
2741 |
|
|
elsif Used_As_Generic_Actual (S)
|
2742 |
|
|
or else (Present (SE) and then Used_As_Generic_Actual (Scope (SE)))
|
2743 |
|
|
then
|
2744 |
|
|
return True;
|
2745 |
|
|
|
2746 |
|
|
-- Else test warnings off
|
2747 |
|
|
|
2748 |
|
|
elsif Warnings_Off_Check_Spec (S) then
|
2749 |
|
|
return True;
|
2750 |
|
|
|
2751 |
|
|
-- All tests for suppressing warning failed
|
2752 |
|
|
|
2753 |
|
|
else
|
2754 |
|
|
return False;
|
2755 |
|
|
end if;
|
2756 |
|
|
end No_Warn_On_In_Out;
|
2757 |
|
|
|
2758 |
|
|
-- Start of processing for Output_Non_Modified_In_Out_Warnings
|
2759 |
|
|
|
2760 |
|
|
begin
|
2761 |
|
|
-- Loop through entities for which a warning may be needed
|
2762 |
|
|
|
2763 |
|
|
for J in In_Out_Warnings.First .. In_Out_Warnings.Last loop
|
2764 |
|
|
declare
|
2765 |
|
|
E1 : constant Entity_Id := In_Out_Warnings.Table (J);
|
2766 |
|
|
|
2767 |
|
|
begin
|
2768 |
|
|
-- Suppress warning in specific cases (see details in comments for
|
2769 |
|
|
-- No_Warn_On_In_Out), or if there is a pragma Unmodified.
|
2770 |
|
|
|
2771 |
|
|
if Has_Pragma_Unmodified_Check_Spec (E1)
|
2772 |
|
|
or else No_Warn_On_In_Out (E1)
|
2773 |
|
|
then
|
2774 |
|
|
null;
|
2775 |
|
|
|
2776 |
|
|
-- Here we generate the warning
|
2777 |
|
|
|
2778 |
|
|
else
|
2779 |
|
|
-- If -gnatwc is set then output message that we could be IN
|
2780 |
|
|
|
2781 |
|
|
if not Is_Trivial_Subprogram (Scope (E1)) then
|
2782 |
|
|
if Warn_On_Constant then
|
2783 |
|
|
Error_Msg_N
|
2784 |
|
|
("?formal parameter & is not modified!", E1);
|
2785 |
|
|
Error_Msg_N
|
2786 |
|
|
("\?mode could be IN instead of `IN OUT`!", E1);
|
2787 |
|
|
|
2788 |
|
|
-- We do not generate warnings for IN OUT parameters
|
2789 |
|
|
-- unless we have at least -gnatwu. This is deliberately
|
2790 |
|
|
-- inconsistent with the treatment of variables, but
|
2791 |
|
|
-- otherwise we get too many unexpected warnings in
|
2792 |
|
|
-- default mode.
|
2793 |
|
|
|
2794 |
|
|
elsif Check_Unreferenced then
|
2795 |
|
|
Error_Msg_N
|
2796 |
|
|
("?formal parameter& is read but "
|
2797 |
|
|
& "never assigned!", E1);
|
2798 |
|
|
end if;
|
2799 |
|
|
end if;
|
2800 |
|
|
|
2801 |
|
|
-- Kill any other warnings on this entity, since this is the
|
2802 |
|
|
-- one that should dominate any other unreferenced warning.
|
2803 |
|
|
|
2804 |
|
|
Set_Warnings_Off (E1);
|
2805 |
|
|
end if;
|
2806 |
|
|
end;
|
2807 |
|
|
end loop;
|
2808 |
|
|
end Output_Non_Modified_In_Out_Warnings;
|
2809 |
|
|
|
2810 |
|
|
----------------------------------------
|
2811 |
|
|
-- Output_Obsolescent_Entity_Warnings --
|
2812 |
|
|
----------------------------------------
|
2813 |
|
|
|
2814 |
|
|
procedure Output_Obsolescent_Entity_Warnings (N : Node_Id; E : Entity_Id) is
|
2815 |
|
|
P : constant Node_Id := Parent (N);
|
2816 |
|
|
S : Entity_Id;
|
2817 |
|
|
|
2818 |
|
|
begin
|
2819 |
|
|
S := Current_Scope;
|
2820 |
|
|
|
2821 |
|
|
-- Do not output message if we are the scope of standard. This means
|
2822 |
|
|
-- we have a reference from a context clause from when it is originally
|
2823 |
|
|
-- processed, and that's too early to tell whether it is an obsolescent
|
2824 |
|
|
-- unit doing the with'ing. In Sem_Ch10.Analyze_Compilation_Unit we make
|
2825 |
|
|
-- sure that we have a later call when the scope is available. This test
|
2826 |
|
|
-- also eliminates all messages for use clauses, which is fine (we do
|
2827 |
|
|
-- not want messages for use clauses, since they are always redundant
|
2828 |
|
|
-- with respect to the associated with clause).
|
2829 |
|
|
|
2830 |
|
|
if S = Standard_Standard then
|
2831 |
|
|
return;
|
2832 |
|
|
end if;
|
2833 |
|
|
|
2834 |
|
|
-- Do not output message if we are in scope of an obsolescent package
|
2835 |
|
|
-- or subprogram.
|
2836 |
|
|
|
2837 |
|
|
loop
|
2838 |
|
|
if Is_Obsolescent (S) then
|
2839 |
|
|
return;
|
2840 |
|
|
end if;
|
2841 |
|
|
|
2842 |
|
|
S := Scope (S);
|
2843 |
|
|
exit when S = Standard_Standard;
|
2844 |
|
|
end loop;
|
2845 |
|
|
|
2846 |
|
|
-- Here we will output the message
|
2847 |
|
|
|
2848 |
|
|
Error_Msg_Sloc := Sloc (E);
|
2849 |
|
|
|
2850 |
|
|
-- Case of with clause
|
2851 |
|
|
|
2852 |
|
|
if Nkind (P) = N_With_Clause then
|
2853 |
|
|
if Ekind (E) = E_Package then
|
2854 |
|
|
Error_Msg_NE
|
2855 |
|
|
("?with of obsolescent package& declared#", N, E);
|
2856 |
|
|
elsif Ekind (E) = E_Procedure then
|
2857 |
|
|
Error_Msg_NE
|
2858 |
|
|
("?with of obsolescent procedure& declared#", N, E);
|
2859 |
|
|
else
|
2860 |
|
|
Error_Msg_NE
|
2861 |
|
|
("?with of obsolescent function& declared#", N, E);
|
2862 |
|
|
end if;
|
2863 |
|
|
|
2864 |
|
|
-- If we do not have a with clause, then ignore any reference to an
|
2865 |
|
|
-- obsolescent package name. We only want to give the one warning of
|
2866 |
|
|
-- withing the package, not one each time it is used to qualify.
|
2867 |
|
|
|
2868 |
|
|
elsif Ekind (E) = E_Package then
|
2869 |
|
|
return;
|
2870 |
|
|
|
2871 |
|
|
-- Procedure call statement
|
2872 |
|
|
|
2873 |
|
|
elsif Nkind (P) = N_Procedure_Call_Statement then
|
2874 |
|
|
Error_Msg_NE
|
2875 |
|
|
("?call to obsolescent procedure& declared#", N, E);
|
2876 |
|
|
|
2877 |
|
|
-- Function call
|
2878 |
|
|
|
2879 |
|
|
elsif Nkind (P) = N_Function_Call then
|
2880 |
|
|
Error_Msg_NE
|
2881 |
|
|
("?call to obsolescent function& declared#", N, E);
|
2882 |
|
|
|
2883 |
|
|
-- Reference to obsolescent type
|
2884 |
|
|
|
2885 |
|
|
elsif Is_Type (E) then
|
2886 |
|
|
Error_Msg_NE
|
2887 |
|
|
("?reference to obsolescent type& declared#", N, E);
|
2888 |
|
|
|
2889 |
|
|
-- Reference to obsolescent component
|
2890 |
|
|
|
2891 |
|
|
elsif Ekind_In (E, E_Component, E_Discriminant) then
|
2892 |
|
|
Error_Msg_NE
|
2893 |
|
|
("?reference to obsolescent component& declared#", N, E);
|
2894 |
|
|
|
2895 |
|
|
-- Reference to obsolescent variable
|
2896 |
|
|
|
2897 |
|
|
elsif Ekind (E) = E_Variable then
|
2898 |
|
|
Error_Msg_NE
|
2899 |
|
|
("?reference to obsolescent variable& declared#", N, E);
|
2900 |
|
|
|
2901 |
|
|
-- Reference to obsolescent constant
|
2902 |
|
|
|
2903 |
|
|
elsif Ekind (E) = E_Constant
|
2904 |
|
|
or else Ekind (E) in Named_Kind
|
2905 |
|
|
then
|
2906 |
|
|
Error_Msg_NE
|
2907 |
|
|
("?reference to obsolescent constant& declared#", N, E);
|
2908 |
|
|
|
2909 |
|
|
-- Reference to obsolescent enumeration literal
|
2910 |
|
|
|
2911 |
|
|
elsif Ekind (E) = E_Enumeration_Literal then
|
2912 |
|
|
Error_Msg_NE
|
2913 |
|
|
("?reference to obsolescent enumeration literal& declared#", N, E);
|
2914 |
|
|
|
2915 |
|
|
-- Generic message for any other case we missed
|
2916 |
|
|
|
2917 |
|
|
else
|
2918 |
|
|
Error_Msg_NE
|
2919 |
|
|
("?reference to obsolescent entity& declared#", N, E);
|
2920 |
|
|
end if;
|
2921 |
|
|
|
2922 |
|
|
-- Output additional warning if present
|
2923 |
|
|
|
2924 |
|
|
for J in Obsolescent_Warnings.First .. Obsolescent_Warnings.Last loop
|
2925 |
|
|
if Obsolescent_Warnings.Table (J).Ent = E then
|
2926 |
|
|
String_To_Name_Buffer (Obsolescent_Warnings.Table (J).Msg);
|
2927 |
|
|
Error_Msg_Strlen := Name_Len;
|
2928 |
|
|
Error_Msg_String (1 .. Name_Len) := Name_Buffer (1 .. Name_Len);
|
2929 |
|
|
Error_Msg_N ("\\?~", N);
|
2930 |
|
|
exit;
|
2931 |
|
|
end if;
|
2932 |
|
|
end loop;
|
2933 |
|
|
end Output_Obsolescent_Entity_Warnings;
|
2934 |
|
|
|
2935 |
|
|
----------------------------------
|
2936 |
|
|
-- Output_Unreferenced_Messages --
|
2937 |
|
|
----------------------------------
|
2938 |
|
|
|
2939 |
|
|
procedure Output_Unreferenced_Messages is
|
2940 |
|
|
begin
|
2941 |
|
|
for J in Unreferenced_Entities.First ..
|
2942 |
|
|
Unreferenced_Entities.Last
|
2943 |
|
|
loop
|
2944 |
|
|
Warn_On_Unreferenced_Entity (Unreferenced_Entities.Table (J));
|
2945 |
|
|
end loop;
|
2946 |
|
|
end Output_Unreferenced_Messages;
|
2947 |
|
|
|
2948 |
|
|
-----------------------------------------
|
2949 |
|
|
-- Output_Unused_Warnings_Off_Warnings --
|
2950 |
|
|
-----------------------------------------
|
2951 |
|
|
|
2952 |
|
|
procedure Output_Unused_Warnings_Off_Warnings is
|
2953 |
|
|
begin
|
2954 |
|
|
for J in Warnings_Off_Pragmas.First .. Warnings_Off_Pragmas.Last loop
|
2955 |
|
|
declare
|
2956 |
|
|
Wentry : Warnings_Off_Entry renames Warnings_Off_Pragmas.Table (J);
|
2957 |
|
|
N : Node_Id renames Wentry.N;
|
2958 |
|
|
E : Node_Id renames Wentry.E;
|
2959 |
|
|
|
2960 |
|
|
begin
|
2961 |
|
|
-- Turn off Warnings_Off, or we won't get the warning!
|
2962 |
|
|
|
2963 |
|
|
Set_Warnings_Off (E, False);
|
2964 |
|
|
|
2965 |
|
|
-- Nothing to do if pragma was used to suppress a general warning
|
2966 |
|
|
|
2967 |
|
|
if Warnings_Off_Used (E) then
|
2968 |
|
|
null;
|
2969 |
|
|
|
2970 |
|
|
-- If pragma was used both in unmodified and unreferenced contexts
|
2971 |
|
|
-- then that's as good as the general case, no warning.
|
2972 |
|
|
|
2973 |
|
|
elsif Warnings_Off_Used_Unmodified (E)
|
2974 |
|
|
and
|
2975 |
|
|
Warnings_Off_Used_Unreferenced (E)
|
2976 |
|
|
then
|
2977 |
|
|
null;
|
2978 |
|
|
|
2979 |
|
|
-- Used only in context where Unmodified would have worked
|
2980 |
|
|
|
2981 |
|
|
elsif Warnings_Off_Used_Unmodified (E) then
|
2982 |
|
|
Error_Msg_NE
|
2983 |
|
|
("?could use Unmodified instead of "
|
2984 |
|
|
& "Warnings Off for &", Pragma_Identifier (N), E);
|
2985 |
|
|
|
2986 |
|
|
-- Used only in context where Unreferenced would have worked
|
2987 |
|
|
|
2988 |
|
|
elsif Warnings_Off_Used_Unreferenced (E) then
|
2989 |
|
|
Error_Msg_NE
|
2990 |
|
|
("?could use Unreferenced instead of "
|
2991 |
|
|
& "Warnings Off for &", Pragma_Identifier (N), E);
|
2992 |
|
|
|
2993 |
|
|
-- Not used at all
|
2994 |
|
|
|
2995 |
|
|
else
|
2996 |
|
|
Error_Msg_NE
|
2997 |
|
|
("?pragma Warnings Off for & unused, "
|
2998 |
|
|
& "could be omitted", N, E);
|
2999 |
|
|
end if;
|
3000 |
|
|
end;
|
3001 |
|
|
end loop;
|
3002 |
|
|
end Output_Unused_Warnings_Off_Warnings;
|
3003 |
|
|
|
3004 |
|
|
---------------------------
|
3005 |
|
|
-- Referenced_Check_Spec --
|
3006 |
|
|
---------------------------
|
3007 |
|
|
|
3008 |
|
|
function Referenced_Check_Spec (E : Entity_Id) return Boolean is
|
3009 |
|
|
begin
|
3010 |
|
|
if Is_Formal (E) and then Present (Spec_Entity (E)) then
|
3011 |
|
|
return Referenced (E) or else Referenced (Spec_Entity (E));
|
3012 |
|
|
else
|
3013 |
|
|
return Referenced (E);
|
3014 |
|
|
end if;
|
3015 |
|
|
end Referenced_Check_Spec;
|
3016 |
|
|
|
3017 |
|
|
----------------------------------
|
3018 |
|
|
-- Referenced_As_LHS_Check_Spec --
|
3019 |
|
|
----------------------------------
|
3020 |
|
|
|
3021 |
|
|
function Referenced_As_LHS_Check_Spec (E : Entity_Id) return Boolean is
|
3022 |
|
|
begin
|
3023 |
|
|
if Is_Formal (E) and then Present (Spec_Entity (E)) then
|
3024 |
|
|
return Referenced_As_LHS (E)
|
3025 |
|
|
or else Referenced_As_LHS (Spec_Entity (E));
|
3026 |
|
|
else
|
3027 |
|
|
return Referenced_As_LHS (E);
|
3028 |
|
|
end if;
|
3029 |
|
|
end Referenced_As_LHS_Check_Spec;
|
3030 |
|
|
|
3031 |
|
|
--------------------------------------------
|
3032 |
|
|
-- Referenced_As_Out_Parameter_Check_Spec --
|
3033 |
|
|
--------------------------------------------
|
3034 |
|
|
|
3035 |
|
|
function Referenced_As_Out_Parameter_Check_Spec
|
3036 |
|
|
(E : Entity_Id) return Boolean
|
3037 |
|
|
is
|
3038 |
|
|
begin
|
3039 |
|
|
if Is_Formal (E) and then Present (Spec_Entity (E)) then
|
3040 |
|
|
return Referenced_As_Out_Parameter (E)
|
3041 |
|
|
or else Referenced_As_Out_Parameter (Spec_Entity (E));
|
3042 |
|
|
else
|
3043 |
|
|
return Referenced_As_Out_Parameter (E);
|
3044 |
|
|
end if;
|
3045 |
|
|
end Referenced_As_Out_Parameter_Check_Spec;
|
3046 |
|
|
|
3047 |
|
|
-----------------------------
|
3048 |
|
|
-- Warn_On_Known_Condition --
|
3049 |
|
|
-----------------------------
|
3050 |
|
|
|
3051 |
|
|
procedure Warn_On_Known_Condition (C : Node_Id) is
|
3052 |
|
|
P : Node_Id;
|
3053 |
|
|
Orig : constant Node_Id := Original_Node (C);
|
3054 |
|
|
Test_Result : Boolean;
|
3055 |
|
|
|
3056 |
|
|
function Is_Known_Branch return Boolean;
|
3057 |
|
|
-- If the type of the condition is Boolean, the constant value of the
|
3058 |
|
|
-- condition is a boolean literal. If the type is a derived boolean
|
3059 |
|
|
-- type, the constant is wrapped in a type conversion of the derived
|
3060 |
|
|
-- literal. If the value of the condition is not a literal, no warnings
|
3061 |
|
|
-- can be produced. This function returns True if the result can be
|
3062 |
|
|
-- determined, and Test_Result is set True/False accordingly. Otherwise
|
3063 |
|
|
-- False is returned, and Test_Result is unchanged.
|
3064 |
|
|
|
3065 |
|
|
procedure Track (N : Node_Id; Loc : Node_Id);
|
3066 |
|
|
-- Adds continuation warning(s) pointing to reason (assignment or test)
|
3067 |
|
|
-- for the operand of the conditional having a known value (or at least
|
3068 |
|
|
-- enough is known about the value to issue the warning). N is the node
|
3069 |
|
|
-- which is judged to have a known value. Loc is the warning location.
|
3070 |
|
|
|
3071 |
|
|
---------------------
|
3072 |
|
|
-- Is_Known_Branch --
|
3073 |
|
|
---------------------
|
3074 |
|
|
|
3075 |
|
|
function Is_Known_Branch return Boolean is
|
3076 |
|
|
begin
|
3077 |
|
|
if Etype (C) = Standard_Boolean
|
3078 |
|
|
and then Is_Entity_Name (C)
|
3079 |
|
|
and then
|
3080 |
|
|
(Entity (C) = Standard_False or else Entity (C) = Standard_True)
|
3081 |
|
|
then
|
3082 |
|
|
Test_Result := Entity (C) = Standard_True;
|
3083 |
|
|
return True;
|
3084 |
|
|
|
3085 |
|
|
elsif Is_Boolean_Type (Etype (C))
|
3086 |
|
|
and then Nkind (C) = N_Unchecked_Type_Conversion
|
3087 |
|
|
and then Is_Entity_Name (Expression (C))
|
3088 |
|
|
and then Ekind (Entity (Expression (C))) = E_Enumeration_Literal
|
3089 |
|
|
then
|
3090 |
|
|
Test_Result :=
|
3091 |
|
|
Chars (Entity (Expression (C))) = Chars (Standard_True);
|
3092 |
|
|
return True;
|
3093 |
|
|
|
3094 |
|
|
else
|
3095 |
|
|
return False;
|
3096 |
|
|
end if;
|
3097 |
|
|
end Is_Known_Branch;
|
3098 |
|
|
|
3099 |
|
|
-----------
|
3100 |
|
|
-- Track --
|
3101 |
|
|
-----------
|
3102 |
|
|
|
3103 |
|
|
procedure Track (N : Node_Id; Loc : Node_Id) is
|
3104 |
|
|
Nod : constant Node_Id := Original_Node (N);
|
3105 |
|
|
|
3106 |
|
|
begin
|
3107 |
|
|
if Nkind (Nod) in N_Op_Compare then
|
3108 |
|
|
Track (Left_Opnd (Nod), Loc);
|
3109 |
|
|
Track (Right_Opnd (Nod), Loc);
|
3110 |
|
|
|
3111 |
|
|
elsif Is_Entity_Name (Nod)
|
3112 |
|
|
and then Is_Object (Entity (Nod))
|
3113 |
|
|
then
|
3114 |
|
|
declare
|
3115 |
|
|
CV : constant Node_Id := Current_Value (Entity (Nod));
|
3116 |
|
|
|
3117 |
|
|
begin
|
3118 |
|
|
if Present (CV) then
|
3119 |
|
|
Error_Msg_Sloc := Sloc (CV);
|
3120 |
|
|
|
3121 |
|
|
if Nkind (CV) not in N_Subexpr then
|
3122 |
|
|
Error_Msg_N ("\\?(see test #)", Loc);
|
3123 |
|
|
|
3124 |
|
|
elsif Nkind (Parent (CV)) =
|
3125 |
|
|
N_Case_Statement_Alternative
|
3126 |
|
|
then
|
3127 |
|
|
Error_Msg_N ("\\?(see case alternative #)", Loc);
|
3128 |
|
|
|
3129 |
|
|
else
|
3130 |
|
|
Error_Msg_N ("\\?(see assignment #)", Loc);
|
3131 |
|
|
end if;
|
3132 |
|
|
end if;
|
3133 |
|
|
end;
|
3134 |
|
|
end if;
|
3135 |
|
|
end Track;
|
3136 |
|
|
|
3137 |
|
|
-- Start of processing for Warn_On_Known_Condition
|
3138 |
|
|
|
3139 |
|
|
begin
|
3140 |
|
|
-- Adjust SCO condition if from source
|
3141 |
|
|
|
3142 |
|
|
if Generate_SCO
|
3143 |
|
|
and then Comes_From_Source (Orig)
|
3144 |
|
|
and then Is_Known_Branch
|
3145 |
|
|
then
|
3146 |
|
|
declare
|
3147 |
|
|
Atrue : Boolean;
|
3148 |
|
|
|
3149 |
|
|
begin
|
3150 |
|
|
Atrue := Test_Result;
|
3151 |
|
|
|
3152 |
|
|
if Present (Parent (C)) and then Nkind (Parent (C)) = N_Op_Not then
|
3153 |
|
|
Atrue := not Atrue;
|
3154 |
|
|
end if;
|
3155 |
|
|
|
3156 |
|
|
Set_SCO_Condition (Orig, Atrue);
|
3157 |
|
|
end;
|
3158 |
|
|
end if;
|
3159 |
|
|
|
3160 |
|
|
-- Argument replacement in an inlined body can make conditions static.
|
3161 |
|
|
-- Do not emit warnings in this case.
|
3162 |
|
|
|
3163 |
|
|
if In_Inlined_Body then
|
3164 |
|
|
return;
|
3165 |
|
|
end if;
|
3166 |
|
|
|
3167 |
|
|
if Constant_Condition_Warnings
|
3168 |
|
|
and then Is_Known_Branch
|
3169 |
|
|
and then Comes_From_Source (Original_Node (C))
|
3170 |
|
|
and then not In_Instance
|
3171 |
|
|
then
|
3172 |
|
|
-- See if this is in a statement or a declaration
|
3173 |
|
|
|
3174 |
|
|
P := Parent (C);
|
3175 |
|
|
loop
|
3176 |
|
|
-- If tree is not attached, do not issue warning (this is very
|
3177 |
|
|
-- peculiar, and probably arises from some other error condition)
|
3178 |
|
|
|
3179 |
|
|
if No (P) then
|
3180 |
|
|
return;
|
3181 |
|
|
|
3182 |
|
|
-- If we are in a declaration, then no warning, since in practice
|
3183 |
|
|
-- conditionals in declarations are used for intended tests which
|
3184 |
|
|
-- may be known at compile time, e.g. things like
|
3185 |
|
|
|
3186 |
|
|
-- x : constant Integer := 2 + (Word'Size = 32);
|
3187 |
|
|
|
3188 |
|
|
-- And a warning is annoying in such cases
|
3189 |
|
|
|
3190 |
|
|
elsif Nkind (P) in N_Declaration
|
3191 |
|
|
or else
|
3192 |
|
|
Nkind (P) in N_Later_Decl_Item
|
3193 |
|
|
then
|
3194 |
|
|
return;
|
3195 |
|
|
|
3196 |
|
|
-- Don't warn in assert or check pragma, since presumably tests in
|
3197 |
|
|
-- such a context are very definitely intended, and might well be
|
3198 |
|
|
-- known at compile time. Note that we have to test the original
|
3199 |
|
|
-- node, since assert pragmas get rewritten at analysis time.
|
3200 |
|
|
|
3201 |
|
|
elsif Nkind (Original_Node (P)) = N_Pragma
|
3202 |
|
|
and then (Pragma_Name (Original_Node (P)) = Name_Assert
|
3203 |
|
|
or else
|
3204 |
|
|
Pragma_Name (Original_Node (P)) = Name_Check)
|
3205 |
|
|
then
|
3206 |
|
|
return;
|
3207 |
|
|
end if;
|
3208 |
|
|
|
3209 |
|
|
exit when Is_Statement (P);
|
3210 |
|
|
P := Parent (P);
|
3211 |
|
|
end loop;
|
3212 |
|
|
|
3213 |
|
|
-- Here we issue the warning unless some sub-operand has warnings
|
3214 |
|
|
-- set off, in which case we suppress the warning for the node. If
|
3215 |
|
|
-- the original expression is an inequality, it has been expanded
|
3216 |
|
|
-- into a negation, and the value of the original expression is the
|
3217 |
|
|
-- negation of the equality. If the expression is an entity that
|
3218 |
|
|
-- appears within a negation, it is clearer to flag the negation
|
3219 |
|
|
-- itself, and report on its constant value.
|
3220 |
|
|
|
3221 |
|
|
if not Operand_Has_Warnings_Suppressed (C) then
|
3222 |
|
|
declare
|
3223 |
|
|
True_Branch : Boolean := Test_Result;
|
3224 |
|
|
Cond : Node_Id := C;
|
3225 |
|
|
|
3226 |
|
|
begin
|
3227 |
|
|
if Present (Parent (C))
|
3228 |
|
|
and then Nkind (Parent (C)) = N_Op_Not
|
3229 |
|
|
then
|
3230 |
|
|
True_Branch := not True_Branch;
|
3231 |
|
|
Cond := Parent (C);
|
3232 |
|
|
end if;
|
3233 |
|
|
|
3234 |
|
|
if True_Branch then
|
3235 |
|
|
if Is_Entity_Name (Original_Node (C))
|
3236 |
|
|
and then Nkind (Cond) /= N_Op_Not
|
3237 |
|
|
then
|
3238 |
|
|
Error_Msg_NE
|
3239 |
|
|
("object & is always True?", Cond, Original_Node (C));
|
3240 |
|
|
Track (Original_Node (C), Cond);
|
3241 |
|
|
|
3242 |
|
|
else
|
3243 |
|
|
Error_Msg_N ("condition is always True?", Cond);
|
3244 |
|
|
Track (Cond, Cond);
|
3245 |
|
|
end if;
|
3246 |
|
|
|
3247 |
|
|
else
|
3248 |
|
|
Error_Msg_N ("condition is always False?", Cond);
|
3249 |
|
|
Track (Cond, Cond);
|
3250 |
|
|
end if;
|
3251 |
|
|
end;
|
3252 |
|
|
end if;
|
3253 |
|
|
end if;
|
3254 |
|
|
end Warn_On_Known_Condition;
|
3255 |
|
|
|
3256 |
|
|
---------------------------------------
|
3257 |
|
|
-- Warn_On_Modified_As_Out_Parameter --
|
3258 |
|
|
---------------------------------------
|
3259 |
|
|
|
3260 |
|
|
function Warn_On_Modified_As_Out_Parameter (E : Entity_Id) return Boolean is
|
3261 |
|
|
begin
|
3262 |
|
|
return
|
3263 |
|
|
(Warn_On_Modified_Unread and then Is_Only_Out_Parameter (E))
|
3264 |
|
|
or else Warn_On_All_Unread_Out_Parameters;
|
3265 |
|
|
end Warn_On_Modified_As_Out_Parameter;
|
3266 |
|
|
|
3267 |
|
|
---------------------------------
|
3268 |
|
|
-- Warn_On_Overlapping_Actuals --
|
3269 |
|
|
---------------------------------
|
3270 |
|
|
|
3271 |
|
|
procedure Warn_On_Overlapping_Actuals (Subp : Entity_Id; N : Node_Id) is
|
3272 |
|
|
Act1, Act2 : Node_Id;
|
3273 |
|
|
Form1, Form2 : Entity_Id;
|
3274 |
|
|
|
3275 |
|
|
begin
|
3276 |
|
|
if not Warn_On_Overlap then
|
3277 |
|
|
return;
|
3278 |
|
|
end if;
|
3279 |
|
|
|
3280 |
|
|
-- Exclude calls rewritten as enumeration literals
|
3281 |
|
|
|
3282 |
|
|
if not Nkind_In (N, N_Function_Call, N_Procedure_Call_Statement) then
|
3283 |
|
|
return;
|
3284 |
|
|
end if;
|
3285 |
|
|
|
3286 |
|
|
-- Exclude calls to library subprograms. Container operations specify
|
3287 |
|
|
-- safe behavior when source and target coincide.
|
3288 |
|
|
|
3289 |
|
|
if Is_Predefined_File_Name
|
3290 |
|
|
(Unit_File_Name (Get_Source_Unit (Sloc (Subp))))
|
3291 |
|
|
then
|
3292 |
|
|
return;
|
3293 |
|
|
end if;
|
3294 |
|
|
|
3295 |
|
|
Form1 := First_Formal (Subp);
|
3296 |
|
|
Act1 := First_Actual (N);
|
3297 |
|
|
while Present (Form1) and then Present (Act1) loop
|
3298 |
|
|
if Ekind (Form1) /= E_In_Parameter then
|
3299 |
|
|
Form2 := First_Formal (Subp);
|
3300 |
|
|
Act2 := First_Actual (N);
|
3301 |
|
|
while Present (Form2) and then Present (Act2) loop
|
3302 |
|
|
if Form1 /= Form2
|
3303 |
|
|
and then Ekind (Form2) /= E_Out_Parameter
|
3304 |
|
|
and then
|
3305 |
|
|
(Denotes_Same_Object (Act1, Act2)
|
3306 |
|
|
or else
|
3307 |
|
|
Denotes_Same_Prefix (Act1, Act2))
|
3308 |
|
|
then
|
3309 |
|
|
-- Exclude generic types and guard against previous errors.
|
3310 |
|
|
|
3311 |
|
|
if Error_Posted (N)
|
3312 |
|
|
or else No (Etype (Act1))
|
3313 |
|
|
or else No (Etype (Act2))
|
3314 |
|
|
then
|
3315 |
|
|
null;
|
3316 |
|
|
|
3317 |
|
|
elsif Is_Generic_Type (Etype (Act1))
|
3318 |
|
|
or else
|
3319 |
|
|
Is_Generic_Type (Etype (Act2))
|
3320 |
|
|
then
|
3321 |
|
|
null;
|
3322 |
|
|
|
3323 |
|
|
-- If the actual is a function call in prefix notation,
|
3324 |
|
|
-- there is no real overlap.
|
3325 |
|
|
|
3326 |
|
|
elsif Nkind (Act2) = N_Function_Call then
|
3327 |
|
|
null;
|
3328 |
|
|
|
3329 |
|
|
-- If type is not by-copy we can assume that the aliasing is
|
3330 |
|
|
-- intended.
|
3331 |
|
|
|
3332 |
|
|
elsif
|
3333 |
|
|
Is_By_Reference_Type (Underlying_Type (Etype (Form1)))
|
3334 |
|
|
then
|
3335 |
|
|
null;
|
3336 |
|
|
|
3337 |
|
|
else
|
3338 |
|
|
declare
|
3339 |
|
|
Act : Node_Id;
|
3340 |
|
|
Form : Entity_Id;
|
3341 |
|
|
|
3342 |
|
|
begin
|
3343 |
|
|
-- Find matching actual
|
3344 |
|
|
|
3345 |
|
|
Act := First_Actual (N);
|
3346 |
|
|
Form := First_Formal (Subp);
|
3347 |
|
|
while Act /= Act2 loop
|
3348 |
|
|
Next_Formal (Form);
|
3349 |
|
|
Next_Actual (Act);
|
3350 |
|
|
end loop;
|
3351 |
|
|
|
3352 |
|
|
if Is_Elementary_Type (Etype (Act1))
|
3353 |
|
|
and then Ekind (Form2) = E_In_Parameter
|
3354 |
|
|
then
|
3355 |
|
|
null; -- No real aliasing
|
3356 |
|
|
|
3357 |
|
|
elsif Is_Elementary_Type (Etype (Act2))
|
3358 |
|
|
and then Ekind (Form2) = E_In_Parameter
|
3359 |
|
|
then
|
3360 |
|
|
null; -- Ditto
|
3361 |
|
|
|
3362 |
|
|
-- If the call was written in prefix notation, and
|
3363 |
|
|
-- thus its prefix before rewriting was a selected
|
3364 |
|
|
-- component, count only visible actuals in the call.
|
3365 |
|
|
|
3366 |
|
|
elsif Is_Entity_Name (First_Actual (N))
|
3367 |
|
|
and then Nkind (Original_Node (N)) = Nkind (N)
|
3368 |
|
|
and then Nkind (Name (Original_Node (N))) =
|
3369 |
|
|
N_Selected_Component
|
3370 |
|
|
and then
|
3371 |
|
|
Is_Entity_Name (Prefix (Name (Original_Node (N))))
|
3372 |
|
|
and then
|
3373 |
|
|
Entity (Prefix (Name (Original_Node (N)))) =
|
3374 |
|
|
Entity (First_Actual (N))
|
3375 |
|
|
then
|
3376 |
|
|
if Act1 = First_Actual (N) then
|
3377 |
|
|
Error_Msg_FE
|
3378 |
|
|
("`IN OUT` prefix overlaps with actual for&?",
|
3379 |
|
|
Act1, Form);
|
3380 |
|
|
|
3381 |
|
|
else
|
3382 |
|
|
-- For greater clarity, give name of formal.
|
3383 |
|
|
|
3384 |
|
|
Error_Msg_Node_2 := Form;
|
3385 |
|
|
Error_Msg_FE
|
3386 |
|
|
("writable actual for & overlaps with"
|
3387 |
|
|
& " actual for&?", Act1, Form);
|
3388 |
|
|
end if;
|
3389 |
|
|
|
3390 |
|
|
else
|
3391 |
|
|
Error_Msg_Node_2 := Form;
|
3392 |
|
|
Error_Msg_FE
|
3393 |
|
|
("writable actual for & overlaps with"
|
3394 |
|
|
& " actual for&?", Act1, Form1);
|
3395 |
|
|
end if;
|
3396 |
|
|
end;
|
3397 |
|
|
end if;
|
3398 |
|
|
|
3399 |
|
|
return;
|
3400 |
|
|
end if;
|
3401 |
|
|
|
3402 |
|
|
Next_Formal (Form2);
|
3403 |
|
|
Next_Actual (Act2);
|
3404 |
|
|
end loop;
|
3405 |
|
|
end if;
|
3406 |
|
|
|
3407 |
|
|
Next_Formal (Form1);
|
3408 |
|
|
Next_Actual (Act1);
|
3409 |
|
|
end loop;
|
3410 |
|
|
end Warn_On_Overlapping_Actuals;
|
3411 |
|
|
|
3412 |
|
|
------------------------------
|
3413 |
|
|
-- Warn_On_Suspicious_Index --
|
3414 |
|
|
------------------------------
|
3415 |
|
|
|
3416 |
|
|
procedure Warn_On_Suspicious_Index (Name : Entity_Id; X : Node_Id) is
|
3417 |
|
|
|
3418 |
|
|
Low_Bound : Uint;
|
3419 |
|
|
-- Set to lower bound for a suspicious type
|
3420 |
|
|
|
3421 |
|
|
Ent : Entity_Id;
|
3422 |
|
|
-- Entity for array reference
|
3423 |
|
|
|
3424 |
|
|
Typ : Entity_Id;
|
3425 |
|
|
-- Array type
|
3426 |
|
|
|
3427 |
|
|
function Is_Suspicious_Type (Typ : Entity_Id) return Boolean;
|
3428 |
|
|
-- Tests to see if Typ is a type for which we may have a suspicious
|
3429 |
|
|
-- index, namely an unconstrained array type, whose lower bound is
|
3430 |
|
|
-- either zero or one. If so, True is returned, and Low_Bound is set
|
3431 |
|
|
-- to this lower bound. If not, False is returned, and Low_Bound is
|
3432 |
|
|
-- undefined on return.
|
3433 |
|
|
--
|
3434 |
|
|
-- For now, we limit this to standard string types, so any other
|
3435 |
|
|
-- unconstrained types return False. We may change our minds on this
|
3436 |
|
|
-- later on, but strings seem the most important case.
|
3437 |
|
|
|
3438 |
|
|
procedure Test_Suspicious_Index;
|
3439 |
|
|
-- Test if index is of suspicious type and if so, generate warning
|
3440 |
|
|
|
3441 |
|
|
------------------------
|
3442 |
|
|
-- Is_Suspicious_Type --
|
3443 |
|
|
------------------------
|
3444 |
|
|
|
3445 |
|
|
function Is_Suspicious_Type (Typ : Entity_Id) return Boolean is
|
3446 |
|
|
LB : Node_Id;
|
3447 |
|
|
|
3448 |
|
|
begin
|
3449 |
|
|
if Is_Array_Type (Typ)
|
3450 |
|
|
and then not Is_Constrained (Typ)
|
3451 |
|
|
and then Number_Dimensions (Typ) = 1
|
3452 |
|
|
and then (Root_Type (Typ) = Standard_String
|
3453 |
|
|
or else
|
3454 |
|
|
Root_Type (Typ) = Standard_Wide_String
|
3455 |
|
|
or else
|
3456 |
|
|
Root_Type (Typ) = Standard_Wide_Wide_String)
|
3457 |
|
|
and then not Has_Warnings_Off (Typ)
|
3458 |
|
|
then
|
3459 |
|
|
LB := Type_Low_Bound (Etype (First_Index (Typ)));
|
3460 |
|
|
|
3461 |
|
|
if Compile_Time_Known_Value (LB) then
|
3462 |
|
|
Low_Bound := Expr_Value (LB);
|
3463 |
|
|
return Low_Bound = Uint_0 or else Low_Bound = Uint_1;
|
3464 |
|
|
end if;
|
3465 |
|
|
end if;
|
3466 |
|
|
|
3467 |
|
|
return False;
|
3468 |
|
|
end Is_Suspicious_Type;
|
3469 |
|
|
|
3470 |
|
|
---------------------------
|
3471 |
|
|
-- Test_Suspicious_Index --
|
3472 |
|
|
---------------------------
|
3473 |
|
|
|
3474 |
|
|
procedure Test_Suspicious_Index is
|
3475 |
|
|
|
3476 |
|
|
function Length_Reference (N : Node_Id) return Boolean;
|
3477 |
|
|
-- Check if node N is of the form Name'Length
|
3478 |
|
|
|
3479 |
|
|
procedure Warn1;
|
3480 |
|
|
-- Generate first warning line
|
3481 |
|
|
|
3482 |
|
|
----------------------
|
3483 |
|
|
-- Length_Reference --
|
3484 |
|
|
----------------------
|
3485 |
|
|
|
3486 |
|
|
function Length_Reference (N : Node_Id) return Boolean is
|
3487 |
|
|
R : constant Node_Id := Original_Node (N);
|
3488 |
|
|
begin
|
3489 |
|
|
return
|
3490 |
|
|
Nkind (R) = N_Attribute_Reference
|
3491 |
|
|
and then Attribute_Name (R) = Name_Length
|
3492 |
|
|
and then Is_Entity_Name (Prefix (R))
|
3493 |
|
|
and then Entity (Prefix (R)) = Ent;
|
3494 |
|
|
end Length_Reference;
|
3495 |
|
|
|
3496 |
|
|
-----------
|
3497 |
|
|
-- Warn1 --
|
3498 |
|
|
-----------
|
3499 |
|
|
|
3500 |
|
|
procedure Warn1 is
|
3501 |
|
|
begin
|
3502 |
|
|
Error_Msg_Uint_1 := Low_Bound;
|
3503 |
|
|
Error_Msg_FE -- CODEFIX
|
3504 |
|
|
("?index for& may assume lower bound of^", X, Ent);
|
3505 |
|
|
end Warn1;
|
3506 |
|
|
|
3507 |
|
|
-- Start of processing for Test_Suspicious_Index
|
3508 |
|
|
|
3509 |
|
|
begin
|
3510 |
|
|
-- Nothing to do if subscript does not come from source (we don't
|
3511 |
|
|
-- want to give garbage warnings on compiler expanded code, e.g. the
|
3512 |
|
|
-- loops generated for slice assignments. Such junk warnings would
|
3513 |
|
|
-- be placed on source constructs with no subscript in sight!)
|
3514 |
|
|
|
3515 |
|
|
if not Comes_From_Source (Original_Node (X)) then
|
3516 |
|
|
return;
|
3517 |
|
|
end if;
|
3518 |
|
|
|
3519 |
|
|
-- Case where subscript is a constant integer
|
3520 |
|
|
|
3521 |
|
|
if Nkind (X) = N_Integer_Literal then
|
3522 |
|
|
Warn1;
|
3523 |
|
|
|
3524 |
|
|
-- Case where original form of subscript is an integer literal
|
3525 |
|
|
|
3526 |
|
|
if Nkind (Original_Node (X)) = N_Integer_Literal then
|
3527 |
|
|
if Intval (X) = Low_Bound then
|
3528 |
|
|
Error_Msg_FE -- CODEFIX
|
3529 |
|
|
("\suggested replacement: `&''First`", X, Ent);
|
3530 |
|
|
else
|
3531 |
|
|
Error_Msg_Uint_1 := Intval (X) - Low_Bound;
|
3532 |
|
|
Error_Msg_FE -- CODEFIX
|
3533 |
|
|
("\suggested replacement: `&''First + ^`", X, Ent);
|
3534 |
|
|
|
3535 |
|
|
end if;
|
3536 |
|
|
|
3537 |
|
|
-- Case where original form of subscript is more complex
|
3538 |
|
|
|
3539 |
|
|
else
|
3540 |
|
|
-- Build string X'First - 1 + expression where the expression
|
3541 |
|
|
-- is the original subscript. If the expression starts with "1
|
3542 |
|
|
-- + ", then the "- 1 + 1" is elided.
|
3543 |
|
|
|
3544 |
|
|
Error_Msg_String (1 .. 13) := "'First - 1 + ";
|
3545 |
|
|
Error_Msg_Strlen := 13;
|
3546 |
|
|
|
3547 |
|
|
declare
|
3548 |
|
|
Sref : Source_Ptr := Sloc (First_Node (Original_Node (X)));
|
3549 |
|
|
Tref : constant Source_Buffer_Ptr :=
|
3550 |
|
|
Source_Text (Get_Source_File_Index (Sref));
|
3551 |
|
|
-- Tref (Sref) is used to scan the subscript
|
3552 |
|
|
|
3553 |
|
|
Pctr : Natural;
|
3554 |
|
|
-- Parentheses counter when scanning subscript
|
3555 |
|
|
|
3556 |
|
|
begin
|
3557 |
|
|
-- Tref (Sref) points to start of subscript
|
3558 |
|
|
|
3559 |
|
|
-- Elide - 1 if subscript starts with 1 +
|
3560 |
|
|
|
3561 |
|
|
if Tref (Sref .. Sref + 2) = "1 +" then
|
3562 |
|
|
Error_Msg_Strlen := Error_Msg_Strlen - 6;
|
3563 |
|
|
Sref := Sref + 2;
|
3564 |
|
|
|
3565 |
|
|
elsif Tref (Sref .. Sref + 1) = "1+" then
|
3566 |
|
|
Error_Msg_Strlen := Error_Msg_Strlen - 6;
|
3567 |
|
|
Sref := Sref + 1;
|
3568 |
|
|
end if;
|
3569 |
|
|
|
3570 |
|
|
-- Now we will copy the subscript to the string buffer
|
3571 |
|
|
|
3572 |
|
|
Pctr := 0;
|
3573 |
|
|
loop
|
3574 |
|
|
-- Count parens, exit if terminating right paren. Note
|
3575 |
|
|
-- check to ignore paren appearing as character literal.
|
3576 |
|
|
|
3577 |
|
|
if Tref (Sref + 1) = '''
|
3578 |
|
|
and then
|
3579 |
|
|
Tref (Sref - 1) = '''
|
3580 |
|
|
then
|
3581 |
|
|
null;
|
3582 |
|
|
else
|
3583 |
|
|
if Tref (Sref) = '(' then
|
3584 |
|
|
Pctr := Pctr + 1;
|
3585 |
|
|
elsif Tref (Sref) = ')' then
|
3586 |
|
|
exit when Pctr = 0;
|
3587 |
|
|
Pctr := Pctr - 1;
|
3588 |
|
|
end if;
|
3589 |
|
|
end if;
|
3590 |
|
|
|
3591 |
|
|
-- Done if terminating double dot (slice case)
|
3592 |
|
|
|
3593 |
|
|
exit when Pctr = 0
|
3594 |
|
|
and then (Tref (Sref .. Sref + 1) = ".."
|
3595 |
|
|
or else
|
3596 |
|
|
Tref (Sref .. Sref + 2) = " ..");
|
3597 |
|
|
|
3598 |
|
|
-- Quit if we have hit EOF character, something wrong
|
3599 |
|
|
|
3600 |
|
|
if Tref (Sref) = EOF then
|
3601 |
|
|
return;
|
3602 |
|
|
end if;
|
3603 |
|
|
|
3604 |
|
|
-- String literals are too much of a pain to handle
|
3605 |
|
|
|
3606 |
|
|
if Tref (Sref) = '"' or else Tref (Sref) = '%' then
|
3607 |
|
|
return;
|
3608 |
|
|
end if;
|
3609 |
|
|
|
3610 |
|
|
-- If we have a 'Range reference, then this is a case
|
3611 |
|
|
-- where we cannot easily give a replacement. Don't try!
|
3612 |
|
|
|
3613 |
|
|
if Tref (Sref .. Sref + 4) = "range"
|
3614 |
|
|
and then Tref (Sref - 1) < 'A'
|
3615 |
|
|
and then Tref (Sref + 5) < 'A'
|
3616 |
|
|
then
|
3617 |
|
|
return;
|
3618 |
|
|
end if;
|
3619 |
|
|
|
3620 |
|
|
-- Else store next character
|
3621 |
|
|
|
3622 |
|
|
Error_Msg_Strlen := Error_Msg_Strlen + 1;
|
3623 |
|
|
Error_Msg_String (Error_Msg_Strlen) := Tref (Sref);
|
3624 |
|
|
Sref := Sref + 1;
|
3625 |
|
|
|
3626 |
|
|
-- If we get more than 40 characters then the expression
|
3627 |
|
|
-- is too long to copy, or something has gone wrong. In
|
3628 |
|
|
-- either case, just skip the attempt at a suggested fix.
|
3629 |
|
|
|
3630 |
|
|
if Error_Msg_Strlen > 40 then
|
3631 |
|
|
return;
|
3632 |
|
|
end if;
|
3633 |
|
|
end loop;
|
3634 |
|
|
end;
|
3635 |
|
|
|
3636 |
|
|
-- Replacement subscript is now in string buffer
|
3637 |
|
|
|
3638 |
|
|
Error_Msg_FE -- CODEFIX
|
3639 |
|
|
("\suggested replacement: `&~`", Original_Node (X), Ent);
|
3640 |
|
|
end if;
|
3641 |
|
|
|
3642 |
|
|
-- Case where subscript is of the form X'Length
|
3643 |
|
|
|
3644 |
|
|
elsif Length_Reference (X) then
|
3645 |
|
|
Warn1;
|
3646 |
|
|
Error_Msg_Node_2 := Ent;
|
3647 |
|
|
Error_Msg_FE
|
3648 |
|
|
("\suggest replacement of `&''Length` by `&''Last`",
|
3649 |
|
|
X, Ent);
|
3650 |
|
|
|
3651 |
|
|
-- Case where subscript is of the form X'Length - expression
|
3652 |
|
|
|
3653 |
|
|
elsif Nkind (X) = N_Op_Subtract
|
3654 |
|
|
and then Length_Reference (Left_Opnd (X))
|
3655 |
|
|
then
|
3656 |
|
|
Warn1;
|
3657 |
|
|
Error_Msg_Node_2 := Ent;
|
3658 |
|
|
Error_Msg_FE
|
3659 |
|
|
("\suggest replacement of `&''Length` by `&''Last`",
|
3660 |
|
|
Left_Opnd (X), Ent);
|
3661 |
|
|
end if;
|
3662 |
|
|
end Test_Suspicious_Index;
|
3663 |
|
|
|
3664 |
|
|
-- Start of processing for Warn_On_Suspicious_Index
|
3665 |
|
|
|
3666 |
|
|
begin
|
3667 |
|
|
-- Only process if warnings activated
|
3668 |
|
|
|
3669 |
|
|
if Warn_On_Assumed_Low_Bound then
|
3670 |
|
|
|
3671 |
|
|
-- Test if array is simple entity name
|
3672 |
|
|
|
3673 |
|
|
if Is_Entity_Name (Name) then
|
3674 |
|
|
|
3675 |
|
|
-- Test if array is parameter of unconstrained string type
|
3676 |
|
|
|
3677 |
|
|
Ent := Entity (Name);
|
3678 |
|
|
Typ := Etype (Ent);
|
3679 |
|
|
|
3680 |
|
|
if Is_Formal (Ent)
|
3681 |
|
|
and then Is_Suspicious_Type (Typ)
|
3682 |
|
|
and then not Low_Bound_Tested (Ent)
|
3683 |
|
|
then
|
3684 |
|
|
Test_Suspicious_Index;
|
3685 |
|
|
end if;
|
3686 |
|
|
end if;
|
3687 |
|
|
end if;
|
3688 |
|
|
end Warn_On_Suspicious_Index;
|
3689 |
|
|
|
3690 |
|
|
--------------------------------------
|
3691 |
|
|
-- Warn_On_Unassigned_Out_Parameter --
|
3692 |
|
|
--------------------------------------
|
3693 |
|
|
|
3694 |
|
|
procedure Warn_On_Unassigned_Out_Parameter
|
3695 |
|
|
(Return_Node : Node_Id;
|
3696 |
|
|
Scope_Id : Entity_Id)
|
3697 |
|
|
is
|
3698 |
|
|
Form : Entity_Id;
|
3699 |
|
|
Form2 : Entity_Id;
|
3700 |
|
|
|
3701 |
|
|
begin
|
3702 |
|
|
-- Ignore if procedure or return statement does not come from source
|
3703 |
|
|
|
3704 |
|
|
if not Comes_From_Source (Scope_Id)
|
3705 |
|
|
or else not Comes_From_Source (Return_Node)
|
3706 |
|
|
then
|
3707 |
|
|
return;
|
3708 |
|
|
end if;
|
3709 |
|
|
|
3710 |
|
|
-- Loop through formals
|
3711 |
|
|
|
3712 |
|
|
Form := First_Formal (Scope_Id);
|
3713 |
|
|
while Present (Form) loop
|
3714 |
|
|
|
3715 |
|
|
-- We are only interested in OUT parameters that come from source
|
3716 |
|
|
-- and are never set in the source, and furthermore only in scalars
|
3717 |
|
|
-- since non-scalars generate too many false positives.
|
3718 |
|
|
|
3719 |
|
|
if Ekind (Form) = E_Out_Parameter
|
3720 |
|
|
and then Never_Set_In_Source_Check_Spec (Form)
|
3721 |
|
|
and then Is_Scalar_Type (Etype (Form))
|
3722 |
|
|
and then not Present (Unset_Reference (Form))
|
3723 |
|
|
then
|
3724 |
|
|
-- Before we issue the warning, an add ad hoc defence against the
|
3725 |
|
|
-- most common case of false positives with this warning which is
|
3726 |
|
|
-- the case where there is a Boolean OUT parameter that has been
|
3727 |
|
|
-- set, and whose meaning is "ignore the values of the other
|
3728 |
|
|
-- parameters". We can't of course reliably tell this case at
|
3729 |
|
|
-- compile time, but the following test kills a lot of false
|
3730 |
|
|
-- positives, without generating a significant number of false
|
3731 |
|
|
-- negatives (missed real warnings).
|
3732 |
|
|
|
3733 |
|
|
Form2 := First_Formal (Scope_Id);
|
3734 |
|
|
while Present (Form2) loop
|
3735 |
|
|
if Ekind (Form2) = E_Out_Parameter
|
3736 |
|
|
and then Root_Type (Etype (Form2)) = Standard_Boolean
|
3737 |
|
|
and then not Never_Set_In_Source_Check_Spec (Form2)
|
3738 |
|
|
then
|
3739 |
|
|
return;
|
3740 |
|
|
end if;
|
3741 |
|
|
|
3742 |
|
|
Next_Formal (Form2);
|
3743 |
|
|
end loop;
|
3744 |
|
|
|
3745 |
|
|
-- Here all conditions are met, record possible unset reference
|
3746 |
|
|
|
3747 |
|
|
Set_Unset_Reference (Form, Return_Node);
|
3748 |
|
|
end if;
|
3749 |
|
|
|
3750 |
|
|
Next_Formal (Form);
|
3751 |
|
|
end loop;
|
3752 |
|
|
end Warn_On_Unassigned_Out_Parameter;
|
3753 |
|
|
|
3754 |
|
|
---------------------------------
|
3755 |
|
|
-- Warn_On_Unreferenced_Entity --
|
3756 |
|
|
---------------------------------
|
3757 |
|
|
|
3758 |
|
|
procedure Warn_On_Unreferenced_Entity
|
3759 |
|
|
(Spec_E : Entity_Id;
|
3760 |
|
|
Body_E : Entity_Id := Empty)
|
3761 |
|
|
is
|
3762 |
|
|
E : Entity_Id := Spec_E;
|
3763 |
|
|
|
3764 |
|
|
begin
|
3765 |
|
|
if not Referenced_Check_Spec (E)
|
3766 |
|
|
and then not Has_Pragma_Unreferenced_Check_Spec (E)
|
3767 |
|
|
and then not Warnings_Off_Check_Spec (E)
|
3768 |
|
|
then
|
3769 |
|
|
case Ekind (E) is
|
3770 |
|
|
when E_Variable =>
|
3771 |
|
|
|
3772 |
|
|
-- Case of variable that is assigned but not read. We suppress
|
3773 |
|
|
-- the message if the variable is volatile, has an address
|
3774 |
|
|
-- clause, is aliased, or is a renaming, or is imported.
|
3775 |
|
|
|
3776 |
|
|
if Referenced_As_LHS_Check_Spec (E)
|
3777 |
|
|
and then No (Address_Clause (E))
|
3778 |
|
|
and then not Is_Volatile (E)
|
3779 |
|
|
then
|
3780 |
|
|
if Warn_On_Modified_Unread
|
3781 |
|
|
and then not Is_Imported (E)
|
3782 |
|
|
and then not Is_Aliased (E)
|
3783 |
|
|
and then No (Renamed_Object (E))
|
3784 |
|
|
then
|
3785 |
|
|
if not Has_Pragma_Unmodified_Check_Spec (E) then
|
3786 |
|
|
Error_Msg_N -- CODEFIX
|
3787 |
|
|
("?variable & is assigned but never read!", E);
|
3788 |
|
|
end if;
|
3789 |
|
|
|
3790 |
|
|
Set_Last_Assignment (E, Empty);
|
3791 |
|
|
end if;
|
3792 |
|
|
|
3793 |
|
|
-- Normal case of neither assigned nor read (exclude variables
|
3794 |
|
|
-- referenced as out parameters, since we already generated
|
3795 |
|
|
-- appropriate warnings at the call point in this case).
|
3796 |
|
|
|
3797 |
|
|
elsif not Referenced_As_Out_Parameter (E) then
|
3798 |
|
|
|
3799 |
|
|
-- We suppress the message for types for which a valid
|
3800 |
|
|
-- pragma Unreferenced_Objects has been given, otherwise
|
3801 |
|
|
-- we go ahead and give the message.
|
3802 |
|
|
|
3803 |
|
|
if not Has_Pragma_Unreferenced_Objects (Etype (E)) then
|
3804 |
|
|
|
3805 |
|
|
-- Distinguish renamed case in message
|
3806 |
|
|
|
3807 |
|
|
if Present (Renamed_Object (E))
|
3808 |
|
|
and then Comes_From_Source (Renamed_Object (E))
|
3809 |
|
|
then
|
3810 |
|
|
Error_Msg_N -- CODEFIX
|
3811 |
|
|
("?renamed variable & is not referenced!", E);
|
3812 |
|
|
else
|
3813 |
|
|
Error_Msg_N -- CODEFIX
|
3814 |
|
|
("?variable & is not referenced!", E);
|
3815 |
|
|
end if;
|
3816 |
|
|
end if;
|
3817 |
|
|
end if;
|
3818 |
|
|
|
3819 |
|
|
when E_Constant =>
|
3820 |
|
|
if Present (Renamed_Object (E))
|
3821 |
|
|
and then Comes_From_Source (Renamed_Object (E))
|
3822 |
|
|
then
|
3823 |
|
|
Error_Msg_N -- CODEFIX
|
3824 |
|
|
("?renamed constant & is not referenced!", E);
|
3825 |
|
|
else
|
3826 |
|
|
Error_Msg_N -- CODEFIX
|
3827 |
|
|
("?constant & is not referenced!", E);
|
3828 |
|
|
end if;
|
3829 |
|
|
|
3830 |
|
|
when E_In_Parameter |
|
3831 |
|
|
E_In_Out_Parameter =>
|
3832 |
|
|
|
3833 |
|
|
-- Do not emit message for formals of a renaming, because
|
3834 |
|
|
-- they are never referenced explicitly.
|
3835 |
|
|
|
3836 |
|
|
if Nkind (Original_Node (Unit_Declaration_Node (Scope (E))))
|
3837 |
|
|
/= N_Subprogram_Renaming_Declaration
|
3838 |
|
|
then
|
3839 |
|
|
-- Suppress this message for an IN OUT parameter of a
|
3840 |
|
|
-- non-scalar type, since it is normal to have only an
|
3841 |
|
|
-- assignment in such a case.
|
3842 |
|
|
|
3843 |
|
|
if Ekind (E) = E_In_Parameter
|
3844 |
|
|
or else not Referenced_As_LHS_Check_Spec (E)
|
3845 |
|
|
or else Is_Scalar_Type (Etype (E))
|
3846 |
|
|
then
|
3847 |
|
|
if Present (Body_E) then
|
3848 |
|
|
E := Body_E;
|
3849 |
|
|
end if;
|
3850 |
|
|
|
3851 |
|
|
if not Is_Trivial_Subprogram (Scope (E)) then
|
3852 |
|
|
Error_Msg_NE -- CODEFIX
|
3853 |
|
|
("?formal parameter & is not referenced!",
|
3854 |
|
|
E, Spec_E);
|
3855 |
|
|
end if;
|
3856 |
|
|
end if;
|
3857 |
|
|
end if;
|
3858 |
|
|
|
3859 |
|
|
when E_Out_Parameter =>
|
3860 |
|
|
null;
|
3861 |
|
|
|
3862 |
|
|
when E_Discriminant =>
|
3863 |
|
|
Error_Msg_N ("?discriminant & is not referenced!", E);
|
3864 |
|
|
|
3865 |
|
|
when E_Named_Integer |
|
3866 |
|
|
E_Named_Real =>
|
3867 |
|
|
Error_Msg_N -- CODEFIX
|
3868 |
|
|
("?named number & is not referenced!", E);
|
3869 |
|
|
|
3870 |
|
|
when Formal_Object_Kind =>
|
3871 |
|
|
Error_Msg_N -- CODEFIX
|
3872 |
|
|
("?formal object & is not referenced!", E);
|
3873 |
|
|
|
3874 |
|
|
when E_Enumeration_Literal =>
|
3875 |
|
|
Error_Msg_N -- CODEFIX
|
3876 |
|
|
("?literal & is not referenced!", E);
|
3877 |
|
|
|
3878 |
|
|
when E_Function =>
|
3879 |
|
|
Error_Msg_N -- CODEFIX
|
3880 |
|
|
("?function & is not referenced!", E);
|
3881 |
|
|
|
3882 |
|
|
when E_Procedure =>
|
3883 |
|
|
Error_Msg_N -- CODEFIX
|
3884 |
|
|
("?procedure & is not referenced!", E);
|
3885 |
|
|
|
3886 |
|
|
when E_Package =>
|
3887 |
|
|
Error_Msg_N -- CODEFIX
|
3888 |
|
|
("?package & is not referenced!", E);
|
3889 |
|
|
|
3890 |
|
|
when E_Exception =>
|
3891 |
|
|
Error_Msg_N -- CODEFIX
|
3892 |
|
|
("?exception & is not referenced!", E);
|
3893 |
|
|
|
3894 |
|
|
when E_Label =>
|
3895 |
|
|
Error_Msg_N -- CODEFIX
|
3896 |
|
|
("?label & is not referenced!", E);
|
3897 |
|
|
|
3898 |
|
|
when E_Generic_Procedure =>
|
3899 |
|
|
Error_Msg_N -- CODEFIX
|
3900 |
|
|
("?generic procedure & is never instantiated!", E);
|
3901 |
|
|
|
3902 |
|
|
when E_Generic_Function =>
|
3903 |
|
|
Error_Msg_N -- CODEFIX
|
3904 |
|
|
("?generic function & is never instantiated!", E);
|
3905 |
|
|
|
3906 |
|
|
when Type_Kind =>
|
3907 |
|
|
Error_Msg_N -- CODEFIX
|
3908 |
|
|
("?type & is not referenced!", E);
|
3909 |
|
|
|
3910 |
|
|
when others =>
|
3911 |
|
|
Error_Msg_N -- CODEFIX
|
3912 |
|
|
("?& is not referenced!", E);
|
3913 |
|
|
end case;
|
3914 |
|
|
|
3915 |
|
|
-- Kill warnings on the entity on which the message has been posted
|
3916 |
|
|
|
3917 |
|
|
Set_Warnings_Off (E);
|
3918 |
|
|
end if;
|
3919 |
|
|
end Warn_On_Unreferenced_Entity;
|
3920 |
|
|
|
3921 |
|
|
--------------------------------
|
3922 |
|
|
-- Warn_On_Useless_Assignment --
|
3923 |
|
|
--------------------------------
|
3924 |
|
|
|
3925 |
|
|
procedure Warn_On_Useless_Assignment
|
3926 |
|
|
(Ent : Entity_Id;
|
3927 |
|
|
N : Node_Id := Empty)
|
3928 |
|
|
is
|
3929 |
|
|
P : Node_Id;
|
3930 |
|
|
X : Node_Id;
|
3931 |
|
|
|
3932 |
|
|
function Check_Ref (N : Node_Id) return Traverse_Result;
|
3933 |
|
|
-- Used to instantiate Traverse_Func. Returns Abandon if a reference to
|
3934 |
|
|
-- the entity in question is found.
|
3935 |
|
|
|
3936 |
|
|
function Test_No_Refs is new Traverse_Func (Check_Ref);
|
3937 |
|
|
|
3938 |
|
|
---------------
|
3939 |
|
|
-- Check_Ref --
|
3940 |
|
|
---------------
|
3941 |
|
|
|
3942 |
|
|
function Check_Ref (N : Node_Id) return Traverse_Result is
|
3943 |
|
|
begin
|
3944 |
|
|
-- Check reference to our identifier. We use name equality here
|
3945 |
|
|
-- because the exception handlers have not yet been analyzed. This
|
3946 |
|
|
-- is not quite right, but it really does not matter that we fail
|
3947 |
|
|
-- to output the warning in some obscure cases of name clashes.
|
3948 |
|
|
|
3949 |
|
|
if Nkind (N) = N_Identifier
|
3950 |
|
|
and then Chars (N) = Chars (Ent)
|
3951 |
|
|
then
|
3952 |
|
|
return Abandon;
|
3953 |
|
|
else
|
3954 |
|
|
return OK;
|
3955 |
|
|
end if;
|
3956 |
|
|
end Check_Ref;
|
3957 |
|
|
|
3958 |
|
|
-- Start of processing for Warn_On_Useless_Assignment
|
3959 |
|
|
|
3960 |
|
|
begin
|
3961 |
|
|
-- Check if this is a case we want to warn on, a scalar or access
|
3962 |
|
|
-- variable with the last assignment field set, with warnings enabled,
|
3963 |
|
|
-- and which is not imported or exported. We also check that it is OK
|
3964 |
|
|
-- to capture the value. We are not going to capture any value, but
|
3965 |
|
|
-- the warning message depends on the same kind of conditions.
|
3966 |
|
|
|
3967 |
|
|
if Is_Assignable (Ent)
|
3968 |
|
|
and then not Is_Return_Object (Ent)
|
3969 |
|
|
and then Present (Last_Assignment (Ent))
|
3970 |
|
|
and then not Is_Imported (Ent)
|
3971 |
|
|
and then not Is_Exported (Ent)
|
3972 |
|
|
and then Safe_To_Capture_Value (N, Ent)
|
3973 |
|
|
and then not Has_Pragma_Unreferenced_Check_Spec (Ent)
|
3974 |
|
|
then
|
3975 |
|
|
-- Before we issue the message, check covering exception handlers.
|
3976 |
|
|
-- Search up tree for enclosing statement sequences and handlers.
|
3977 |
|
|
|
3978 |
|
|
P := Parent (Last_Assignment (Ent));
|
3979 |
|
|
while Present (P) loop
|
3980 |
|
|
|
3981 |
|
|
-- Something is really wrong if we don't find a handled statement
|
3982 |
|
|
-- sequence, so just suppress the warning.
|
3983 |
|
|
|
3984 |
|
|
if No (P) then
|
3985 |
|
|
Set_Last_Assignment (Ent, Empty);
|
3986 |
|
|
return;
|
3987 |
|
|
|
3988 |
|
|
-- When we hit a package/subprogram body, issue warning and exit
|
3989 |
|
|
|
3990 |
|
|
elsif Nkind (P) = N_Subprogram_Body
|
3991 |
|
|
or else Nkind (P) = N_Package_Body
|
3992 |
|
|
then
|
3993 |
|
|
-- Case of assigned value never referenced
|
3994 |
|
|
|
3995 |
|
|
if No (N) then
|
3996 |
|
|
declare
|
3997 |
|
|
LA : constant Node_Id := Last_Assignment (Ent);
|
3998 |
|
|
|
3999 |
|
|
begin
|
4000 |
|
|
-- Don't give this for OUT and IN OUT formals, since
|
4001 |
|
|
-- clearly caller may reference the assigned value. Also
|
4002 |
|
|
-- never give such warnings for internal variables.
|
4003 |
|
|
|
4004 |
|
|
if Ekind (Ent) = E_Variable
|
4005 |
|
|
and then not Is_Internal_Name (Chars (Ent))
|
4006 |
|
|
then
|
4007 |
|
|
-- Give appropriate message, distinguishing between
|
4008 |
|
|
-- assignment statements and out parameters.
|
4009 |
|
|
|
4010 |
|
|
if Nkind_In (Parent (LA), N_Procedure_Call_Statement,
|
4011 |
|
|
N_Parameter_Association)
|
4012 |
|
|
then
|
4013 |
|
|
Error_Msg_NE
|
4014 |
|
|
("?& modified by call, but value never "
|
4015 |
|
|
& "referenced", LA, Ent);
|
4016 |
|
|
|
4017 |
|
|
else
|
4018 |
|
|
Error_Msg_NE -- CODEFIX
|
4019 |
|
|
("?useless assignment to&, value never "
|
4020 |
|
|
& "referenced!", LA, Ent);
|
4021 |
|
|
end if;
|
4022 |
|
|
end if;
|
4023 |
|
|
end;
|
4024 |
|
|
|
4025 |
|
|
-- Case of assigned value overwritten
|
4026 |
|
|
|
4027 |
|
|
else
|
4028 |
|
|
declare
|
4029 |
|
|
LA : constant Node_Id := Last_Assignment (Ent);
|
4030 |
|
|
|
4031 |
|
|
begin
|
4032 |
|
|
Error_Msg_Sloc := Sloc (N);
|
4033 |
|
|
|
4034 |
|
|
-- Give appropriate message, distinguishing between
|
4035 |
|
|
-- assignment statements and out parameters.
|
4036 |
|
|
|
4037 |
|
|
if Nkind_In (Parent (LA), N_Procedure_Call_Statement,
|
4038 |
|
|
N_Parameter_Association)
|
4039 |
|
|
then
|
4040 |
|
|
Error_Msg_NE
|
4041 |
|
|
("?& modified by call, but value overwritten #!",
|
4042 |
|
|
LA, Ent);
|
4043 |
|
|
else
|
4044 |
|
|
Error_Msg_NE -- CODEFIX
|
4045 |
|
|
("?useless assignment to&, value overwritten #!",
|
4046 |
|
|
LA, Ent);
|
4047 |
|
|
end if;
|
4048 |
|
|
end;
|
4049 |
|
|
end if;
|
4050 |
|
|
|
4051 |
|
|
-- Clear last assignment indication and we are done
|
4052 |
|
|
|
4053 |
|
|
Set_Last_Assignment (Ent, Empty);
|
4054 |
|
|
return;
|
4055 |
|
|
|
4056 |
|
|
-- Enclosing handled sequence of statements
|
4057 |
|
|
|
4058 |
|
|
elsif Nkind (P) = N_Handled_Sequence_Of_Statements then
|
4059 |
|
|
|
4060 |
|
|
-- Check exception handlers present
|
4061 |
|
|
|
4062 |
|
|
if Present (Exception_Handlers (P)) then
|
4063 |
|
|
|
4064 |
|
|
-- If we are not at the top level, we regard an inner
|
4065 |
|
|
-- exception handler as a decisive indicator that we should
|
4066 |
|
|
-- not generate the warning, since the variable in question
|
4067 |
|
|
-- may be accessed after an exception in the outer block.
|
4068 |
|
|
|
4069 |
|
|
if Nkind (Parent (P)) /= N_Subprogram_Body
|
4070 |
|
|
and then Nkind (Parent (P)) /= N_Package_Body
|
4071 |
|
|
then
|
4072 |
|
|
Set_Last_Assignment (Ent, Empty);
|
4073 |
|
|
return;
|
4074 |
|
|
|
4075 |
|
|
-- Otherwise we are at the outer level. An exception
|
4076 |
|
|
-- handler is significant only if it references the
|
4077 |
|
|
-- variable in question, or if the entity in question
|
4078 |
|
|
-- is an OUT or IN OUT parameter, which which case
|
4079 |
|
|
-- the caller can reference it after the exception
|
4080 |
|
|
-- handler completes.
|
4081 |
|
|
|
4082 |
|
|
else
|
4083 |
|
|
if Is_Formal (Ent) then
|
4084 |
|
|
Set_Last_Assignment (Ent, Empty);
|
4085 |
|
|
return;
|
4086 |
|
|
|
4087 |
|
|
else
|
4088 |
|
|
X := First (Exception_Handlers (P));
|
4089 |
|
|
while Present (X) loop
|
4090 |
|
|
if Test_No_Refs (X) = Abandon then
|
4091 |
|
|
Set_Last_Assignment (Ent, Empty);
|
4092 |
|
|
return;
|
4093 |
|
|
end if;
|
4094 |
|
|
|
4095 |
|
|
X := Next (X);
|
4096 |
|
|
end loop;
|
4097 |
|
|
end if;
|
4098 |
|
|
end if;
|
4099 |
|
|
end if;
|
4100 |
|
|
end if;
|
4101 |
|
|
|
4102 |
|
|
P := Parent (P);
|
4103 |
|
|
end loop;
|
4104 |
|
|
end if;
|
4105 |
|
|
end Warn_On_Useless_Assignment;
|
4106 |
|
|
|
4107 |
|
|
---------------------------------
|
4108 |
|
|
-- Warn_On_Useless_Assignments --
|
4109 |
|
|
---------------------------------
|
4110 |
|
|
|
4111 |
|
|
procedure Warn_On_Useless_Assignments (E : Entity_Id) is
|
4112 |
|
|
Ent : Entity_Id;
|
4113 |
|
|
begin
|
4114 |
|
|
if Warn_On_Modified_Unread
|
4115 |
|
|
and then In_Extended_Main_Source_Unit (E)
|
4116 |
|
|
then
|
4117 |
|
|
Ent := First_Entity (E);
|
4118 |
|
|
while Present (Ent) loop
|
4119 |
|
|
Warn_On_Useless_Assignment (Ent);
|
4120 |
|
|
Next_Entity (Ent);
|
4121 |
|
|
end loop;
|
4122 |
|
|
end if;
|
4123 |
|
|
end Warn_On_Useless_Assignments;
|
4124 |
|
|
|
4125 |
|
|
-----------------------------
|
4126 |
|
|
-- Warnings_Off_Check_Spec --
|
4127 |
|
|
-----------------------------
|
4128 |
|
|
|
4129 |
|
|
function Warnings_Off_Check_Spec (E : Entity_Id) return Boolean is
|
4130 |
|
|
begin
|
4131 |
|
|
if Is_Formal (E) and then Present (Spec_Entity (E)) then
|
4132 |
|
|
|
4133 |
|
|
-- Note: use of OR here instead of OR ELSE is deliberate, we want
|
4134 |
|
|
-- to mess with flags on both entities.
|
4135 |
|
|
|
4136 |
|
|
return Has_Warnings_Off (E)
|
4137 |
|
|
or
|
4138 |
|
|
Has_Warnings_Off (Spec_Entity (E));
|
4139 |
|
|
|
4140 |
|
|
else
|
4141 |
|
|
return Has_Warnings_Off (E);
|
4142 |
|
|
end if;
|
4143 |
|
|
end Warnings_Off_Check_Spec;
|
4144 |
|
|
|
4145 |
|
|
end Sem_Warn;
|