[Ada] Consolidate handling of implicit dereferences into semantic analysis
authorEric Botcazou <ebotcazou@adacore.com>
Mon, 16 Mar 2020 18:28:47 +0000 (19:28 +0100)
committerPierre-Marie de Rodat <derodat@adacore.com>
Thu, 11 Jun 2020 09:53:42 +0000 (05:53 -0400)
2020-06-11  Eric Botcazou  <ebotcazou@adacore.com>

gcc/ada/

* checks.adb (Build_Discriminant_Checks): Build an explicit
dereference when the type is an access type.
* exp_atag.adb (Build_CW_Membership): Add explicit dereferences.
(Build_Get_Access_Level): Likewise.
(Build_Get_Alignment): Likewise.
(Build_Inherit_Prims): Likewise.
(Build_Get_Transportable): Likewise.
(Build_Set_Size_Function): Likewise.
* exp_ch3.adb (Build_Offset_To_Top_Function): Likewise.
* exp_ch4.adb (Expand_Allocator_Expression): Likewise.
(Expand_N_Indexed_Component ): Remove code dealing with implicit
dereferences.
(Expand_N_Selected_Component): Likewise.
(Expand_N_Slice): Likewise.
* exp_ch9.adb (Add_Formal_Renamings): Add explicit dereference.
(Expand_Accept_Declarations): Likewise.
(Build_Simple_Entry_Call): Remove code dealing with implicit
dereferences.
(Expand_N_Requeue_Statement): Likewise.
* exp_disp.adb (Expand_Dispatching_Call): Build an explicit
dereference when the controlling type is an access type.
* exp_spark.adb (Expand_SPARK_N_Selected_Component): Delete.
(Expand_SPARK_N_Slice_Or_Indexed_Component): Likewise.
(Expand_SPARK): Do not call them.
* sem_ch4.adb (Process_Implicit_Dereference_Prefix): Delete.
(Process_Indexed_Component): Call Implicitly_Designated_Type
to get the designated type for an implicit dereference.
(Analyze_Overloaded_Selected_Component): Do not insert an
explicit dereference here.
(Analyze_Selected_Component): Likewise.
(Analyze_Slice): Call Implicitly_Designated_Type to get the
designated type for an implicit dereference.
* sem_ch8.adb (Has_Components): New predicate extracted from...
(Is_Appropriate_For_Record): ...this.  Delete.
(Is_Appropriate_For_Entry_Prefix): Likewise.
(Analyze_Renamed_Entry): Deal with implicit dereferences.
(Find_Selected_Component): Do not insert an explicit dereference
here.  Call Implicitly_Designated_Type to get the designated type
for an implicit dereference.  Call Has_Components, Is_Task_Type
and Is_Protected_Type directly.  Adjust test for error.
* sem_res.adb (Resolve_Implicit_Dereference): New procedure.
(Resolve_Call): Call Resolve_Indexed_Component last.
(Resolve_Entry): Call Resolve_Implicit_Dereference on the prefix.
(Resolve_Indexed_Component): Call Implicitly_Designated_Type to
get the designated type for an implicit dereference and
Resolve_Implicit_Dereference on the prefix at the end.
(Resolve_Selected_Component): Likewise.
(Resolve_Slice): Likewise.  Do not apply access checks here.
* sem_util.ads (Implicitly_Designated_Type): Declare.
* sem_util.adb (Copy_And_Maybe_Dereference): Simplify.
(Implicitly_Designated_Type): New function.
(Object_Access_Level): Fix typo.
* sem_warn.adb (Check_Unset_Reference): Test Comes_From_Source
on the original node.

13 files changed:
gcc/ada/checks.adb
gcc/ada/exp_atag.adb
gcc/ada/exp_ch3.adb
gcc/ada/exp_ch4.adb
gcc/ada/exp_ch9.adb
gcc/ada/exp_disp.adb
gcc/ada/exp_spark.adb
gcc/ada/sem_ch4.adb
gcc/ada/sem_ch8.adb
gcc/ada/sem_res.adb
gcc/ada/sem_util.adb
gcc/ada/sem_util.ads
gcc/ada/sem_warn.adb

index ae62a9d6aaec5e4082b4f20af59c7d844a3388e5..641a5b28174caba348de06b04be9d3f8a5e6e5ef 100644 (file)
@@ -3964,6 +3964,15 @@ package body Checks is
                Duplicate_Subexpr_No_Checks
                  (Aggregate_Discriminant_Val (Disc_Ent));
 
+         elsif Is_Access_Type (Etype (N)) then
+            Dref :=
+              Make_Selected_Component (Loc,
+                Prefix        =>
+                  Make_Explicit_Dereference (Loc,
+                    Duplicate_Subexpr_No_Checks (N, Name_Req => True)),
+                Selector_Name => Make_Identifier (Loc, Chars (Disc_Ent)));
+
+            Set_Is_In_Discriminant_Check (Dref);
          else
             Dref :=
               Make_Selected_Component (Loc,
index b7bbc2065488e4827f941e26780305c57be393e7..bdd3f055f81f32394e88a0479109ec3f87fbc903 100644 (file)
@@ -229,14 +229,18 @@ package body Exp_Atag is
             Make_Op_Subtract (Loc,
               Left_Opnd =>
                 Make_Selected_Component (Loc,
-                  Prefix        => New_Occurrence_Of (Obj_TSD, Loc),
+                  Prefix        =>
+                    Make_Explicit_Dereference (Loc,
+                      New_Occurrence_Of (Obj_TSD, Loc)),
                   Selector_Name =>
                      New_Occurrence_Of
                        (RTE_Record_Component (RE_Idepth), Loc)),
 
                Right_Opnd =>
                  Make_Selected_Component (Loc,
-                   Prefix        => New_Occurrence_Of (Typ_TSD, Loc),
+                   Prefix        =>
+                     Make_Explicit_Dereference (Loc,
+                       New_Occurrence_Of (Typ_TSD, Loc)),
                    Selector_Name =>
                      New_Occurrence_Of
                        (RTE_Record_Component (RE_Idepth), Loc)))),
