diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 472a6fdcd2df2837a724ecc6fb2eeb0fd3df4049..95c898b3768d0163ec73cd776df841294f936a6e 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,38 @@
+2019-07-11  Claire Dross  <dross@adacore.com>
+
+	* gnat1drv.adb: SPARK checking rules for pointer aliasing are
+	moved to GNATprove backend.
+	* sem_spark.ads, sem_spark.adb (Sem_SPARK): Is now a generic
+	unit. Takes as parameters:
+	 - Retysp which is used to query the most underlying type
+	   visible in SPARK. We do not introduce aliasing checks for
+	   types which are not visibly deep.
+	 - Component_Is_Visible_In_SPARK is used to avoid doing pointer
+	   aliasing checks on components which are not visible in SPARK.
+	 - Emit_Messages returns True in the second phase of SPARK
+	   analysis. Error messages for failed aliasing checks are only
+	   output in this case.
+	Additionally, errors on constructs not supported in SPARK are
+	removed as duplicates of marking errors. Components are stored
+	in the permission map using their original component to avoid
+	inconsistencies between components of different views of the
+	same type.
+	(Check_Expression): Handle delta constraints.
+	(Is_Deep): Exported so that we can check for SPARK restrictions
+	on deep types inside SPARK semantic checkings.
+	(Is_Traversal_Function): Exported so that we can check for SPARK
+	restrictions on traversal functions inside SPARK semantic
+	checkings.
+	(Check_Call_Statement, Read_Indexes): Check wether we are
+	dealing with a subprogram pointer type before querying called
+	entity.
+	(Is_Subpath_Expression): Image attribute can appear inside a
+	path.
+	(Check_Loop_Statement): Correct order of statements in the loop.
+	(Check_Node): Ignore raise nodes.
+	(Check_Statement): Use Last_Non_Pragma to get the object
+	declaration in an extended return statement.
+
 2019-07-11  Patrick Bernardi  <bernardi@adacore.com>
 
 	* bindgen.adb (Gen_Main): Do not generate a reference to
diff --git a/gcc/ada/gnat1drv.adb b/gcc/ada/gnat1drv.adb
index 55a57ddc7e8c641f35a5611ceeb335fa518feaea..ecb3ccdd39917639f32a6e632f1d0d773f9381d4 100644
--- a/gcc/ada/gnat1drv.adb
+++ b/gcc/ada/gnat1drv.adb
@@ -63,7 +63,6 @@ with Sem_Ch13;
 with Sem_Elim;
 with Sem_Eval;
 with Sem_Prag;
-with Sem_SPARK; use Sem_SPARK;
 with Sem_Type;
 with Set_Targ;
 with Sinfo;     use Sinfo;
@@ -1586,13 +1585,6 @@ begin
 
       if GNATprove_Mode then
 
-         --  Perform the new SPARK checking rules for pointer aliasing. This is
-         --  only activated in GNATprove mode and on SPARK code.
-
-         if Debug_Flag_FF then
-            Check_Safe_Pointers (Main_Unit_Node);
-         end if;
-
          --  In GNATprove mode we're writing the ALI much earlier than usual
          --  as flow analysis needs the file present in order to append its
          --  own globals to it.
diff --git a/gcc/ada/sem_spark.adb b/gcc/ada/sem_spark.adb
index 10c82fffc73cd703833b742ef0ee6f1759b19cea..67aa4537c1d4dbe77355e4080ee7598e138cfaa5 100644
--- a/gcc/ada/sem_spark.adb
+++ b/gcc/ada/sem_spark.adb
@@ -641,7 +641,8 @@ package body Sem_SPARK is
    pragma Precondition (Nkind_In (Expr, N_Index_Or_Discriminant_Constraint,
                                         N_Range_Constraint,
                                         N_Subtype_Indication,
-                                        N_Digits_Constraint)
+                                        N_Digits_Constraint,
+                                        N_Delta_Constraint)
                         or else Nkind (Expr) in N_Subexpr);
 
    procedure Check_Globals (Subp : Entity_Id);
@@ -744,10 +745,6 @@ package body Sem_SPARK is
    --  A procedure that is called when deep globals or aliased globals are used
    --  without any global aspect.
 
-   function Is_Deep (Typ : Entity_Id) return Boolean;
-   --  A function that can tell if a type is deep or not. Returns true if the
-   --  type passed as argument is deep.
-
    function Is_Path_Expression (Expr : Node_Id) return Boolean;
    --  Return whether Expr corresponds to a path
 
@@ -759,8 +756,6 @@ package body Sem_SPARK is
    --  a prefix, in the sense that they could still refer to overlapping memory
    --  locations.
 
-   function Is_Traversal_Function (E : Entity_Id) return Boolean;
-
    function Is_Traversal_Function_Call (Expr : Node_Id) return Boolean;
 
    function Loop_Of_Exit (N : Node_Id) return Entity_Id;
