2007-08-14 Robert Dewar <dewar@adacore.com>
authorcharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 14 Aug 2007 08:41:15 +0000 (08:41 +0000)
committercharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 14 Aug 2007 08:41:15 +0000 (08:41 +0000)
    Ed Schonberg  <schonberg@adacore.com>

* sem_ch5.adb: Improve warnings on redundant assignments

* sem_util.ads, sem_util.adb: (Is_Variable): Add defense against junk
parameter
(Is_Synchronized_Tagged_Type): New subprogram that returns true
in case of synchronized tagged types (AARM 3.9.4 (6/2)).
(Safe_To_Capture_Value): Can now return True for constants, even if Cond
is set to False. Improves handling of Known_[Not_]Null.
(Wrong_Type): Special case address arithmetic attempt
(Collect_Abstract_Interfaces): Add new formal to allow collecting
abstract interfaces just using the partial view of private types.
(Has_Abstract_Interfaces): Add new formal to allow checking types
covering interfaces using the partial view of private types.
(Is_Fully_Initialized_Type): Special VM case for uTag component. This
component still needs to be defined in this case, but is never
initialized as VMs are using other dispatching mechanisms.
(Abstract_Interface_List): For a protected type, use base type to get
proper declaration.
Improve warnings on redundant assignments
(Is_Variable): Handle properly an implicit dereference of a prefixed
function call.
(Build_Actual_Subtype): If this is an actual subtype for an
unconstrained formal parameter, use the sloc of the body for the new
declaration, to prevent anomalises in the debugger.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@127427 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ada/sem_ch5.adb
gcc/ada/sem_util.adb
gcc/ada/sem_util.ads

index 5df476b..abc3d82 100644 (file)
@@ -250,7 +250,8 @@ package body Sem_Ch5 is
    --  Start of processing for Analyze_Assignment
 
    begin
-      Mark_Static_Coextensions (Rhs);
+      Mark_Coextensions (N, Rhs);
+
       Analyze (Rhs);
       Analyze (Lhs);
 
@@ -579,10 +580,10 @@ package body Sem_Ch5 is
         and then Can_Never_Be_Null (T1)
         and then not Assignment_OK (Lhs)
       then
-         if Nkind (Rhs) = N_Null then
+         if Known_Null (Rhs) then
             Apply_Compile_Time_Constraint_Error
               (N   => Rhs,
-               Msg => "(Ada 2005) NULL not allowed in null-excluding objects?",
+               Msg => "(Ada 2005) null not allowed in null-excluding objects?",
                Reason => CE_Null_Not_Allowed);
             return;
 
@@ -640,11 +641,9 @@ package body Sem_Ch5 is
 
          and then Comes_From_Source (N)
 
-         --  Where the entity is the same on both sides
+         --  Where the object is the same on both sides
 
-         and then Is_Entity_Name (Lhs)
-         and then Is_Entity_Name (Original_Node (Rhs))
-         and then Entity (Lhs) = Entity (Original_Node (Rhs))
+         and then Same_Object (Lhs, Original_Node (Rhs))
 
          --  But exclude the case where the right side was an operation
          --  that got rewritten (e.g. JUNK + K, where K was known to be
@@ -654,8 +653,13 @@ package body Sem_Ch5 is
 
         and then Nkind (Original_Node (Rhs)) not in N_Op
       then
-         Error_Msg_NE
-           ("?useless assignment of & to itself", N, Entity (Lhs));
+         if Nkind (Lhs) in N_Has_Entity then
+            Error_Msg_NE
+              ("?useless assignment of & to itself!", N, Entity (Lhs));
+         else
+            Error_Msg_N
+              ("?useless assignment of object to itself!", N);
+         end if;
       end if;
 
       --  Check for non-allowed composite assignment
@@ -1071,7 +1075,6 @@ package body Sem_Ch5 is
 
          begin
             Alt := First (Alternatives (N));
-
             while Present (Alt) loop
                if Alt /= Chosen then
                   Remove_Warning_Messages (Statements (Alt));
@@ -1341,7 +1344,6 @@ package body Sem_Ch5 is
 
             if Present (Elsif_Parts (N)) then
                E := First (Elsif_Parts (N));
-
                while Present (E) loop
                   Remove_Warning_Messages (Then_Statements (E));
                   Next (E);
@@ -2035,7 +2037,7 @@ package body Sem_Ch5 is
                --  the Ada RM annoyingly requires a useless return here!
 
                if Nkind (Original_Node (N)) /= N_Raise_Statement
-                 or else Nkind (Nxt) /= N_Return_Statement
+                 or else Nkind (Nxt) /= N_Simple_Return_Statement
                then
                   --  The rather strange shenanigans with the warning message
                   --  here reflects the fact that Kill_Dead_Code is very good
@@ -2077,7 +2079,7 @@ package body Sem_Ch5 is
 
                   --  Now issue the warning
 
-                  Error_Msg ("?unreachable code", Error_Loc);
+                  Error_Msg ("?unreachable code!", Error_Loc);
                end if;
 
             --  If the unconditional transfer of control instruction is
index 2e61802..04fe93c 100644 (file)
@@ -37,7 +37,6 @@ with Freeze;   use Freeze;
 with Lib;      use Lib;
 with Lib.Xref; use Lib.Xref;
 with Nlists;   use Nlists;
-with Nmake;    use Nmake;
 with Output;   use Output;
 with Opt;      use Opt;
 with Rtsfind;  use Rtsfind;
@@ -63,6 +62,8 @@ with Uname;    use Uname;
 
 package body Sem_Util is
 
+   use Nmake;
+
    -----------------------
    -- Local Subprograms --
    -----------------------
@@ -94,7 +95,13 @@ package body Sem_Util is
 
    begin
       if Is_Concurrent_Type (Typ) then
-         Nod := Parent (Typ);
+
+         --  If we are dealing with a synchronized subtype, go to the base
+         --  type, whose declaration has the interface list.
+
+         --  Shouldn't this be Declaration_Node???
+
+         Nod := Parent (Base_Type (Typ));
 
       elsif Ekind (Typ) = E_Record_Type_With_Private then
          if Nkind (Parent (Typ)) = N_Full_Type_Declaration then
@@ -245,7 +252,9 @@ package body Sem_Util is
      (T : Entity_Id;
       N : Node_Or_Entity_Id) return Node_Id
    is
-      Loc         : constant Source_Ptr := Sloc (N);
+      Loc : Source_Ptr;
+      --  Normally Sloc (N), but may point to corresponding body in some cases
+
       Constraints : List_Id;
       Decl        : Node_Id;
       Discr       : Entity_Id;
@@ -256,8 +265,28 @@ package body Sem_Util is
       Obj         : Node_Id;
 
    begin
+      Loc := Sloc (N);
+
       if Nkind (N) = N_Defining_Identifier then
          Obj := New_Reference_To (N, Loc);
+
+         --  If this is a formal parameter of a subprogram declaration, and
+         --  we are compiling the body, we want the declaration for the
+         --  actual subtype to carry the source position of the body, to
+         --  prevent anomalies in gdb when stepping through the code.
+
+         if Is_Formal (N) then
+            declare
+               Decl : constant Node_Id := Unit_Declaration_Node (Scope (N));
+            begin
+               if Nkind (Decl) = N_Subprogram_Declaration
+                 and then Present (Corresponding_Body (Decl))
+               then
+                  Loc := Sloc (Corresponding_Body (Decl));
+               end if;
+            end;
+         end if;
+
       else
          Obj := N;
       end if;
@@ -1082,7 +1111,8 @@ package body Sem_Util is
    procedure Collect_Abstract_Interfaces
      (T                         : Entity_Id;
       Ifaces_List               : out Elist_Id;
-      Exclude_Parent_Interfaces : Boolean := False)
+      Exclude_Parent_Interfaces : Boolean := False;
+      Use_Full_View             : Boolean := True)
    is
       procedure Add_Interface (Iface : Entity_Id);
       --  Add the interface it if is not already in the list
