Patchwork [Ada] Warn for suspicious same range nested loops

login
register
mail settings
Submitter Arnaud Charlet
Date Oct. 29, 2012, 10:08 a.m.
Message ID <20121029100811.GA20982@adacore.com>
Download mbox | patch
Permalink /patch/194933/
State New
Headers show

Comments

Arnaud Charlet - Oct. 29, 2012, 10:08 a.m.
If nested loops appear where the iteration ranges are over the
same range of a multi-dimensional range (where the range number
has been defaulted to 1), then a warning is issued as shown in
the following example:

     1. procedure Warn2D is
     2.    type E is array (Integer range <>, Integer range <>)
     3.      of Integer;
     4.    S : Integer := 0;
     5.    EE : E (1 .. 3, 1 .. 3) := (Others => (Others => 0));
     6. begin
     7.    for J in EE'Range loop
     8.       for K in EE'Range loop
                         |
        >>> warning: inner range same as outer range at line 7

     9.          S := S + EE (J, K);
    10.       end loop;
    11.    end loop;
    12. end Warn2D;

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

2012-10-29  Robert Dewar  <dewar@adacore.com>

	* sem_ch5.adb (Analyze_Loop_Statement): Add warning for identical
	inner/outer ranges.

Patch

Index: sem_ch5.adb
===================================================================
--- sem_ch5.adb	(revision 192908)
+++ sem_ch5.adb	(working copy)
@@ -2626,6 +2626,56 @@ 
       Push_Scope (Ent);
       Analyze_Iteration_Scheme (Iter);
 
+      --  Check for following case which merits a warning if the type E of is
+      --  a multi-dimensional array (and no explicit subscript ranges present).
+
+      --      for J in E'Range
+      --         for K in E'Range
+
+      if Present (Iter)
+        and then Present (Loop_Parameter_Specification (Iter))
+      then
+         declare
+            LPS : constant Node_Id := Loop_Parameter_Specification (Iter);
+            DSD : constant Node_Id :=
+                    Original_Node (Discrete_Subtype_Definition (LPS));
+         begin
+            if Nkind (DSD) = N_Attribute_Reference
+              and then Attribute_Name (DSD) = Name_Range
+              and then No (Expressions (DSD))
+            then
+               declare
+                  Typ : constant Entity_Id := Etype (Prefix (DSD));
+               begin
+                  if Is_Array_Type (Typ)
+                    and then Number_Dimensions (Typ) > 1
+                    and then Nkind (Parent (N)) = N_Loop_Statement
+                    and then Present (Iteration_Scheme (Parent (N)))
+                  then
+                     declare
+                        OIter : constant Node_Id :=
+                          Iteration_Scheme (Parent (N));
+                        OLPS  : constant Node_Id :=
+                          Loop_Parameter_Specification (OIter);
+                        ODSD  : constant Node_Id :=
+                          Original_Node (Discrete_Subtype_Definition (OLPS));
+                     begin
+                        if Nkind (ODSD) = N_Attribute_Reference
+                          and then Attribute_Name (ODSD) = Name_Range
+                          and then No (Expressions (ODSD))
+                          and then Etype (Prefix (ODSD)) = Typ
+                        then
+                           Error_Msg_Sloc := Sloc (ODSD);
+                           Error_Msg_N
+                             ("inner range same as outer range#?", DSD);
+                        end if;
+                     end;
+                  end if;
+               end;
+            end if;
+         end;
+      end if;
+
       --  Analyze the statements of the body except in the case of an Ada 2012
       --  iterator with the expander active. In this case the expander will do
       --  a rewrite of the loop into a while loop. We will then analyze the