@@ -255,7 +259,9 @@ package body Exp_Atag is
                 Make_Indexed_Component (Loc,
                   Prefix      =>
                     Make_Selected_Component (Loc,
-                      Prefix        => New_Occurrence_Of (Obj_TSD, Loc),
+                      Prefix        =>
+                        Make_Explicit_Dereference (Loc,
+                          New_Occurrence_Of (Obj_TSD, Loc)),
                       Selector_Name =>
                         New_Occurrence_Of
                           (RTE_Record_Component (RE_Tags_Table), Loc)),
@@ -293,8 +299,9 @@ package body Exp_Atag is
       return
         Make_Selected_Component (Loc,
           Prefix =>
-            Build_TSD (Loc,
-              Unchecked_Convert_To (RTE (RE_Address), Tag_Node)),
+            Make_Explicit_Dereference (Loc,
+              Build_TSD (Loc,
+                Unchecked_Convert_To (RTE (RE_Address), Tag_Node))),
           Selector_Name =>
             New_Occurrence_Of
               (RTE_Record_Component (RE_Access_Level), Loc));
@@ -311,8 +318,10 @@ package body Exp_Atag is
    begin
       return
         Make_Selected_Component (Loc,
-          Prefix        =>
-            Build_TSD (Loc, Unchecked_Convert_To (RTE (RE_Address), Tag_Node)),
+          Prefix =>
+            Make_Explicit_Dereference (Loc,
+              Build_TSD (Loc,
+                Unchecked_Convert_To (RTE (RE_Address), Tag_Node))),
           Selector_Name =>
             New_Occurrence_Of (RTE_Record_Component (RE_Alignment), Loc));
    end Build_Get_Alignment;
@@ -639,7 +648,8 @@ package body Exp_Atag is
                  Prefix =>
                    Make_Selected_Component (Loc,
                      Prefix =>
-                       Build_DT (Loc, New_Tag_Node),
+                       Make_Explicit_Dereference (Loc,
+                         Build_DT (Loc, New_Tag_Node)),
                      Selector_Name =>
                        New_Occurrence_Of
                          (RTE_Record_Component (RE_Prims_Ptr), Loc)),
@@ -651,7 +661,8 @@ package body Exp_Atag is
                  Prefix =>
                    Make_Selected_Component (Loc,
                      Prefix =>
-                       Build_DT (Loc, Old_Tag_Node),
+                       Make_Explicit_Dereference (Loc,
+                         Build_DT (Loc, Old_Tag_Node)),
                      Selector_Name =>
                        New_Occurrence_Of
                          (RTE_Record_Component (RE_Prims_Ptr), Loc)),
@@ -728,8 +739,9 @@ package body Exp_Atag is
       return
         Make_Selected_Component (Loc,
           Prefix =>
-            Build_TSD (Loc,
-              Unchecked_Convert_To (RTE (RE_Address), Tag_Node)),
+            Make_Explicit_Dereference (Loc,
+              Build_TSD (Loc,
+                Unchecked_Convert_To (RTE (RE_Address), Tag_Node))),
           Selector_Name =>
             New_Occurrence_Of
               (RTE_Record_Component (RE_Transportable), Loc));
@@ -884,8 +896,9 @@ package body Exp_Atag is
           Name =>
             Make_Selected_Component (Loc,
               Prefix =>
-                Build_TSD (Loc,
-                  Unchecked_Convert_To (RTE (RE_Address), Tag_Node)),
+                Make_Explicit_Dereference (Loc,
+                  Build_TSD (Loc,
+                    Unchecked_Convert_To (RTE (RE_Address), Tag_Node))),
               Selector_Name =>
                 New_Occurrence_Of
                   (RTE_Record_Component (RE_Size_Func), Loc)),
index f412debb65ced13f47ba935bb4140512ae3097d9..7d13cd6cd2ba62aa7557e54841ac7cdba9cef71d 100644 (file)
@@ -2257,8 +2257,9 @@ package body Exp_Ch3 is
                           Prefix         =>
                             Make_Selected_Component (Loc,
                               Prefix        =>
-                                Unchecked_Convert_To (Acc_Type,
-                                  Make_Identifier (Loc, Name_uO)),
+                                Make_Explicit_Dereference (Loc,
+                                  Unchecked_Convert_To (Acc_Type,
+                                    Make_Identifier (Loc, Name_uO))),
                               Selector_Name =>
                                 New_Occurrence_Of (Iface_Comp, Loc)),
                           Attribute_Name => Name_Position))))));
index d416c06a8fe8965b4c6baa781a1d55562c5c2d4e..7a84215366f0e3df848b185db5601c1d0db792ab 100644 (file)
@@ -1073,7 +1073,9 @@ package body Exp_Ch4 is
 
          elsif Is_Tagged_Type (T) and then not Is_Class_Wide_Type (T) then
             TagT := T;
-            TagR := New_Occurrence_Of (Temp, Loc);
+            TagR :=
+              Make_Explicit_Dereference (Loc,
+                Prefix => New_Occurrence_Of (Temp, Loc));
 
          elsif Is_Private_Type (T)
            and then Is_Tagged_Type (Underlying_Type (T))
@@ -6868,7 +6870,6 @@ package body Exp_Ch4 is
       Typ : constant Entity_Id  := Etype (N);
       P   : constant Node_Id    := Prefix (N);
       T   : constant Entity_Id  := Etype (P);
-      Atp : Entity_Id;
 
    begin
       --  A special optimization, if we have an indexed component that is
@@ -6917,20 +6918,6 @@ package body Exp_Ch4 is
          Make_Build_In_Place_Iface_Call_In_Anonymous_Context (P);
       end if;
 
