68
69
type Usage is array (Rule_Detail) of Boolean;
69
70
Rule_Used : Usage := (others => False);
71
Rule_Type : array (Rule_Detail) of Rule_Types;
72
Rule_Label : array (Rule_Detail) of Ada.Strings.Wide_Unbounded.Unbounded_Wide_String;
72
Ctl_Kinds : array (Rule_Detail) of Control_Kinds;
73
Ctl_Labels : array (Rule_Detail) of Ada.Strings.Wide_Unbounded.Unbounded_Wide_String;
74
With_In : array (Rule_Detail) of Boolean;
80
82
User_Message ("Rule: " & Rule_Id);
81
Help_On_Flags (Header => "Parameter 1:", Footer => "(optional, default=certain)");
83
Help_On_Flags (Header => "Parameter 1: [with_in] ",
84
Footer => "(optional, default=certain)");
82
85
User_Message ("Control subprogram or entry calls where the same variable is given");
83
86
User_Message ("for more than one [in] out parameter.");
84
User_Message ("This rule can detect non-straightforward aliasing cases, see doc for details");
87
User_Message ("If ""with_in"" is given, consider also in parameters");
91
procedure Add_Use (Label : in Wide_String;
92
Rule_Use_Type : in Rule_Types) is
94
procedure Add_Control (Ctl_Label : in Wide_String; Ctl_Kind : in Control_Kinds) is
93
95
use Ada.Strings.Wide_Unbounded;
94
96
use Framework.Language, Thick_Queries;
96
Detail : Rule_Detail := Certain;
98
101
if Parameter_Exists then
99
Detail := Get_Flag_Parameter (Allow_Any => False);
102
In_Flag := Get_Modifier ("WITH_IN");
103
Detail := Get_Flag_Parameter (Allow_Any => False);
102
109
if Rule_Used (Detail) then
110
117
Parameter_Error (Rule_Id, "only one parameter allowed");
113
Rule_Type (Detail) := Rule_Use_Type;
114
Rule_Label (Detail) := To_Unbounded_Wide_String (Label);
120
Ctl_Kinds (Detail) := Ctl_Kind;
121
Ctl_Labels (Detail) := To_Unbounded_Wide_String (Ctl_Label);
115
122
Rule_Used (Detail) := True;
123
With_In (Detail) := In_Flag;
145
153
-- If weaker checks have been specified, force them for stronger ones
146
154
if Rule_Used (Unlikely) and not Rule_Used (Possible) then
147
155
Rule_Used (Possible) := True;
148
Rule_Type (Possible) := Rule_Type (Unlikely);
149
Rule_Label (Possible) := Rule_Label (Unlikely);
156
Ctl_Kinds (Possible) := Ctl_Kinds (Unlikely);
157
Ctl_Labels (Possible) := Ctl_Labels (Unlikely);
158
With_In (Possible) := With_In (Unlikely);
151
160
if Rule_Used (Possible) and not Rule_Used (Certain) then
152
161
Rule_Used (Certain) := True;
153
Rule_Type (Certain) := Rule_Type (Possible);
154
Rule_Label (Certain) := Rule_Label (Possible);
162
Ctl_Kinds (Certain) := Ctl_Kinds (Possible);
163
Ctl_Labels (Certain) := Ctl_Labels (Possible);
164
With_In (Certain) := With_In (Possible);
160
170
-- Process_Call --
161
171
------------------
163
type Parameters_Table is array (Asis.List_Index range <>) of Asis.List_Index;
173
type Parameters_Descr is
175
Mode : Asis.Mode_Kinds;
176
Expr : Asis.Expression;
166
-- Some of the algorithms in this procedure are a bit convoluted, because we avoid
167
-- using normalized formals and actuals list, which are UNIMPLEMENTED in some versions
169
-- Some rewriting might be in order when the problem goes away...
179
type Parameters_Table is array (Asis.List_Index range <>) of Parameters_Descr;
171
181
procedure Process_Call (Call : in Asis.Statement) is
172
use Asis, Asis.Declarations, Asis.Elements, Asis.Expressions, Asis.Statements;
182
use Asis, Asis.Elements, Asis.Expressions, Asis.Statements;
173
183
use Thick_Queries, Framework.Reports, Ada.Strings.Wide_Unbounded;
203
213
return '"' & Defining_Name_Image (Name) & " => "
204
214
& Trim_All (Element_Image (Actual_Parameter (Actuals (Position)))) & '"';
206
return '"' & Name_Image (Name) & " => "
216
return '"' & A4G_Bugs.Name_Image (Name) & " => "
207
217
& Trim_All (Element_Image (Actual_Parameter (Actuals (Position)))) & '"';
209
219
end Association_Image;
212
TCP_Top : ASIS_Natural := To_Check_Parameters'First - 1;
214
pragma Warnings (Off, To_Check_Parameters);
215
-- GNAT warns that To_Check_Parameters may be used before it has a value,
216
-- but the algorithm ensures that this does not happen, because the loop on J
217
-- is not executed the first time.
219
221
Param_Proximity : Proximity;
221
if Actuals'Length = 1 then
222
-- Only 1 parameter => no possible aliasing
223
if Actuals'Length <= 1 then
224
-- 0 or 1 parameter => no possible aliasing
231
233
for I in Actuals'Range loop
232
Mode := Mode_Kind (Enclosing_Element (Formal_Name (Call, I)));
234
if Mode in An_Out_Mode .. An_In_Out_Mode then
235
for J in List_Index range To_Check_Parameters'First .. TCP_Top loop
236
Param_Proximity := Variables_Proximity (Actual_Parameter (Actuals (To_Check_Parameters (J))),
237
Actual_Parameter (Actuals (I)));
238
if Rule_Used (Param_Proximity.Confidence) and then Param_Proximity.Overlap /= None then
240
To_Wide_String (Rule_Label (Param_Proximity.Confidence)),
241
Rule_Type (Param_Proximity.Confidence),
243
Choose (Param_Proximity.Confidence = Certain,
245
Choose (Param_Proximity.Confidence = Possible,
248
& " aliasing between parameters "
249
& Association_Image (To_Check_Parameters (J))
251
& Association_Image (I)
256
TCP_Top := TCP_Top + 1;
257
To_Check_Parameters (TCP_Top) := I;
234
To_Check_Parameters (I) := (Mode_Kind (Enclosing_Element (Formal_Name (Call, I))),
235
Actual_Parameter (Actuals (I)));
236
for J in List_Index range To_Check_Parameters'First .. I-1 loop
237
Param_Proximity := Variables_Proximity (To_Check_Parameters (J).Expr,
238
To_Check_Parameters (I).Expr);
239
if Rule_Used (Param_Proximity.Confidence)
240
and then Param_Proximity.Overlap /= None
241
and then (((To_Check_Parameters (I).Mode in An_Out_Mode .. An_In_Out_Mode
242
or else With_In (Param_Proximity.Confidence))
243
and To_Check_Parameters (J).Mode in An_Out_Mode .. An_In_Out_Mode)
244
or ((To_Check_Parameters (J).Mode in An_Out_Mode .. An_In_Out_Mode
245
or else With_In (Param_Proximity.Confidence))
246
and To_Check_Parameters (I).Mode in An_Out_Mode .. An_In_Out_Mode))
249
To_Wide_String (Ctl_Labels (Param_Proximity.Confidence)),
250
Ctl_Kinds (Param_Proximity.Confidence),
252
Choose (Param_Proximity.Confidence = Certain,
254
Choose (Param_Proximity.Confidence = Possible,
257
& " aliasing between parameters "
258
& Association_Image (J)
260
& Association_Image (I)
261
266
end Process_Call;
264
Framework.Rules_Manager.Register_Semantic (Rule_Id,
266
Add_Use => Add_Use'Access,
267
Command => Command'Access,
268
Prepare => Prepare'Access);
269
Framework.Rules_Manager.Register (Rule_Id,
270
Rules_Manager.Semantic,
271
Help_CB => Help'Access,
272
Add_Control_CB => Add_Control'Access,
273
Command_CB => Command'Access,
274
Prepare_CB => Prepare'Access);
269
275
end Rules.Parameter_Aliasing;