[multiple changes]
authorArnaud Charlet <charlet@gcc.gnu.org>
Tue, 2 Aug 2011 13:39:08 +0000 (15:39 +0200)
committerArnaud Charlet <charlet@gcc.gnu.org>
Tue, 2 Aug 2011 13:39:08 +0000 (15:39 +0200)
2011-08-02  Hristian Kirtchev  <kirtchev@adacore.com>

* exp_ch5.adb (Expand_Iterator_Loop): Code cleanup and refactoring.
When a container is provided via a function call, generate a renaming
of the function result. This avoids the creation of a transient scope
and the premature finalization of the container.
* exp_ch7.adb (Is_Container_Cursor): Removed.
(Wrap_Transient_Declaration): Remove the supression of the finalization
of the list controller when the declaration denotes a container cursor,
it is not needed.

2011-08-02  Yannick Moy  <moy@adacore.com>

* restrict.adb (Check_Formal_Restriction): only issue a warning if the
node is from source, instead of the original node being from source.
* sem_aggr.adb
(Resolve_Array_Aggregate): refine the check for a static expression, to
recognize also static ranges
* sem_ch3.adb, sem_ch3.ads (Analyze_Component_Declaration,
Array_Type_Declaration): postpone the test for the type being a subtype
mark after the type has been resolved, so that component-selection and
expanded-name are discriminated.
(Make_Index, Process_Range_Expr_In_Decl): add a parameter In_Iter_Schm
to distinguish the case of an iteration scheme, so that an error is
issed on a non-static range in SPARK except in an iteration scheme.
* sem_ch5.adb (Analyze_Iteration_Scheme): call Make_Index with
In_Iter_Schm = True.
* sem_ch6.adb (Analyze_Subprogram_Specification): refine the check for
user-defined operators so that they are allowed in renaming
* sem_ch8.adb
(Find_Selected_Component): refine the check for prefixing of operators
so that they are allowed in renaming. Move the checks for restrictions
on selector name after analysis discriminated between
component-selection and expanded-name.
* sem_res.adb (Resolve_Op_Concat_Arg): do not issue a warning on
concatenation argument of string type if it is static.
* sem_util.adb, sem_util.ads
(Check_Later_Vs_Basic_Declarations): add a new function
Is_Later_Declarative_Item to decice which declarations are allowed as
later items, in the two different modes Ada 83 and SPARK. In the SPARK
mode, add that renamings are considered as later items.
(Enclosing_Package): new function to return the enclosing package
(Enter_Name): correct the rule for homonyms in SPARK
(Is_SPARK_Initialization_Expr): default to returning True on nodes not
from source (result of expansion) to avoid issuing wrong warnings.

2011-08-02  Ed Schonberg  <schonberg@adacore.com>

* errout.adb: On anything but an expression First_Node returns its
argument.

From-SVN: r177152

14 files changed:
gcc/ada/ChangeLog
gcc/ada/errout.adb
gcc/ada/exp_ch5.adb
gcc/ada/exp_ch7.adb
gcc/ada/restrict.adb
gcc/ada/sem_aggr.adb
gcc/ada/sem_ch3.adb
gcc/ada/sem_ch3.ads
gcc/ada/sem_ch5.adb
gcc/ada/sem_ch6.adb
gcc/ada/sem_ch8.adb
gcc/ada/sem_res.adb
gcc/ada/sem_util.adb
gcc/ada/sem_util.ads

index 79c2ce742daabc6dc7027060206454cf63347339..854196c6398b82fe99befaef62ad5f547a29716c 100644 (file)
@@ -1,3 +1,54 @@
+2011-08-02  Hristian Kirtchev  <kirtchev@adacore.com>
+
+       * exp_ch5.adb (Expand_Iterator_Loop): Code cleanup and refactoring.
+       When a container is provided via a function call, generate a renaming
+       of the function result. This avoids the creation of a transient scope
+       and the premature finalization of the container.
+       * exp_ch7.adb (Is_Container_Cursor): Removed.
+       (Wrap_Transient_Declaration): Remove the supression of the finalization
+       of the list controller when the declaration denotes a container cursor,
+       it is not needed.
+
+2011-08-02  Yannick Moy  <moy@adacore.com>
+
+       * restrict.adb (Check_Formal_Restriction): only issue a warning if the
+       node is from source, instead of the original node being from source.
+       * sem_aggr.adb
+       (Resolve_Array_Aggregate): refine the check for a static expression, to
+       recognize also static ranges
+       * sem_ch3.adb, sem_ch3.ads (Analyze_Component_Declaration,
+       Array_Type_Declaration): postpone the test for the type being a subtype
+       mark after the type has been resolved, so that component-selection and
+       expanded-name are discriminated.
+       (Make_Index, Process_Range_Expr_In_Decl): add a parameter In_Iter_Schm
+       to distinguish the case of an iteration scheme, so that an error is
+       issed on a non-static range in SPARK except in an iteration scheme.
+       * sem_ch5.adb (Analyze_Iteration_Scheme): call Make_Index with
+       In_Iter_Schm = True.
+       * sem_ch6.adb (Analyze_Subprogram_Specification): refine the check for
+       user-defined operators so that they are allowed in renaming
+       * sem_ch8.adb
+       (Find_Selected_Component): refine the check for prefixing of operators
+       so that they are allowed in renaming. Move the checks for restrictions
+       on selector name after analysis discriminated between
+       component-selection and expanded-name.
+       * sem_res.adb (Resolve_Op_Concat_Arg): do not issue a warning on
+       concatenation argument of string type if it is static.
+       * sem_util.adb, sem_util.ads
+       (Check_Later_Vs_Basic_Declarations): add a new function
+       Is_Later_Declarative_Item to decice which declarations are allowed as
+       later items, in the two different modes Ada 83 and SPARK. In the SPARK
+       mode, add that renamings are considered as later items.
+       (Enclosing_Package): new function to return the enclosing package
+       (Enter_Name): correct the rule for homonyms in SPARK
+       (Is_SPARK_Initialization_Expr): default to returning True on nodes not
+       from source (result of expansion) to avoid issuing wrong warnings.
+
+2011-08-02  Ed Schonberg  <schonberg@adacore.com>
+
+       * errout.adb: On anything but an expression First_Node returns its
+       argument.
+
 2011-08-02  Pascal Obry  <obry@adacore.com>
 
        * prj-proc.adb, make.adb, makeutl.adb: Minor reformatting.