@@ -959,7 +954,7 @@ package body Sem_SPARK is
                null;
             else
                Handle_Parameter_Or_Global (Expr       => Item,
-                                           Formal_Typ => Etype (Item),
+                                           Formal_Typ => Retysp (Etype (Item)),
                                            Param_Mode => Kind,
                                            Subp       => Subp,
                                            Global_Var => True);
@@ -1076,9 +1071,12 @@ package body Sem_SPARK is
            and then (Is_Traversal_Function_Call (Expr)
                       or else Get_Root_Object (Borrowed) /= Var)
          then
-            Error_Msg_NE
-              ("source of assignment must have & as root (SPARK RM 3.10(8)))",
-               Expr, Var);
+            if Emit_Messages then
+               Error_Msg_NE
+                 ("source of assignment must have & as root" &
+                    " (SPARK RM 3.10(8)))",
+                  Expr, Var);
+            end if;
             return;
          end if;
 
@@ -1105,9 +1103,12 @@ package body Sem_SPARK is
            and then (Is_Traversal_Function_Call (Expr)
                       or else Get_Root_Object (Observed) /= Var)
          then
-            Error_Msg_NE
-              ("source of assignment must have & as root (SPARK RM 3.10(8)))",
-               Expr, Var);
+            if Emit_Messages then
+               Error_Msg_NE
+                 ("source of assignment must have & as root" &
+                    " (SPARK RM 3.10(8)))",
+                  Expr, Var);
+            end if;
             return;
          end if;
 
@@ -1197,15 +1198,19 @@ package body Sem_SPARK is
 
             if not Is_Decl then
                if not Is_Entity_Name (Target) then
-                  Error_Msg_N
-                    ("target of borrow must be stand-alone variable",
-                     Target);
+                  if Emit_Messages then
+                     Error_Msg_N
+                       ("target of borrow must be stand-alone variable",
+                        Target);
+                  end if;
                   return;
 
                elsif Target_Root /= Expr_Root then
-                  Error_Msg_NE
-                    ("source of borrow must be variable &",
-                     Expr, Target);
+                  if Emit_Messages then
+                     Error_Msg_NE
+                       ("source of borrow must be variable &",
+                        Expr, Target);
+                  end if;
                   return;
                end if;
             end if;
@@ -1220,7 +1225,9 @@ package body Sem_SPARK is
             Check_Expression (Expr, Move);
 
          else
-            Error_Msg_N ("expression not allowed as source of move", Expr);
+            if Emit_Messages then
+               Error_Msg_N ("expression not allowed as source of move", Expr);
+            end if;
             return;
          end if;
 
@@ -1253,7 +1260,7 @@ package body Sem_SPARK is
       begin
          Check_Parameter_Or_Global
            (Expr       => Actual,
-            Typ        => Underlying_Type (Etype (Formal)),
+            Typ        => Retysp (Etype (Formal)),
             Kind       => Ekind (Formal),
             Subp       => Subp,
             Global_Var => False);
@@ -1287,7 +1294,15 @@ package body Sem_SPARK is
    begin
       Inside_Procedure_Call := True;
       Check_Params (Call);
-      Check_Globals (Get_Called_Entity (Call));
+      if Ekind (Get_Called_Entity (Call)) = E_Subprogram_Type then
+         if Emit_Messages then
+            Error_Msg_N
+              ("call through access to subprogram is not allowed in SPARK",
+               Call);
+         end if;
+      else
+         Check_Globals (Get_Called_Entity (Call));
+      end if;
 
       Inside_Procedure_Call := False;
       Update_Params (Call);
@@ -1322,8 +1337,10 @@ package body Sem_SPARK is
         and then Is_Anonymous_Access_Type (Etype (Spec_Id))
         and then not Is_Traversal_Function (Spec_Id)
       then
-         Error_Msg_N ("anonymous access type for result only allowed for "
-                      & "traveral functions", Spec_Id);
+         if Emit_Messages then
+            Error_Msg_N ("anonymous access type for result only allowed for "
+                         & "traversal functions", Spec_Id);
+         end if;
          return;
       end if;
 
@@ -1585,7 +1602,10 @@ package body Sem_SPARK is
 
       begin
          if not Is_Subpath_Expression (Expr) then
-            Error_Msg_N ("name expected here for move/borrow/observe", Expr);
+            if Emit_Messages then
+               Error_Msg_N
+                 ("name expected here for move/borrow/observe", Expr);
+            end if;
             return;
          end if;
 
@@ -1617,7 +1637,15 @@ package body Sem_SPARK is
 
             when N_Function_Call =>
                Read_Params (Expr);
-               Check_Globals (Get_Called_Entity (Expr));
+               if Ekind (Get_Called_Entity (Expr)) = E_Subprogram_Type then
+                  if Emit_Messages then
+                     Error_Msg_N
+                       ("call through access to subprogram is not allowed in "
+                        & "SPARK", Expr);
+                  end if;
+               else
+                  Check_Globals (Get_Called_Entity (Expr));
+               end if;
 
             when N_Op_Concat =>
                Read_Expression (Left_Opnd (Expr));