@@ -1121,20 +1151,34 @@ package body Sem_Util is
       -------------
 
       procedure Collect (Typ : Entity_Id) is
-         Iface_List : constant List_Id := Abstract_Interface_List (Typ);
          Ancestor   : Entity_Id;
+         Full_T     : Entity_Id;
+         Iface_List : List_Id;
          Id         : Node_Id;
          Iface      : Entity_Id;
 
       begin
+         Full_T := Typ;
+
+         --  Handle private types
+
+         if Use_Full_View
+           and then Is_Private_Type (Typ)
+           and then Present (Full_View (Typ))
+         then
+            Full_T := Full_View (Typ);
+         end if;
+
+         Iface_List := Abstract_Interface_List (Full_T);
+
          --  Include the ancestor if we are generating the whole list of
          --  abstract interfaces.
 
          --  In concurrent types the ancestor interface (if any) is the
          --  first element of the list of interface types.
 
-         if Is_Concurrent_Type (Typ)
-           or else Is_Concurrent_Record_Type (Typ)
+         if Is_Concurrent_Type (Full_T)
+           or else Is_Concurrent_Record_Type (Full_T)
          then
             if Is_Non_Empty_List (Iface_List) then
                Ancestor := Etype (First (Iface_List));
@@ -1145,7 +1189,7 @@ package body Sem_Util is
                end if;
             end if;
 
-         elsif Etype (Typ) /= Typ
+         elsif Etype (Full_T) /= Typ
 
             --  Protect the frontend against wrong sources. For example:
 
@@ -1158,9 +1202,9 @@ package body Sem_Util is
             --      type C is new B with null record;
             --    end P;
 
-           and then Etype (Typ) /= T
+           and then Etype (Full_T) /= T
          then
-            Ancestor := Etype (Typ);
+            Ancestor := Etype (Full_T);
             Collect (Ancestor);
 
             if Is_Interface (Ancestor)
@@ -1179,8 +1223,8 @@ package body Sem_Util is
             --  first element of the list of interface types and we have
             --  already processed them while climbing to the root type.
 
-            if Is_Concurrent_Type (Typ)
-              or else Is_Concurrent_Record_Type (Typ)
+            if Is_Concurrent_Type (Full_T)
+              or else Is_Concurrent_Record_Type (Full_T)
             then
                Next (Id);
             end if;
@@ -1303,6 +1347,94 @@ package body Sem_Util is
       Collect (Tagged_Type);
    end Collect_Interface_Components;
 
