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