@@ -1664,9 +1692,10 @@ package body Sem_SPARK is
                      --  There can be only one element for a value of deep type
                      --  in order to avoid aliasing.
 
-                     if not (Box_Present (Assoc))
+                     if not Box_Present (Assoc)
                        and then Is_Deep (Etype (Expression (Assoc)))
                        and then not Is_Singleton_Choice (CL)
+                       and then Emit_Messages
                      then
                         Error_Msg_F
                           ("singleton choice required to prevent aliasing",
@@ -1725,11 +1754,16 @@ package body Sem_SPARK is
                  (Get_Attribute_Id (Attribute_Name (Expr)) =
                     Attribute_Loop_Entry
                   or else
-                  Get_Attribute_Id (Attribute_Name (Expr)) = Attribute_Update);
+                  Get_Attribute_Id (Attribute_Name (Expr)) = Attribute_Update
+                  or else
+                  Get_Attribute_Id (Attribute_Name (Expr)) = Attribute_Image);
 
                Read_Expression (Prefix (Expr));
 
                if Get_Attribute_Id (Attribute_Name (Expr)) = Attribute_Update
+                 or else (Get_Attribute_Id (Attribute_Name (Expr)) =
+                            Attribute_Image
+                          and then Is_Type_Name (Prefix (Expr)))
                then
                   Read_Expression_List (Expressions (Expr));
                end if;
@@ -1761,7 +1795,9 @@ package body Sem_SPARK is
       --  Read mode.
 
       if Mode /= Read then
-         Error_Msg_N ("name expected here for move/borrow/observe", Expr);
+         if Emit_Messages then
+            Error_Msg_N ("name expected here for move/borrow/observe", Expr);
+         end if;
          return;
       end if;
 
@@ -1804,6 +1840,13 @@ package body Sem_SPARK is
             end if;
             return;
 
+         when N_Delta_Constraint =>
+            Read_Expression (Delta_Expression (Expr));
+            if Present (Range_Constraint (Expr)) then
+               Read_Expression (Range_Constraint (Expr));
+            end if;
+            return;
+
          when others =>
             null;
       end case;
@@ -1934,8 +1977,7 @@ package body Sem_SPARK is
                      raise Program_Error;
 
                   when others =>
-                     Error_Msg_Name_1 := Aname;
-                     Error_Msg_N ("attribute % not allowed in SPARK", Expr);
+                     null;
                end case;
             end;
 
@@ -1999,7 +2041,7 @@ package body Sem_SPARK is
          when N_Delta_Aggregate
             | N_Target_Name
          =>
-            Error_Msg_N ("unsupported construct in SPARK", Expr);
+            null;
 
          --  Procedure calls are handled in Check_Node
 
@@ -2330,16 +2372,16 @@ package body Sem_SPARK is
                         KeyO := Perm_Tree_Maps.Get_First_Key
                           (Component (Orig_Tree));
                         while KeyO.Present loop
+                           CompN := Perm_Tree_Maps.Get
+                             (Component (New_Tree), KeyO.K);
+                           CompO := Perm_Tree_Maps.Get
+                             (Component (Orig_Tree), KeyO.K);
                            pragma Assert (CompO /= null);
 
                            Check_Is_Less_Restrictive_Tree (CompN, CompO, E);
 
                            KeyO := Perm_Tree_Maps.Get_Next_Key
                              (Component (Orig_Tree));
-                           CompN := Perm_Tree_Maps.Get
-                             (Component (New_Tree), KeyO.K);
-                           CompO := Perm_Tree_Maps.Get
-                             (Component (Orig_Tree), KeyO.K);
                         end loop;
                      end;
 
@@ -2362,12 +2404,15 @@ package body Sem_SPARK is
          Expl       : Node_Id)
       is
       begin
-         Error_Msg_Node_2 := Loop_Id;
-         Error_Msg_N ("insufficient permission for & when exiting loop &", E);
-         Perm_Mismatch (Exp_Perm => Perm,
-                        Act_Perm => Found_Perm,
-                        N        => Loop_Id,
-                        Expl     => Expl);
+         if Emit_Messages then
+            Error_Msg_Node_2 := Loop_Id;
+            Error_Msg_N
+              ("insufficient permission for & when exiting loop &", E);
+            Perm_Mismatch (Exp_Perm => Perm,
+                           Act_Perm => Found_Perm,
+                           N        => Loop_Id,
+                           Expl     => Expl);
+         end if;
       end Perm_Error_Loop_Exit;
 
       --  Local variables
@@ -2543,6 +2588,7 @@ package body Sem_SPARK is
             | N_Package_Instantiation
             | N_Package_Renaming_Declaration
             | N_Procedure_Instantiation
+            | N_Raise_xxx_Error
             | N_Record_Representation_Clause
             | N_Subprogram_Declaration
             | N_Subprogram_Renaming_Declaration
@@ -2745,7 +2791,7 @@ package body Sem_SPARK is
       Prag_Id : constant Pragma_Id := Get_Pragma_Id (Prag);
       Arg1    : constant Node_Id :=
         First (Pragma_Argument_Associations (Prag));