+   -----------------------------
+   -- Collect_Interfaces_Info --
+   -----------------------------
+
+   procedure Collect_Interfaces_Info
+     (T               : Entity_Id;
+      Ifaces_List     : out Elist_Id;
+      Components_List : out Elist_Id;
+      Tags_List       : out Elist_Id)
+   is
+      Comps_List : Elist_Id;
+      Comp_Elmt  : Elmt_Id;
+      Comp_Iface : Entity_Id;
+      Iface_Elmt : Elmt_Id;
+      Iface      : Entity_Id;
+
+      function Search_Tag (Iface : Entity_Id) return Entity_Id;
+      --  Search for the secondary tag associated with the interface type
+      --  Iface that is implemented by T.
+
+      ----------------
+      -- Search_Tag --
+      ----------------
+
+      function Search_Tag (Iface : Entity_Id) return Entity_Id is
+         ADT : Elmt_Id;
+
+      begin
+         ADT := Next_Elmt (First_Elmt (Access_Disp_Table (T)));
+         while Present (ADT)
+            and then Ekind (Node (ADT)) = E_Constant
+            and then Related_Interface (Node (ADT)) /= Iface
+         loop
+            Next_Elmt (ADT);
+         end loop;
+
+         pragma Assert (Ekind (Node (ADT)) = E_Constant);
+         return Node (ADT);
+      end Search_Tag;
+
+   --  Start of processing for Collect_Interfaces_Info
+
+   begin
+      Collect_Abstract_Interfaces  (T, Ifaces_List);
+      Collect_Interface_Components (T, Comps_List);
+
+      --  Search for the record component and tag associated with each
+      --  interface type of T.
+
+      Components_List := New_Elmt_List;
+      Tags_List       := New_Elmt_List;
+
+      Iface_Elmt := First_Elmt (Ifaces_List);
+      while Present (Iface_Elmt) loop
+         Iface := Node (Iface_Elmt);
+
+         --  Associate the primary tag component and the primary dispatch table
+         --  with all the interfaces that are parents of T
+
+         if Is_Parent (Iface, T) then
+            Append_Elmt (First_Tag_Component (T), Components_List);
+            Append_Elmt (Node (First_Elmt (Access_Disp_Table (T))), Tags_List);
+
+         --  Otherwise search for the tag component and secondary dispatch
+         --  table of Iface
+
+         else
+            Comp_Elmt := First_Elmt (Comps_List);
+            while Present (Comp_Elmt) loop
+               Comp_Iface := Related_Interface (Node (Comp_Elmt));
+
+               if Comp_Iface = Iface
+                 or else Is_Parent (Iface, Comp_Iface)
+               then
+                  Append_Elmt (Node (Comp_Elmt), Components_List);
+                  Append_Elmt (Search_Tag (Comp_Iface), Tags_List);
+                  exit;
+               end if;
+
+               Next_Elmt (Comp_Elmt);
+            end loop;
+            pragma Assert (Present (Comp_Elmt));
+         end if;
+
+         Next_Elmt (Iface_Elmt);
+      end loop;
+   end Collect_Interfaces_Info;
+
    ----------------------------------
    -- Collect_Primitive_Operations --
    ----------------------------------
