diff mbox

[Ada] Implement new warnings for suspicious mod values

Message ID 20120130121652.GA29702@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet Jan. 30, 2012, 12:16 p.m. UTC
This patch implements additional warnings for suspicious mod values
as shown by the following test program. These warnings are under
control of the warning flag -gnatw.m (on by default).

     1. package susmod is
     2.    type r is mod 2 * 32;
                           |
        >>> warning: suspicious "mod" value, was ** intended?

     3.    H : Integer := 2458;
     4.    J : Integer := H mod 2 * 32;
                                  |
        >>> warning: suspicious "mod" value, was ** intended?

     5. end susmod;

Tested on x86_64-pc-linux-gnu, committed on trunk

2012-01-30  Robert Dewar  <dewar@adacore.com>

	* sem.adb (Analyze): Call Analyze_Mod for N_Op_Mod mode.
	* sem_ch3.adb (Modular_Type_Declaration): Warn on mod value of
	form 2 * small-literal.
	* sem_ch4.adb (Analyze_Mod): New procedure (warn on suspicious
	mod value).
	* sem_ch4.ads (Analyze_Mod): New procedure.
diff mbox

Patch

Index: sem_ch3.adb
===================================================================
--- sem_ch3.adb	(revision 183704)
+++ sem_ch3.adb	(working copy)
@@ -16808,6 +16808,21 @@ 
    --  Start of processing for Modular_Type_Declaration
 
    begin
+      --  If the mod expression is (exactly) 2 * literal, where literal is
+      --  64 or less,then almost certainly the * was meant to be **. Warn!
+
+      if Warn_On_Suspicious_Modulus_Value
+        and then Nkind (Mod_Expr) = N_Op_Multiply
+        and then Nkind (Left_Opnd (Mod_Expr)) = N_Integer_Literal
+        and then Intval (Left_Opnd (Mod_Expr)) = Uint_2
+        and then Nkind (Right_Opnd (Mod_Expr)) = N_Integer_Literal
+        and then Intval (Right_Opnd (Mod_Expr)) <= Uint_64
+      then
+         Error_Msg_N ("suspicious MOD value, was '*'* intended'??", Mod_Expr);
+      end if;
+
+      --  Proceed with analysis of mod expression
+
       Analyze_And_Resolve (Mod_Expr, Any_Integer);
       Set_Etype (T, T);
       Set_Ekind (T, E_Modular_Integer_Type);
Index: sem.adb
===================================================================
--- sem.adb	(revision 183694)
+++ sem.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2011, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2012, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -376,7 +376,7 @@ 
             Analyze_Unary_Op (N);
 
          when N_Op_Mod =>
-            Analyze_Arithmetic_Op (N);
+            Analyze_Mod (N);
 
          when N_Op_Multiply =>
             Analyze_Arithmetic_Op (N);
Index: sem_ch4.adb
===================================================================
--- sem_ch4.adb	(revision 183694)
+++ sem_ch4.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2011, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2012, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -62,6 +62,7 @@ 
 with Sinfo;    use Sinfo;
 with Snames;   use Snames;
 with Tbuild;   use Tbuild;
+with Uintp;    use Uintp;
 
 package body Sem_Ch4 is
 
@@ -2637,6 +2638,34 @@ 
       end if;
    end Analyze_Membership_Op;
 
+   -----------------
+   -- Analyze_Mod --
+   -----------------
+
+   procedure Analyze_Mod (N : Node_Id) is
+   begin
+      --  A special warning check, if we have an expression of the form:
+      --    expr mod 2 * literal
+      --  where literal is 64 or less, then probably what was meant was
+      --    expr mod 2 ** literal
+      --  so issue an appropriate warning.
+
+      if Warn_On_Suspicious_Modulus_Value
+        and then Nkind (Right_Opnd (N)) = N_Integer_Literal
+        and then Intval (Right_Opnd (N)) = Uint_2
+        and then Nkind (Parent (N)) = N_Op_Multiply
+        and then Nkind (Right_Opnd (Parent (N))) = N_Integer_Literal
+        and then Intval (Right_Opnd (Parent (N))) <= Uint_64
+      then
+         Error_Msg_N
+           ("suspicious MOD value, was '*'* intended'??", Parent (N));
+      end if;
+
+      --  Remaining processing is same as for other arithmetic operators
+
+      Analyze_Arithmetic_Op (N);
+   end Analyze_Mod;
+
    ----------------------
    -- Analyze_Negation --
    ----------------------
Index: sem_ch4.ads
===================================================================
--- sem_ch4.ads	(revision 183694)
+++ sem_ch4.ads	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---          Copyright (C) 1992-2011, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2012, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -39,6 +39,7 @@ 
    procedure Analyze_Expression_With_Actions   (N : Node_Id);
    procedure Analyze_Logical_Op                (N : Node_Id);
    procedure Analyze_Membership_Op             (N : Node_Id);
+   procedure Analyze_Mod                       (N : Node_Id);
    procedure Analyze_Negation                  (N : Node_Id);
    procedure Analyze_Null                      (N : Node_Id);
    procedure Analyze_Qualified_Expression      (N : Node_Id);