-      Arg2    : Node_Id;
+      Arg2    : Node_Id := Empty;
 
    begin
       if Present (Arg1) then
@@ -2903,17 +2949,20 @@ package body Sem_SPARK is
       --  function.
 
       if No (Root) then
-         if Nkind (Expr) = N_Function_Call then
-            Error_Msg_N
-              ("incorrect borrow or observe (SPARK RM 3.10(3))", Expr);
-            Error_Msg_N
-              ("\function called must be a traversal function", Expr);
-         else
-            Error_Msg_N
-              ("incorrect borrow or observe (SPARK RM 3.10(3))", Expr);
-            Error_Msg_N
-              ("\expression must be part of stand-alone object or parameter",
-               Expr);
+         if Emit_Messages then
+            if Nkind (Expr) = N_Function_Call then
+               Error_Msg_N
+                 ("incorrect borrow or observe (SPARK RM 3.10(3))", Expr);
+               Error_Msg_N
+                 ("\function called must be a traversal function", Expr);
+            else
+               Error_Msg_N
+                 ("incorrect borrow or observe (SPARK RM 3.10(3))", Expr);
+               Error_Msg_N
+                 ("\expression must be part of stand-alone object or " &
+                    "parameter",
+                  Expr);
+            end if;
          end if;
 
          Status := Error;
@@ -2958,7 +3007,9 @@ package body Sem_SPARK is
                if No (Get_Root_Object
                        (Target, Through_Traversal => False))
                then
-                  Error_Msg_N ("illegal target for assignment", Target);
+                  if Emit_Messages then
+                     Error_Msg_N ("illegal target for assignment", Target);
+                  end if;
                   return;
                end if;
 
@@ -3064,7 +3115,7 @@ package body Sem_SPARK is
                      if Is_Anonymous_Access_Type (Return_Typ) then
                         pragma Assert (Is_Traversal_Function (Subp));
 
-                        if Nkind (Expr) /= N_Null then
+                        if Nkind (Expr) /= N_Null and then Emit_Messages then
                            declare
                               Expr_Root : constant Entity_Id :=
                                 Get_Root_Object (Expr);
@@ -3089,9 +3140,11 @@ package body Sem_SPARK is
                            Check_Expression (Expr, Move);
 
                         else
-                           Error_Msg_N
-                             ("expression not allowed as source of move",
-                              Expr);
+                           if Emit_Messages then
+                              Error_Msg_N
+                                ("expression not allowed as source of move",
+                                 Expr);
+                           end if;
                            return;
                         end if;
 
@@ -3114,14 +3167,14 @@ package body Sem_SPARK is
                Subp  : constant Entity_Id :=
                  Return_Applies_To (Return_Statement_Entity (Stmt));
                Decls : constant List_Id := Return_Object_Declarations (Stmt);
-               Decl  : constant Node_Id := Last (Decls);
+               Decl  : constant Node_Id := Last_Non_Pragma (Decls);
                Obj   : constant Entity_Id := Defining_Identifier (Decl);
                Perm  : Perm_Kind;
 
             begin
                --  SPARK RM 3.10(5): return statement of traversal function
 
-               if Is_Traversal_Function (Subp) then
+               if Is_Traversal_Function (Subp) and then Emit_Messages then
                   Error_Msg_N
                     ("extended return cannot apply to a traversal function",
                      Stmt);
@@ -3254,7 +3307,7 @@ package body Sem_SPARK is
             | N_Selective_Accept
             | N_Timed_Entry_Call
          =>
-            Error_Msg_N ("unsupported construct in SPARK", Stmt);
+            null;
 
          --  The following nodes are never generated in GNATprove mode
 
@@ -3270,12 +3323,12 @@ package body Sem_SPARK is
    ----------------
 
    procedure Check_Type (Typ : Entity_Id) is
-      Check_Typ : constant Entity_Id := Underlying_Type (Typ);
+      Check_Typ : constant Entity_Id := Retysp (Typ);
 
    begin
       case Type_Kind'(Ekind (Check_Typ)) is
          when Access_Kind =>
-            case Access_Kind'(Ekind (Underlying_Type (Check_Typ))) is
+            case Access_Kind'(Ekind (Check_Typ)) is
                when E_Access_Type
                   | E_Anonymous_Access_Type
                =>
@@ -3283,18 +3336,26 @@ package body Sem_SPARK is
                when E_Access_Subtype =>
                   Check_Type (Base_Type (Check_Typ));
                when E_Access_Attribute_Type =>
-                  Error_Msg_N ("access attribute not allowed in SPARK",
-                               Check_Typ);
+                  if Emit_Messages then
+                     Error_Msg_N ("access attribute not allowed in SPARK",
+                                  Check_Typ);
+                  end if;
                when E_Allocator_Type =>
-                  Error_Msg_N ("missing type resolution", Check_Typ);
+                  if Emit_Messages then
+                     Error_Msg_N ("missing type resolution", Check_Typ);
+                  end if;
                when E_General_Access_Type =>