index cfe1d038e1a90367d81b38af021df7faa7c29490..06878e8ebb151e1e988cebff4ef32ee444720df6 100644 (file)
@@ -1345,16 +1345,13 @@ package body Errout is
    --  Start of processing for First_Node
 
    begin
-      if Nkind (C) in N_Unit_Body
-        or else Nkind (C) in N_Proper_Body
-      then
-         return C;
-
-      else
+      if Nkind (C) in N_Subexpr then
          Earliest := Original_Node (C);
          Eloc := Sloc (Earliest);
          Search_Tree_First (Original_Node (C));
          return Earliest;
+      else
+         return C;
       end if;
    end First_Node;
 
index de277662978defe5b1736e44187e55669d997fb2..a7b73cda222b1a5722cb81e5b381f1c181b79290 100644 (file)
@@ -2766,106 +2766,104 @@ package body Exp_Ch5 is
    --------------------------
 
    procedure Expand_Iterator_Loop (N : Node_Id) is
-      Loc        : constant Source_Ptr := Sloc (N);
-      Isc        : constant Node_Id    := Iteration_Scheme (N);
-      I_Spec     : constant Node_Id    := Iterator_Specification (Isc);
-      Id         : constant Entity_Id  := Defining_Identifier (I_Spec);
-
-      Container : constant Node_Id := Name (I_Spec);
-      --  An expression whose type is an array or a predefined container
+      Isc    : constant Node_Id    := Iteration_Scheme (N);
+      I_Spec : constant Node_Id    := Iterator_Specification (Isc);
+      Id     : constant Entity_Id  := Defining_Identifier (I_Spec);
+      Loc    : constant Source_Ptr := Sloc (N);
+      Stats  : constant List_Id    := Statements (N);
 
-      Typ : constant Entity_Id  := Etype (Container);
+      Container     : constant Node_Id   := Name (I_Spec);
+      Container_Typ : constant Entity_Id := Etype (Container);
 
       Cursor   : Entity_Id;
       New_Loop : Node_Id;
-      Stats    : List_Id;
 
    begin
-      if Is_Array_Type (Typ) then
+      --  Processing for arrays
+
+      if Is_Array_Type (Container_Typ) then
+
+         --  for Element of Array loop
+         --
+         --  This case requires an internally generated cursor to iterate over
+         --  the array.
+
          if Of_Present (I_Spec) then
             Cursor := Make_Temporary (Loc, 'C');
 
-            --  for Elem of Arr loop ...
+            --  Generate:
+            --    Element : Component_Type renames Container (Cursor);
 
-            declare
-               Decl : constant Node_Id :=
-                        Make_Object_Renaming_Declaration (Loc,
-                          Defining_Identifier => Id,
-                          Subtype_Mark        =>
-                            New_Occurrence_Of (Component_Type (Typ), Loc),
-                          Name                =>
-                            Make_Indexed_Component (Loc,
-                              Prefix      => Relocate_Node (Container),
-                              Expressions =>
-                                New_List (New_Occurrence_Of (Cursor, Loc))));
-            begin
-               Stats := Statements (N);
-               Prepend (Decl, Stats);
+            Prepend_To (Stats,
+              Make_Object_Renaming_Declaration (Loc,
+                Defining_Identifier => Id,
+                Subtype_Mark =>
+                  New_Reference_To (Component_Type (Container_Typ), Loc),
+                Name =>
+                  Make_Indexed_Component (Loc,
+                    Prefix => Relocate_Node (Container),
+                    Expressions => New_List (
+                      New_Reference_To (Cursor, Loc)))));
 
-               New_Loop :=
-                 Make_Loop_Statement (Loc,
-                   Iteration_Scheme =>
-                     Make_Iteration_Scheme (Loc,
-                       Loop_Parameter_Specification =>
-                         Make_Loop_Parameter_Specification (Loc,
-                           Defining_Identifier         => Cursor,
-                           Discrete_Subtype_Definition =>
-                              Make_Attribute_Reference (Loc,
-                                Prefix         => Relocate_Node (Container),
-                                Attribute_Name => Name_Range),
-                           Reverse_Present => Reverse_Present (I_Spec))),
-                   Statements       => Stats,
-                   End_Label        => Empty);
-            end;
+         --  for Index in Array loop
+         --
+         --  This case utilizes the already given cursor name
 
          else
-            --  for Index in Array loop ...
-
-            --  The cursor (index into the array) is the source Id
-
             Cursor := Id;
-            New_Loop :=
-              Make_Loop_Statement (Loc,
-                Iteration_Scheme =>
-                  Make_Iteration_Scheme (Loc,
-                    Loop_Parameter_Specification =>
-                      Make_Loop_Parameter_Specification (Loc,
-                        Defining_Identifier         => Cursor,
-                        Discrete_Subtype_Definition =>
-                           Make_Attribute_Reference (Loc,
-                             Prefix         => Relocate_Node (Container),
-                             Attribute_Name => Name_Range),
-                        Reverse_Present => Reverse_Present (I_Spec))),
-                Statements       => Statements (N),
-                End_Label        => Empty);
          end if;
 
