61
63
-- is already the procedure itself, but the name must be attached to where the procedure is declared,
62
64
-- i.e. the enclosing scope.
64
Rule_Used : Boolean := False;
66
Rule_Context : Basic_Rule_Context;
66
type Subrules is (Strict, Overloading, Both);
67
subtype True_Subrules is Subrules range Strict .. Overloading;
68
package Subrules_Flag_Utilities is new Framework.Language.Flag_Utilities (Subrules);
70
type Rule_Usage is array (True_Subrules) of Boolean;
71
Not_Used : constant Rule_Usage := (others => False);
73
Rule_Used : Rule_Usage := Not_Used;
74
Save_Used : Rule_Usage;
75
Rule_Context : array (True_Subrules) of Basic_Rule_Context;
68
77
type Identifier_Data (Length : Positive) is
70
79
Name : Wide_String (1..Length);
71
80
Short_Last : Positive;
72
81
Elem : Asis.Element;
82
Other_Elem : Asis.Element;
73
83
Is_Callable : Boolean;
75
85
package Visible_Identifiers is new Framework.Scope_Manager.Scoped_Store (Identifier_Data);
92
use Subrules_Flag_Utilities;
83
94
User_Message ("Rule: " & Rule_Id);
84
User_Message ("Parameter(s): none");
95
Help_On_Flags ("Parameter(s): ", Footer => "(default = strict)");
85
96
User_Message ("Control occurrences of local identifiers that hide an outer identical name");
92
procedure Add_Use (Label : in Wide_String;
93
Rule_Use_Type : in Rule_Types) is
94
use Framework.Language;
103
procedure Add_Control (Ctl_Label : in Wide_String; Ctl_Kind : in Control_Kinds) is
104
use Framework.Language, Subrules_Flag_Utilities;
98
Parameter_Error (Rule_Id, "this rule can be specified only once");
101
if Parameter_Exists then
102
Parameter_Error (Rule_Id, "No parameter allowed");
105
Rule_Context := Basic.New_Context (Rule_Use_Type, Label);
107
if Parameter_Exists then
108
while Parameter_Exists loop
109
Subrule := Get_Flag_Parameter (Allow_Any => False);
111
when True_Subrules =>
112
if Rule_Used (Subrule) then
113
Parameter_Error (Rule_Id, "subrule already specified");
115
Rule_Used (Subrule) := True;
116
Rule_Context (Subrule) := Basic.New_Context (Ctl_Kind, Ctl_Label);
118
if Rule_Used /= (True_Subrules => False) then
119
Parameter_Error (Rule_Id, "subrule already specified");
121
Rule_Used := (others => True);
122
Rule_Context := (others => Basic.New_Context (Ctl_Kind, Ctl_Label));
126
Rule_Used (Strict) := True;
127
Rule_Context (Strict) := Basic.New_Context (Ctl_Kind, Ctl_Label);
140
Rule_Used := Not_Used;
120
142
Save_Used := Rule_Used;
143
Rule_Used := Not_Used;
123
145
Rule_Used := Save_Used;
155
if Rule_Used /= (True_Subrules => False) then
156
Visible_Identifiers.Activate;
127
160
---------------------------
128
161
-- Process_Defining_Name --
129
162
---------------------------
131
164
procedure Process_Defining_Name (Name : in Asis.Defining_Name) is
132
use Thick_Queries, Asis, Asis.Elements, Asis.Declarations;
165
use Asis, Asis.Elements, Asis.Declarations;
166
use Thick_Queries, Framework.Scope_Manager;
134
168
Scope : Asis.Element;
136
-- This function detects names that are not to be processed by this rule, since
137
-- they do not hide anything nor can they be hidden:
138
-- - Names of record components (but not protected components)
139
-- - Names of formal parameters in a SP renaming declaration
140
-- - Names of formal parameters in the declaration of an access to SP type
141
170
function Not_An_Appropriate_Name return Boolean is
171
-- This function detects names that are not to be processed by this rule, since
172
-- they do not hide anything nor can they be hidden:
173
-- - Names of record components (but not protected components), including discriminants
174
-- - Names of formal parameters in a SP renaming declaration
175
-- - Names of formal parameters in the declaration of an access to SP type
142
176
Decl : constant Asis.Declaration := Enclosing_Element (Name);
143
177
Decl_Enclosing : constant Asis.Element := Enclosing_Element (Decl);
145
179
case Declaration_Kind (Decl) is
146
180
when A_Component_Declaration =>
147
181
return Definition_Kind (Decl_Enclosing) /= A_Protected_Definition;
182
when A_Discriminant_Specification =>
148
184
when A_Parameter_Specification =>
149
185
case Element_Kind (Decl_Enclosing) is
150
186
when A_Definition =>
163
199
end Not_An_Appropriate_Name;
165
-- This function returns True if Left and Right are the same scopes,
166
-- or if Left is a body and Right is the corresponding specification
167
function Are_Equivalent_Scopes (Left, Right : Asis.Element) return Boolean is
201
function Other_Part (Elem : Asis.Defining_Name) return Asis.Element is
202
-- Returns the declaration of the completion of Elem if any
168
203
Decl : Asis.Declaration;
170
if Is_Equal (Left, Right) then
173
case Element_Kind (Left) is
175
| An_Exception_Handler
179
-- Corresponding_Declaration cannot be called on some declarations
180
-- if it were, it would simply return its argument, so let's do it by hand
181
case Declaration_Kind (Left) is
182
when An_Entry_Declaration
183
| A_Formal_Procedure_Declaration
184
| A_Formal_Function_Declaration
188
Decl := Corresponding_Declaration (Left);
190
if Is_Nil (Decl) then
191
-- No corresponding specification
205
Decl := Enclosing_Element (Elem);
206
case Declaration_Kind (Decl) is
207
when A_Private_Type_Declaration
208
| A_Private_Extension_Declaration
209
| An_Incomplete_Type_Declaration
211
return Corresponding_Type_Declaration (Decl);
212
when A_Deferred_Constant_Declaration =>
213
return Corresponding_Constant_Declaration (Elem);
214
when A_Function_Declaration
215
| A_Generic_Package_Declaration
216
| A_Generic_Procedure_Declaration
217
| A_Generic_Function_Declaration
218
| A_Package_Declaration
219
| A_Procedure_Declaration
220
| A_Single_Task_Declaration
221
| A_Task_Type_Declaration
222
| A_Protected_Type_Declaration
223
| A_Single_Protected_Declaration
225
return Corresponding_Body (Decl);
226
when An_Entry_Declaration =>
227
if Is_Task_Entry (Decl) then
228
-- Task entries have no body...
194
return Is_Equal (Decl, Right);
231
return Corresponding_Body (Decl);
197
end Are_Equivalent_Scopes;
199
238
begin -- Process_Defining_Name
200
if not Rule_Used then
239
if Rule_Used = Not_Used then
203
242
Rules_Manager.Enter (Rule_Id);
223
262
Is_Scope_Name : constant Boolean := Is_Equal (Enclosing_Scope (Name), Current_Scope);
224
263
-- Is_Scope_Name is True if Name is the defining name for the current scope
225
264
-- => it belongs to the enclosing scope
265
Already_There : Boolean;
227
function Is_Same (Check : Identifier_Data) return Boolean is
228
-- If both are callable entities, compare with profiles
229
-- otherwise, compare without profile
267
type Hiding_Kinds is (Hides, Overloads, Not_Hiding);
268
function Hiding_Kind (Check : Identifier_Data) return Hiding_Kinds is
231
if Callable_Name then
232
if Check.Is_Callable then
233
return Check.Name = Full_Name;
270
if not Callable_Name or else not Check.Is_Callable then
271
-- At least one is not a callable entity => no overloading
272
if Check.Name (1 .. Check.Short_Last) = Short_Name then
235
return Check.Name (1 .. Check.Short_Last) = Short_Name;
277
elsif Check.Name = Full_Name then
278
-- Overloadable and names match with profile
280
elsif Check.Name (1 .. Check.Short_Last) = Short_Name then
281
-- Overloadable and names match without profile
238
return Check.Name (1 .. Check.Short_Last) = Short_Name;
243
289
if Is_Scope_Name then
246
292
Scope := Current_Scope;
295
Already_There := False;
249
296
-- If scope is nil, it is the defining name of a library unit
250
297
-- => cannot hide anything
251
298
if not Is_Nil (Scope) then
252
299
Visible_Identifiers.Reset (All_Scopes);
253
301
while Visible_Identifiers.Data_Available loop
254
if Is_Same (Visible_Identifiers.Current_Data) then
256
-- Discard the case where we find a name declared within a scope equivalent
257
-- to the scope of Name:
258
-- this corresponds for example to a spec and corresponding body, incomplete
259
-- type and corresponding full declarations...
260
-- These must correspond to the same entity, otherwise it would not be allowed
262
if not Are_Equivalent_Scopes (Scope, Visible_Identifiers.Current_Data_Scope) then
266
'"' & Framework.Language.Adjust_Image (To_Title (Full_Name))
267
& """ hides declaration at "
268
& Image (Get_Location (Visible_Identifiers.Current_Data.Elem)));
302
-- Discard the case where we find the definition of another view
303
-- of the same entity
304
if Is_Equal (Visible_Identifiers.Current_Data.Other_Elem,
305
Enclosing_Element (Name))
307
Already_There := True;
309
case Hiding_Kind (Visible_Identifiers.Current_Data) is
311
if Rule_Used (Strict) then
313
Rule_Context (Strict),
315
'"' & Framework.Language.Adjust_Image (To_Title (Full_Name))
316
& """ hides declaration at "
317
& Image (Get_Location (Visible_Identifiers.Current_Data.Elem)));
320
if Rule_Used (Overloading) then
322
Rule_Context (Overloading),
324
'"' & Framework.Language.Adjust_Image (To_Title (Full_Name))
325
& """ overloads declaration at "
326
& Image (Get_Location (Visible_Identifiers.Current_Data.Elem)));
272
332
Visible_Identifiers.Next;
276
if Is_Scope_Name then
277
-- This is the defining name of the program unit that defines the current scope
278
-- it must be associated to the enclosing scope
279
Visible_Identifiers.Push_Enclosing ((Full_Name'Length,
285
Visible_Identifiers.Push ((Full_Name'Length,
336
if not Already_There then
337
if Is_Scope_Name then
338
-- This is the defining name of the program unit that defines the current scope
339
-- it must be associated to the enclosing scope
340
Visible_Identifiers.Push_Enclosing ((Full_Name'Length,
347
Visible_Identifiers.Push ((Full_Name'Length,
292
356
end Process_Defining_Name;
295
359
-- Process_With_Clause --
296
360
-------------------------
298
procedure Process_With_Clause (With_Clause : Asis.Clause) is
362
procedure Process_With_Clause (With_Clause : in Asis.Clause) is
299
363
-- Names in with clauses cannot hide anything, but can be hidden
300
364
use Asis, Asis.Clauses, Asis.Elements, Asis.Expressions, Thick_Queries;
302
if not Rule_Used then
366
if Rule_Used = Not_Used then
305
369
Rules_Manager.Enter (Rule_Id);
321
385
Failure ("Unexpected name in with clause", All_Names (I));
324
Short_Name : constant Wide_String := To_Upper (Name_Image (Name));
388
Short_Name : constant Wide_String := To_Upper (A4G_Bugs.Name_Image (Name));
325
389
Full_Name : constant Wide_String := Short_Name & Profile_Image (Name, With_Profile => False);
327
391
-- Bind names to scope 0
328
392
Visible_Identifiers.Push_Enclosing ((Full_Name'Length, Full_Name,
329
393
Short_Name'Length, Name,
330
395
Is_Callable_Construct (Name)));
332
397
exit when Expression_Kind (Current) = An_Identifier;
337
402
end Process_With_Clause;
340
Framework.Rules_Manager.Register_Semantic (Rule_Id,
342
Add_Use => Add_Use'Access,
343
Command => Command'Access);
405
Framework.Rules_Manager.Register (Rule_Id,
406
Rules_Manager.Semantic,
407
Help_CB => Help'Access,
408
Add_Control_CB => Add_Control'Access,
409
Command_CB => Command'Access,
410
Prepare_CB => Prepare'Access);
344
411
end Rules.Local_Hiding;