-                  Error_Msg_NE
-                    ("general access type & not allowed in SPARK",
-                     Check_Typ, Check_Typ);
+                  if Emit_Messages then
+                     Error_Msg_NE
+                       ("general access type & not allowed in SPARK",
+                        Check_Typ, Check_Typ);
+                  end if;
                when Access_Subprogram_Kind =>
-                  Error_Msg_NE
-                    ("access to subprogram type & not allowed in SPARK",
-                     Check_Typ, Check_Typ);
+                  if Emit_Messages then
+                     Error_Msg_NE
+                       ("access to subprogram type & not allowed in SPARK",
+                        Check_Typ, Check_Typ);
+                  end if;
             end case;
 
          when E_Array_Type
@@ -3307,9 +3368,11 @@ package body Sem_SPARK is
               and then (Is_Tagged_Type (Check_Typ)
                         or else Is_Class_Wide_Type (Check_Typ))
             then
-               Error_Msg_NE
-                 ("tagged type & cannot be owning in SPARK",
-                  Check_Typ, Check_Typ);
+               if Emit_Messages then
+                  Error_Msg_NE
+                    ("tagged type & cannot be owning in SPARK",
+                     Check_Typ, Check_Typ);
+               end if;
 
             else
                declare
@@ -3317,7 +3380,12 @@ package body Sem_SPARK is
                begin
                   Comp := First_Component_Or_Discriminant (Check_Typ);
                   while Present (Comp) loop
-                     Check_Type (Etype (Comp));
+
+                     --  Ignore components which are not visible in SPARK
+
+                     if Component_Is_Visible_In_SPARK (Comp) then
+                        Check_Type (Etype (Comp));
+                     end if;
                      Next_Component_Or_Discriminant (Comp);
                   end loop;
                end;
@@ -3333,14 +3401,14 @@ package body Sem_SPARK is
          =>
             null;
 
-         --  The following should not arise as underlying types
+         --  Do not check type whose full view is not SPARK
 
          when E_Private_Type
             | E_Private_Subtype
             | E_Limited_Private_Type
             | E_Limited_Private_Subtype
          =>
-            raise Program_Error;
+            null;
       end case;
    end Check_Type;
 
@@ -3526,7 +3594,8 @@ package body Sem_SPARK is
                            pragma Assert (Nkind (N) = N_Selected_Component);
                            declare
                               Comp : constant Entity_Id :=
-                                Entity (Selector_Name (N));
+                                Original_Record_Component
+                                  (Entity (Selector_Name (N)));
                               D : constant Perm_Tree_Access :=
                                 Perm_Tree_Maps.Get
                                   (Component (C.Tree_Access), Comp);
@@ -3577,7 +3646,9 @@ package body Sem_SPARK is
    is
    begin
       if not Is_Subpath_Expression (Expr) then
-         Error_Msg_N ("name expected here for path", Expr);
+         if Emit_Messages then
+            Error_Msg_N ("name expected here for path", Expr);
+         end if;
          return Empty;
       end if;
 
@@ -3630,7 +3701,9 @@ package body Sem_SPARK is
                  Attribute_Loop_Entry
                or else
                Get_Attribute_Id (Attribute_Name (Expr)) =
-                 Attribute_Update);
+                 Attribute_Update
+               or else Get_Attribute_Id (Attribute_Name (Expr)) =
+                 Attribute_Image);
             return Empty;
 
          when others =>
@@ -3750,22 +3823,27 @@ package body Sem_SPARK is
 
    function Is_Deep (Typ : Entity_Id) return Boolean is
    begin
-      case Type_Kind'(Ekind (Underlying_Type (Typ))) is
+      case Type_Kind'(Ekind (Retysp (Typ))) is
          when Access_Kind =>
             return True;
 
          when E_Array_Type
             | E_Array_Subtype
          =>
-            return Is_Deep (Component_Type (Underlying_Type (Typ)));
+            return Is_Deep (Component_Type (Retysp (Typ)));
 
          when Record_Kind =>
             declare
                Comp : Entity_Id;
             begin
-               Comp := First_Component_Or_Discriminant (Typ);
+               Comp := First_Component_Or_Discriminant (Retysp (Typ));
                while Present (Comp) loop
-                  if Is_Deep (Etype (Comp)) then
+
+                  --  Ignore components not visible in SPARK
+
+                  if Component_Is_Visible_In_SPARK (Comp)
+                    and then Is_Deep (Etype (Comp))
+                  then
                      return True;
                   end if;
                   Next_Component_Or_Discriminant (Comp);
@@ -3783,14 +3861,14 @@ package body Sem_SPARK is
          =>
             return False;
 
-         --  The following should not arise as underlying types
+         --  Ignore full view of types if it is not in SPARK
 
          when E_Private_Type
             | E_Private_Subtype
             | E_Limited_Private_Type
             | E_Limited_Private_Subtype
          =>
-            raise Program_Error;
+            return False;
       end case;
    end Is_Deep;
 