-      --  Iterators over containers
+         --  Generate:
+         --    for Cursor in [reverse] Container'Range loop
+         --       Element : Component_Type renames Container (Cursor);
+         --       --  for the "of" form
+         --
+         --       <original loop statements>
+         --    end loop;
+
+         New_Loop :=
+           Make_Loop_Statement (Loc,
+             Iteration_Scheme =>
+               Make_Iteration_Scheme (Loc,
+                 Loop_Parameter_Specification =>
+                   Make_Loop_Parameter_Specification (Loc,
+                     Defining_Identifier => Cursor,
+                       Discrete_Subtype_Definition =>
+                         Make_Attribute_Reference (Loc,
+                           Prefix => Relocate_Node (Container),
+                           Attribute_Name => Name_Range),
+                      Reverse_Present => Reverse_Present (I_Spec))),
+              Statements => Stats,
+              End_Label  => Empty);
+
+      --  Processing for containers
 
       else
          --  In both cases these require a cursor of the proper type
 
-         --    Cursor : P.Cursor_Type := Container.First;
-         --    while Cursor /= P.No_Element loop
+         --    Cursor : Pack.Cursor := Container.First;
+         --    while Cursor /= Pack.No_Element loop
+         --       Obj : Pack.Element_Type renames Element (Cursor);
+         --       --  for the "of" form
 
-         --       Obj : P.Element_Type renames Element (Cursor);
-         --       --  For the "of" form, the element name renames the element
-         --       --  designated by the cursor.
+         --       <original loop statements>
 
-         --       Statements;
-         --       P.Next (Cursor);
+         --       Pack.Next (Cursor);
          --    end loop;
 
-         --  with the obvious replacements if "reverse" is specified.
+         --  with the obvious replacements if "reverse" is specified. Pack is
+         --  the name of the package which instantiates the container.
 
          declare
             Element_Type : constant Entity_Id := Etype (Id);
-            Pack         : constant Entity_Id := Scope (Base_Type (Typ));
+            Pack         : constant Entity_Id :=
+                             Scope (Base_Type (Container_Typ));
+            Cntr         : Node_Id;
             Name_Init    : Name_Id;
             Name_Step    : Name_Id;
 
          begin
-            Stats := Statements (N);
+            --  The "of" case uses an internally generated cursor
 
             if Of_Present (I_Spec) then
                Cursor := Make_Temporary (Loc, 'C');
@@ -2873,16 +2871,6 @@ package body Exp_Ch5 is
                Cursor := Id;
             end if;
 
-            --  Must verify that the container has a reverse iterator ???
-
-            if Reverse_Present (I_Spec) then
-               Name_Init := Name_Last;
-               Name_Step := Name_Previous;
-            else
-               Name_Init := Name_First;
-               Name_Step := Name_Next;
-            end if;
-
             --  The code below only handles containers where Element is not a
             --  primitive operation of the container. This excludes for now the
             --  Hi-Lite formal containers. Generate:
@@ -2893,33 +2881,52 @@ package body Exp_Ch5 is
                Prepend_To (Stats,
                  Make_Object_Renaming_Declaration (Loc,
                    Defining_Identifier => Id,
-                   Subtype_Mark        =>
+                   Subtype_Mark =>
                      New_Occurrence_Of (Element_Type, Loc),
-                   Name                =>
+                   Name =>
                      Make_Indexed_Component (Loc,
                        Prefix =>
                          Make_Selected_Component (Loc,
-                           Prefix        =>  New_Occurrence_Of (Pack, Loc),
+                           Prefix =>
+                             New_Occurrence_Of (Pack, Loc),
                            Selector_Name =>
                              Make_Identifier (Loc, Chars => Name_Element)),
-                       Expressions =>
-                         New_List (New_Occurrence_Of (Cursor, Loc)))));
+                       Expressions => New_List (
+                         New_Occurrence_Of (Cursor, Loc)))));
+            end if;
+
+            --  Determine the advancement and initialization steps for the
+            --  cursor.
+
+            --  Must verify that the container has a reverse iterator ???
+
+            if Reverse_Present (I_Spec) then
+               Name_Init := Name_Last;
+               Name_Step := Name_Previous;
+            else
+               Name_Init := Name_First;
+               Name_Step := Name_Next;
             end if;
 
-            --  For both iterator forms, add call to step operation (Next or
-            --  Previous) to advance cursor.
+            --  For both iterator forms, add a call to the step operation to
+            --  advance the cursor. Generate:
+            --
+            --    Pack.[Next | Prev] (Cursor);
 
             Append_To (Stats,
               Make_Procedure_Call_Statement (Loc,
                 Name =>
                   Make_Selected_Component (Loc,
-                    Prefix        => New_Occurrence_Of (Pack, Loc),
-                    Selector_Name => Make_Identifier (Loc, Name_Step)),
-                Parameter_Associations =>
-                  New_List (New_Occurrence_Of (Cursor, Loc))));
+                    Prefix =>
+                      New_Occurrence_Of (Pack, Loc),
+                    Selector_Name =>
+                      Make_Identifier (Loc, Name_Step)),
+
+                Parameter_Associations => New_List (
+                  New_Occurrence_Of (Cursor, Loc))));
 
             --  Generate:
-            --    while Cursor /= No_Element loop
+            --    while Cursor /= Pack.No_Element loop
             --       <Stats>
             --    end loop;
 
@@ -2940,30 +2947,53 @@ package body Exp_Ch5 is
                 Statements => Stats,
                 End_Label  => Empty);
 
-            --  When the cursor is internally generated, associate it with the
-            --  loop statement.
+            Cntr := Relocate_Node (Container);
 
-            if Of_Present (I_Spec) then
-               Set_Ekind (Cursor, E_Variable);
-               Set_Related_Expression (Cursor, New_Loop);
+            --  When the container is provided by a function call, create an
+            --  explicit renaming of the function result. Generate:
+            --
+            --    Cnn : Container_Typ renames Func_Call (...);
+            --
+            --  The renaming avoids the generation of a transient scope when
+            --  initializing the cursor and the premature finalization of the
+            --  container.
+
+            if Nkind (Cntr) = N_Function_Call then
+               declare
+                  Ren_Id : constant Entity_Id := Make_Temporary (Loc, 'C');
+
+               begin
+                  Insert_Action (N,
+                    Make_Object_Renaming_Declaration (Loc,
+                      Defining_Identifier => Ren_Id,
+                      Subtype_Mark =>
+                        New_Reference_To (Container_Typ, Loc),
+                      Name => Cntr));
+
+                  Cntr := New_Reference_To (Ren_Id, Loc);
+               end;
             end if;
 
             --  Create the declaration of the cursor and insert it before the
             --  source loop. Generate:
             --
