60
59
type Keywords is (K_Range, K_Logical_True, K_Logical_False, K_Parentheses, K_Logical);
61
60
subtype To_Check is Keywords range Keywords'First .. Keywords'Pred (K_Logical);
62
package Check_Flags_Utilities is new Framework.Language.Flag_Utilities (Keywords, "K_");
63
use Check_Flags_Utilities;
63
65
type Usage_Entry is
65
67
Used : Boolean := False;
66
68
Label : Unbounded_Wide_String;
68
70
type Usages is array (To_Check) of Usage_Entry;
70
72
Context : array (Rule_Types) of Usages;
71
73
Rule_Used : Boolean;
72
74
Save_Used : Boolean;
78
function Image (Check : To_Check) return Wide_String is
80
Img : constant Wide_String := To_Lower (To_Check'Wide_Image (Check));
83
return Img (3 .. Img'Last);
93
User_Message ("Rule: " & Rule_Id);
94
User_Message ("Parameter(s): ranges | logical | logical_true | logical_false");
95
User_Message (" | parentheses (optional, default=all)");
96
User_Message ("Control occurrence of various forms of expressions that could be made simpler:");
97
User_Message (" T'FIRST .. T'LAST that can be replaced by T'RANGE or T.");
98
User_Message (" <expression> = (/=) True/False");
99
User_Message (" if (<expression>) or case (<expression>)");
83
User_Message ("Rule: " & Rule_Id);
84
Help_On_Flags (Header => "Parameter(s):", Footer => "(optional, default=all)");
85
User_Message ("Control occurrence of various forms of expressions that could be made simpler:");
86
User_Message (" T'FIRST .. T'LAST that can be replaced by T'RANGE or T.");
87
User_Message (" <expression> = (/=) True/False");
88
User_Message (" Unnecessary parentheses");
171
157
------------------
173
159
procedure Process_Call (Call : in Asis.Expression) is
174
use Ada.Strings.Wide_Unbounded, Asis,
175
Asis.Elements, Asis.Expressions, Framework.Reports, Thick_Queries;
160
use Asis, Asis.Elements, Asis.Expressions, Framework.Reports, Thick_Queries;
177
162
type Param_Kind is (Static_True, Static_False, Expr);
178
163
function "+" (Left : Wide_String) return Unbounded_Wide_String renames To_Unbounded_Wide_String;
231
215
Rules_Manager.Enter (Rule_Id);
233
if Op in An_Equal_Operator .. A_Not_Equal_Operator then
235
P : constant Asis.Association_List := Function_Call_Parameters (Call);
236
L : constant Param_Kind := Get_Kind (Actual_Parameter (P(1)));
237
R : constant Param_Kind := Get_Kind (Actual_Parameter (P(2)));
239
if Message_Table (Op, L, R) /= Null_Unbounded_Wide_String then
240
-- Report the highest priority from Check/Search
241
if Context (Check)(K_Logical_False).Used and then (L = Static_False or R = Static_False) then
243
To_Wide_String (Context (Check)(K_Logical_False).Label),
246
To_Wide_String (Message_Table (Op, L, R)));
247
elsif Context (Check)(K_Logical_True).Used and then (L = Static_True or R = Static_True) then
249
To_Wide_String (Context (Check)(K_Logical_True).Label),
252
To_Wide_String (Message_Table (Op, L, R)));
253
elsif Context (Search)(K_Logical_False).Used and then (L = Static_False or R = Static_False) then
255
To_Wide_String (Context (Search)(K_Logical_False).Label),
258
To_Wide_String (Message_Table (Op, L, R)));
259
elsif Context (Search)(K_Logical_True).Used and then (L = Static_True or R = Static_True) then
261
To_Wide_String (Context (Search) (K_Logical_True).Label),
264
To_Wide_String (Message_Table (Op, L, R)));
218
Op : constant Asis.Operator_Kinds := Operator_Kind (Prefix (Call));
220
if Op in An_Equal_Operator .. A_Not_Equal_Operator then
222
P : constant Asis.Association_List := Function_Call_Parameters (Call);
223
L : constant Param_Kind := Get_Kind (Actual_Parameter (P(1)));
224
R : constant Param_Kind := Get_Kind (Actual_Parameter (P(2)));
226
if Message_Table (Op, L, R) /= Null_Unbounded_Wide_String then
227
-- Report the highest priority from Check/Search
228
if Context (Check)(K_Logical_False).Used and then (L = Static_False or R = Static_False) then
230
To_Wide_String (Context (Check)(K_Logical_False).Label),
233
To_Wide_String (Message_Table (Op, L, R)));
234
elsif Context (Check)(K_Logical_True).Used and then (L = Static_True or R = Static_True) then
236
To_Wide_String (Context (Check)(K_Logical_True).Label),
239
To_Wide_String (Message_Table (Op, L, R)));
240
elsif Context (Search)(K_Logical_False).Used and then (L = Static_False or R = Static_False) then
242
To_Wide_String (Context (Search)(K_Logical_False).Label),
245
To_Wide_String (Message_Table (Op, L, R)));
246
elsif Context (Search)(K_Logical_True).Used and then (L = Static_True or R = Static_True) then
248
To_Wide_String (Context (Search) (K_Logical_True).Label),
251
To_Wide_String (Message_Table (Op, L, R)));
267
-- Always report Count
268
if Context (Count)(K_Logical_False).Used and then (L = Static_False or R = Static_False) then
270
To_Wide_String (Context (Count) (K_Logical_False).Label),
273
To_Wide_String (Message_Table (Op, L, R)));
274
elsif Context (Count)(K_Logical_True).Used and then (L = Static_True or R = Static_True) then
276
To_Wide_String (Context (Count) (K_Logical_True).Label),
279
To_Wide_String (Message_Table (Op, L, R)));
254
-- Always report Count
255
if Context (Count)(K_Logical_False).Used and then (L = Static_False or R = Static_False) then
257
To_Wide_String (Context (Count) (K_Logical_False).Label),
260
To_Wide_String (Message_Table (Op, L, R)));
261
elsif Context (Count)(K_Logical_True).Used and then (L = Static_True or R = Static_True) then
263
To_Wide_String (Context (Count) (K_Logical_True).Label),
266
To_Wide_String (Message_Table (Op, L, R)));
284
272
end Process_Call;
286
274
-------------------
619
617
end Process_Range;
621
------------------------
622
-- Process_Case_Or_If --
623
------------------------
625
procedure Process_Case_Or_If (Stmt : in Asis.Element) is
626
use Asis, Asis.Elements, Asis.Statements, Utilities, Framework.Reports;
628
Expr : Asis.Expression;
629
Message : constant Wide_String := "Unnecessary parentheses in expression of ""if"" or ""case""";
631
if not Rule_Used then
634
Rules_Manager.Enter (Rule_Id);
636
if Statement_Kind (Stmt) = A_Case_Statement then
637
Expr := Case_Expression (Stmt);
638
elsif Path_Kind (Stmt) in An_If_Path .. An_Elsif_Path then
639
Expr := Condition_Expression (Stmt);
641
Failure ("Not a case or if statement");
644
if Expression_Kind (Expr) = A_Parenthesized_Expression then
619
---------------------------
620
-- Process_Parenthesized --
621
---------------------------
623
procedure Process_Parenthesized (Expr : in Asis.Expression) is
624
use Asis, Asis.Elements, Asis.Expressions, Framework.Reports;
626
procedure Do_Report is
627
Message : constant Wide_String := "Unnecessary parentheses in expression";
645
629
if Context (Check)(K_Parentheses).Used then
647
631
To_Wide_String (Context (Check)(K_Parentheses).Label),
651
635
elsif Context (Search)(K_Parentheses).Used then
653
637
To_Wide_String (Context (Search)(K_Parentheses).Label),
661
645
To_Wide_String (Context (Count)(K_Parentheses).Label),
667
end Process_Case_Or_If;
652
type Priority_Level is (Logical, Relational, Adding, Multiplying, Highest, Primary);
653
Priority : constant array (Asis.Operator_Kinds) of Priority_Level
654
:= (Not_An_Operator => Primary,
655
An_And_Operator .. An_Xor_Operator => Logical,
656
An_Equal_Operator .. A_Greater_Than_Or_Equal_Operator => Relational,
657
A_Plus_Operator .. A_Unary_Minus_Operator => Adding,
658
A_Multiply_Operator .. A_Rem_Operator => Multiplying,
659
An_Exponentiate_Operator .. A_Not_Operator => Highest);
661
Enclosing : Asis.Element;
662
Enclosed : Asis.Element;
664
if not Rule_Used then
667
Rules_Manager.Enter (Rule_Id);
669
Enclosing := Enclosing_Element (Expr);
670
if Element_Kind (Enclosing) = An_Association then
671
Enclosing := Enclosing_Element (Enclosing);
674
case Expression_Kind (Enclosing) is
675
when Not_An_Expression
676
| A_Parenthesized_Expression
680
when A_Function_Call =>
681
if Is_Prefix_Call (Enclosing) then
684
Enclosed := Expression_Parenthesized (Expr);
685
case Expression_Kind (Enclosed) is
686
when A_Function_Call =>
687
if Is_Prefix_Call (Enclosed)
688
or else Priority (Operator_Kind (Prefix (Enclosing)))
689
< Priority (Operator_Kind (Prefix (Enclosed)))
693
when An_And_Then_Short_Circuit .. An_Or_Else_Short_Circuit =>
700
when An_And_Then_Short_Circuit
701
| An_Or_Else_Short_Circuit
703
Enclosed := Expression_Parenthesized (Expr);
704
case Expression_Kind (Enclosed) is
705
when An_And_Then_Short_Circuit .. An_Or_Else_Short_Circuit =>
706
if Expression_Kind (Enclosing) = Expression_Kind (Enclosed) then
709
when A_Function_Call =>
710
if Is_Prefix_Call (Enclosed) or else Priority (Operator_Kind (Prefix (Enclosed))) > Logical then
721
end Process_Parenthesized;
670
Framework.Rules_Manager.Register (Rule_Id,
672
Add_Use => Add_Use'Access,
673
Command => Command'Access);
724
Framework.Rules_Manager.Register_Semantic (Rule_Id,
726
Add_Use => Add_Use'Access,
727
Command => Command'Access);
674
728
end Rules.Simplifiable_expressions;