A warning is added for if statements which have no else or elsif,
and a then that is a single null statement, and a condition that
has no obvious side effects. The following is compiled with
-gnatwr.d

     1. function WarnOnIf (X : Integer) return Boolean is
     2.    V : Integer with Volatile;
     3.
     4. begin
     5.    V := 32;
     6.
     7.    if True then                     -- warn
           |
        >>> warning: if statement has no effect [-gnatwr]

     8.       null;
     9.    end if;
    10.
    11.    if X > 5 or else X < 3 then      -- warn
           |
        >>> warning: if statement has no effect [-gnatwr]

    12.       null;
    13.    end if;
    14.
    15.    if WarnOnIf (X - 1) then         -- no warn (call)
    16.       null;
    17.    end if;
    18.
    19.    if V > 3 then                    -- no warn (volatile)
    20.       null;
    21.    end if;
    22.
    23.    return False;
    24. end WarnOnIf;

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

2013-10-10  Robert Dewar  <de...@adacore.com>

        * sem_ch5.adb (Analyze_If_Statement): Warn on redundant if
        statement.
        * sem_util.ads, sem_util.adb (Has_No_Obvious_Side_Effects): New
        function.

Index: sem_ch5.adb
===================================================================
--- sem_ch5.adb (revision 203358)
+++ sem_ch5.adb (working copy)
@@ -1577,6 +1577,37 @@
             Remove_Warning_Messages (Then_Statements (N));
          end if;
       end if;
+
+      --  Warn on redundant if statement that has no effect
+
+      if Warn_On_Redundant_Constructs
+
+        --  Condition must not have obvious side effect
+
+        and then Has_No_Obvious_Side_Effects (Condition (N))
+
+        --  No elsif parts of else part
+
+        and then No (Elsif_Parts (N))
+        and then No (Else_Statements (N))
+
+        --  Then must be a single null statement
+
+        and then List_Length (Then_Statements (N)) = 1
+      then
+         --  Go to original node, since we may have rewritten something as
+         --  a null statement (e.g. a case we could figure the outcome of).
+
+         declare
+            T : constant Node_Id := First (Then_Statements (N));
+            S : constant Node_Id := Original_Node (T);
+
+         begin
+            if Comes_From_Source (S) and then Nkind (S) = N_Null_Statement then
+               Error_Msg_N ("if statement has no effect?r?", N);
+            end if;
+         end;
+      end if;
    end Analyze_If_Statement;
 
    ----------------------------------------
Index: sem_util.adb
===================================================================
--- sem_util.adb        (revision 203365)
+++ sem_util.adb        (working copy)
@@ -6456,6 +6456,45 @@
       return False;
    end Has_Interfaces;
 
+   ---------------------------------
+   -- Has_No_Obvious_Side_Effects --
+   ---------------------------------
+
+   function Has_No_Obvious_Side_Effects (N : Node_Id) return Boolean is
+   begin
+      --  For now, just handle literals, constants, and non-volatile
+      --  variables and expressions combining these with operators or
+      --  short circuit forms.
+
+      if Nkind (N) in N_Numeric_Or_String_Literal then
+         return True;
+
+      elsif Nkind (N) = N_Character_Literal then
+         return True;
+
+      elsif Nkind (N) in N_Unary_Op then
+         return Has_No_Obvious_Side_Effects (Right_Opnd (N));
+
+      elsif Nkind (N) in N_Binary_Op or else Nkind (N) in N_Short_Circuit then
+         return Has_No_Obvious_Side_Effects (Left_Opnd (N))
+                   and then
+                Has_No_Obvious_Side_Effects (Right_Opnd (N));
+
+      elsif Nkind (N) in N_Has_Entity then
+         return Present (Entity (N))
+           and then Ekind_In (Entity (N), E_Variable,
+                                          E_Constant,
+                                          E_Enumeration_Literal,
+                                          E_In_Parameter,
+                                          E_Out_Parameter,
+                                          E_In_Out_Parameter)
+           and then not Is_Volatile (Entity (N));
+
+      else
+         return False;
+      end if;
+   end Has_No_Obvious_Side_Effects;
+
    ------------------------
    -- Has_Null_Exclusion --
    ------------------------
Index: sem_util.ads
===================================================================
--- sem_util.ads        (revision 203365)
+++ sem_util.ads        (working copy)
@@ -742,6 +742,17 @@
    --  Use_Full_View controls if the check is done using its full view (if
    --  available).
 
+   function Has_No_Obvious_Side_Effects (N : Node_Id) return Boolean;
+   --  This is a simple minded function for determining whether an expression
+   --  has no obvious side effects. It is used only for determining whether
+   --  warnings are needed in certain situations, and is not guaranteed to
+   --  be accurate in either direction. Exceptions may mean an expression
+   --  does in fact have side effects, but this may be ignored and True is
+   --  returned, or a complex expression may in fact be side effect free
+   --  but we don't recognize it here and return False. The Side_Effect_Free
+   --  routine in Remove_Side_Effects is much more extensive and perhaps could
+   --  be shared, so that this routine would be more accurate.
+
    function Has_Null_Exclusion (N : Node_Id) return Boolean;
    --  Determine whether node N has a null exclusion
 

Reply via email to