-            --    C : Cursor_Type := Container.First;
+            --    C : Pack.Cursor_Type := Container.[First | Last];
 
             Insert_Action (N,
               Make_Object_Declaration (Loc,
                 Defining_Identifier => Cursor,
-                Object_Definition   =>
+                Object_Definition =>
                   Make_Selected_Component (Loc,
-                    Prefix        => New_Occurrence_Of (Pack, Loc),
-                    Selector_Name => Make_Identifier (Loc, Name_Cursor)),
+                    Prefix =>
+                      New_Occurrence_Of (Pack, Loc),
+                    Selector_Name =>
+                      Make_Identifier (Loc, Name_Cursor)),
+
                 Expression =>
                   Make_Selected_Component (Loc,
-                    Prefix        => Relocate_Node (Container),
-                    Selector_Name => Make_Identifier (Loc, Name_Init))));
+                    Prefix => Cntr,
+                    Selector_Name =>
+                      Make_Identifier (Loc, Name_Init))));
 
             --  If the range of iteration is given by a function call that
             --  returns a container, the finalization actions have been saved
index a344d9318799f1d23c6322e683a074b7435e48bc..4d64b84b2a7314eb858dfa070f8c2b72d3342177 100644 (file)
@@ -3427,36 +3427,6 @@ package body Exp_Ch7 is
       S              : Entity_Id;
       Uses_SS        : Boolean;
 
-      function Is_Container_Cursor (Decl : Node_Id) return Boolean;
-      --  Determine whether object declaration Decl is a cursor used to iterate
-      --  over an Ada 2005/12 container.
-
-      -------------------------
-      -- Is_Container_Cursor --
-      -------------------------
-
-      function Is_Container_Cursor (Decl : Node_Id) return Boolean is
-         Def_Id : constant Entity_Id := Defining_Identifier (Decl);
-         Expr   : constant Node_Id   := Expression (Decl);
-
-      begin
-         --  A cursor declaration appears in the following form:
-         --
-         --    Index : Pack.Cursor := First (...);
-
-         return
-           Chars (Etype (Def_Id)) = Name_Cursor
-             and then Present (Expr)
-             and then Nkind (Expr) = N_Function_Call
-             and then Chars (Name (Expr)) = Name_First
-             and then
-               (Nkind (Parent (Decl)) = N_Expression_With_Actions
-                  or else
-                Nkind (Related_Expression (Def_Id)) = N_Loop_Statement);
-      end Is_Container_Cursor;
-
-   --  Start of processing for Wrap_Transient_Declaration
-
    begin
       S := Current_Scope;
       Enclosing_S := Scope (S);
@@ -3534,27 +3504,6 @@ package body Exp_Ch7 is
          then
             null;
 
-         --  The declaration of a container cursor is a special context where
-         --  the finalization of the list controller needs to be supressed. In
-         --  the following simplified example:
-         --
-         --    LC   : Simple_List_Controller;
-         --    Temp : Ptr_Typ := Container_Creator_Function'Reference;
-         --    Deep_Tag_Attach (Temp, LC);
-         --    Obj  : Pack.Cursor := First (Temp.all);
-         --    Finalize (LC);
-         --    <execute the loop>
-         --
-         --  the finalization of the list controller destroys the contents of
-         --  container Temp, and as a result Obj points to nothing. Note that
-         --  Temp will be finalized by the finalization list of the enclosing
-         --  scope.
-
-         elsif Ada_Version >= Ada_2012
-           and then Is_Container_Cursor (N)
-         then
-            null;
-
          --  Finalize the list controller
 
          else
index 1190f690b215dea2ecc718f69e8f2da234a84016..08af7e688f91f1a3f826db119cfa6d42ce22a28b 100644 (file)
@@ -117,7 +117,7 @@ package body Restrict is
       Msg_Issued          : Boolean;
       Save_Error_Msg_Sloc : Source_Ptr;
    begin
-      if Force or else Comes_From_Source (Original_Node (N)) then
+      if Force or else Comes_From_Source (N) then
 
          --  Since the call to Restriction_Msg from Check_Restriction may set
          --  Error_Msg_Sloc to the location of the pragma restriction, save and
@@ -125,16 +125,16 @@ package body Restrict is
 
          --  ??? N in call to Check_Restriction should be First_Node (N), but
          --  this causes an exception to be raised when analyzing osint.adb.
-         --  To be modified.
+         --  To be modified together with the calls to Error_Msg_N.
 
          Save_Error_Msg_Sloc := Error_Msg_Sloc;
          Check_Restriction (Msg_Issued, SPARK, N);  --  N -> First_Node (N)
          Error_Msg_Sloc := Save_Error_Msg_Sloc;
 
          if Msg_Issued then
-            Error_Msg_F ("\\| " & Msg, N);
+            Error_Msg_N ("\\| " & Msg, N);  --  Error_Msg_N -> Error_Msg_F
          elsif SPARK_Mode then
-            Error_Msg_F ("|~~" & Msg, N);
+            Error_Msg_N ("|~~" & Msg, N);  --  Error_Msg_N -> Error_Msg_F
          end if;
       end if;
    end Check_Formal_Restriction;
@@ -145,7 +145,7 @@ package body Restrict is
    begin
       pragma Assert (Msg2'Length /= 0 and then Msg2 (Msg2'First) = '\');
 
-      if Comes_From_Source (Original_Node (N)) then
+      if Comes_From_Source (N) then
 
          --  Since the call to Restriction_Msg from Check_Restriction may set
          --  Error_Msg_Sloc to the location of the pragma restriction, save and