@@ -3910,8 +3988,10 @@ package body Sem_SPARK is
 
                when N_Selected_Component =>
                   if Nkind (Expr_Elt) /= N_Selected_Component
-                    or else Entity (Selector_Name (Prefix_Elt))
-                         /= Entity (Selector_Name (Expr_Elt))
+                    or else Original_Record_Component
+                              (Entity (Selector_Name (Prefix_Elt)))
+                         /= Original_Record_Component
+                              (Entity (Selector_Name (Expr_Elt)))
                   then
                      return False;
                   end if;
@@ -3962,7 +4042,10 @@ package body Sem_SPARK is
                        Attribute_Update
                      or else
                      Get_Attribute_Id (Attribute_Name (Expr)) =
-                       Attribute_Loop_Entry))
+                       Attribute_Loop_Entry
+                     or else
+                     Get_Attribute_Id (Attribute_Name (Expr)) =
+                       Attribute_Image))
        or else Nkind (Expr) = N_Op_Concat;
    end Is_Subpath_Expression;
 
@@ -3985,7 +4068,7 @@ package body Sem_SPARK is
 
         --  and the function's first parameter is of an access type.
 
-        and then Is_Access_Type (Etype (First_Formal (E)));
+        and then Is_Access_Type (Retysp (Etype (First_Formal (E))));
    end Is_Traversal_Function;
 
    --------------------------------
@@ -4363,14 +4446,16 @@ package body Sem_SPARK is
    begin
       Set_Root_Object (N, Root, Is_Deref);
 
-      if Is_Deref then
-         Error_Msg_NE
-           ("insufficient permission on dereference from &", N, Root);
-      else
-         Error_Msg_NE ("insufficient permission for &", N, Root);
-      end if;
+      if Emit_Messages then
+         if Is_Deref then
+            Error_Msg_NE
+              ("insufficient permission on dereference from &", N, Root);
+         else
+            Error_Msg_NE ("insufficient permission for &", N, Root);
+         end if;
 
-      Perm_Mismatch (N, Perm, Found_Perm, Expl, Forbidden_Perm);
+         Perm_Mismatch (N, Perm, Found_Perm, Expl, Forbidden_Perm);
+      end if;
    end Perm_Error;
 
    -------------------------------
@@ -4385,10 +4470,12 @@ package body Sem_SPARK is
       Expl       : Node_Id)
    is
    begin
-      Error_Msg_Node_2 := Subp;
-      Error_Msg_NE ("insufficient permission for & when returning from &",
-                    Subp, E);
-      Perm_Mismatch (Subp, Perm, Found_Perm, Expl);
+      if Emit_Messages then
+         Error_Msg_Node_2 := Subp;
+         Error_Msg_NE ("insufficient permission for & when returning from &",
+                       Subp, E);
+         Perm_Mismatch (Subp, Perm, Found_Perm, Expl);
+      end if;
    end Perm_Error_Subprogram_End;
 
    ------------------
@@ -4429,7 +4516,9 @@ package body Sem_SPARK is
                Var := Key.K;
                Borrowed := Get (Current_Borrowers, Var);
 
-               if Is_Prefix_Or_Almost (Pref => Borrowed, Expr => Expr) then
+               if Is_Prefix_Or_Almost (Pref => Borrowed, Expr => Expr)
+                 and then Emit_Messages
+               then
                   Error_Msg_Sloc := Sloc (Borrowed);
                   Error_Msg_N ("object was borrowed #", Expr);
                end if;
@@ -4465,7 +4554,9 @@ package body Sem_SPARK is
                Var := Key.K;
                Observed := Get (Current_Observers, Var);
 
-               if Is_Prefix_Or_Almost (Pref => Observed, Expr => Expr) then
+               if Is_Prefix_Or_Almost (Pref => Observed, Expr => Expr)
+                 and then Emit_Messages
+               then
                   Error_Msg_Sloc := Sloc (Observed);
                   Error_Msg_N ("object was observed #", Expr);
                end if;
@@ -4543,6 +4634,7 @@ package body Sem_SPARK is
                if Is_Deep (Expr_Type)
                  and then not Inside_Procedure_Call
                  and then Present (Get_Root_Object (Expr))
+                 and then Emit_Messages
                then
                   Error_Msg_N ("illegal move during elaboration", Expr);
                end if;
@@ -4587,7 +4679,7 @@ package body Sem_SPARK is
             --  Forbidden during elaboration
 
             if Inside_Elaboration then
-               if not Inside_Procedure_Call then
+               if not Inside_Procedure_Call and then Emit_Messages then
                   Error_Msg_N ("illegal borrow during elaboration", Expr);
                end if;
 
@@ -4606,7 +4698,7 @@ package body Sem_SPARK is
             --  Forbidden during elaboration
 
             if Inside_Elaboration then
-               if not Inside_Procedure_Call then
+               if not Inside_Procedure_Call and then Emit_Messages then
                   Error_Msg_N ("illegal observe during elaboration", Expr);
                end if;
 