-      --  If the prefix is an access type, then we unconditionally rewrite if
-      --  as an explicit dereference. This simplifies processing for several
-      --  cases, including packed array cases and certain cases in which checks
-      --  must be generated. We used to try to do this only when it was
-      --  necessary, but it cleans up the code to do it all the time.
-
-      if Is_Access_Type (T) then
-         Insert_Explicit_Dereference (P);
-         Analyze_And_Resolve (P, Designated_Type (T));
-         Atp := Designated_Type (T);
-      else
-         Atp := T;
-      end if;
-
       --  Generate index and validity checks
 
       Generate_Index_Checks (N);
@@ -6942,8 +6929,8 @@ package body Exp_Ch4 is
       --  If selecting from an array with atomic components, and atomic sync
       --  is not suppressed for this array type, set atomic sync flag.
 
-      if (Has_Atomic_Components (Atp)
-           and then not Atomic_Synchronization_Disabled (Atp))
+      if (Has_Atomic_Components (T)
+           and then not Atomic_Synchronization_Disabled (T))
         or else (Is_Atomic (Typ)
                   and then not Atomic_Synchronization_Disabled (Typ))
         or else (Is_Entity_Name (P)
@@ -10580,7 +10567,7 @@ package body Exp_Ch4 is
       Par   : constant Node_Id    := Parent (N);
       P     : constant Node_Id    := Prefix (N);
       S     : constant Node_Id    := Selector_Name (N);
-      Ptyp  : Entity_Id           := Underlying_Type (Etype (P));
+      Ptyp  : constant Entity_Id  := Underlying_Type (Etype (P));
       Disc  : Entity_Id;
       New_N : Node_Id;
       Dcon  : Elmt_Id;
@@ -10631,21 +10618,6 @@ package body Exp_Ch4 is
    --  Start of processing for Expand_N_Selected_Component
 
    begin
-      --  Insert explicit dereference if required
-
-      if Is_Access_Type (Ptyp) then
-
-         --  First set prefix type to proper access type, in case it currently
-         --  has a private (non-access) view of this type.
-
-         Set_Etype (P, Ptyp);
-
-         Insert_Explicit_Dereference (P);
-         Analyze_And_Resolve (P, Designated_Type (Ptyp));
-
-         Ptyp := Etype (P);
-      end if;
-
       --  Deal with discriminant check required
 
       if Do_Discriminant_Check (N) then
@@ -11018,23 +10990,10 @@ package body Exp_Ch4 is
       --  Local variables
 
       Pref     : constant Node_Id := Prefix (N);
-      Pref_Typ : Entity_Id        := Etype (Pref);
 
    --  Start of processing for Expand_N_Slice
 
    begin
-      --  Special handling for access types
-
-      if Is_Access_Type (Pref_Typ) then
-         Pref_Typ := Designated_Type (Pref_Typ);
-
-         Rewrite (Pref,
-           Make_Explicit_Dereference (Sloc (N),
-            Prefix => Relocate_Node (Pref)));
-
-         Analyze_And_Resolve (Pref, Pref_Typ);
-      end if;
-
       --  Ada 2005 (AI-318-02): If the prefix is a call to a build-in-place
       --  function, then additional actuals must be passed.
 
index 49d3c1f324b4985413d2c4abe5c970d1385e492e..3d417ff995cd45dafdee9d717efc3f7614b5104f 100644 (file)
@@ -737,8 +737,9 @@ package body Exp_Ch9 is
          Renamed_Formal :=
            Make_Selected_Component (Loc,
              Prefix        =>
-               Unchecked_Convert_To (Entry_Parameters_Type (Ent),
-                 Make_Identifier (Loc, Chars (Ptr))),
+               Make_Explicit_Dereference (Loc,
+                 Unchecked_Convert_To (Entry_Parameters_Type (Ent),
+                   Make_Identifier (Loc, Chars (Ptr)))),
              Selector_Name => New_Occurrence_Of (Comp, Loc));
 
          Decl :=
@@ -4523,12 +4524,6 @@ package body Exp_Ch9 is
          Ent_Acc := Entry_Parameters_Type (Ent);
          Conctyp := Etype (Concval);
 
-         --  If prefix is an access type, dereference to obtain the task type
-
-         if Is_Access_Type (Conctyp) then
-            Conctyp := Designated_Type (Conctyp);
-         end if;
-
          --  Special case for protected subprogram calls
 
          if Is_Protected_Type (Conctyp)
@@ -6015,9 +6010,10 @@ package body Exp_Ch9 is
                   Renamed_Formal :=
                      Make_Selected_Component (Loc,
                        Prefix        =>
-                         Unchecked_Convert_To (
-                           Entry_Parameters_Type (Ent),
-                           New_Occurrence_Of (Ann, Loc)),
+                         Make_Explicit_Dereference (Loc,
+                           Unchecked_Convert_To (
+                             Entry_Parameters_Type (Ent),
+                             New_Occurrence_Of (Ann, Loc))),
                        Selector_Name =>
                          New_Occurrence_Of (Comp, Loc));
 
@@ -10533,16 +10529,6 @@ package body Exp_Ch9 is
       Extract_Entry (N, Concval, Ename, Index);
       Conc_Typ := Etype (Concval);
 
-      --  If the prefix is an access to class-wide type, dereference to get
-      --  object and entry type.
-
-      if Is_Access_Type (Conc_Typ) then
-         Conc_Typ := Designated_Type (Conc_Typ);
-         Rewrite (Concval,
-           Make_Explicit_Dereference (Loc, Relocate_Node (Concval)));
-         Analyze_And_Resolve (Concval, Conc_Typ);
-      end if;
-
       --  Examine the scope stack in order to find nearest enclosing protected
       --  or task type. This will constitute our invocation source.
 
index b8cbd4a227500bc769ff6a0c4945a3dbc2479452..b57ba586062d3454fb9ada80b5bf1e78bd889b0f 100644 (file)
@@ -1114,6 +1114,14 @@ package body Exp_Disp is
       then
          Controlling_Tag := Duplicate_Subexpr (Ctrl_Arg);
 
+      elsif Is_Access_Type (Ctrl_Typ) then
+         Controlling_Tag :=
+           Make_Selected_Component (Loc,
+             Prefix        =>
+               Make_Explicit_Dereference (Loc,
+                 Duplicate_Subexpr_Move_Checks (Ctrl_Arg)),
+             Selector_Name => New_Occurrence_Of (DTC_Entity (Subp), Loc));
+
       else
          Controlling_Tag :=
            Make_Selected_Component (Loc,
index 0e6c745270af86bccd898683f2ada5babb9055c0..b8b303c1f3a44a32f90e72d4bb914c212fff61da 100644 (file)
@@ -69,12 +69,6 @@ package body Exp_SPARK is
    procedure Expand_SPARK_N_Op_Ne (N : Node_Id);
    --  Rewrite operator /= based on operator = when defined explicitly
 
-   procedure Expand_SPARK_N_Selected_Component (N : Node_Id);
-   --  Insert explicit dereference if required
-
-   procedure Expand_SPARK_N_Slice_Or_Indexed_Component (N : Node_Id);
-   --  Insert explicit dereference if required
-
    ------------------
    -- Expand_SPARK --
    ------------------
@@ -136,14 +130,6 @@ package body Exp_SPARK is
                Expand_SPARK_N_Freeze_Type (Entity (N));
             end if;
 
-         when N_Indexed_Component
-            | N_Slice
-         =>
-            Expand_SPARK_N_Slice_Or_Indexed_Component (N);
-
-         when N_Selected_Component =>
-            Expand_SPARK_N_Selected_Component (N);
-
          --  In SPARK mode, no other constructs require expansion
 
          when others =>
@@ -481,40 +467,4 @@ package body Exp_SPARK is
       end if;
    end Expand_SPARK_Potential_Renaming;
 
-   ---------------------------------------
-   -- Expand_SPARK_N_Selected_Component --
-   ---------------------------------------
-
-   procedure Expand_SPARK_N_Selected_Component (N : Node_Id) is
-      Pref : constant Node_Id   := Prefix (N);
-      Typ  : constant Entity_Id := Underlying_Type (Etype (Pref));
-
-   begin
-      if Present (Typ) and then Is_Access_Type (Typ) then
-
-         --  First set prefix type to proper access type, in case it currently
-         --  has a private (non-access) view of this type.
-
-         Set_Etype (Pref, Typ);
-
-         Insert_Explicit_Dereference (Pref);
-         Analyze_And_Resolve (Pref, Designated_Type (Typ));
-      end if;
-   end Expand_SPARK_N_Selected_Component;
-
-   -----------------------------------------------
-   -- Expand_SPARK_N_Slice_Or_Indexed_Component --
-   -----------------------------------------------
-
-   procedure Expand_SPARK_N_Slice_Or_Indexed_Component (N : Node_Id) is
-      Pref : constant Node_Id   := Prefix (N);
-      Typ  : constant Entity_Id := Etype (Pref);
-
-   begin
-      if Is_Access_Type (Typ) then
-         Insert_Explicit_Dereference (Pref);
-         Analyze_And_Resolve (Pref, Designated_Type (Typ));
-      end if;
-   end Expand_SPARK_N_Slice_Or_Indexed_Component;
-
 end Exp_SPARK;
index 3d3e2c7c122abad72acf4b580afe56d0cc7679cd..a710ba23f6d17434cd94c75371144ff1db5df033 100644 (file)
@@ -171,6 +171,7 @@ package body Sem_Ch4 is
    --  being called. The caller will have verified that the object is legal
    --  for the call. If the remaining parameters match, the first parameter
    --  will rewritten as a dereference if needed, prior to completing analysis.
+
    procedure Check_Misspelled_Selector
      (Prefix : Entity_Id;
       Sel    : Node_Id);
@@ -276,20 +277,6 @@ package body Sem_Ch4 is
    --  type is not directly visible. The routine uses this type to emit a more
    --  informative message.
 
-   function Process_Implicit_Dereference_Prefix
-     (E : Entity_Id;
-      P : Node_Id) return Entity_Id;
-   --  Called when P is the prefix of an implicit dereference, denoting an
-   --  object E. The function returns the designated type of the prefix, taking
-   --  into account that the designated type of an anonymous access type may be
-   --  a limited view, when the nonlimited view is visible.
-   --
-   --  If in semantics only mode (-gnatc or generic), the function also records
-   --  that the prefix is a reference to E, if any. Normally, such a reference
-   --  is generated only when the implicit dereference is expanded into an
-   --  explicit one, but for consistency we must generate the reference when
-   --  expansion is disabled as well.
-
    procedure Remove_Abstract_Operations (N : Node_Id);
    --  Ada 2005: implementation of AI-310. An abstract non-dispatching
    --  operation is not a candidate interpretation.
@@ -2351,7 +2338,10 @@ package body Sem_Ch4 is
 
       procedure Process_Function_Call;
       --  Prefix in indexed component form is an overloadable entity, so the
-      --  node is a function call. Reformat it as such.
+      --  node is very likely a function call; reformat it as such. The only
+      --  exception is a call to a parameterless function that returns an
+      --  array type, or an access type thereof, in which case this will be
+      --  undone later by Resolve_Call or Resolve_Entry_Call.
 
       procedure Process_Indexed_Component;
       --  Prefix in indexed component form is actually an indexed component.
@@ -2462,7 +2452,7 @@ package body Sem_Ch4 is
             if Is_Access_Type (Array_Type) then
                Error_Msg_NW
                  (Warn_On_Dereference, "?d?implicit dereference", N);
-               Array_Type := Process_Implicit_Dereference_Prefix (Pent, P);
+               Array_Type := Implicitly_Designated_Type (Array_Type);
             end if;
 
             if Is_Array_Type (Array_Type) then
@@ -3898,18 +3888,6 @@ package body Sem_Ch4 is
                   Set_Etype (Sel, Etype (Comp));
                   Set_Etype (N,   Etype (Comp));
                   Set_Etype (Nam, It.Typ);
-
-                  --  For access type case, introduce explicit dereference for
-                  --  more uniform treatment of entry calls. Do this only once
-                  --  if several interpretations yield an access type.
-
-                  if Is_Access_Type (Etype (Nam))
-                    and then Nkind (Nam) /= N_Explicit_Dereference
-                  then
-                     Insert_Explicit_Dereference (Nam);
-                     Error_Msg_NW
-                       (Warn_On_Dereference, "?d?implicit dereference", N);
-                  end if;
                end if;
 
                Next_Entity (Comp);
@@ -4379,7 +4357,6 @@ package body Sem_Ch4 is
       In_Scope      : Boolean;
       Is_Private_Op : Boolean;
       Parent_N      : Node_Id;
-      Pent          : Entity_Id := Empty;
       Prefix_Type   : Entity_Id;
 
       Type_To_Use : Entity_Id;
@@ -4408,7 +4385,8 @@ package body Sem_Ch4 is
       --  indexed component rather than a function call.
 
       function Has_Dereference (Nod : Node_Id) return Boolean;
-      --  Check whether prefix includes a dereference at any level.
+      --  Check whether prefix includes a dereference, explicit or implicit,
+      --  at any recursive level.
 
       --------------------------------
       -- Find_Component_In_Instance --
@@ -4520,10 +4498,6 @@ package body Sem_Ch4 is
          if Nkind (Nod) = N_Explicit_Dereference then
             return True;
 
-         --  When expansion is disabled an explicit dereference may not have
-         --  been inserted, but if this is an access type the indirection makes
-         --  the call safe.
-
          elsif Is_Access_Type (Etype (Nod)) then
             return True;
 
@@ -4576,16 +4550,7 @@ package body Sem_Ch4 is
 
          else
             Error_Msg_NW (Warn_On_Dereference, "?d?implicit dereference", N);
-
-            if Is_Entity_Name (Name) then
-               Pent := Entity (Name);
-            elsif Nkind (Name) = N_Selected_Component
-              and then Is_Entity_Name (Selector_Name (Name))
-            then
-               Pent := Entity (Selector_Name (Name));
-            end if;
-
-            Prefix_Type := Process_Implicit_Dereference_Prefix (Pent, Name);
+            Prefix_Type := Implicitly_Designated_Type (Prefix_Type);
          end if;
 
       --  If we have an explicit dereference of a remote access-to-class-wide
@@ -4673,11 +4638,6 @@ package body Sem_Ch4 is
          Set_Etype (N, Etype (Comp));
          Check_Implicit_Dereference (N, Etype (Comp));
 
-         if Is_Access_Type (Etype (Name)) then
-            Insert_Explicit_Dereference (Name);
-            Error_Msg_NW (Warn_On_Dereference, "?d?implicit dereference", N);
-         end if;
-
       elsif Is_Record_Type (Prefix_Type) then
 
          --  Find component with given name. In an instance, if the node is
@@ -4978,15 +4938,6 @@ package body Sem_Ch4 is
                if Ekind (Comp) = E_Discriminant then
                   Set_Original_Discriminant (Sel, Comp);
                end if;
-
-               --  For access type case, introduce explicit dereference for
-               --  more uniform treatment of entry calls.
-
-               if Is_Access_Type (Etype (Name)) then
-                  Insert_Explicit_Dereference (Name);
-                  Error_Msg_NW
-                    (Warn_On_Dereference, "?d?implicit dereference", N);
-               end if;
             end if;
 
             <<Next_Comp>>
@@ -5455,8 +5406,8 @@ package body Sem_Ch4 is
          Set_Etype (N, Any_Type);
 
          if Is_Access_Type (Array_Type) then
-            Array_Type := Designated_Type (Array_Type);
             Error_Msg_NW (Warn_On_Dereference, "?d?implicit dereference", N);
+            Array_Type := Implicitly_Designated_Type (Array_Type);
          end if;
 
          if not Is_Array_Type (Array_Type) then
@@ -7401,48 +7352,6 @@ package body Sem_Ch4 is
       end if;
    end Operator_Check;
 
-   -----------------------------------------
-   -- Process_Implicit_Dereference_Prefix --
-   -----------------------------------------
-
-   function Process_Implicit_Dereference_Prefix
-     (E : Entity_Id;
-      P : Entity_Id) return Entity_Id
-   is
-      Ref : Node_Id;
-      Typ : constant Entity_Id := Designated_Type (Etype (P));
-
-   begin
-      if Present (E)
-        and then (Operating_Mode = Check_Semantics or else not Expander_Active)
-      then
-         --  We create a dummy reference to E to ensure that the reference is
-         --  not considered as part of an assignment (an implicit dereference
-         --  can never assign to its prefix). The Comes_From_Source attribute
-         --  needs to be propagated for accurate warnings.
-
-         Ref := New_Occurrence_Of (E, Sloc (P));
-         Set_Comes_From_Source (Ref, Comes_From_Source (P));
-         Generate_Reference (E, Ref);
-      end if;
-
-      --  An implicit dereference is a legal occurrence of an incomplete type
-      --  imported through a limited_with clause, if the full view is visible.
-
-      if From_Limited_With (Typ)
-        and then not From_Limited_With (Scope (Typ))
-        and then
-          (Is_Immediately_Visible (Scope (Typ))
-            or else
-              (Is_Child_Unit (Scope (Typ))
-                and then Is_Visible_Lib_Unit (Scope (Typ))))
-      then
-         return Available_View (Typ);
-      else
-         return Typ;
-      end if;
-   end Process_Implicit_Dereference_Prefix;
-
    --------------------------------
    -- Remove_Abstract_Operations --
    --------------------------------
index 555862b76f0125032d566c6a3b4e63f5ccc68be4..e8d5a90c23ef92e3bc0bb01d6603a7a95aaeff8e 100644 (file)
@@ -501,6 +501,10 @@ package body Sem_Ch8 is
    --  Ada 2005 (AI-262): Determines if the current compilation unit has a
    --  private with on E.
 
+   function Has_Components (Typ : Entity_Id) return Boolean;
+   --  Determine if given type has components, i.e. is either a record type or
+   --  type or a type that has discriminants.
+
    function Has_Implicit_Operator (N : Node_Id) return Boolean;
    --  N is an expanded name whose selector is an operator name (e.g. P."+").
    --  declarative part contains an implicit declaration of an operator if it
@@ -515,14 +519,6 @@ package body Sem_Ch8 is
    --  specification are discarded and replaced with those of the renamed
    --  subprogram, which are then used to recheck the default values.
 
-   function Is_Appropriate_For_Entry_Prefix (T : Entity_Id) return Boolean;
-   --  True if it is of a task type, a protected type, or else an access to one
-   --  of these types.
-
-   function Is_Appropriate_For_Record (T : Entity_Id) return Boolean;
-   --  Prefix is appropriate for record if it is of a record type, or an access
-   --  to such.
-
    function Most_Descendant_Use_Clause
      (Clause1 : Entity_Id;
       Clause2 : Entity_Id) return Entity_Id;
@@ -1736,6 +1732,9 @@ package body Sem_Ch8 is
          --  The prefix can be an arbitrary expression that yields a task or
          --  protected object, so it must be resolved.
 
+         if Is_Access_Type (Etype (Prefix (Nam))) then
+            Insert_Explicit_Dereference (Prefix (Nam));
+         end if;
          Resolve (Prefix (Nam), Scope (Old_S));
       end if;
 
@@ -7333,23 +7332,6 @@ package body Sem_Ch8 is
                Set_Etype (N, C_Etype);
             end;
 
-            --  If this is the name of an entry or protected operation, and
-            --  the prefix is an access type, insert an explicit dereference,
-            --  so that entry calls are treated uniformly.
-
-            if Is_Access_Type (Etype (P))
-              and then Is_Concurrent_Type (Designated_Type (Etype (P)))
-            then
-               declare
-                  New_P : constant Node_Id :=
-                            Make_Explicit_Dereference (Sloc (P),
-                              Prefix => Relocate_Node (P));
-               begin
-                  Rewrite (P, New_P);
-                  Set_Etype (P, Designated_Type (Etype (Prefix (P))));
-               end;
-            end if;
-
          --  If the selected component appears within a default expression
          --  and it has an actual subtype, the preanalysis has not yet
          --  completed its analysis, because Insert_Actions is disabled in
@@ -7393,37 +7375,16 @@ package body Sem_Ch8 is
             Write_Entity_Info (P_Type, "      "); Write_Eol;
          end if;
 
-         --  The designated type may be a limited view with no components.
-         --  Check whether the non-limited view is available, because in some
-         --  cases this will not be set when installing the context. Rewrite
-         --  the node by introducing an explicit dereference at once, and
-         --  setting the type of the rewritten prefix to the non-limited view
-         --  of the original designated type.
+         --  If the prefix's type is an access type, get to the record type
 
          if Is_Access_Type (P_Type) then
-            declare
-               Desig_Typ : constant Entity_Id :=
-                             Directly_Designated_Type (P_Type);
-
-            begin
-               if Is_Incomplete_Type (Desig_Typ)
-                 and then From_Limited_With (Desig_Typ)
-                 and then Present (Non_Limited_View (Desig_Typ))
-               then
-                  Rewrite (P,
-                    Make_Explicit_Dereference (Sloc (P),
-                      Prefix => Relocate_Node (P)));
-
-                  Set_Etype (P, Get_Full_View (Non_Limited_View (Desig_Typ)));
-                  P_Type := Etype (P);
-               end if;
-            end;
+            P_Type := Implicitly_Designated_Type (P_Type);
          end if;
 
          --  First check for components of a record object (not the
          --  result of a call, which is handled below).
 
-         if Is_Appropriate_For_Record (P_Type)
+         if Has_Components (P_Type)
            and then not Is_Overloadable (P_Name)
            and then not Is_Type (P_Name)
          then
@@ -7437,7 +7398,7 @@ package body Sem_Ch8 is
 
          --  Reference to type name in predicate/invariant expression
 
-         elsif Is_Appropriate_For_Entry_Prefix (P_Type)
+         elsif (Is_Task_Type (P_Type) or else Is_Protected_Type (P_Type))
            and then not In_Open_Scopes (P_Name)
            and then (not Is_Concurrent_Type (Etype (P_Name))
                       or else not In_Open_Scopes (Etype (P_Name)))
@@ -7616,16 +7577,6 @@ package body Sem_Ch8 is
          else
             --  Format node as expanded name, to avoid cascaded errors
 
-            --  If the limited_with transformation was applied earlier, restore
-            --  source for proper error reporting.
-
-            if not Comes_From_Source (P)
-              and then Nkind (P) = N_Explicit_Dereference
-            then
-               Rewrite (P, Prefix (P));
-               P_Type := Etype (P);
-            end if;
-
             Change_Selected_Component_To_Expanded_Name (N);
             Set_Entity (N, Any_Id);
             Set_Etype  (N, Any_Type);
@@ -7687,8 +7638,8 @@ package body Sem_Ch8 is
 
                Error_Msg_N ("invalid prefix in selected component&", P);
 
-               if Is_Access_Type (P_Type)
-                 and then Ekind (Designated_Type (P_Type)) = E_Incomplete_Type
+               if Is_Incomplete_Type (P_Type)
+                 and then Is_Access_Type (Etype (P))
                then
                   Error_Msg_N
                     ("\dereference must not be of an incomplete type "
@@ -8042,6 +7993,20 @@ package body Sem_Ch8 is
       end if;
    end Find_Type;
 
+   --------------------
+   -- Has_Components --
+   --------------------
+
+   function Has_Components (Typ : Entity_Id) return Boolean is
+   begin
+      return Is_Record_Type (Typ)
+        or else (Is_Private_Type (Typ) and then Has_Discriminants (Typ))
+        or else (Is_Task_Type (Typ) and then Has_Discriminants (Typ))
+        or else (Is_Incomplete_Type (Typ)
+                  and then From_Limited_With (Typ)
+                  and then Is_Record_Type (Available_View (Typ)));
+   end Has_Components;
+
    ------------------------------------
    -- Has_Implicit_Character_Literal --
    ------------------------------------
@@ -8485,57 +8450,6 @@ package body Sem_Ch8 is
       end loop;
    end Install_Use_Clauses;
 
-   -------------------------------------
-   -- Is_Appropriate_For_Entry_Prefix --
-   -------------------------------------
-
-   function Is_Appropriate_For_Entry_Prefix (T : Entity_Id) return Boolean is
-      P_Type : Entity_Id := T;
-
-   begin
-      if Is_Access_Type (P_Type) then
-         P_Type := Designated_Type (P_Type);
-      end if;
-
-      return Is_Task_Type (P_Type) or else Is_Protected_Type (P_Type);
-   end Is_Appropriate_For_Entry_Prefix;
-
-   -------------------------------
-   -- Is_Appropriate_For_Record --
-   -------------------------------
-
-   function Is_Appropriate_For_Record (T : Entity_Id) return Boolean is
-
-      function Has_Components (T1 : Entity_Id) return Boolean;
-      --  Determine if given type has components (i.e. is either a record
-      --  type or a type that has discriminants).
-
-      --------------------
-      -- Has_Components --
-      --------------------
-
-      function Has_Components (T1 : Entity_Id) return Boolean is
-      begin
-         return Is_Record_Type (T1)
-           or else (Is_Private_Type (T1) and then Has_Discriminants (T1))
-           or else (Is_Task_Type (T1) and then Has_Discriminants (T1))
-           or else (Is_Incomplete_Type (T1)
-                     and then From_Limited_With (T1)
-                     and then Present (Non_Limited_View (T1))
-                     and then Is_Record_Type
-                                (Get_Full_View (Non_Limited_View (T1))));
-      end Has_Components;
-
-   --  Start of processing for Is_Appropriate_For_Record
-
-   begin
-      return
-        Present (T)
-          and then (Has_Components (T)
-                     or else (Is_Access_Type (T)
-                               and then Has_Components (Designated_Type (T))));
-   end Is_Appropriate_For_Record;
-
    ----------------------
    -- Mark_Use_Clauses --
    ----------------------
index d17231102a125fab61ac9e83f4d42d6b6f21cf3b..6c244dbbfe441205c80275592e44d8a121c68aad 100644 (file)
@@ -226,6 +226,12 @@ package body Sem_Res is
    --  is the context type, which is used when the operation is a protected
    --  function with no arguments, and the return value is indexed.
 
+   procedure Resolve_Implicit_Dereference (P : Node_Id);
+   --  Called when P is the prefix of an indexed component, or of a selected
+   --  component, or of a slice. If P is of an access type, we unconditionally
+   --  rewrite it as an explicit dereference. This ensures that the expander
+   --  and the code generator have a fully explicit tree to work with.
+
    procedure Resolve_Intrinsic_Operator (N : Node_Id; Typ : Entity_Id);
    --  A call to a user-defined intrinsic operator is rewritten as a call to
    --  the corresponding predefined operator, with suitable conversions. Note
@@ -6369,7 +6375,6 @@ package body Sem_Res is
 
                   Set_Etype (Prefix (N), Ret_Type);
                   Set_Etype (N, Typ);
-                  Resolve_Indexed_Component (N, Typ);
 
                   if Legacy_Elaboration_Checks then
                      Check_Elab_Call (Prefix (N));
@@ -6381,6 +6386,8 @@ package body Sem_Res is
                   --  the ABE Processing phase.
 
                   Build_Call_Marker (Prefix (N));
+
+                  Resolve_Indexed_Component (N, Typ);
                end if;
             end if;
 
@@ -7783,10 +7790,12 @@ package body Sem_Res is
 
       if Nkind (Entry_Name) = N_Selected_Component then
          Resolve (Prefix (Entry_Name));
+         Resolve_Implicit_Dereference (Prefix (Entry_Name));
 
       else pragma Assert (Nkind (Entry_Name) = N_Indexed_Component);
          Nam := Entity (Selector_Name (Prefix (Entry_Name)));
          Resolve (Prefix (Prefix (Entry_Name)));
+         Resolve_Implicit_Dereference (Prefix (Prefix (Entry_Name)));
          Index := First (Expressions (Entry_Name));
          Resolve (Index, Entry_Index_Type (Nam));
 
@@ -8723,6 +8732,21 @@ package body Sem_Res is
       Analyze_Dimension (N);
    end Resolve_If_Expression;
 
+   ----------------------------------
+   -- Resolve_Implicit_Dereference --
+   ----------------------------------
+
+   procedure Resolve_Implicit_Dereference (P : Node_Id) is
+      Desig_Typ : Entity_Id;
+
+   begin
+      if Is_Access_Type (Etype (P)) then
+         Desig_Typ := Implicitly_Designated_Type (Etype (P));
+         Insert_Explicit_Dereference (P);
+         Analyze_And_Resolve (P, Desig_Typ);
+      end if;
+   end Resolve_Implicit_Dereference;
+
    -------------------------------
    -- Resolve_Indexed_Component --
    -------------------------------
@@ -8795,12 +8819,12 @@ package body Sem_Res is
       Resolve (Name, Array_Type);
       Array_Type := Get_Actual_Subtype_If_Available (Name);
 
-      --  If prefix is access type, dereference to get real array type.
-      --  Note: we do not apply an access check because the expander always
-      --  introduces an explicit dereference, and the check will happen there.
+      --  If the prefix's type is an access type, get to the real array type.
+      --  Note: we do not apply an access check because an explicit dereference
+      --  will be introduced later, and the check will happen there.
 
       if Is_Access_Type (Array_Type) then
-         Array_Type := Designated_Type (Array_Type);
+         Array_Type := Implicitly_Designated_Type (Array_Type);
       end if;
 
       --  If name was overloaded, set component type correctly now
@@ -8840,6 +8864,7 @@ package body Sem_Res is
          end loop;
       end if;
 
+      Resolve_Implicit_Dereference (Prefix (N));
       Analyze_Dimension (N);
 
       --  Do not generate the warning on suspicious index if we are analyzing
@@ -10402,12 +10427,12 @@ package body Sem_Res is
          Generate_Reference (Entity (S), S, 'r');
       end if;
 
-      --  If prefix is an access type, the node will be transformed into an
-      --  explicit dereference during expansion. The type of the node is the
-      --  designated type of that of the prefix.
+      --  If the prefix's type is an access type, get to the real record type.
+      --  Note: we do not apply an access check because an explicit dereference
+      --  will be introduced later, and the check will happen there.
 
       if Is_Access_Type (Etype (P)) then
-         T := Designated_Type (Etype (P));
+         T := Implicitly_Designated_Type (Etype (P));
          Check_Fully_Declared_Prefix (T, P);
 
       else
@@ -10482,6 +10507,7 @@ package body Sem_Res is
             Prefix (N));
       end if;
 
+      Resolve_Implicit_Dereference (Prefix (N));
       Analyze_Dimension (N);
    end Resolve_Selected_Component;
 
@@ -10712,9 +10738,12 @@ package body Sem_Res is
 
       Resolve (Name, Array_Type);
 
+      --  If the prefix's type is an access type, get to the real array type.
+      --  Note: we do not apply an access check because an explicit dereference
+      --  will be introduced later, and the check will happen there.
+
       if Is_Access_Type (Array_Type) then
-         Apply_Access_Check (N);
-         Array_Type := Designated_Type (Array_Type);
+         Array_Type := Implicitly_Designated_Type (Array_Type);
 
          --  If the prefix is an access to an unconstrained array, we must use
          --  the actual subtype of the object to perform the index checks. The
@@ -10858,6 +10887,7 @@ package body Sem_Res is
          Warn_On_Suspicious_Index (Name, High_Bound (Drange));
       end if;
 
+      Resolve_Implicit_Dereference (Prefix (N));
       Analyze_Dimension (N);
       Eval_Slice (N);
    end Resolve_Slice;
index cce55a6c58ae1d73ffec86e9b795ee1a7f0f81c5..c6c8d10c7964ed678986d9409e4348b41c181885 100644 (file)
@@ -1354,14 +1354,12 @@ package body Sem_Util is
          New_N : constant Node_Id := New_Copy_Tree (N);
 
       begin
-         if Is_Access_Type (Etype (New_N)) then
-            --  Copy the parent to have a proper Sloc on the dereference
+         if Is_Access_Type (Etype (N)) then
+            return Make_Explicit_Dereference (Sloc (Parent (N)), New_N);
 
-            Set_Parent (New_N, Parent (N));
-            Insert_Explicit_Dereference (New_N);
+         else
+            return New_N;
          end if;
-
-         return New_N;
       end Copy_And_Maybe_Dereference;
 
    --  Start of processing for Build_Actual_Subtype_Of_Component
@@ -12515,6 +12513,32 @@ package body Sem_Util is
       return False;
    end Implements_Interface;
 
+   --------------------------------
+   -- Implicitly_Designated_Type --
+   --------------------------------
+
+   function Implicitly_Designated_Type (Typ : Entity_Id) return Entity_Id is
+      Desig : constant Entity_Id := Designated_Type (Typ);
+
+   begin
+      --  An implicit dereference is a legal occurrence of an incomplete type
+      --  imported through a limited_with clause, if the full view is visible.
+
+      if Is_Incomplete_Type (Desig)
+        and then From_Limited_With (Desig)
+        and then not From_Limited_With (Scope (Desig))
+        and then
+          (Is_Immediately_Visible (Scope (Desig))
+            or else
+              (Is_Child_Unit (Scope (Desig))
+                and then Is_Visible_Lib_Unit (Scope (Desig))))
+      then
+         return Available_View (Desig);
+      else
+         return Desig;
+      end if;
+   end Implicitly_Designated_Type;
+
    ------------------------------------
    -- In_Assertion_Expression_Pragma --
    ------------------------------------
@@ -23402,7 +23426,7 @@ package body Sem_Util is
          Orig_Pre := Original_Node (Prefix (Orig_Obj));
 
          if Is_Access_Type (Etype (Orig_Pre)) then
-            return Type_Access_Level (Etype (Prefix (Orig_Obj)));
+            return Type_Access_Level (Etype (Orig_Pre));
          else
             return Object_Access_Level (Prefix (Orig_Obj));
          end if;
index b794e8098224710efee6c1a1a85fa3569e518c8a..253184412703943d6c554a75c4191ed4ffc1de63 100644 (file)
@@ -1391,6 +1391,11 @@ package Sem_Util is
       Exclude_Parents : Boolean := False) return Boolean;
    --  Returns true if the Typ_Ent implements interface Iface_Ent
 
+   function Implicitly_Designated_Type (Typ : Entity_Id) return Entity_Id;
+   --  Called when Typ is the type of the prefix of an implicit dereference.
+   --  Return the designated type of Typ, taking into account that this type
+   --  may be a limited view, when the nonlimited view is visible.
+
    function In_Assertion_Expression_Pragma (N : Node_Id) return Boolean;
    --  Returns True if node N appears within a pragma that acts as an assertion
    --  expression. See Sem_Prag for the list of qualifying pragmas.
index ca019ef9d318ab327863a1e49e3ffa4f6aeecf23..3fe77b077bcfa747afc536a40cc3f35217694828 100644 (file)
@@ -1872,7 +1872,7 @@ package body Sem_Warn is
       --  have a reference from generated code, it is bogus (e.g. calls to init
       --  procs to set default discriminant values).
 
-      if not Comes_From_Source (N) then
+      if not Comes_From_Source (Original_Node (N)) then
          return;
       end if;