index d76c35f7d58e271683737446a082d9d0c13d061e..421d04c9f20788c125c4af7f7641fb6397c445de 100644 (file)
@@ -1838,7 +1838,10 @@ package body Sem_Aggr is
 
                      --  In SPARK or ALFA, the choice must be static
 
-                     if not Is_Static_Expression (Choice) then
+                     if not (Is_Static_Expression (Choice)
+                              or else (Nkind (Choice) = N_Range
+                                        and then Is_Static_Range (Choice)))
+                     then
                         Check_Formal_Restriction
                           ("choice should be static", Choice);
                      end if;
index 16a6b7dc77f872b4d0f95232863906d1f87660f6..1884d03cb1076bdf1e74740b086957815acfe256 100644 (file)
@@ -1782,13 +1782,13 @@ package body Sem_Ch3 is
       Enter_Name (Id);
 
       if Present (Typ) then
+         T := Find_Type_Of_Object
+                (Subtype_Indication (Component_Definition (N)), N);
+
          if not Nkind_In (Typ, N_Identifier, N_Expanded_Name) then
             Check_Formal_Restriction ("subtype mark required", Typ);
          end if;
 
-         T := Find_Type_Of_Object
-                (Subtype_Indication (Component_Definition (N)), N);
-
       --  Ada 2005 (AI-230): Access Definition case
 
       else
@@ -4597,12 +4597,12 @@ package body Sem_Ch3 is
 
       Nb_Index := 1;
       while Present (Index) loop
+         Analyze (Index);
+
          if not Nkind_In (Index, N_Identifier, N_Expanded_Name) then
             Check_Formal_Restriction ("subtype mark required", Index);
          end if;
 
-         Analyze (Index);
-
          --  Add a subtype declaration for each index of private array type
          --  declaration whose etype is also private. For example:
 
@@ -4672,12 +4672,12 @@ package body Sem_Ch3 is
       --  Process subtype indication if one is present
 
       if Present (Component_Typ) then
+         Element_Type := Process_Subtype (Component_Typ, P, Related_Id, 'C');
+
          if not Nkind_In (Component_Typ, N_Identifier, N_Expanded_Name) then
             Check_Formal_Restriction ("subtype mark required", Component_Typ);
          end if;
 
-         Element_Type := Process_Subtype (Component_Typ, P, Related_Id, 'C');
-
       --  Ada 2005 (AI-230): Access Definition case
 
       else pragma Assert (Present (Access_Definition (Component_Def)));
@@ -16140,7 +16140,8 @@ package body Sem_Ch3 is
      (I            : Node_Id;
       Related_Nod  : Node_Id;
       Related_Id   : Entity_Id := Empty;
-      Suffix_Index : Nat := 1)
+      Suffix_Index : Nat := 1;
+      In_Iter_Schm : Boolean := False)
    is
       R      : Node_Id;
       T      : Entity_Id;
@@ -16252,7 +16253,7 @@ package body Sem_Ch3 is
          end if;
 
          R := I;
-         Process_Range_Expr_In_Decl (R, T);
+         Process_Range_Expr_In_Decl (R, T, In_Iter_Schm => In_Iter_Schm);
 
       elsif Nkind (I) = N_Subtype_Indication then
 
@@ -16269,7 +16270,8 @@ package body Sem_Ch3 is
          R := Range_Expression (Constraint (I));
 
          Resolve (R, T);
-         Process_Range_Expr_In_Decl (R, Entity (Subtype_Mark (I)));
+         Process_Range_Expr_In_Decl
+           (R, Entity (Subtype_Mark (I)), In_Iter_Schm => In_Iter_Schm);
 
       elsif Nkind (I) = N_Attribute_Reference then
 
@@ -17908,10 +17910,11 @@ package body Sem_Ch3 is
    --------------------------------
 
    procedure Process_Range_Expr_In_Decl
-     (R           : Node_Id;
-      T           : Entity_Id;
-      Check_List  : List_Id := Empty_List;
-      R_Check_Off : Boolean := False)
+     (R            : Node_Id;
+      T            : Entity_Id;
+      Check_List   : List_Id := Empty_List;
+      R_Check_Off  : Boolean := False;
+      In_Iter_Schm : Boolean := False)
    is
       Lo, Hi      : Node_Id;
       R_Checks    : Check_Result;
@@ -17922,7 +17925,13 @@ package body Sem_Ch3 is
       Analyze_And_Resolve (R, Base_Type (T));
 
       if Nkind (R) = N_Range then
-         if not Is_Static_Range (R) then
+
+         --  In SPARK/ALFA, all ranges should be static, with the exception of
+         --  the discrete type definition of a loop parameter specification.
+
+         if not In_Iter_Schm
+           and then not Is_Static_Range (R)
+         then
             Check_Formal_Restriction ("range should be static", R);
          end if;
 
index 7888a3200b0125fc196ef48851bd4090bd1126d6..514cdf3f0f9b6fe30f1da616de714c5881e6591b 100644 (file)
@@ -192,14 +192,17 @@ package Sem_Ch3 is
      (I            : Node_Id;
       Related_Nod  : Node_Id;
       Related_Id   : Entity_Id := Empty;
-      Suffix_Index : Nat := 1);
+      Suffix_Index : Nat := 1;
+      In_Iter_Schm : Boolean := False);
    --  Process an index that is given in an array declaration, an entry
    --  family declaration or a loop iteration. The index is given by an
    --  index declaration (a 'box'), or by a discrete range. The later can
    --  be the name of a discrete type, or a subtype indication.
    --
    --  Related_Nod is the node where the potential generated implicit types
-   --  will be inserted. The 2 last parameters are used for creating the name.
+   --  will be inserted. The next last parameters are used for creating the
+   --  name. In_Iter_Schm is True if Make_Index is called on the discrete
+   --  subtype definition in an iteration scheme.
 
    procedure Make_Class_Wide_Type (T : Entity_Id);
    --  A Class_Wide_Type is created for each tagged type definition. The