@@ -1449,6 +1581,8 @@ package body Sem_Util is
       Warn : Boolean    := False) return Node_Id
    is
       Msgc : String (1 .. Msg'Length + 2);
+      --  Copy of message, with room for possible ? and ! at end
+
       Msgl : Natural;
       Wmsg : Boolean;
       P    : Node_Id;
@@ -1471,11 +1605,8 @@ package body Sem_Util is
             Eloc := Sloc (N);
          end if;
 
-         --  Make all such messages unconditional
-
          Msgc (1 .. Msg'Length) := Msg;
-         Msgc (Msg'Length + 1) := '!';
-         Msgl := Msg'Length + 1;
+         Msgl := Msg'Length;
 
          --  Message is a warning, even in Ada 95 case
 
@@ -1499,9 +1630,15 @@ package body Sem_Util is
             Wmsg := True;
 
          --  Otherwise we have a real error message (Ada 95 static case)
+         --  and we make this an unconditional message. Note that in the
+         --  warning case we do not make the message unconditional, it seems
+         --  quite reasonable to delete messages like this (about exceptions
+         --  that will be raised) in dead code.
 
          else
             Wmsg := False;
+            Msgl := Msgl + 1;
+            Msgc (Msgl) := '!';
          end if;
 
          --  Should we generate a warning? The answer is not quite yes. The
@@ -2549,7 +2686,7 @@ package body Sem_Util is
      (Def_Id      : Entity_Id;
       First_Hom   : Entity_Id;
       Ifaces_List : Elist_Id;
-      In_Scope    : Boolean := True) return Entity_Id
+      In_Scope    : Boolean) return Entity_Id
    is
       Candidate : Entity_Id := Empty;
       Hom       : Entity_Id := Empty;
@@ -2823,7 +2960,7 @@ package body Sem_Util is
 
       --  After examining all candidates for overriding, we are left with
       --  the best match which is a mode incompatible interface routine.
-      --  Do not emit an error of the Expander is active since this error
+      --  Do not emit an error if the Expander is active since this error
       --  will be detected later on after all concurrent types are expanded
       --  and all wrappers are built. This check is meant for spec-only
       --  compilations.
@@ -2833,23 +2970,26 @@ package body Sem_Util is
       then
          Iface_Typ := Find_Parameter_Type (Parent (First_Formal (Candidate)));
 
-         --  Def_Id is primitive of a protected type, the candidate is
-         --  primitive of a limited or synchronized interface.
+         --  Def_Id is primitive of a protected type, declared inside the type,
+         --  and the candidate is primitive of a limited or synchronized
+         --  interface.
 
-         if Is_Protected_Type (Tag_Typ)
+         if In_Scope
+           and then Is_Protected_Type (Tag_Typ)
            and then
              (Is_Limited_Interface (Iface_Typ)
                 or else Is_Protected_Interface (Iface_Typ)
                 or else Is_Synchronized_Interface (Iface_Typ)
                 or else Is_Task_Interface (Iface_Typ))
          then
+            --  Must reword this message, comma before to in -gnatj mode ???
+
             Error_Msg_NE
               ("first formal of & must be of mode `OUT`, `IN OUT` or " &
                "access-to-variable", Tag_Typ, Candidate);
-
             Error_Msg_N
               ("\to be overridden by protected procedure or entry " &
-               "(`R`M 9.4(11))", Tag_Typ);
+               "(RM 9.4(11.9/2))", Tag_Typ);
          end if;
       end if;
 
@@ -3630,7 +3770,10 @@ package body Sem_Util is
    -- Has_Abstract_Interfaces --
    -----------------------------
 
-   function Has_Abstract_Interfaces (Tagged_Type : Entity_Id) return Boolean is
+   function Has_Abstract_Interfaces
+     (Tagged_Type   : Entity_Id;
+      Use_Full_View : Boolean := True) return Boolean
+   is
       Typ : Entity_Id;
 
    begin
@@ -3645,19 +3788,22 @@ package body Sem_Util is
          return True;
       end if;
 
+      Typ := Tagged_Type;
+
       --  Handle private types
 
-      if Present (Full_View (Tagged_Type)) then
+      if Use_Full_View
+        and then Present (Full_View (Tagged_Type))
+      then
          Typ := Full_View (Tagged_Type);
-      else
-         Typ := Tagged_Type;
       end if;
 
       loop
          if Is_Interface (Typ)
-           or else (Present (Abstract_Interfaces (Typ))
-                      and then
-                        not Is_Empty_Elmt_List (Abstract_Interfaces (Typ)))
+           or else
+             (Is_Record_Type (Typ)
+               and then Present (Abstract_Interfaces (Typ))
+               and then not Is_Empty_Elmt_List (Abstract_Interfaces (Typ)))
          then
             return True;
          end if;
@@ -4276,7 +4422,7 @@ package body Sem_Util is
                   --  Or if expression obeys rules for preelaboration. For
                   --  now we approximate this by testing if the default
                   --  expression is a static expression or if it is an
-                  --  access attribute reference.
+                  --  access attribute reference, or the literal null.
 
                   --  This is an approximation, it is probably incomplete???
 
@@ -4292,6 +4438,9 @@ package body Sem_Util is
                then
                   null;
 
+               elsif Nkind (Exp) = N_Null then
+                  null;
+
                else
                   Has_PE := False;
                   exit;
@@ -5020,7 +5169,7 @@ package body Sem_Util is
          --  Anonymous access discriminants carry a list of all nested
          --  controlled coextensions.
 
-          and then not Is_Coextension (N)
+          and then not Is_Dynamic_Coextension (N)
           and then not Is_Static_Coextension (N);
    end Is_Coextension_Root;
 
@@ -5361,7 +5510,7 @@ package body Sem_Util is
                         Indx_Typ := Full_View (Indx_Typ);
                      end if;
 
-                     if No (Indx_Typ) then
+                     if No (Indx_Typ) or else Etype (Indx_Typ) = Any_Type then
                         return False;
                      else
                         Lbd := Type_Low_Bound  (Indx_Typ);
@@ -5449,6 +5598,14 @@ package body Sem_Util is
                  and then (No (Parent (Ent))
                              or else No (Expression (Parent (Ent))))
                  and then not Is_Fully_Initialized_Type (Etype (Ent))
+
+                  --  Special VM case for uTag component, which needs to be
+                  --  defined in this case, but is never initialized as VMs
+                  --  are using other dispatching mechanisms. Ignore this
+                  --  uninitialized case.
+
+                 and then (VM_Target = No_VM
+                            or else Chars (Ent) /= Name_uTag)
                then
                   return False;
                end if;
@@ -5593,10 +5750,10 @@ package body Sem_Util is
 
    function Is_Library_Level_Entity (E : Entity_Id) return Boolean is
    begin
-      --  The following is a small optimization, and it also handles
-      --  properly discriminals, which in task bodies might appear in
-      --  expressions before the corresponding procedure has been
-      --  created, and which therefore do not have an assigned scope.
+      --  The following is a small optimization, and it also properly handles
+      --  discriminals, which in task bodies might appear in expressions before
+      --  the corresponding procedure has been created, and which therefore do
+      --  not have an assigned scope.
 
       if Ekind (E) in Formal_Kind then
          return False;
@@ -5640,7 +5797,7 @@ package body Sem_Util is
    function Is_Object_Reference (N : Node_Id) return Boolean is
    begin
       if Is_Entity_Name (N) then
-         return Is_Object (Entity (N));
+         return Present (Entity (N)) and then Is_Object (Entity (N));
 
       else
          case Nkind (N) is
@@ -6233,6 +6390,31 @@ package body Sem_Util is
           or else Nkind (N) = N_Procedure_Call_Statement;
    end Is_Statement;
 
+   ---------------------------------
+   -- Is_Synchronized_Tagged_Type --
+   ---------------------------------
+
+   function Is_Synchronized_Tagged_Type (E : Entity_Id) return Boolean is
+      Kind : constant Entity_Kind := Ekind (Base_Type (E));
+
+   begin
+      --  A task or protected type derived from an interface is a tagged type.
+      --  Such a tagged type is called a synchronized tagged type, as are
+      --  synchronized interfaces and private extensions whose declaration
+      --  includes the reserved word synchronized.
+
+      return (Is_Tagged_Type (E)
+                and then (Kind = E_Task_Type
+                           or else Kind = E_Protected_Type))
+            or else
+             (Is_Interface (E)
+                and then Is_Synchronized_Interface (E))
+            or else
+             (Ekind (E) = E_Record_Type_With_Private
+                and then (Synchronized_Present (Parent (E))
+                           or else Is_Synchronized_Interface (Etype (E))));
+   end Is_Synchronized_Tagged_Type;
+
    -----------------
    -- Is_Transfer --
    -----------------
@@ -6241,7 +6423,7 @@ package body Sem_Util is
       Kind : constant Node_Kind := Nkind (N);
 
    begin
-      if Kind = N_Return_Statement
+      if Kind = N_Simple_Return_Statement
            or else
          Kind = N_Extended_Return_Statement
            or else
@@ -6384,12 +6566,19 @@ package body Sem_Util is
       --  variable, even though the original node may not be (since it could
       --  be a constant of the access type).
 
+      --  In Ada 2005 we have a further case to consider: the prefix may be
+      --  a function call given in prefix notation. The original node appears
+      --  to be a selected component, but we need to examine the call.
+
       elsif Nkind (N) = N_Explicit_Dereference
         and then Nkind (Orig_Node) /= N_Explicit_Dereference
         and then Present (Etype (Orig_Node))
         and then Is_Access_Type (Etype (Orig_Node))
       then
-         return Is_Variable_Prefix (Original_Node (Prefix (N)));
+         return Is_Variable_Prefix (Original_Node (Prefix (N)))
+           or else
+             (Nkind (Orig_Node) = N_Function_Call
+               and then not Is_Access_Constant (Etype (Prefix (N))));
 
       --  A function call is never a variable
 
@@ -6398,7 +6587,9 @@ package body Sem_Util is
 
       --  All remaining checks use the original node
 
-      elsif Is_Entity_Name (Orig_Node) then
+      elsif Is_Entity_Name (Orig_Node)
+        and then Present (Entity (Orig_Node))
+      then
          declare
             E : constant Entity_Id := Entity (Orig_Node);
             K : constant Entity_Kind := Ekind (E);
@@ -6782,7 +6973,7 @@ package body Sem_Util is
 
          when N_Attribute_Reference =>
             return N = Prefix (P)
-              and then Name_Modifies_Prefix (Attribute_Name (P));
+              and then Name_Implies_Lvalue_Prefix (Attribute_Name (P));
 
          when N_Expanded_Name        |
               N_Explicit_Dereference |
@@ -6897,13 +7088,15 @@ package body Sem_Util is
       end case;
    end May_Be_Lvalue;
 
-   ------------------------------
-   -- Mark_Static_Coextensions --
-   ------------------------------
+   -----------------------
+   -- Mark_Coextensions --
+   -----------------------
+
+   procedure Mark_Coextensions (Context_Nod : Node_Id; Root_Nod : Node_Id) is
+      Is_Dynamic : Boolean := False;
 
-   procedure Mark_Static_Coextensions (Root_Node : Node_Id) is
       function Mark_Allocator (N : Node_Id) return Traverse_Result;
-      --  Recognize an allocator node and label it as a static coextension
+      --  Recognize an allocator node and label it as a dynamic coextension
 
       --------------------
       -- Mark_Allocator --
@@ -6912,7 +7105,11 @@ package body Sem_Util is
       function Mark_Allocator (N : Node_Id) return Traverse_Result is
       begin
          if Nkind (N) = N_Allocator then
-            Set_Is_Static_Coextension (N);
+            if Is_Dynamic then
+               Set_Is_Dynamic_Coextension (N);
+            else
+               Set_Is_Static_Coextension (N);
+            end if;
          end if;
 
          return OK;
@@ -6920,16 +7117,26 @@ package body Sem_Util is
 
       procedure Mark_Allocators is new Traverse_Proc (Mark_Allocator);
 
-   --  Start of processing for Mark_Static_Coextensions
+   --  Start of processing Mark_Coextensions
 
    begin
-      --  Do not mark allocators that stem from an initial allocator because
-      --  these will never be static.
+      case Nkind (Context_Nod) is
+         when N_Assignment_Statement    |
+              N_Simple_Return_Statement =>
+            Is_Dynamic := Nkind (Expression (Context_Nod)) = N_Allocator;
 
-      if Nkind (Root_Node) /= N_Allocator then
-         Mark_Allocators (Root_Node);
-      end if;
-   end Mark_Static_Coextensions;
+         when N_Object_Declaration =>
+            Is_Dynamic := Nkind (Root_Nod) = N_Allocator;
+
+         --  This routine should not be called for constructs which may not
+         --  contain coextensions.
+
+         when others =>
+            raise Program_Error;
+      end case;
+
+      Mark_Allocators (Root_Nod);
+   end Mark_Coextensions;
 
    ----------------------
    -- Needs_One_Actual --
@@ -7082,7 +7289,7 @@ package body Sem_Util is
       Success : out Boolean)
    is
       Actuals     : constant List_Id := Parameter_Associations (N);