@@ -4803,7 +4895,7 @@ package body Sem_SPARK is
       while Present (Formal) loop
          Return_Parameter_Or_Global
            (Id         => Formal,
-            Typ        => Underlying_Type (Etype (Formal)),
+            Typ        => Retysp (Etype (Formal)),
             Kind       => Ekind (Formal),
             Subp       => Subp,
             Global_Var => False);
@@ -4876,6 +4968,7 @@ package body Sem_SPARK is
       E    : Entity_Id;
       Expl : Node_Id)
    is
+      Check_Ty : constant Entity_Id := Retysp (E);
    begin
       --  Shallow extensions are set to RW
 
@@ -4894,7 +4987,7 @@ package body Sem_SPARK is
          --  precision.
 
          when Entire_Object =>
-            case Ekind (E) is
+            case Ekind (Check_Ty) is
                when E_Array_Type
                   | E_Array_Subtype
                =>
@@ -4908,7 +5001,8 @@ package body Sem_SPARK is
                              Permission          => Read_Write,
                              Children_Permission => Read_Write));
                   begin
-                     Set_Perm_Extensions_Move (C, Component_Type (E), Expl);
+                     Set_Perm_Extensions_Move
+                       (C, Component_Type (Check_Ty), Expl);
                      T.all.Tree := (Kind         => Array_Component,
                                     Is_Node_Deep => Is_Node_Deep (T),
                                     Explanation  => Expl,
@@ -4923,17 +5017,36 @@ package body Sem_SPARK is
                      Hashtbl : Perm_Tree_Maps.Instance;
 
                   begin
-                     Comp := First_Component_Or_Discriminant (E);
+                     Comp := First_Component_Or_Discriminant (Check_Ty);
                      while Present (Comp) loop
-                        C := new Perm_Tree_Wrapper'
-                          (Tree =>
-                             (Kind                => Entire_Object,
-                              Is_Node_Deep        => Is_Deep (Etype (Comp)),
-                              Explanation         => Expl,
-                              Permission          => Read_Write,
-                              Children_Permission => Read_Write));
-                        Set_Perm_Extensions_Move (C, Etype (Comp), Expl);
-                        Perm_Tree_Maps.Set (Hashtbl, Comp, C);
+
+                        --  Unfold components which are visible in SPARK
+
+                        if Component_Is_Visible_In_SPARK (Comp) then
+                           C := new Perm_Tree_Wrapper'
+                             (Tree =>
+                                (Kind                => Entire_Object,
+                                 Is_Node_Deep        => Is_Deep (Etype (Comp)),
+                                 Explanation         => Expl,
+                                 Permission          => Read_Write,
+                                 Children_Permission => Read_Write));
+                           Set_Perm_Extensions_Move (C, Etype (Comp), Expl);
+
+                        --  Hidden components are never deep
+
+                        else
+                           C := new Perm_Tree_Wrapper'
+                             (Tree =>
+                                (Kind                => Entire_Object,
+                                 Is_Node_Deep        => False,
+                                 Explanation         => Expl,
+                                 Permission          => Read_Write,
+                                 Children_Permission => Read_Write));
+                           Set_Perm_Extensions (C, Read_Write, Expl => Expl);
+                        end if;
+
+                        Perm_Tree_Maps.Set
+                          (Hashtbl, Original_Record_Component (Comp), C);
                         Next_Component_Or_Discriminant (Comp);
                      end loop;
 
@@ -4955,7 +5068,8 @@ package body Sem_SPARK is
             Set_Perm_Extensions (T, No_Access, Expl);
 
          when Array_Component =>
-            Set_Perm_Extensions_Move (Get_Elem (T), Component_Type (E), Expl);
+            Set_Perm_Extensions_Move
+              (Get_Elem (T), Component_Type (Check_Ty), Expl);
 
          when Record_Component =>
             declare
@@ -4963,11 +5077,23 @@ package body Sem_SPARK is
                Comp : Entity_Id;
 
             begin
-               Comp := First_Component_Or_Discriminant (E);
+               Comp := First_Component_Or_Discriminant (Check_Ty);
                while Present (Comp) loop
-                  C := Perm_Tree_Maps.Get (Component (T), Comp);
+                  C := Perm_Tree_Maps.Get
+                    (Component (T), Original_Record_Component (Comp));
                   pragma Assert (C /= null);
-                  Set_Perm_Extensions_Move (C, Etype (Comp), Expl);
+
+                  --  Move visible components
+
+                  if Component_Is_Visible_In_SPARK (Comp) then
+                     Set_Perm_Extensions_Move (C, Etype (Comp), Expl);
+
+                  --  Hidden components are never deep
+
+                  else
+                     Set_Perm_Extensions (C, Read_Write, Expl => Expl);
+                  end if;
+
                   Next_Component_Or_Discriminant (Comp);
                end loop;
             end;
@@ -5073,7 +5199,9 @@ package body Sem_SPARK is
 
                if Kind (C) = Record_Component then
                   declare
-                     Comp : constant Entity_Id := Entity (Selector_Name (N));
+                     Comp : constant Entity_Id :=
+                       Original_Record_Component
+                         (Entity (Selector_Name (N)));
                      D : constant Perm_Tree_Access :=
                        Perm_Tree_Maps.Get (Component (C), Comp);
                      pragma Assert (D /= null);
@@ -5102,11 +5230,14 @@ package body Sem_SPARK is
 
                   begin
                      Comp :=
-                       First_Component_Or_Discriminant (Etype (Prefix (N)));
+                       First_Component_Or_Discriminant
+                         (Retysp (Etype (Prefix (N))));
 
                      while Present (Comp) loop
                         if Perm /= None
-                          and then Comp = Entity (Selector_Name (N))
+                          and then Original_Record_Component (Comp) =
+                          Original_Record_Component
+                            (Entity (Selector_Name (N)))
                         then
                            P := Perm;
                         else
@@ -5116,15 +5247,22 @@ package body Sem_SPARK is
                         D := new Perm_Tree_Wrapper'
                           (Tree =>
                              (Kind                => Entire_Object,
-                              Is_Node_Deep        => Is_Deep (Etype (Comp)),
+                              Is_Node_Deep        =>
+                                --  Hidden components are never deep
+                                Component_Is_Visible_In_SPARK (Comp)
+                                  and then Is_Deep (Etype (Comp)),
                               Explanation         => Expl,
                               Permission          => P,
                               Children_Permission => Child_P));
-                        Perm_Tree_Maps.Set (Hashtbl, Comp, D);
+                        Perm_Tree_Maps.Set
+                          (Hashtbl, Original_Record_Component (Comp), D);
 
                         --  Store the tree to return for this component
 
-                        if Comp = Entity (Selector_Name (N)) then
+                        if Original_Record_Component (Comp) =
+                          Original_Record_Component
+                            (Entity (Selector_Name (N)))
+                        then
                            D_This := D;
                         end if;
 
@@ -5380,14 +5518,6 @@ package body Sem_SPARK is
             --  Functions cannot have outputs in SPARK
 
             elsif Ekind (Subp) = E_Function then
-               if Kind = E_Out_Parameter then
-                  Error_Msg_N ("function with OUT parameter is not "
-                               & "allowed in SPARK", Id);
-               else
-                  Error_Msg_N ("function with `IN OUT` parameter is not "
-                               & "allowed in SPARK", Id);
-               end if;
-
                return;
 
             --  Deep types define a borrow or a move
@@ -5424,7 +5554,7 @@ package body Sem_SPARK is
       while Present (Formal) loop
          Setup_Parameter_Or_Global
            (Id         => Formal,
-            Typ        => Underlying_Type (Etype (Formal)),
+            Typ        => Retysp (Etype (Formal)),
             Kind       => Ekind (Formal),
             Subp       => Subp,
             Global_Var => False,
@@ -5457,11 +5587,12 @@ package body Sem_SPARK is
       while Present (Comp) loop
          Setup_Parameter_Or_Global
            (Id         => Comp,
-            Typ        => Underlying_Type (Etype (Comp)),
+            Typ        => Retysp (Etype (Comp)),
             Kind       => Kind,
             Subp       => Subp,
             Global_Var => False,
             Expl       => Comp);
+
          Next_Component_Or_Discriminant (Comp);
       end loop;
    end Setup_Protected_Components;
diff --git a/gcc/ada/sem_spark.ads b/gcc/ada/sem_spark.ads
index ee4126acc5df63628a69d9e0d402b4685fb4c16d..0e8b29b41f7bf2176a9d98549fa00fe0f7d2607b 100644
--- a/gcc/ada/sem_spark.ads
+++ b/gcc/ada/sem_spark.ads
@@ -132,12 +132,34 @@
 --  get read-write permission, which can be specified using the node's
 --  Children_Permission field.
 
+--  The implementation is done as a generic, so that GNATprove can instantiate
+--  it with suitable formal arguments that depend on the SPARK_Mode boundary
+--  as well as the two-phase architecture of GNATprove (which runs the GNAT
+--  front end twice, once for global generation and once for analysis).
+
 with Types; use Types;
 
+generic
+   with function Retysp (X : Entity_Id) return Entity_Id;
+   --  Return the representative type in SPARK for a type.
+
+   with function Component_Is_Visible_In_SPARK (C : Entity_Id) return Boolean;
+   --  Return whether a component is visible in SPARK. No aliasing check is
+   --  performed for a component that is visible.
+
+   with function Emit_Messages return Boolean;
+   --  Return True when error messages should be emitted.
+
 package Sem_SPARK is
 
    procedure Check_Safe_Pointers (N : Node_Id);
    --  The entry point of this package. It analyzes a node and reports errors
    --  when there are violations of ownership rules.
 
+   function Is_Deep (Typ : Entity_Id) return Boolean;
+   --  A function that can tell whether a type is deep. Returns True if the
+   --  type passed as argument is deep.
+
+   function Is_Traversal_Function (E : Entity_Id) return Boolean;
+
 end Sem_SPARK;