@@ -251,10 +254,11 @@ package Sem_Ch3 is
    --    Priv_T is the private view of the type whose full declaration is in N.
 
    procedure Process_Range_Expr_In_Decl
-     (R           : Node_Id;
-      T           : Entity_Id;
-      Check_List  : List_Id := Empty_List;
-      R_Check_Off : Boolean := False);
+     (R            : Node_Id;
+      T            : Entity_Id;
+      Check_List   : List_Id := Empty_List;
+      R_Check_Off  : Boolean := False;
+      In_Iter_Schm : Boolean := False);
    --  Process a range expression that appears in a declaration context. The
    --  range is analyzed and resolved with the base type of the given type, and
    --  an appropriate check for expressions in non-static contexts made on the
@@ -265,7 +269,8 @@ package Sem_Ch3 is
    --  when the subprogram is called from Build_Record_Init_Proc and is used to
    --  return a set of constraint checking statements generated by the Checks
    --  package. R_Check_Off is set to True when the call to Range_Check is to
-   --  be skipped.
+   --  be skipped. In_Iter_Schm is True if Process_Range_Expr_In_Decl is called
+   --  on the discrete subtype definition in an iteration scheme.
 
    function Process_Subtype
      (S           : Node_Id;
index 4c92b6ed0b9c63eb7136a6015b948bd35c985ed4..7dd2e89c799c995c441d1e6094da0212d5e1f2a1 100644 (file)
@@ -2060,7 +2060,7 @@ package body Sem_Ch5 is
 
                Check_Controlled_Array_Attribute (DS);
 
-               Make_Index (DS, LP);
+               Make_Index (DS, LP, In_Iter_Schm => True);
 
                Set_Ekind (Id, E_Loop_Parameter);
 
index 97f57a93353d060edb7ce5d8846225fe6b51d8c9..186664673f295a97fcfa49c47b4ec889276f9c1c 100644 (file)
@@ -3073,9 +3073,12 @@ package body Sem_Ch6 is
    --  Start of processing for Analyze_Subprogram_Specification
 
    begin
-      --  User-defined operator is not allowed in SPARK or ALFA
+      --  User-defined operator is not allowed in SPARK or ALFA, except as
+      --  a renaming.
 
-      if Nkind (Defining_Unit_Name (N)) = N_Defining_Operator_Symbol then
+      if Nkind (Defining_Unit_Name (N)) = N_Defining_Operator_Symbol
+        and then Nkind (Parent (N)) /= N_Subprogram_Renaming_Declaration
+      then
          Check_Formal_Restriction ("user-defined operator is not allowed", N);
       end if;
 
index a07449c009736b1c1768e38c8a1102f9f0da708f..90da2a64aab161dd9087c4aa7ca28d3cd162e55f 100644 (file)
@@ -5348,13 +5348,15 @@ package body Sem_Ch8 is
       end if;
 
       --  Selector name cannot be a character literal or an operator symbol in
-      --  SPARK.
+      --  SPARK, except for the operator symbol in a renaming.
 
       if SPARK_Mode or else Restriction_Check_Required (SPARK) then
          if Nkind (Selector_Name (N)) = N_Character_Literal then
             Check_Formal_Restriction
               ("character literal cannot be prefixed", N);
-         elsif Nkind (Selector_Name (N)) = N_Operator_Symbol then
+         elsif Nkind (Selector_Name (N)) = N_Operator_Symbol
+           and then Nkind (Parent (N)) /= N_Subprogram_Renaming_Declaration
+         then
             Check_Formal_Restriction ("operator symbol cannot be prefixed", N);
          end if;
       end if;
@@ -5485,18 +5487,6 @@ package body Sem_Ch8 is
       elsif Is_Entity_Name (P) then
          P_Name := Entity (P);
 
-         --  Selector name is restricted in SPARK
-
-         if SPARK_Mode or else Restriction_Check_Required (SPARK) then
-            if Is_Subprogram (P_Name) then
-               Check_Formal_Restriction
-                 ("prefix of expanded name cannot be a subprogram", P);
-            elsif Ekind (P_Name) = E_Loop then
-               Check_Formal_Restriction
-                 ("prefix of expanded name cannot be a loop statement", P);
-            end if;
-         end if;
-
          --  The prefix may denote an enclosing type which is the completion
          --  of an incomplete type declaration.
 
@@ -5693,6 +5683,20 @@ package body Sem_Ch8 is
             end if;
          end if;
 
+         --  Selector name is restricted in SPARK
+
+         if Nkind (N) = N_Expanded_Name
+           and then (SPARK_Mode or else Restriction_Check_Required (SPARK))
+         then
+            if Is_Subprogram (P_Name) then
+               Check_Formal_Restriction
+                 ("prefix of expanded name cannot be a subprogram", P);
+            elsif Ekind (P_Name) = E_Loop then
+               Check_Formal_Restriction
+                 ("prefix of expanded name cannot be a loop statement", P);
+            end if;
+         end if;
+
       else
          --  If prefix is not the name of an entity, it must be an expression,
          --  whose type is appropriate for a record. This is determined by
index f32e05274516e0e281d956586fb7459de4911da5..3f778c3a809b145d4820b293e68c0035d1adbf43 100644 (file)
@@ -6786,6 +6786,8 @@ package body Sem_Res is
          if Is_Array_Type (T)
            and then Base_Type (T) /= Standard_String
            and then Base_Type (Etype (L)) = Base_Type (Etype (R))
+           and then Etype (L) /= Any_Composite  --  or else L in error
+           and then Etype (R) /= Any_Composite  --  or else R in error
            and then not Matching_Static_Array_Bounds (Etype (L), Etype (R))
          then
             Check_Formal_Restriction
@@ -7322,17 +7324,21 @@ package body Sem_Res is
       --  bounds. Of course the types have to match, so only check if operands
       --  are compatible and the node itself has no errors.
 
-      if Is_Array_Type (B_Typ)
-        and then Nkind (N) in N_Binary_Op
-        and then
-          Base_Type (Etype (Left_Opnd (N)))
-            = Base_Type (Etype (Right_Opnd (N)))
-        and then not Matching_Static_Array_Bounds (Etype (Left_Opnd (N)),
-                                                   Etype (Right_Opnd (N)))
-      then
-         Check_Formal_Restriction
-           ("array types should have matching static bounds", N);
-      end if;
+      declare
+         Left_Typ  : constant Node_Id := Etype (Left_Opnd (N));
+         Right_Typ : constant Node_Id := Etype (Right_Opnd (N));
+      begin
+         if Is_Array_Type (B_Typ)
+           and then Nkind (N) in N_Binary_Op
+           and then Base_Type (Left_Typ) = Base_Type (Right_Typ)
+           and then Left_Typ /= Any_Composite  --  or else Left_Opnd in error
+           and then Right_Typ /= Any_Composite  --  or else Right_Opnd in error
+           and then not Matching_Static_Array_Bounds (Left_Typ, Right_Typ)
+         then
+            Check_Formal_Restriction
+              ("array types should have matching static bounds", N);
+         end if;
+      end;
 
    end Resolve_Logical_Op;
 
@@ -7702,9 +7708,9 @@ package body Sem_Res is
          end if;
 
       elsif Is_String_Type (Etype (Arg)) then
-         if Nkind (Arg) /= N_String_Literal then
+         if not Is_Static_Expression (Arg) then
             Check_Formal_Restriction
-              ("string operand for concatenation should be a literal", N);
+              ("string operand for concatenation should be static", N);
          end if;
 
       --  Do not issue error on an operand that is neither a character nor a
@@ -7984,6 +7990,7 @@ package body Sem_Res is
 
       if Is_Array_Type (Target_Typ)
         and then Is_Array_Type (Etype (Expr))
+        and then Etype (Expr) /= Any_Composite  --  or else Expr in error
         and then not Matching_Static_Array_Bounds (Target_Typ, Etype (Expr))
       then
          Check_Formal_Restriction
@@ -9109,6 +9116,7 @@ package body Sem_Res is
 
       if Is_Array_Type (Target_Typ)
         and then Is_Array_Type (Operand_Typ)
+        and then Operand_Typ /= Any_Composite  --  or else Operand in error
         and then not Matching_Static_Array_Bounds (Target_Typ, Operand_Typ)
       then
          Check_Formal_Restriction
index a16c06a7113db97f6af6b3f625272b7fbdbdd0bf..5239f5dd104efbef50111f5bf80cf101f6e53925 100644 (file)
@@ -1111,6 +1111,45 @@ package body Sem_Util is
    is
       Body_Sloc : Source_Ptr;
       Decl      : Node_Id;
+
+      function Is_Later_Declarative_Item (Decl : Node_Id) return Boolean;
+      --  Return whether Decl is considered as a declarative item.
+      --  When During_Parsing is True, the semantics of Ada 83 is followed.
+      --  When During_Parsing is False, the semantics of SPARK is followed.
+
+      -------------------------------
+      -- Is_Later_Declarative_Item --
+      -------------------------------
+
+      function Is_Later_Declarative_Item (Decl : Node_Id) return Boolean is
+      begin
+         if Nkind (Decl) in N_Later_Decl_Item then
+            return True;
+
+         elsif Nkind (Decl) = N_Pragma then
+            return True;
+
+         elsif During_Parsing then
+            return False;
+
+         --  In SPARK, a package declaration is not considered as a later
+         --  declarative item.
+
+         elsif Nkind (Decl) = N_Package_Declaration then
+            return False;
+
+         --  In SPARK, a renaming is considered as a later declarative item
+
+         elsif Nkind (Decl) in N_Renaming_Declaration then
+            return True;
+
+         else
+            return False;
+         end if;
+      end Is_Later_Declarative_Item;
+
+   --  Start of Check_Later_Vs_Basic_Declarations
+
    begin
       Decl := First (Decls);
 
@@ -1131,12 +1170,7 @@ package body Sem_Util is
             Body_Sloc := Sloc (Decl);
 
             Inner : while Present (Decl) loop
-               if (Nkind (Decl) not in N_Later_Decl_Item
-                    or else (not During_Parsing
-                              and then
-                                Nkind (Decl) = N_Package_Declaration))
-                 and then Nkind (Decl) /= N_Pragma
-               then
+               if not Is_Later_Declarative_Item (Decl) then
                   if During_Parsing then
                      if Ada_Version = Ada_83 then
                         Error_Msg_Sloc := Body_Sloc;
@@ -2896,6 +2930,30 @@ package body Sem_Util is
       return Current_Node;
    end Enclosing_Lib_Unit_Node;
 
+   -----------------------
+   -- Enclosing_Package --
+   -----------------------
+
+   function Enclosing_Package (E : Entity_Id) return Entity_Id is
+      Dynamic_Scope : constant Entity_Id := Enclosing_Dynamic_Scope (E);
+
+   begin
+      if Dynamic_Scope = Standard_Standard then
+         return Standard_Standard;
+
+      elsif Dynamic_Scope = Empty then
+         return Empty;
+
+      elsif Ekind_In (Dynamic_Scope, E_Package, E_Package_Body,
+                      E_Generic_Package)
+      then
+         return Dynamic_Scope;
+
+      else
+         return Enclosing_Package (Dynamic_Scope);
+      end if;
+   end Enclosing_Package;
+
    --------------------------
    -- Enclosing_Subprogram --
    --------------------------
@@ -3260,38 +3318,51 @@ package body Sem_Util is
       --  Declaring a homonym is not allowed in SPARK or ALFA ...
 
       if Present (C)
+        and then (Restriction_Check_Required (SPARK)
+                   or else Formal_Verification_Mode)
+      then
 
-        --  ... unless the new declaration is in a subprogram, and the visible
-        --  declaration is a variable declaration or a parameter specification
-        --  outside that subprogram.
+         declare
+            Enclosing_Subp : constant Node_Id := Enclosing_Subprogram (Def_Id);
+            Enclosing_Pack : constant Node_Id := Enclosing_Package (Def_Id);
+            Other_Scope    : constant Node_Id := Enclosing_Dynamic_Scope (C);
+         begin
 
-        and then not
-          (Nkind_In (Parent (Parent (Def_Id)), N_Subprogram_Body,
-                                               N_Function_Specification,
-                                               N_Procedure_Specification)
-           and then
-             Nkind_In (Parent (C), N_Object_Declaration,
-                                   N_Parameter_Specification))
+            --  ... unless the new declaration is in a subprogram, and the
+            --  visible declaration is a variable declaration or a parameter
+            --  specification outside that subprogram.
 
-        --  ... or the new declaration is in a package, and the visible
-        --  declaration occurs outside that package.
+            if Present (Enclosing_Subp)
+              and then Nkind_In (Parent (C), N_Object_Declaration,
+                                 N_Parameter_Specification)
+              and then not Scope_Within_Or_Same (Other_Scope, Enclosing_Subp)
+            then
+               null;
 
-        and then not
-          Nkind_In (Parent (Parent (Def_Id)), N_Package_Specification,
-                                              N_Package_Body)
+            --  ... or the new declaration is in a package, and the visible
+            --  declaration occurs outside that package.
 
-        --  ... or the new declaration is a component declaration in a record
-        --  type definition.
+            elsif Present (Enclosing_Pack)
+              and then not Scope_Within_Or_Same (Other_Scope, Enclosing_Pack)
+            then
+               null;
 
-        and then Nkind (Parent (Def_Id)) /= N_Component_Declaration
+            --  ... or the new declaration is a component declaration in a
+            --  record type definition.
 
-        --  Don't issue error for non-source entities
+            elsif Nkind (Parent (Def_Id)) = N_Component_Declaration then
+               null;
 
-        and then Comes_From_Source (Def_Id)
-        and then Comes_From_Source (C)
-      then
-         Error_Msg_Sloc := Sloc (C);
-         Check_Formal_Restriction ("redeclaration of identifier &#", Def_Id);
+            --  Don't issue error for non-source entities
+
+            elsif Comes_From_Source (Def_Id)
+              and then Comes_From_Source (C)
+            then
+               Error_Msg_Sloc := Sloc (C);
+               Check_Formal_Restriction
+                 ("redeclaration of identifier &#", Def_Id);
+            end if;
+         end;
       end if;
 
       --  Warn if new entity hides an old one
@@ -7432,23 +7503,25 @@ package body Sem_Util is
       Is_Ok     : Boolean;
       Expr      : Node_Id;
       Comp_Assn : Node_Id;
-      Choice    : Node_Id;
 
    begin
       Is_Ok := True;
 
+      if not Comes_From_Source (N) then
+         goto Done;
+      end if;
+
       pragma Assert (Nkind (N) in N_Subexpr);
 
       case Nkind (N) is
          when N_Character_Literal |
               N_Integer_Literal   |
               N_Real_Literal      |
-              N_String_Literal    |
-              N_Expanded_Name     |
-              N_Membership_Test   =>
+              N_String_Literal    =>
             null;
 
-         when N_Identifier =>
+         when N_Identifier    |
+              N_Expanded_Name =>
             if Is_Entity_Name (N)
               and then Present (Entity (N))  --  needed in some cases
             then
@@ -7459,7 +7532,11 @@ package body Sem_Util is
                        E_Named_Real          =>
                      null;
                   when others =>
-                     Is_Ok := False;
+                     if Is_Type (Entity (N)) then
+                        null;
+                     else
+                        Is_Ok := False;
+                     end if;
                end case;
             end if;
 
@@ -7470,7 +7547,9 @@ package body Sem_Util is
          when N_Unary_Op =>
             Is_Ok := Is_SPARK_Initialization_Expr (Right_Opnd (N));
 
-         when N_Binary_Op | N_Short_Circuit =>
+         when N_Binary_Op       |
+              N_Short_Circuit   |
+              N_Membership_Test =>
             Is_Ok := Is_SPARK_Initialization_Expr (Left_Opnd (N))
               and then Is_SPARK_Initialization_Expr (Right_Opnd (N));
 
@@ -7492,18 +7571,6 @@ package body Sem_Util is
 
             Comp_Assn := First (Component_Associations (N));
             while Present (Comp_Assn) loop
-               Choice := First (Choices (Comp_Assn));
-               while Present (Choice) loop
-                  if Nkind (Choice) in N_Subexpr
-                    and then not Is_SPARK_Initialization_Expr (Choice)
-                  then
-                     Is_Ok := False;
-                     goto Done;
-                  end if;
-
-                  Next (Choice);
-               end loop;
-
                Expr := Expression (Comp_Assn);
                if Present (Expr)  --  needed for box association
                  and then not Is_SPARK_Initialization_Expr (Expr)
@@ -7530,6 +7597,12 @@ package body Sem_Util is
                Next (Expr);
             end loop;
 
+         --  Selected components might be expanded named not yet resolved, so
+         --  default on the safe side. (Eg on sparklex.ads)
+
+         when N_Selected_Component =>
+            null;
+
          when others =>
             Is_Ok := False;
       end case;
index c52b68a507e3c4a61cf0cfe22443371c066c3c0d..aeb35571be1b4846489af1a39c08b599c884310f 100644 (file)
@@ -339,6 +339,10 @@ package Sem_Util is
    --  Returns the enclosing N_Compilation_Unit Node that is the root of a
    --  subtree containing N.
 
+   function Enclosing_Package (E : Entity_Id) return Entity_Id;
+   --  Utility function to return the Ada entity of the package enclosing
+   --  the entity E, if any. Returns Empty if no enclosing package.
+
    function Enclosing_Subprogram (E : Entity_Id) return Entity_Id;
    --  Utility function to return the Ada entity of the subprogram enclosing
    --  the entity E, if any. Returns Empty if no enclosing subprogram.