-      Actual      : Node_Id   := Empty;
+      Actual      : Node_Id := Empty;
       Formal      : Entity_Id;
       Last        : Node_Id := Empty;
       First_Named : Node_Id := Empty;
@@ -8089,26 +8296,30 @@ package body Sem_Util is
       Cond : Boolean := False) return Boolean
    is
    begin
-      --  The only entities for which we track constant values are variables,
-      --  which are not renamings, out parameters and in out parameters, so
-      --  check if we have this case.
+      --  The only entities for which we track constant values are variables
+      --  which are not renamings, constants, out parameters, and in out
+      --  parameters, so check if we have this case.
+
+      --  Note: it may seem odd to track constant values for constants, but in
+      --  fact this routine is used for other purposes than simply capturing
+      --  the value. In particular, the setting of Known[_Non]_Null.
 
       if (Ekind (Ent) = E_Variable and then No (Renamed_Object (Ent)))
-           or else
-         Ekind (Ent) = E_Out_Parameter
-           or else
-         Ekind (Ent) = E_In_Out_Parameter
+            or else
+          Ekind (Ent) = E_Constant
+            or else
+          Ekind (Ent) = E_Out_Parameter
+            or else
+          Ekind (Ent) = E_In_Out_Parameter
       then
          null;
 
-      --  For conditionals, we also allow constants, loop parameters and all
-      --  formals, including in parameters.
+      --  For conditionals, we also allow loop parameters and all formals,
+      --  including in parameters.
 
       elsif Cond
         and then
-          (Ekind (Ent) = E_Constant
-             or else
-           Ekind (Ent) = E_Loop_Parameter
+          (Ekind (Ent) = E_Loop_Parameter
              or else
            Ekind (Ent) = E_In_Parameter)
       then
@@ -8122,10 +8333,9 @@ package body Sem_Util is
          return False;
       end if;
 
-      --  Skip volatile and aliased variables, since funny things might
-      --  be going on in these cases which we cannot necessarily track.
-      --  Also skip any variable for which an address clause is given,
-      --  or whose address is taken
+      --  Skip if volatile or aliased, since funny things might be going on in
+      --  these cases which we cannot necessarily track. Also skip any variable
+      --  for which an address clause is given, or whose address is taken.
 
       if Treat_As_Volatile (Ent)
         or else Is_Aliased (Ent)
@@ -8135,9 +8345,9 @@ package body Sem_Util is
          return False;
       end if;
 
-      --  OK, all above conditions are met. We also require that the scope
-      --  of the reference be the same as the scope of the entity, not
-      --  counting packages and blocks and loops.
+      --  OK, all above conditions are met. We also require that the scope of
+      --  the reference be the same as the scope of the entity, not counting
+      --  packages and blocks and loops.
 
       declare
          E_Scope : constant Entity_Id := Scope (Ent);
@@ -8227,6 +8437,84 @@ package body Sem_Util is
       end if;
    end Same_Name;
 
+   -----------------
+   -- Same_Object --
+   -----------------
+
+   function Same_Object (Node1, Node2 : Node_Id) return Boolean is
+      N1 : constant Node_Id := Original_Node (Node1);
+      N2 : constant Node_Id := Original_Node (Node2);
+      --  We do the tests on original nodes, since we are most interested
+      --  in the original source, not any expansion that got in the way.
+
+      K1 : constant Node_Kind := Nkind (N1);
+      K2 : constant Node_Kind := Nkind (N2);
+
+   begin
+      --  First case, both are entities with same entity
+
+      if K1 in N_Has_Entity
+        and then K2 in N_Has_Entity
+        and then Present (Entity (N1))
+        and then Present (Entity (N2))
+        and then (Ekind (Entity (N1)) = E_Variable
+                    or else
+                  Ekind (Entity (N1)) = E_Constant)
+        and then Entity (N1) = Entity (N2)
+      then
+         return True;
+
+      --  Second case, selected component with same selector, same record
+
+      elsif K1 = N_Selected_Component
+        and then K2 = N_Selected_Component
+        and then Chars (Selector_Name (N1)) = Chars (Selector_Name (N2))
+      then
+         return Same_Object (Prefix (N1), Prefix (N2));
+
+      --  Third case, indexed component with same subscripts, same array
+
+      elsif K1 = N_Indexed_Component
+        and then K2 = N_Indexed_Component
+        and then Same_Object (Prefix (N1), Prefix (N2))
+      then
+         declare
+            E1, E2 : Node_Id;
+         begin
+            E1 := First (Expressions (N1));
+            E2 := First (Expressions (N2));
+            while Present (E1) loop
+               if not Same_Value (E1, E2) then
+                  return False;
+               else
+                  Next (E1);
+                  Next (E2);
+               end if;
+            end loop;
+
+            return True;
+         end;
+
+      --  Fourth case, slice of same array with same bounds
+
+      elsif K1 = N_Slice
+        and then K2 = N_Slice
+        and then Nkind (Discrete_Range (N1)) = N_Range
+        and then Nkind (Discrete_Range (N2)) = N_Range
+        and then Same_Value (Low_Bound (Discrete_Range (N1)),
+                             Low_Bound (Discrete_Range (N2)))
+        and then Same_Value (High_Bound (Discrete_Range (N1)),
+                             High_Bound (Discrete_Range (N2)))
+      then
+         return Same_Name (Prefix (N1), Prefix (N2));
+
+      --  All other cases, not clearly the same object
+
+      else
+         return False;
+      end if;
+   end Same_Object;
+
    ---------------
    -- Same_Type --
    ---------------
@@ -8251,6 +8539,24 @@ package body Sem_Util is
       end if;
    end Same_Type;
 
+   ----------------
+   -- Same_Value --
+   ----------------
+
+   function Same_Value (Node1, Node2 : Node_Id) return Boolean is
+   begin
+      if Compile_Time_Known_Value (Node1)
+        and then Compile_Time_Known_Value (Node2)
+        and then Expr_Value (Node1) = Expr_Value (Node2)
+      then
+         return True;
+      elsif Same_Object (Node1, Node2) then
+         return True;
+      else
+         return False;
+      end if;
+   end Same_Value;
+
    ------------------------
    -- Scope_Is_Transient --
    ------------------------
@@ -8886,7 +9192,6 @@ package body Sem_Util is
       --  There is no simple way to insure that it is consistent ???
 
       elsif In_Instance then
-
          if Etype (Etype (Expr)) = Etype (Expected_Type)
            and then
              (Has_Private_Declaration (Expected_Type)
@@ -8924,6 +9229,29 @@ package body Sem_Util is
          Error_Msg_N ("result must be general access type!", Expr);
          Error_Msg_NE ("add ALL to }!", Expr, Expec_Type);
 
+      --  Another special check, if the expected type is an integer type,
+      --  but the expression is of type System.Address, and the parent is
+      --  an addition or subtraction operation whose left operand is the
+      --  expression in question and whose right operand is of an integral
+      --  type, then this is an attempt at address arithmetic, so give
+      --  appropriate message.
+
+      elsif Is_Integer_Type (Expec_Type)
+        and then Is_RTE (Found_Type, RE_Address)
+        and then (Nkind (Parent (Expr)) = N_Op_Add
+                    or else
+                  Nkind (Parent (Expr)) = N_Op_Subtract)
+        and then Expr = Left_Opnd (Parent (Expr))
+        and then Is_Integer_Type (Etype (Right_Opnd (Parent (Expr))))
+      then
+         Error_Msg_N
+           ("address arithmetic not predefined in package System",
+            Parent (Expr));
+         Error_Msg_N
+           ("\possible missing with/use of System.Storage_Elements",
+            Parent (Expr));
+         return;
+
       --  If the expected type is an anonymous access type, as for access
       --  parameters and discriminants, the error is on the designated types.
 
index 0a89132..42cd17d 100644 (file)
@@ -28,6 +28,7 @@
 
 with Einfo;  use Einfo;
 with Namet;  use Namet;
+with Nmake;
 with Types;  use Types;
 with Uintp;  use Uintp;
 with Urealp; use Urealp;
@@ -147,10 +148,13 @@ package Sem_Util is
    procedure Collect_Abstract_Interfaces
      (T                         : Entity_Id;
       Ifaces_List               : out Elist_Id;
-      Exclude_Parent_Interfaces : Boolean := False);
+      Exclude_Parent_Interfaces : Boolean := False;
+      Use_Full_View             : Boolean := True);
    --  Ada 2005 (AI-251): Collect whole list of abstract interfaces that are
    --  directly or indirectly implemented by T. Exclude_Parent_Interfaces is
    --  used to avoid addition of inherited interfaces to the generated list.
+   --  Use_Full_View is used to collect the interfaces using the full-view
+   --  (if available).
 
    procedure Collect_Interface_Components
      (Tagged_Type     : Entity_Id;
@@ -158,6 +162,17 @@ package Sem_Util is
    --  Ada 2005 (AI-251): Collect all the tag components associated with the
    --  secondary dispatch tables of a tagged type.
 
+   procedure Collect_Interfaces_Info
+     (T               : Entity_Id;
+      Ifaces_List     : out Elist_Id;
+      Components_List : out Elist_Id;
+      Tags_List       : out Elist_Id);
+   --  Ada 2005 (AI-251): Collect all the interfaces associated with T plus
+   --  the record component and tag associated with each of these interfaces.
+   --  On exit Ifaces_List, Components_List and Tags_List have the same number
+   --  of elements, and elements at the same position on these tables provide
+   --  information on the same interface type.
+
    function Collect_Primitive_Operations (T : Entity_Id) return Elist_Id;
    --  Called upon type derivation and extension. We scan the declarative
    --  part in  which the type appears, and collect subprograms that have
@@ -282,7 +297,7 @@ package Sem_Util is
      (Def_Id      : Entity_Id;
       First_Hom   : Entity_Id;
       Ifaces_List : Elist_Id;
-      In_Scope    : Boolean := True) return Entity_Id;
+      In_Scope    : Boolean) return Entity_Id;
    --  Determine whether entry or subprogram Def_Id overrides a primitive
    --  operation that belongs to one of the interfaces in Ifaces_List. A
    --  specific homonym chain can be specified by setting First_Hom. Flag
@@ -443,8 +458,12 @@ package Sem_Util is
    --  Result of Has_Compatible_Alignment test, description found below. Note
    --  that the values are arranged in increasing order of problematicness.
 
-   function Has_Abstract_Interfaces (Tagged_Type : Entity_Id) return Boolean;
-   --  Returns true if Tagged_Type implements some abstract interface
+   function Has_Abstract_Interfaces
+     (Tagged_Type   : Entity_Id;
+      Use_Full_View : Boolean := True) return Boolean;
+   --  Returns true if Tagged_Type implements some abstract interface. In case
+   --  private types the argument Use_Full_View controls if the check is done
+   --  using its full view (if available).
 
    function Has_Compatible_Alignment
      (Obj  : Entity_Id;
@@ -689,6 +708,9 @@ package Sem_Util is
    --  the N_Statement_Other_Than_Procedure_Call subtype from Sinfo).
    --  Note that a label is *not* a statement, and will return False.
 
+   function Is_Synchronized_Tagged_Type (E : Entity_Id) return Boolean;
+   --  Returns True if E is a synchronized tagged type (AARM 3.9.4 (6/2))
+
    function Is_Transfer (N : Node_Id) return Boolean;
    --  Returns True if the node N is a statement which is known to cause
    --  an unconditional transfer of control at runtime, i.e. the following
@@ -723,17 +745,16 @@ package Sem_Util is
    procedure Kill_Current_Values;
    --  This procedure is called to clear all constant indications from all
    --  entities in the current scope and in any parent scopes if the current
-   --  scope is a block or a package (and that recursion continues to the
-   --  top scope that is not a block or a package). This is used when the
-   --  sequential flow-of-control assumption is violated (occurence of a
-   --  label, head of a loop, or start of an exception handler). The effect
-   --  of the call is to clear the Constant_Value field (but we do not need
-   --  to clear the Is_True_Constant flag, since that only gets reset if
-   --  there really is an assignment somewhere in the entity scope). This
-   --  procedure also calls Kill_All_Checks, since this is a special case
-   --  of needing to forget saved values. This procedure also clears any
-   --  Is_Known_Non_Null flags in variables, constants or parameters
-   --  since these are also not known to be valid.
+   --  scope is a block or a package (and that recursion continues to the top
+   --  scope that is not a block or a package). This is used when the
+   --  sequential flow-of-control assumption is violated (occurence of a label,
+   --  head of a loop, or start of an exception handler). The effect of the
+   --  call is to clear the Constant_Value field (but we do not need to clear
+   --  the Is_True_Constant flag, since that only gets reset if there really is
+   --  an assignment somewhere in the entity scope). This procedure also calls
+   --  Kill_All_Checks, since this is a special case of needing to forget saved
+   --  values. This procedure also clears Is_Known_Non_Null flags in variables,
+   --  constants or parameters since these are also not known to be valid.
 
    procedure Kill_Current_Values (Ent : Entity_Id);
    --  This performs the same processing as described above for the form with
@@ -753,10 +774,27 @@ package Sem_Util is
    --  direction. Cases which may possibly be assignments but are not known to
    --  be may return True from May_Be_Lvalue, but False from this function.
 
-   procedure Mark_Static_Coextensions (Root_Node : Node_Id);
-   --  Perform a tree traversal starting from Root_Node while marking every
-   --  allocator as a static coextension. Cleanup for this action is performed
-   --  in Resolve_Allocator.
+   function Make_Simple_Return_Statement
+     (Sloc       : Source_Ptr;
+      Expression : Node_Id := Empty) return Node_Id
+     renames Nmake.Make_Return_Statement;
+   --  See Sinfo. We rename Make_Return_Statement to the correct Ada 2005
+   --  terminology here. Clients should use Make_Simple_Return_Statement.
+
+   Make_Return_Statement : constant := -2 ** 33;
+   --  Attempt to prevent accidental uses of Make_Return_Statement. If this
+   --  and the one in Nmake are both potentially use-visible, it will cause
+   --  a compilation error. Note that type and value are irrelevant.
+
+   N_Return_Statement : constant := -2**33;
+   --  Attempt to prevent accidental uses of N_Return_Statement; similar to
+   --  Make_Return_Statement above.
+
+   procedure Mark_Coextensions (Context_Nod : Node_Id; Root_Nod : Node_Id);
+   --  Given a node which designates the context of analysis and an origin in
+   --  the tree, traverse from Root_Nod and mark all allocators as either
+   --  dynamic or static depending on Context_Nod. Any erroneous marking is
+   --  cleaned up during resolution.
 
    function May_Be_Lvalue (N : Node_Id) return Boolean;
    --  Determines if N could be an lvalue (e.g. an assignment left hand side).
@@ -911,7 +949,15 @@ package Sem_Util is
    --  capture actual value information, but we can capture conditional tests.
 
    function Same_Name (N1, N2 : Node_Id) return Boolean;
-   --  Determine if two (possibly expanded) names are the same name
+   --  Determine if two (possibly expanded) names are the same name. This is
+   --  a purely syntactic test, and N1 and N2 need not be analyzed.
+
+   function Same_Object (Node1, Node2 : Node_Id) return Boolean;
+   --  Determine if Node1 and Node2 are known to designate the same object.
+   --  This is a semantic test and both nodesmust be fully analyzed. A result
+   --  of True is decisively correct. A result of False does not necessarily
+   --  mean that different objects are designated, just that this could not
+   --  be reliably determined at compile time.
 
    function Same_Type (T1, T2 : Entity_Id) return Boolean;
    --  Determines if T1 and T2 represent exactly the same type. Two types
@@ -922,6 +968,13 @@ package Sem_Util is
    --  False is indecisive (e.g. the compiler may not be able to tell that
    --  two constraints are identical).
 
+   function Same_Value (Node1, Node2 : Node_Id) return Boolean;
+   --  Determines if Node1 and Node2 are known to be the same value, which is
+   --  true if they are both compile time known values and have the same value,
+   --  or if they are the same object (in the sense of function Same_Object).
+   --  A result of False does not necessarily mean they have different values,
+   --  just that it is not possible to determine they have the same value.
+
    function Scope_Within_Or_Same (Scope1, Scope2 : Entity_Id) return Boolean;
    --  Determines if the entity Scope1 is the same as Scope2, or if it is
    --  inside it, where both entities represent scopes. Note that scopes
@@ -967,7 +1020,7 @@ package Sem_Util is
    --  value from T2 to T1. It does NOT copy the RM_Size field, which must be
    --  separately set if this is required to be copied also.
 
-   function Scope_Is_Transient  return Boolean;
+   function Scope_Is_Transient return Boolean;
    --  True if the current scope is transient
 
    function Static_Integer (N : Node_Id) return Uint;