OSDN Git Service

* gigi.h (standard_datatypes): Add ADT_fdesc_type and ADT_null_fdesc.
[pf3gnuchains/gcc-fork.git] / gcc / ada / trans.c
index e004002..4dc5202 100644 (file)
@@ -6,7 +6,7 @@
  *                                                                          *
  *                          C Implementation File                           *
  *                                                                          *
- *          Copyright (C) 1992-2004, Free Software Foundation, Inc.         *
+ *          Copyright (C) 1992-2008, Free Software Foundation, Inc.         *
  *                                                                          *
  * GNAT is free software;  you can  redistribute it  and/or modify it under *
  * terms of the  GNU General Public License as published  by the Free Soft- *
@@ -16,8 +16,8 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License *
  * for  more details.  You should have  received  a copy of the GNU General *
  * Public License  distributed with GNAT;  see file COPYING.  If not, write *
- * to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, *
- * MA 02111-1307, USA.                                                      *
+ * to  the  Free Software Foundation,  51  Franklin  Street,  Fifth  Floor, *
+ * Boston, MA 02110-1301, USA.                                              *
  *                                                                          *
  * GNAT was originally developed  by the GNAT team at  New York University. *
  * Extensive contributions were provided by Ada Core Technologies Inc.      *
@@ -35,6 +35,7 @@
 #include "rtl.h"
 #include "expr.h"
 #include "ggc.h"
+#include "cgraph.h"
 #include "function.h"
 #include "except.h"
 #include "debug.h"
 #include "ada-tree.h"
 #include "gigi.h"
 
+/* We should avoid allocating more than ALLOCA_THRESHOLD bytes via alloca,
+   for fear of running out of stack space.  If we need more, we use xmalloc
+   instead.  */
+#define ALLOCA_THRESHOLD 1000
+
+/* Let code below know whether we are targetting VMS without need of
+   intrusive preprocessor directives.  */
+#ifndef TARGET_ABI_OPEN_VMS
+#define TARGET_ABI_OPEN_VMS 0
+#endif
+
+extern char *__gnat_to_canonical_file_spec (char *);
+
 int max_gnat_nodes;
 int number_names;
+int number_files;
 struct Node *Nodes_Ptr;
 Node_Id *Next_Node_Ptr;
 Node_Id *Prev_Node_Ptr;
@@ -75,6 +90,31 @@ const char *ref_filename;
    types with representation information. */
 bool type_annotate_only;
 
+/* When not optimizing, we cache the 'First, 'Last and 'Length attributes
+   of unconstrained array IN parameters to avoid emitting a great deal of
+   redundant instructions to recompute them each time.  */
+struct parm_attr GTY (())
+{
+  int id; /* GTY doesn't like Entity_Id.  */
+  int dim;
+  tree first;
+  tree last;
+  tree length;
+};
+
+typedef struct parm_attr *parm_attr;
+
+DEF_VEC_P(parm_attr);
+DEF_VEC_ALLOC_P(parm_attr,gc);
+
+struct language_function GTY(())
+{
+  VEC(parm_attr,gc) *parm_attr_cache;
+};
+
+#define f_parm_attr_cache \
+  DECL_STRUCT_FUNCTION (current_function_decl)->language->parm_attr_cache
+
 /* A structure used to gather together information about a statement group.
    We use this to gather related statements, for example the "then" part
    of a IF.  In the case where it represents a lexical scope, we may also
@@ -82,7 +122,6 @@ bool type_annotate_only;
 
 struct stmt_group GTY((chain_next ("%h.previous"))) {
   struct stmt_group *previous; /* Previous code group.  */
-  struct stmt_group *global;   /* Global code group from the level.  */
   tree stmt_list;              /* List of statements for this code group. */
   tree block;                  /* BLOCK for this code group, if any. */
   tree cleanups;               /* Cleanups for this code group, if any.  */
@@ -131,21 +170,26 @@ static GTY(()) tree gnu_loop_label_stack;
    TREE_VALUE of each entry is the label at the end of the switch.  */
 static GTY(()) tree gnu_switch_label_stack;
 
+/* List of TREE_LIST nodes containing the stacks for N_{Push,Pop}_*_Label.  */
+static GTY(()) tree gnu_constraint_error_label_stack;
+static GTY(()) tree gnu_storage_error_label_stack;
+static GTY(()) tree gnu_program_error_label_stack;
+
 /* Map GNAT tree codes to GCC tree codes for simple expressions.  */
 static enum tree_code gnu_codes[Number_Node_Kinds];
 
 /* Current node being treated, in case abort called.  */
 Node_Id error_gnat_node;
 
+static void init_code_table (void);
 static void Compilation_Unit_to_gnu (Node_Id);
 static void record_code_position (Node_Id);
 static void insert_code_for (Node_Id);
-static void start_stmt_group (void);
-static void add_cleanup (tree);
+static void add_cleanup (tree, Node_Id);
 static tree mark_visited (tree *, int *, void *);
-static tree mark_unvisited (tree *, int *, void *);
-static tree end_stmt_group (void);
+static tree unshare_save_expr (tree *, int *, void *);
 static void add_stmt_list (List_Id);
+static void push_exception_label_stack (tree *, Entity_Id);
 static tree build_stmt_group (List_Id, bool);
 static void push_stack (tree *, tree, tree);
 static void pop_stack (tree *);
@@ -158,17 +202,16 @@ static tree emit_range_check (tree, Node_Id);
 static tree emit_index_check (tree, tree, tree, tree);
 static tree emit_check (tree, tree, int);
 static tree convert_with_check (Entity_Id, tree, bool, bool, bool);
-static bool addressable_p (tree);
-static tree assoc_to_constructor (Node_Id, tree);
+static bool larger_record_type_p (tree, tree);
+static bool addressable_p (tree, tree);
+static tree assoc_to_constructor (Entity_Id, Node_Id, tree);
 static tree extract_values (tree, tree);
 static tree pos_to_constructor (Node_Id, tree, Entity_Id);
 static tree maybe_implicit_deref (tree);
+static tree gnat_stabilize_reference (tree, bool);
 static tree gnat_stabilize_reference_1 (tree, bool);
-static void annotate_with_node (tree, Node_Id);
-
-/* Constants for +0.5 and -0.5 for float-to-integer rounding.  */
-static REAL_VALUE_TYPE dconstp5;
-static REAL_VALUE_TYPE dconstmp5;
+static void set_expr_location_from_node (tree, Node_Id);
+static int lvalue_required_p (Node_Id, tree, int);
 \f
 /* This is the main program of the back-end.  It sets up all the table
    structures and then generates code.  */
@@ -178,17 +221,19 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name,
       struct Node *nodes_ptr, Node_Id *next_node_ptr, Node_Id *prev_node_ptr,
       struct Elist_Header *elists_ptr, struct Elmt_Item *elmts_ptr,
       struct String_Entry *strings_ptr, Char_Code *string_chars_ptr,
-      struct List_Header *list_headers_ptr, Int number_units ATTRIBUTE_UNUSED,
-      char *file_info_ptr ATTRIBUTE_UNUSED, Entity_Id standard_integer,
-      Entity_Id standard_long_long_float, Entity_Id standard_exception_type,
-      Int gigi_operating_mode)
+      struct List_Header *list_headers_ptr, Nat number_file,
+      struct File_Info_Type *file_info_ptr ATTRIBUTE_UNUSED,
+      Entity_Id standard_integer, Entity_Id standard_long_long_float,
+      Entity_Id standard_exception_type, Int gigi_operating_mode)
 {
   tree gnu_standard_long_long_float;
   tree gnu_standard_exception_type;
   struct elab_info *info;
+  int i ATTRIBUTE_UNUSED;
 
   max_gnat_nodes = max_gnat_node;
   number_names = number_name;
+  number_files = number_file;
   Nodes_Ptr = nodes_ptr;
   Next_Node_Ptr = next_node_ptr;
   Prev_Node_Ptr = prev_node_ptr;
@@ -200,6 +245,32 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name,
 
   type_annotate_only = (gigi_operating_mode == 1);
 
+  for (i = 0; i < number_files; i++)
+    {
+      /* Use the identifier table to make a permanent copy of the filename as
+        the name table gets reallocated after Gigi returns but before all the
+        debugging information is output.  The __gnat_to_canonical_file_spec
+        call translates filenames from pragmas Source_Reference that contain
+        host style syntax not understood by gdb. */
+      const char *filename
+       = IDENTIFIER_POINTER
+          (get_identifier
+           (__gnat_to_canonical_file_spec
+            (Get_Name_String (file_info_ptr[i].File_Name))));
+
+      /* We rely on the order isomorphism between files and line maps.  */
+      gcc_assert ((int) line_table->used == i);
+
+      /* We create the line map for a source file at once, with a fixed number
+        of columns chosen to avoid jumping over the next power of 2.  */
+      linemap_add (line_table, LC_ENTER, 0, filename, 1);
+      linemap_line_start (line_table, file_info_ptr[i].Num_Source_Lines, 252);
+      linemap_position_for_column (line_table, 252 - 1);
+      linemap_add (line_table, LC_LEAVE, 0, NULL, 0);
+    }
+
+  /* Initialize ourselves.  */
+  init_code_table ();
   init_gnat_to_gnu ();
   gnat_compute_largest_alignment ();
   init_dummy_type ();
@@ -212,6 +283,20 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name,
       TYPE_SIZE_UNIT (void_type_node) = size_zero_node;
     }
 
+  /* Enable GNAT stack checking method if needed */
+  if (!Stack_Check_Probes_On_Target)
+    set_stack_check_libfunc (gen_rtx_SYMBOL_REF (Pmode, "_gnat_stack_check"));
+
+  /* Give names and make TYPE_DECLs for common types.  */
+  create_type_decl (get_identifier (SIZE_TYPE), sizetype,
+                   NULL, false, true, Empty);
+  create_type_decl (get_identifier ("integer"), integer_type_node,
+                   NULL, false, true, Empty);
+  create_type_decl (get_identifier ("unsigned char"), char_type_node,
+                   NULL, false, true, Empty);
+  create_type_decl (get_identifier ("long integer"), long_integer_type_node,
+                   NULL, false, true, Empty);
+
   /* Save the type we made for integer as the type for Standard.Integer.
      Then make the rest of the standard types.  Note that some of these
      may be subtypes.  */
@@ -219,6 +304,10 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name,
                 false);
 
   gnu_except_ptr_stack = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE);
+  gnu_constraint_error_label_stack
+    = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE);
+  gnu_storage_error_label_stack = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE);
+  gnu_program_error_label_stack = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE);
 
   gnu_standard_long_long_float
     = gnat_to_gnu_entity (Base_Type (standard_long_long_float), NULL_TREE, 0);
@@ -236,12 +325,11 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name,
 #endif
 
   /* If we are using the GCC exception mechanism, let GCC know.  */
-  if (Exception_Mechanism == GCC_ZCX)
+  if (Exception_Mechanism == Back_End_Exceptions)
     gnat_init_gcc_eh ();
 
-  if (Nkind (gnat_root) != N_Compilation_Unit)
-    abort ();
-
+  gcc_assert (Nkind (gnat_root) == N_Compilation_Unit);
+  start_stmt_group ();
   Compilation_Unit_to_gnu (gnat_root);
 
   /* Now see if we have any elaboration procedures to deal with. */
@@ -250,13 +338,20 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name,
       tree gnu_body = DECL_SAVED_TREE (info->elab_proc);
       tree gnu_stmts;
 
-      /* Mark everything we have as not visited.  */
-      walk_tree_without_duplicates (&gnu_body, mark_unvisited, NULL);
+      /* Unshare SAVE_EXPRs between subprograms.  These are not unshared by
+        the gimplifier for obvious reasons, but it turns out that we need to
+        unshare them for the global level because of SAVE_EXPRs made around
+        checks for global objects and around allocators for global objects
+        of variable size, in order to prevent node sharing in the underlying
+        expression.  Note that this implicitly assumes that the SAVE_EXPR
+        nodes themselves are not shared between subprograms, which would be
+        an upstream bug for which we would not change the outcome.  */
+      walk_tree_without_duplicates (&gnu_body, unshare_save_expr, NULL);
 
       /* Set the current function to be the elaboration procedure and gimplify
         what we have.  */
       current_function_decl = info->elab_proc;
-      gimplify_body (&gnu_body, info->elab_proc);
+      gimplify_body (&gnu_body, info->elab_proc, true);
 
       /* We should have a BIND_EXPR, but it may or may not have any statements
         in it.  If it doesn't have any, we have nothing to do.  */
@@ -266,7 +361,10 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name,
 
       /* If there are no statements, there is no elaboration code.  */
       if (!gnu_stmts || !STATEMENT_LIST_HEAD (gnu_stmts))
-       Set_Has_No_Elaboration_Code (info->gnat_node, 1);
+       {
+         Set_Has_No_Elaboration_Code (info->gnat_node, 1);
+         cgraph_remove_node (cgraph_node (info->elab_proc));
+       }
       else
        {
          /* Otherwise, compile the function.  Note that we'll be gimplifying
@@ -275,40 +373,111 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name,
          end_subprog_body (gnu_body);
        }
     }
+
+  /* We cannot track the location of errors past this point.  */
+  error_gnat_node = Empty;
 }
 \f
-/* Perform initializations for this module.  */
-
-void
-gnat_init_stmt_group ()
+/* Return a positive value if an lvalue is required for GNAT_NODE.
+   GNU_TYPE is the type that will be used for GNAT_NODE in the
+   translated GNU tree.  ALIASED indicates whether the underlying
+   object represented by GNAT_NODE is aliased in the Ada sense.
+
+   The function climbs up the GNAT tree starting from the node and
+   returns 1 upon encountering a node that effectively requires an
+   lvalue downstream.  It returns int instead of bool to facilitate
+   usage in non purely binary logic contexts.  */
+
+static int
+lvalue_required_p (Node_Id gnat_node, tree gnu_type, int aliased)
 {
-  /* Initialize ourselves.  */
-  init_code_table ();
-  start_stmt_group ();
+  Node_Id gnat_parent = Parent (gnat_node), gnat_temp;
 
-  current_stmt_group->global = current_stmt_group;
+  switch (Nkind (gnat_parent))
+    {
+    case N_Reference:
+      return 1;
 
-  /* Enable GNAT stack checking method if needed */
-  if (!Stack_Check_Probes_On_Target)
-    set_stack_check_libfunc (gen_rtx_SYMBOL_REF (Pmode, "_gnat_stack_check"));
+    case N_Attribute_Reference:
+      {
+       unsigned char id = Get_Attribute_Id (Attribute_Name (gnat_parent));
+       return id == Attr_Address
+              || id == Attr_Access
+              || id == Attr_Unchecked_Access
+              || id == Attr_Unrestricted_Access;
+      }
+
+    case N_Parameter_Association:
+    case N_Function_Call:
+    case N_Procedure_Call_Statement:
+      return (must_pass_by_ref (gnu_type) || default_pass_by_ref (gnu_type));
+
+    case N_Indexed_Component:
+      /* Only the array expression can require an lvalue.  */
+      if (Prefix (gnat_parent) != gnat_node)
+       return 0;
+
+      /* ??? Consider that referencing an indexed component with a
+        non-constant index forces the whole aggregate to memory.
+        Note that N_Integer_Literal is conservative, any static
+        expression in the RM sense could probably be accepted.  */
+      for (gnat_temp = First (Expressions (gnat_parent));
+          Present (gnat_temp);
+          gnat_temp = Next (gnat_temp))
+       if (Nkind (gnat_temp) != N_Integer_Literal)
+         return 1;
 
-  if (Exception_Mechanism == Front_End_ZCX)
-    abort ();
+      /* ... fall through ... */
+
+    case N_Slice:
+      /* Only the array expression can require an lvalue.  */
+      if (Prefix (gnat_parent) != gnat_node)
+       return 0;
+
+      aliased |= Has_Aliased_Components (Etype (gnat_node));
+      return lvalue_required_p (gnat_parent, gnu_type, aliased);
+
+    case N_Selected_Component:
+      aliased |= Is_Aliased (Entity (Selector_Name (gnat_parent)));
+      return lvalue_required_p (gnat_parent, gnu_type, aliased);
+
+    case N_Object_Renaming_Declaration:
+      /* We need to make a real renaming only if the constant object is
+        aliased or if we may use a renaming pointer; otherwise we can
+        optimize and return the rvalue.  We make an exception if the object
+        is an identifier since in this case the rvalue can be propagated
+        attached to the CONST_DECL.  */
+      return (aliased != 0
+             /* This should match the constant case of the renaming code.  */
+             || Is_Composite_Type (Etype (Name (gnat_parent)))
+             || Nkind (Name (gnat_parent)) == N_Identifier);
+
+    default:
+      return 0;
+    }
 
-  REAL_ARITHMETIC (dconstp5, RDIV_EXPR, dconst1, dconst2);
-  REAL_ARITHMETIC (dconstmp5, RDIV_EXPR, dconstm1, dconst2);
+  gcc_unreachable ();
 }
-\f
+
 /* Subroutine of gnat_to_gnu to translate gnat_node, an N_Identifier,
-   to a GCC tree, which is returned.  GNU_RESULT_TYPE_P is a pointer to
-   where we should place the result type.  */
+   to a GCC tree, which is returned.  GNU_RESULT_TYPE_P is a pointer
+   to where we should place the result type.  */
 
 static tree
 Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
 {
-  tree gnu_result_type;
-  tree gnu_result;
   Node_Id gnat_temp, gnat_temp_type;
+  tree gnu_result, gnu_result_type;
+
+  /* Whether we should require an lvalue for GNAT_NODE.  Needed in
+     specific circumstances only, so evaluated lazily.  < 0 means
+     unknown, > 0 means known true, 0 means known false.  */
+  int require_lvalue = -1;
+
+  /* If GNAT_NODE is a constant, whether we should use the initialization
+     value instead of the constant entity, typically for scalars with an
+     address clause when the parent doesn't require an lvalue.  */
+  bool use_constant_initializer = false;
 
   /* If the Etype of this node does not equal the Etype of the Entity,
      something is wrong with the entity map, probably in generic
@@ -323,23 +492,23 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
               ? gnat_node : Entity (gnat_node));
   gnat_temp_type = Etype (gnat_temp);
 
-  if (Etype (gnat_node) != gnat_temp_type
-      && !(Is_Packed (gnat_temp_type)
-          && Etype (gnat_node) == Packed_Array_Type (gnat_temp_type))
-      && !(Is_Class_Wide_Type (Etype (gnat_node)))
-      && !(IN (Ekind (gnat_temp_type), Private_Kind)
-          && Present (Full_View (gnat_temp_type))
-          && ((Etype (gnat_node) == Full_View (gnat_temp_type))
-              || (Is_Packed (Full_View (gnat_temp_type))
-                  && (Etype (gnat_node)
-                      == Packed_Array_Type (Full_View (gnat_temp_type))))))
-      && (!Is_Itype (Etype (gnat_node)) || !Is_Itype (gnat_temp_type))
-      && (Ekind (gnat_temp) == E_Variable
-         || Ekind (gnat_temp) == E_Component
-         || Ekind (gnat_temp) == E_Constant
-         || Ekind (gnat_temp) == E_Loop_Parameter
-         || IN (Ekind (gnat_temp), Formal_Kind)))
-    abort ();
+  gcc_assert (Etype (gnat_node) == gnat_temp_type
+             || (Is_Packed (gnat_temp_type)
+                 && Etype (gnat_node) == Packed_Array_Type (gnat_temp_type))
+             || (Is_Class_Wide_Type (Etype (gnat_node)))
+             || (IN (Ekind (gnat_temp_type), Private_Kind)
+                 && Present (Full_View (gnat_temp_type))
+                 && ((Etype (gnat_node) == Full_View (gnat_temp_type))
+                     || (Is_Packed (Full_View (gnat_temp_type))
+                         && (Etype (gnat_node)
+                             == Packed_Array_Type (Full_View
+                                                   (gnat_temp_type))))))
+             || (Is_Itype (Etype (gnat_node)) && Is_Itype (gnat_temp_type))
+             || !(Ekind (gnat_temp) == E_Variable
+                  || Ekind (gnat_temp) == E_Component
+                  || Ekind (gnat_temp) == E_Constant
+                  || Ekind (gnat_temp) == E_Loop_Parameter
+                  || IN (Ekind (gnat_temp), Formal_Kind)));
 
   /* If this is a reference to a deferred constant whose partial view is an
      unconstrained private type, the proper type is on the full view of the
@@ -351,20 +520,17 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
      in particular if it is a derived type  */
   if (Is_Private_Type (gnat_temp_type)
       && Has_Unknown_Discriminants (gnat_temp_type)
-      && Present (Full_View (gnat_temp))
-      && !Is_Type (gnat_temp))
+      && Ekind (gnat_temp) == E_Constant
+      && Present (Full_View (gnat_temp)))
     {
       gnat_temp = Full_View (gnat_temp);
       gnat_temp_type = Etype (gnat_temp);
-      gnu_result_type = get_unpadded_type (gnat_temp_type);
     }
   else
     {
-      /* Expand the type of this identitier first, in case it is an enumeral
-        literal, which only get made when the type is expanded.  There is no
-        order-of-elaboration issue here.  We want to use the Actual_Subtype if
-        it has already been elaborated, otherwise the Etype.  Avoid using
-        Actual_Subtype for packed arrays to simplify things.  */
+      /* We want to use the Actual_Subtype if it has already been elaborated,
+        otherwise the Etype.  Avoid using Actual_Subtype for packed arrays to
+        simplify things.  */
       if ((Ekind (gnat_temp) == E_Constant
           || Ekind (gnat_temp) == E_Variable || Is_Formal (gnat_temp))
          && !(Is_Array_Type (Etype (gnat_temp))
@@ -374,11 +540,41 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
        gnat_temp_type = Actual_Subtype (gnat_temp);
       else
        gnat_temp_type = Etype (gnat_node);
+    }
 
-      gnu_result_type = get_unpadded_type (gnat_temp_type);
+  /* Expand the type of this identifier first, in case it is an enumeral
+     literal, which only get made when the type is expanded.  There is no
+     order-of-elaboration issue here.  */
+  gnu_result_type = get_unpadded_type (gnat_temp_type);
+
+  /* If this is a non-imported scalar constant with an address clause,
+     retrieve the value instead of a pointer to be dereferenced unless
+     an lvalue is required.  This is generally more efficient and actually
+     required if this is a static expression because it might be used
+     in a context where a dereference is inappropriate, such as a case
+     statement alternative or a record discriminant.  There is no possible
+     volatile-ness shortciruit here since Volatile constants must be imported
+     per C.6. */
+  if (Ekind (gnat_temp) == E_Constant && Is_Scalar_Type (gnat_temp_type)
+      && !Is_Imported (gnat_temp)
+      && Present (Address_Clause (gnat_temp)))
+    {
+      require_lvalue = lvalue_required_p (gnat_node, gnu_result_type,
+                                         Is_Aliased (gnat_temp));
+      use_constant_initializer = !require_lvalue;
     }
 
-  gnu_result = gnat_to_gnu_entity (gnat_temp, NULL_TREE, 0);
+  if (use_constant_initializer)
+    {
+      /* If this is a deferred constant, the initializer is attached to the
+        the full view.  */
+      if (Present (Full_View (gnat_temp)))
+       gnat_temp = Full_View (gnat_temp);
+
+      gnu_result = gnat_to_gnu (Expression (Declaration_Node (gnat_temp)));
+    }
+  else
+    gnu_result = gnat_to_gnu_entity (gnat_temp, NULL_TREE, 0);
 
   /* If we are in an exception handler, force this variable into memory to
      ensure optimization does not remove stores that appear redundant but are
@@ -388,24 +584,30 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
      handler, only if it is referenced in the handler and declared in an
      enclosing block, but we have no way of testing that right now.
 
-     ??? Also, for now all we can do is make it volatile.  But we only
-     do this for SJLJ.  */
+     ??? We used to essentially set the TREE_ADDRESSABLE flag on the variable
+     here, but it can now be removed by the Tree aliasing machinery if the
+     address of the variable is never taken.  All we can do is to make the
+     variable volatile, which might incur the generation of temporaries just
+     to access the memory in some circumstances.  This can be avoided for
+     variables of non-constant size because they are automatically allocated
+     to memory.  There might be no way of allocating a proper temporary for
+     them in any case.  We only do this for SJLJ though.  */
   if (TREE_VALUE (gnu_except_ptr_stack)
-      && TREE_CODE (gnu_result) == VAR_DECL)
+      && TREE_CODE (gnu_result) == VAR_DECL
+      && TREE_CODE (DECL_SIZE_UNIT (gnu_result)) == INTEGER_CST)
     TREE_THIS_VOLATILE (gnu_result) = TREE_SIDE_EFFECTS (gnu_result) = 1;
 
   /* Some objects (such as parameters passed by reference, globals of
      variable size, and renamed objects) actually represent the address
      of the object.  In that case, we must do the dereference.  Likewise,
-     deal with parameters to foreign convention subprograms.  Call fold
-     here since GNU_RESULT may be a CONST_DECL.  */
+     deal with parameters to foreign convention subprograms.  */
   if (DECL_P (gnu_result)
       && (DECL_BY_REF_P (gnu_result)
          || (TREE_CODE (gnu_result) == PARM_DECL
              && DECL_BY_COMPONENT_PTR_P (gnu_result))))
     {
       bool ro = DECL_POINTS_TO_READONLY_P (gnu_result);
-      tree initial;
+      tree renamed_obj;
 
       if (TREE_CODE (gnu_result) == PARM_DECL
          && DECL_BY_COMPONENT_PTR_P (gnu_result))
@@ -414,37 +616,23 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
                            convert (build_pointer_type (gnu_result_type),
                                     gnu_result));
 
-      /* If the object is constant, we try to do the dereference directly
-        through the DECL_INITIAL.  This is actually required in order to get
-        correct aliasing information for renamed objects that are components
-        of non-aliased aggregates, because the type of the renamed object and
-        that of the aggregate don't alias.
-
-        Note that we expect the initial value to have been stabilized.
-        If it contains e.g. a variable reference, we certainly don't want
-        to re-evaluate the variable each time the renaming is used.
-
-        Stabilization is currently not performed at the global level but
-        create_var_decl avoids setting DECL_INITIAL if the value is not
-        constant then, and we get to the pointer dereference below.
-
-        ??? Couldn't the aliasing issue show up again in this case ?
-        There is no obvious reason why not.  */
-      else if (TREE_READONLY (gnu_result)
-              && DECL_INITIAL (gnu_result)
-              /* Strip possible conversion to reference type.  */
-              && ((initial = TREE_CODE (DECL_INITIAL (gnu_result))
-                   == NOP_EXPR
-                   ? TREE_OPERAND (DECL_INITIAL (gnu_result), 0)
-                   : DECL_INITIAL (gnu_result), 1))
-              && TREE_CODE (initial) == ADDR_EXPR
-              && (TREE_CODE (TREE_OPERAND (initial, 0)) == ARRAY_REF
-                  || (TREE_CODE (TREE_OPERAND (initial, 0))
-                      == COMPONENT_REF)))
-       gnu_result = TREE_OPERAND (initial, 0);
-      else
+      /* If it's a renaming pointer and we are at the right binding level,
+        we can reference the renamed object directly, since the renamed
+        expression has been protected against multiple evaluations.  */
+      else if (TREE_CODE (gnu_result) == VAR_DECL
+              && (renamed_obj = DECL_RENAMED_OBJECT (gnu_result)) != 0
+              && (! DECL_RENAMING_GLOBAL_P (gnu_result)
+                  || global_bindings_p ()))
+       gnu_result = renamed_obj;
+
+      /* Return the underlying CST for a CONST_DECL like a few lines below,
+        after dereferencing in this case.  */
+      else if (TREE_CODE (gnu_result) == CONST_DECL)
        gnu_result = build_unary_op (INDIRECT_REF, NULL_TREE,
-                                    fold (gnu_result));
+                                    DECL_INITIAL (gnu_result));
+
+      else
+       gnu_result = build_unary_op (INDIRECT_REF, NULL_TREE, gnu_result);
 
       TREE_READONLY (gnu_result) = TREE_STATIC (gnu_result) = ro;
     }
@@ -461,24 +649,27 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
        gnu_result_type = TREE_TYPE (TYPE_FIELDS (gnu_result_type));
     }
 
-  /* We always want to return the underlying INTEGER_CST for an enumeration
-     literal to avoid the need to call fold in lots of places.  But don't do
-     this is the parent will be taking the address of this object.  */
-  if (TREE_CODE (gnu_result) == CONST_DECL)
+  /* If we have a constant declaration and its initializer at hand,
+     try to return the latter to avoid the need to call fold in lots
+     of places and the need of elaboration code if this Id is used as
+     an initializer itself.  */
+  if (TREE_CONSTANT (gnu_result)
+      && DECL_P (gnu_result)
+      && DECL_INITIAL (gnu_result))
     {
-      gnat_temp = Parent (gnat_node);
-      if (!DECL_CONST_CORRESPONDING_VAR (gnu_result)
-         || (Nkind (gnat_temp) != N_Reference
-             && !(Nkind (gnat_temp) == N_Attribute_Reference
-                  && ((Get_Attribute_Id (Attribute_Name (gnat_temp))
-                       == Attr_Address)
-                      || (Get_Attribute_Id (Attribute_Name (gnat_temp))
-                          == Attr_Access)
-                      || (Get_Attribute_Id (Attribute_Name (gnat_temp))
-                           == Attr_Unchecked_Access)
-                      || (Get_Attribute_Id (Attribute_Name (gnat_temp))
-                          == Attr_Unrestricted_Access)))))
-       gnu_result = DECL_INITIAL (gnu_result);
+      tree object
+       = (TREE_CODE (gnu_result) == CONST_DECL
+          ? DECL_CONST_CORRESPONDING_VAR (gnu_result) : gnu_result);
+
+      /* If there is a corresponding variable, we only want to return
+        the CST value if an lvalue is not required.  Evaluate this
+        now if we have not already done so.  */
+      if (object && require_lvalue < 0)
+       require_lvalue = lvalue_required_p (gnat_node, gnu_result_type,
+                                           Is_Aliased (gnat_temp));
+
+      if (!object || !require_lvalue)
+       gnu_result = unshare_expr (DECL_INITIAL (gnu_result));
     }
 
   *gnu_result_type_p = gnu_result_type;
@@ -496,10 +687,11 @@ Pragma_to_gnu (Node_Id gnat_node)
 
   /* Check for (and ignore) unrecognized pragma and do nothing if we are just
      annotating types.  */
-  if (type_annotate_only || !Is_Pragma_Name (Chars (gnat_node)))
+  if (type_annotate_only
+      || !Is_Pragma_Name (Chars (Pragma_Identifier (gnat_node))))
     return gnu_result;
 
-  switch (Get_Pragma_Id (Chars (gnat_node)))
+  switch (Get_Pragma_Id (Chars (Pragma_Identifier (gnat_node))))
     {
     case Pragma_Inspection_Point:
       /* Do nothing at top level: all such variables are already viewable.  */
@@ -510,13 +702,48 @@ Pragma_to_gnu (Node_Id gnat_node)
           Present (gnat_temp);
           gnat_temp = Next (gnat_temp))
        {
-         tree gnu_expr = gnat_to_gnu (Expression (gnat_temp));
+         Node_Id gnat_expr = Expression (gnat_temp);
+         tree gnu_expr = gnat_to_gnu (gnat_expr);
+         int use_address;
+         enum machine_mode mode;
+         tree asm_constraint = NULL_TREE;
+#ifdef ASM_COMMENT_START
+         char *comment;
+#endif
 
          if (TREE_CODE (gnu_expr) == UNCONSTRAINED_ARRAY_REF)
            gnu_expr = TREE_OPERAND (gnu_expr, 0);
 
-         gnu_expr = build1 (USE_STMT, void_type_node, gnu_expr);
-         annotate_with_node (gnu_expr, gnat_node);
+         /* Use the value only if it fits into a normal register,
+            otherwise use the address.  */
+         mode = TYPE_MODE (TREE_TYPE (gnu_expr));
+         use_address = ((GET_MODE_CLASS (mode) != MODE_INT
+                         && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
+                        || GET_MODE_SIZE (mode) > UNITS_PER_WORD);
+
+         if (use_address)
+           gnu_expr = build_unary_op (ADDR_EXPR, NULL_TREE, gnu_expr);
+
+#ifdef ASM_COMMENT_START
+         comment = concat (ASM_COMMENT_START,
+                           " inspection point: ",
+                           Get_Name_String (Chars (gnat_expr)),
+                           use_address ? " address" : "",
+                           " is in %0",
+                           NULL);
+         asm_constraint = build_string (strlen (comment), comment);
+         free (comment);
+#endif
+         gnu_expr = build4 (ASM_EXPR, void_type_node,
+                            asm_constraint,
+                            NULL_TREE,
+                            tree_cons
+                            (build_tree_list (NULL_TREE,
+                                              build_string (1, "g")),
+                             gnu_expr, NULL_TREE),
+                            NULL_TREE);
+         ASM_VOLATILE_P (gnu_expr) = 1;
+         set_expr_location_from_node (gnu_expr, gnat_node);
          append_to_statement_list (gnu_expr, &gnu_result);
        }
       break;
@@ -536,8 +763,7 @@ Pragma_to_gnu (Node_Id gnat_node)
          break;
 
        default:
-         abort ();
-         break;
+         gcc_unreachable ();
        }
       break;
 
@@ -623,7 +849,55 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
 
       /* If we are taking 'Address of an unconstrained object, this is the
         pointer to the underlying array.  */
-      gnu_prefix = maybe_unconstrained_array (gnu_prefix);
+      if (attribute == Attr_Address)
+       gnu_prefix = maybe_unconstrained_array (gnu_prefix);
+
+      /* If we are building a static dispatch table, we have to honor
+        TARGET_VTABLE_USES_DESCRIPTORS if we want to be compatible
+        with the C++ ABI.  We do it in the non-static case as well,
+        see gnat_to_gnu_entity, case E_Access_Subprogram_Type.  */
+      else if (TARGET_VTABLE_USES_DESCRIPTORS
+              && Is_Dispatch_Table_Entity (Etype (gnat_node)))
+       {
+         tree gnu_field, gnu_list = NULL_TREE, t;
+         /* Descriptors can only be built here for top-level functions.  */
+         bool build_descriptor = (global_bindings_p () != 0);
+         int i;
+
+         gnu_result_type = get_unpadded_type (Etype (gnat_node));
+
+         /* If we're not going to build the descriptor, we have to retrieve
+            the one which will be built by the linker (or by the compiler
+            later if a static chain is requested).  */
+         if (!build_descriptor)
+           {
+             gnu_result = build_unary_op (ADDR_EXPR, NULL_TREE, gnu_prefix);
+             gnu_result = fold_convert (build_pointer_type (gnu_result_type),
+                                        gnu_result);
+             gnu_result = build1 (INDIRECT_REF, gnu_result_type, gnu_result);
+           }
+
+         for (gnu_field = TYPE_FIELDS (gnu_result_type), i = 0;
+              i < TARGET_VTABLE_USES_DESCRIPTORS;
+              gnu_field = TREE_CHAIN (gnu_field), i++)
+           {
+             if (build_descriptor)
+               {
+                 t = build2 (FDESC_EXPR, TREE_TYPE (gnu_field), gnu_prefix,
+                             build_int_cst (NULL_TREE, i));
+                 TREE_CONSTANT (t) = 1;
+                 TREE_INVARIANT (t) = 1;
+               }
+             else
+               t = build3 (COMPONENT_REF, ptr_void_ftype, gnu_result,
+                           gnu_field, NULL_TREE);
+
+             gnu_list = tree_cons (gnu_field, t, gnu_list);
+           }
+
+         gnu_result = gnat_build_constructor (gnu_result_type, gnu_list);
+         break;
+       }
 
       /* ... fall through ... */
 
@@ -651,6 +925,29 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
          if (TREE_CODE (gnu_expr) == ADDR_EXPR)
            TREE_STATIC (gnu_expr) = TREE_CONSTANT (gnu_expr) = 1;
        }
+
+      /* For other address attributes applied to a nested function,
+        find an inner ADDR_EXPR and annotate it so that we can issue
+        a useful warning with -Wtrampolines.  */
+      else if (TREE_CODE (TREE_TYPE (gnu_prefix)) == FUNCTION_TYPE)
+       {
+         for (gnu_expr = gnu_result;
+              TREE_CODE (gnu_expr) == NOP_EXPR
+              || TREE_CODE (gnu_expr) == CONVERT_EXPR;
+              gnu_expr = TREE_OPERAND (gnu_expr, 0))
+           ;
+
+         if (TREE_CODE (gnu_expr) == ADDR_EXPR
+             && decl_function_context (TREE_OPERAND (gnu_expr, 0)))
+           {
+             set_expr_location_from_node (gnu_expr, gnat_node);
+
+             /* Check that we're not violating the No_Implicit_Dynamic_Code
+                restriction.  Be conservative if we don't know anything
+                about the trampoline strategy for the target.  */
+             Check_Implicit_Dynamic_Code_Allowed (gnat_node);
+           }
+       }
       break;
 
     case Attr_Pool_Address:
@@ -677,11 +974,12 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
            tree gnu_char_ptr_type = build_pointer_type (char_type_node);
            tree gnu_pos = byte_position (TYPE_FIELDS (gnu_obj_type));
            tree gnu_byte_offset
-             = convert (gnu_char_ptr_type,
+             = convert (sizetype,
                         size_diffop (size_zero_node, gnu_pos));
+           gnu_byte_offset = fold_build1 (NEGATE_EXPR, sizetype, gnu_byte_offset);
 
            gnu_ptr = convert (gnu_char_ptr_type, gnu_ptr);
-           gnu_ptr = build_binary_op (MINUS_EXPR, gnu_char_ptr_type,
+           gnu_ptr = build_binary_op (POINTER_PLUS_EXPR, gnu_char_ptr_type,
                                       gnu_ptr, gnu_byte_offset);
          }
 
@@ -745,14 +1043,28 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
                  = size_binop (MAX_EXPR, gnu_result,
                                DECL_SIZE (TREE_OPERAND (gnu_expr, 1)));
            }
+         else if (Nkind (Prefix (gnat_node)) == N_Explicit_Dereference)
+           {
+             Node_Id gnat_deref = Prefix (gnat_node);
+             Node_Id gnat_actual_subtype = Actual_Designated_Subtype (gnat_deref);
+             tree gnu_ptr_type = TREE_TYPE (gnat_to_gnu (Prefix (gnat_deref)));
+             if (TYPE_FAT_OR_THIN_POINTER_P (gnu_ptr_type)
+               && Present (gnat_actual_subtype))
+               {
+                 tree gnu_actual_obj_type = gnat_to_gnu_type (gnat_actual_subtype);
+                 gnu_type = build_unc_object_type_from_ptr (gnu_ptr_type,
+                              gnu_actual_obj_type, get_identifier ("SIZE"));
+               }
+
+             gnu_result = TYPE_SIZE (gnu_type);
+           }
          else
            gnu_result = TYPE_SIZE (gnu_type);
        }
       else
        gnu_result = rm_size (gnu_type);
 
-      if (!gnu_result)
-       abort ();
+      gcc_assert (gnu_result);
 
       /* Deal with a self-referential size by returning the maximum size for a
         type and by qualifying the size with the object for 'Size of an
@@ -760,8 +1072,7 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
       if (CONTAINS_PLACEHOLDER_P (gnu_result))
        {
          if (TREE_CODE (gnu_prefix) != TYPE_DECL)
-           gnu_result = substitute_placeholder_in_expr (gnu_result,
-                                                        gnu_expr);
+           gnu_result = substitute_placeholder_in_expr (gnu_result, gnu_expr);
          else
            gnu_result = max_size (gnu_result, true);
        }
@@ -782,8 +1093,8 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
 
       if (attribute == Attr_Max_Size_In_Storage_Elements)
        gnu_result = convert (sizetype,
-                             fold (build (CEIL_DIV_EXPR, bitsizetype,
-                                          gnu_result, bitsize_unit_node)));
+                             fold_build2 (CEIL_DIV_EXPR, bitsizetype,
+                                          gnu_result, bitsize_unit_node));
       break;
 
     case Attr_Alignment:
@@ -797,10 +1108,9 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
       gnu_result_type = get_unpadded_type (Etype (gnat_node));
       prefix_unused = true;
 
-      if (TREE_CODE (gnu_prefix) == COMPONENT_REF)
-       gnu_result = size_int (DECL_ALIGN (TREE_OPERAND (gnu_prefix, 1)));
-      else
-       gnu_result = size_int (TYPE_ALIGN (gnu_type) / BITS_PER_UNIT);
+      gnu_result = size_int ((TREE_CODE (gnu_prefix) == COMPONENT_REF
+                             ? DECL_ALIGN (TREE_OPERAND (gnu_prefix, 1))
+                             : TYPE_ALIGN (gnu_type)) / BITS_PER_UNIT);
       break;
 
     case Attr_First:
@@ -840,11 +1150,18 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
       {
        int Dimension = (Present (Expressions (gnat_node))
                         ? UI_To_Int (Intval (First (Expressions (gnat_node))))
-                        : 1);
+                        : 1), i;
+       struct parm_attr *pa = NULL;
+       Entity_Id gnat_param = Empty;
 
        /* Make sure any implicit dereference gets done.  */
        gnu_prefix = maybe_implicit_deref (gnu_prefix);
        gnu_prefix = maybe_unconstrained_array (gnu_prefix);
+       /* We treat unconstrained array In parameters specially.  */
+       if (Nkind (Prefix (gnat_node)) == N_Identifier
+           && !Is_Constrained (Etype (Prefix (gnat_node)))
+           && Ekind (Entity (Prefix (gnat_node))) == E_In_Parameter)
+         gnat_param = Entity (Prefix (gnat_node));
        gnu_type = TREE_TYPE (gnu_prefix);
        prefix_unused = true;
        gnu_result_type = get_unpadded_type (Etype (gnat_node));
@@ -863,40 +1180,91 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
            Dimension = ndim + 1 - Dimension;
          }
 
-       for (; Dimension > 1; Dimension--)
+       for (i = 1; i < Dimension; i++)
          gnu_type = TREE_TYPE (gnu_type);
 
-       if (TREE_CODE (gnu_type) != ARRAY_TYPE)
-         abort ();
+       gcc_assert (TREE_CODE (gnu_type) == ARRAY_TYPE);
 
+       /* When not optimizing, look up the slot associated with the parameter
+          and the dimension in the cache and create a new one on failure.  */
+       if (!optimize && Present (gnat_param))
+         {
+           for (i = 0; VEC_iterate (parm_attr, f_parm_attr_cache, i, pa); i++)
+             if (pa->id == gnat_param && pa->dim == Dimension)
+               break;
+
+           if (!pa)
+             {
+               pa = GGC_CNEW (struct parm_attr);
+               pa->id = gnat_param;
+               pa->dim = Dimension;
+               VEC_safe_push (parm_attr, gc, f_parm_attr_cache, pa);
+             }
+         }
+
+       /* Return the cached expression or build a new one.  */
        if (attribute == Attr_First)
-         gnu_result
-           = TYPE_MIN_VALUE (TYPE_INDEX_TYPE (TYPE_DOMAIN (gnu_type)));
+         {
+           if (pa && pa->first)
+             {
+               gnu_result = pa->first;
+               break;
+             }
+
+           gnu_result
+             = TYPE_MIN_VALUE (TYPE_INDEX_TYPE (TYPE_DOMAIN (gnu_type)));
+         }
+
        else if (attribute == Attr_Last)
-         gnu_result
-           = TYPE_MAX_VALUE (TYPE_INDEX_TYPE (TYPE_DOMAIN (gnu_type)));
-       else
-         /* 'Length or 'Range_Length.  */
          {
-           tree gnu_compute_type
-             = gnat_signed_or_unsigned_type (0,
-                                             get_base_type (gnu_result_type));
+           if (pa && pa->last)
+             {
+               gnu_result = pa->last;
+               break;
+             }
 
            gnu_result
-             = build_binary_op
-               (MAX_EXPR, gnu_compute_type,
-                build_binary_op
-                (PLUS_EXPR, gnu_compute_type,
-                 build_binary_op
-                 (MINUS_EXPR, gnu_compute_type,
-                  convert (gnu_compute_type,
-                           TYPE_MAX_VALUE
-                           (TYPE_INDEX_TYPE (TYPE_DOMAIN (gnu_type)))),
-                  convert (gnu_compute_type,
-                           TYPE_MIN_VALUE
-                           (TYPE_INDEX_TYPE (TYPE_DOMAIN (gnu_type))))),
-                 convert (gnu_compute_type, integer_one_node)),
-                convert (gnu_compute_type, integer_zero_node));
+             = TYPE_MAX_VALUE (TYPE_INDEX_TYPE (TYPE_DOMAIN (gnu_type)));
+         }
+
+       else /* attribute == Attr_Range_Length || attribute == Attr_Length  */
+         {
+           if (pa && pa->length)
+             {
+               gnu_result = pa->length;
+               break;
+             }
+           else
+             {
+               tree gnu_compute_type
+                 = signed_or_unsigned_type_for
+                     (0, get_base_type (gnu_result_type));
+
+               tree index_type
+                 = TYPE_INDEX_TYPE (TYPE_DOMAIN (gnu_type));
+               tree lb
+                 = convert (gnu_compute_type, TYPE_MIN_VALUE (index_type));
+               tree hb
+                 = convert (gnu_compute_type, TYPE_MAX_VALUE (index_type));
+               
+               /* We used to compute the length as max (hb - lb + 1, 0),
+                  which could overflow for some cases of empty arrays, e.g.
+                  when lb == index_type'first.
+
+                  We now compute it as (hb < lb) ? 0 : hb - lb + 1, which
+                  could overflow as well, but only for extremely large arrays
+                  which we expect never to encounter in practice.  */
+
+               gnu_result
+                 = build3
+                   (COND_EXPR, gnu_compute_type,
+                    build_binary_op (LT_EXPR, gnu_compute_type, hb, lb),
+                    convert (gnu_compute_type, integer_zero_node),
+                    build_binary_op
+                    (PLUS_EXPR, gnu_compute_type,
+                     build_binary_op (MINUS_EXPR, gnu_compute_type, hb, lb),
+                     convert (gnu_compute_type, integer_one_node)));
+             }
          }
 
        /* If this has a PLACEHOLDER_EXPR, qualify it by the object we are
@@ -904,6 +1272,23 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
           an unconstrained array type.  */
        gnu_result = SUBSTITUTE_PLACEHOLDER_IN_EXPR (gnu_result,
                                                     gnu_prefix);
+
+       /* Cache the expression we have just computed.  Since we want to do it
+          at runtime, we force the use of a SAVE_EXPR and let the gimplifier
+          create the temporary.  */
+       if (pa)
+         {
+           gnu_result
+             = build1 (SAVE_EXPR, TREE_TYPE (gnu_result), gnu_result);
+           TREE_SIDE_EFFECTS (gnu_result) = 1;
+           TREE_INVARIANT (gnu_result) = 1;
+           if (attribute == Attr_First)
+             pa->first = gnu_result;
+           else if (attribute == Attr_Last)
+             pa->last = gnu_result;
+           else
+             pa->length = gnu_result;
+         }
        break;
       }
 
@@ -936,13 +1321,13 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
            break;
          }
 
-       else if (TREE_CODE (gnu_prefix) != COMPONENT_REF
-                && !(attribute == Attr_Bit_Position
-                     && TREE_CODE (gnu_prefix) == FIELD_DECL))
-         abort ();
+       else
+         gcc_assert (TREE_CODE (gnu_prefix) == COMPONENT_REF
+                     || (attribute == Attr_Bit_Position
+                         && TREE_CODE (gnu_prefix) == FIELD_DECL));
 
        get_inner_reference (gnu_prefix, &bitsize, &bitpos, &gnu_offset,
-                            &mode, &unsignedp, &volatilep);
+                            &mode, &unsignedp, &volatilep, false);
 
        if (TREE_CODE (gnu_prefix) == COMPONENT_REF)
          {
@@ -1039,8 +1424,7 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
             && TYPE_MULTI_ARRAY_P (TREE_TYPE (gnu_type)))
        gnu_type = TREE_TYPE (gnu_type);
 
-      if (TREE_CODE (gnu_type) != ARRAY_TYPE)
-       abort ();
+      gcc_assert (TREE_CODE (gnu_type) == ARRAY_TYPE);
 
       /* Note this size cannot be self-referential.  */
       gnu_result = TYPE_SIZE (TREE_TYPE (gnu_type));
@@ -1104,8 +1488,8 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
      example in AARM 11.6(5.e). */
   if (prefix_unused && TREE_SIDE_EFFECTS (gnu_prefix)
       && !Is_Entity_Name (Prefix (gnat_node)))
-    gnu_result = fold (build (COMPOUND_EXPR, TREE_TYPE (gnu_result),
-                             gnu_prefix, gnu_result));
+    gnu_result = fold_build2 (COMPOUND_EXPR, TREE_TYPE (gnu_result),
+                             gnu_prefix, gnu_result);
 
   *gnu_result_type_p = gnu_result_type;
   return gnu_result;
@@ -1150,6 +1534,7 @@ Case_Statement_to_gnu (Node_Id gnat_node)
        gnat_when = Next_Non_Pragma (gnat_when))
     {
       Node_Id gnat_choice;
+      int choices_added = 0;
 
       /* First compile all the different case choices for the current WHEN
         alternative.  */
@@ -1175,8 +1560,7 @@ Case_Statement_to_gnu (Node_Id gnat_node)
            case N_Identifier:
            case N_Expanded_Name:
              /* This represents either a subtype range or a static value of
-                some kind; Ekind says which.  If a static value, fall through
-                to the next case.  */
+                some kind; Ekind says which.  */
              if (IN (Ekind (Entity (gnat_choice)), Type_Kind))
                {
                  tree gnu_type = get_unpadded_type (Entity (gnat_choice));
@@ -1197,28 +1581,41 @@ Case_Statement_to_gnu (Node_Id gnat_node)
              break;
 
            default:
-             abort ();
+             gcc_unreachable ();
            }
 
-         add_stmt_with_node (build (CASE_LABEL_EXPR, void_type_node,
-                                    gnu_low, gnu_high,
-                                    create_artificial_label ()),
-                             gnat_choice);
+         /* If the case value is a subtype that raises Constraint_Error at
+            run-time because of a wrong bound, then gnu_low or gnu_high is
+            not transtaleted into an INTEGER_CST.  In such a case, we need
+            to ensure that the when statement is not added in the tree,
+            otherwise it will crash the gimplifier.  */
+         if ((!gnu_low || TREE_CODE (gnu_low) == INTEGER_CST)
+             && (!gnu_high || TREE_CODE (gnu_high) == INTEGER_CST))
+           {
+             add_stmt_with_node (build3 (CASE_LABEL_EXPR, void_type_node,
+                                         gnu_low, gnu_high,
+                                         create_artificial_label ()),
+                                 gnat_choice);
+             choices_added++;
+           }
        }
 
-      /* Push a binding level here in case variables are declared since we want
-        them to be local to this set of statements instead of the block
+      /* Push a binding level here in case variables are declared as we want
+        them to be local to this set of statements instead of to the block
         containing the Case statement.  */
-      add_stmt (build_stmt_group (Statements (gnat_when), true));
-      add_stmt (build1 (GOTO_EXPR, void_type_node,
-                       TREE_VALUE (gnu_switch_label_stack)));
+      if (choices_added > 0)
+       {
+         add_stmt (build_stmt_group (Statements (gnat_when), true));
+         add_stmt (build1 (GOTO_EXPR, void_type_node,
+                           TREE_VALUE (gnu_switch_label_stack)));
+       }
     }
 
   /* Now emit a definition of the label all the cases branched to. */
   add_stmt (build1 (LABEL_EXPR, void_type_node,
                    TREE_VALUE (gnu_switch_label_stack)));
-  gnu_result = build (SWITCH_EXPR, TREE_TYPE (gnu_expr), gnu_expr,
-                     end_stmt_group (), NULL_TREE);
+  gnu_result = build3 (SWITCH_EXPR, TREE_TYPE (gnu_expr), gnu_expr,
+                      end_stmt_group (), NULL_TREE);
   pop_stack (&gnu_switch_label_stack);
 
   return gnu_result;
@@ -1241,7 +1638,9 @@ Loop_Statement_to_gnu (Node_Id gnat_node)
   TREE_TYPE (gnu_loop_stmt) = void_type_node;
   TREE_SIDE_EFFECTS (gnu_loop_stmt) = 1;
   LOOP_STMT_LABEL (gnu_loop_stmt) = create_artificial_label ();
-  annotate_with_node (gnu_loop_stmt, gnat_node);
+  set_expr_location_from_node (gnu_loop_stmt, gnat_node);
+  Sloc_to_locus (Sloc (End_Label (gnat_node)),
+                &DECL_SOURCE_LOCATION (LOOP_STMT_LABEL (gnu_loop_stmt)));
 
   /* Save the end label of this LOOP_STMT in a stack so that the corresponding
      N_Exit_Statement can find it.  */
@@ -1282,11 +1681,11 @@ Loop_Statement_to_gnu (Node_Id gnat_node)
          || tree_int_cst_equal (gnu_last, gnu_limit))
        {
          gnu_cond_expr
-           = build (COND_EXPR, void_type_node,
-                    build_binary_op (LE_EXPR, integer_type_node,
-                                     gnu_low, gnu_high),
-                    NULL_TREE, alloc_stmt_list ());
-         annotate_with_node (gnu_cond_expr, gnat_loop_spec);
+           = build3 (COND_EXPR, void_type_node,
+                     build_binary_op (LE_EXPR, integer_type_node,
+                                      gnu_low, gnu_high),
+                     NULL_TREE, alloc_stmt_list ());
+         set_expr_location_from_node (gnu_cond_expr, gnat_loop_spec);
        }
 
       /* Open a new nesting level that will surround the loop to declare the
@@ -1321,7 +1720,7 @@ Loop_Statement_to_gnu (Node_Id gnat_node)
                           gnu_loop_var,
                           convert (TREE_TYPE (gnu_loop_var),
                                    integer_one_node));
-      annotate_with_node (LOOP_STMT_UPDATE (gnu_loop_stmt),
+      set_expr_location_from_node (LOOP_STMT_UPDATE (gnu_loop_stmt),
                          gnat_iter_scheme);
     }
 
@@ -1362,16 +1761,64 @@ Loop_Statement_to_gnu (Node_Id gnat_node)
   return gnu_result;
 }
 \f
+/* Emit statements to establish __gnat_handle_vms_condition as a VMS condition
+   handler for the current function.  */
+
+/* This is implemented by issuing a call to the appropriate VMS specific
+   builtin.  To avoid having VMS specific sections in the global gigi decls
+   array, we maintain the decls of interest here.  We can't declare them
+   inside the function because we must mark them never to be GC'd, which we
+   can only do at the global level.  */
+
+static GTY(()) tree vms_builtin_establish_handler_decl = NULL_TREE;
+static GTY(()) tree gnat_vms_condition_handler_decl = NULL_TREE;
+
+static void
+establish_gnat_vms_condition_handler (void)
+{
+  tree establish_stmt;
+
+  /* Elaborate the required decls on the first call.  Check on the decl for
+     the gnat condition handler to decide, as this is one we create so we are
+     sure that it will be non null on subsequent calls.  The builtin decl is
+     looked up so remains null on targets where it is not implemented yet.  */
+  if (gnat_vms_condition_handler_decl == NULL_TREE)
+    {
+      vms_builtin_establish_handler_decl
+       = builtin_decl_for
+         (get_identifier ("__builtin_establish_vms_condition_handler"));
+
+      gnat_vms_condition_handler_decl
+       = create_subprog_decl (get_identifier ("__gnat_handle_vms_condition"),
+                              NULL_TREE,
+                              build_function_type_list (integer_type_node,
+                                                        ptr_void_type_node,
+                                                        ptr_void_type_node,
+                                                        NULL_TREE),
+                              NULL_TREE, 0, 1, 1, 0, Empty);
+    }
+
+  /* Do nothing if the establish builtin is not available, which might happen
+     on targets where the facility is not implemented.  */
+  if (vms_builtin_establish_handler_decl == NULL_TREE)
+    return;
+
+  establish_stmt
+    = build_call_1_expr (vms_builtin_establish_handler_decl,
+                        build_unary_op
+                        (ADDR_EXPR, NULL_TREE,
+                         gnat_vms_condition_handler_decl));
+
+  add_stmt (establish_stmt);
+}
+\f
 /* Subroutine of gnat_to_gnu to process gnat_node, an N_Subprogram_Body.  We
    don't return anything.  */
 
 static void
 Subprogram_Body_to_gnu (Node_Id gnat_node)
 {
-  /* Save debug output mode in case it is reset.  */
-  enum debug_info_type save_write_symbols = write_symbols;
-  const struct gcc_debug_hooks *const save_debug_hooks = debug_hooks;
-  /* Definining identifier of a parameter to the subprogram.  */
+  /* Defining identifier of a parameter to the subprogram.  */
   Entity_Id gnat_param;
   /* The defining identifier for the subprogram body. Note that if a
      specification has appeared before for this body, then the identifier
@@ -1386,6 +1833,7 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
   tree gnu_subprog_type;
   tree gnu_cico_list;
   tree gnu_result;
+  VEC(parm_attr,gc) *cache;
 
   /* If this is a generic object or if it has been eliminated,
      ignore it.  */
@@ -1394,14 +1842,6 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
       || Is_Eliminated (gnat_subprog_id))
     return;
 
-  /* If debug information is suppressed for the subprogram, turn debug
-     mode off for the duration of processing.  */
-  if (!Needs_Debug_Info (gnat_subprog_id))
-    {
-      write_symbols = NO_DEBUG;
-      debug_hooks = &do_nothing_debug_hooks;
-    }
-
   /* If this subprogram acts as its own spec, define it.  Otherwise, just get
      the already-elaborated tree node.  However, if this subprogram had its
      elaboration deferred, we will already have made a tree node for it.  So
@@ -1415,15 +1855,23 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
 
   gnu_subprog_type = TREE_TYPE (gnu_subprog_decl);
 
+  /* Propagate the debug mode.  */
+  if (!Needs_Debug_Info (gnat_subprog_id))
+    DECL_IGNORED_P (gnu_subprog_decl) = 1;
+
   /* Set the line number in the decl to correspond to that of the body so that
-     the line number notes are written
-     correctly.  */
+     the line number notes are written correctly.  */
   Sloc_to_locus (Sloc (gnat_node), &DECL_SOURCE_LOCATION (gnu_subprog_decl));
 
+  /* Initialize the information structure for the function.  */
+  allocate_struct_function (gnu_subprog_decl, false);
+  DECL_STRUCT_FUNCTION (gnu_subprog_decl)->language
+    = GGC_CNEW (struct language_function);
+
   begin_subprog_body (gnu_subprog_decl);
   gnu_cico_list = TYPE_CI_CO_LIST (gnu_subprog_type);
 
-  /* If there are OUT parameters, we need to ensure that the return statement
+  /* If there are Out parameters, we need to ensure that the return statement
      properly copies them out.  We do this by making a new block and converting
      any inner return into a goto to a label at the end of the block.  */
   push_stack (&gnu_return_label_stack, NULL_TREE,
@@ -1434,17 +1882,17 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
   gnat_pushlevel ();
 
   /* See if there are any parameters for which we don't yet have GCC entities.
-     These must be for OUT parameters for which we will be making VAR_DECL
+     These must be for Out parameters for which we will be making VAR_DECL
      nodes here.  Fill them in to TYPE_CI_CO_LIST, which must contain the empty
      entry as well.  We can match up the entries because TYPE_CI_CO_LIST is in
      the order of the parameters.  */
-  for (gnat_param = First_Formal (gnat_subprog_id);
+  for (gnat_param = First_Formal_With_Extras (gnat_subprog_id);
        Present (gnat_param);
        gnat_param = Next_Formal_With_Extras (gnat_param))
     if (!present_gnu_tree (gnat_param))
       {
        /* Skip any entries that have been already filled in; they must
-          correspond to IN OUT parameters.  */
+          correspond to In Out parameters.  */
        for (; gnu_cico_list && TREE_VALUE (gnu_cico_list);
             gnu_cico_list = TREE_CHAIN (gnu_cico_list))
          ;
@@ -1455,14 +1903,53 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
                     gnat_to_gnu_entity (gnat_param, NULL_TREE, 1));
       }
 
+  /* On VMS, establish our condition handler to possibly turn a condition into
+     the corresponding exception if the subprogram has a foreign convention or
+     is exported.
+
+     To ensure proper execution of local finalizations on condition instances,
+     we must turn a condition into the corresponding exception even if there
+     is no applicable Ada handler, and need at least one condition handler per
+     possible call chain involving GNAT code.  OTOH, establishing the handler
+     has a cost so we want to minimize the number of subprograms into which
+     this happens.  The foreign or exported condition is expected to satisfy
+     all the constraints.  */
+  if (TARGET_ABI_OPEN_VMS
+      && (Has_Foreign_Convention (gnat_node) || Is_Exported (gnat_node)))
+    establish_gnat_vms_condition_handler ();
+
   process_decls (Declarations (gnat_node), Empty, Empty, true, true);
 
   /* Generate the code of the subprogram itself.  A return statement will be
-     present and any OUT parameters will be handled there.  */
+     present and any Out parameters will be handled there.  */
   add_stmt (gnat_to_gnu (Handled_Statement_Sequence (gnat_node)));
   gnat_poplevel ();
   gnu_result = end_stmt_group ();
 
+  /* If we populated the parameter attributes cache, we need to make sure
+     that the cached expressions are evaluated on all possible paths.  */
+  cache = DECL_STRUCT_FUNCTION (gnu_subprog_decl)->language->parm_attr_cache;
+  if (cache)
+    {
+      struct parm_attr *pa;
+      int i;
+
+      start_stmt_group ();
+
+      for (i = 0; VEC_iterate (parm_attr, cache, i, pa); i++)
+       {
+         if (pa->first)
+           add_stmt (pa->first);
+         if (pa->last)
+           add_stmt (pa->last);
+         if (pa->length)
+           add_stmt (pa->length);
+       }
+
+      add_stmt (gnu_result);
+      gnu_result = end_stmt_group ();
+    }
+
   /* If we made a special return label, we need to make a block that contains
      the definition of that label and the copying to the return value.  That
      block first contains the function, then the label and copy statement.  */
@@ -1487,9 +1974,7 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
        gnu_retval = build_unary_op (INDIRECT_REF, NULL_TREE, gnu_retval);
 
       add_stmt_with_node
-       (build1 (RETURN_EXPR, void_type_node,
-                build (MODIFY_EXPR, TREE_TYPE (gnu_retval),
-                       DECL_RESULT (current_function_decl), gnu_retval)),
+       (build_return_expr (DECL_RESULT (gnu_subprog_decl), gnu_retval),
         gnat_node);
       gnat_poplevel ();
       gnu_result = end_stmt_group ();
@@ -1497,36 +1982,37 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
 
   pop_stack (&gnu_return_label_stack);
 
-  /* Initialize the information node for the function and set the
-     end location.  */
-  allocate_struct_function (current_function_decl);
+  /* Set the end location.  */
   Sloc_to_locus
     ((Present (End_Label (Handled_Statement_Sequence (gnat_node)))
       ? Sloc (End_Label (Handled_Statement_Sequence (gnat_node)))
       : Sloc (gnat_node)),
-     &cfun->function_end_locus);
+     &DECL_STRUCT_FUNCTION (gnu_subprog_decl)->function_end_locus);
 
   end_subprog_body (gnu_result);
 
   /* Disconnect the trees for parameters that we made variables for from the
      GNAT entities since these are unusable after we end the function.  */
-  for (gnat_param = First_Formal (gnat_subprog_id);
+  for (gnat_param = First_Formal_With_Extras (gnat_subprog_id);
        Present (gnat_param);
        gnat_param = Next_Formal_With_Extras (gnat_param))
     if (TREE_CODE (get_gnu_tree (gnat_param)) == VAR_DECL)
       save_gnu_tree (gnat_param, NULL_TREE, false);
 
+  if (DECL_FUNCTION_STUB (gnu_subprog_decl))
+    build_function_stub (gnu_subprog_decl, gnat_subprog_id);
+
   mark_out_of_scope (Defining_Unit_Name (Specification (gnat_node)));
-  write_symbols = save_write_symbols;
-  debug_hooks = save_debug_hooks;
 }
 \f
 /* Subroutine of gnat_to_gnu to translate gnat_node, either an N_Function_Call
    or an N_Procedure_Call_Statement, to a GCC tree, which is returned.
-   GNU_RESULT_TYPE_P is a pointer to where we should place the result type.  */
+   GNU_RESULT_TYPE_P is a pointer to where we should place the result type.
+   If GNU_TARGET is non-null, this must be a function call and the result
+   of the call is to be placed into that object.  */
 
 static tree
-call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
+call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
 {
   tree gnu_result;
   /* The GCC node corresponding to the GNAT subprogram name.  This can either
@@ -1556,8 +2042,7 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
        Eliminate_Error_Msg (gnat_node, Entity (Name (gnat_node)));
     }
 
-  if (TREE_CODE (gnu_subprog_type) != FUNCTION_TYPE)
-    abort ();
+  gcc_assert (TREE_CODE (gnu_subprog_type) == FUNCTION_TYPE);
 
   /* If we are calling a stubbed function, make this into a raise of
      Program_Error.  Elaborate all our args first.  */
@@ -1569,14 +2054,57 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
           gnat_actual = Next_Actual (gnat_actual))
        add_stmt (gnat_to_gnu (gnat_actual));
 
-      if (Nkind (gnat_node) == N_Function_Call)
+      {
+       tree call_expr
+         = build_call_raise (PE_Stubbed_Subprogram_Called, gnat_node,
+                             N_Raise_Program_Error);
+
+       if (Nkind (gnat_node) == N_Function_Call && !gnu_target)
+         {
+           *gnu_result_type_p = TREE_TYPE (gnu_subprog_type);
+           return build1 (NULL_EXPR, *gnu_result_type_p, call_expr);
+         }
+       else
+         return call_expr;
+      }
+    }
+
+  /* If we are calling by supplying a pointer to a target, set up that
+     pointer as the first argument.  Use GNU_TARGET if one was passed;
+     otherwise, make a target by building a variable of the maximum size
+     of the type.  */
+  if (TYPE_RETURNS_BY_TARGET_PTR_P (gnu_subprog_type))
+    {
+      tree gnu_real_ret_type
+       = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (gnu_subprog_type)));
+
+      if (!gnu_target)
        {
-         *gnu_result_type_p = TREE_TYPE (gnu_subprog_type);
-         return build1 (NULL_EXPR, *gnu_result_type_p,
-                        build_call_raise (PE_Stubbed_Subprogram_Called));
+         tree gnu_obj_type
+           = maybe_pad_type (gnu_real_ret_type,
+                             max_size (TYPE_SIZE (gnu_real_ret_type), true),
+                             0, Etype (Name (gnat_node)), "PAD", false,
+                             false, false);
+
+         /* ??? We may be about to create a static temporary if we happen to
+            be at the global binding level.  That's a regression from what
+            the 3.x back-end would generate in the same situation, but we
+            don't have a mechanism in Gigi for creating automatic variables
+            in the elaboration routines.  */
+         gnu_target
+           = create_var_decl (create_tmp_var_name ("LR"), NULL, gnu_obj_type,
+                              NULL, false, false, false, false, NULL,
+                              gnat_node);
        }
-      else
-       return build_call_raise (PE_Stubbed_Subprogram_Called);
+
+      gnu_actual_list
+       = tree_cons (NULL_TREE,
+                    build_unary_op (ADDR_EXPR, NULL_TREE,
+                                    unchecked_convert (gnu_real_ret_type,
+                                                       gnu_target,
+                                                       false)),
+                    NULL_TREE);
+
     }
 
   /* The only way we can be making a call via an access type is if Name is an
@@ -1584,120 +2112,145 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
      type the access type is pointing to.  Otherwise, get the formals from
      entity being called.  */
   if (Nkind (Name (gnat_node)) == N_Explicit_Dereference)
-    gnat_formal = First_Formal (Etype (Name (gnat_node)));
+    gnat_formal = First_Formal_With_Extras (Etype (Name (gnat_node)));
   else if (Nkind (Name (gnat_node)) == N_Attribute_Reference)
     /* Assume here that this must be 'Elab_Body or 'Elab_Spec.  */
     gnat_formal = 0;
   else
-    gnat_formal = First_Formal (Entity (Name (gnat_node)));
+    gnat_formal = First_Formal_With_Extras (Entity (Name (gnat_node)));
 
   /* Create the list of the actual parameters as GCC expects it, namely a chain
      of TREE_LIST nodes in which the TREE_VALUE field of each node is a
-     parameter-expression and the TREE_PURPOSE field is null.  Skip OUT
+     parameter-expression and the TREE_PURPOSE field is null.  Skip Out
      parameters not passed by reference and don't need to be copied in.  */
   for (gnat_actual = First_Actual (gnat_node);
        Present (gnat_actual);
        gnat_formal = Next_Formal_With_Extras (gnat_formal),
        gnat_actual = Next_Actual (gnat_actual))
     {
+      tree gnu_formal
+       = (present_gnu_tree (gnat_formal)
+          ? get_gnu_tree (gnat_formal) : NULL_TREE);
       tree gnu_formal_type = gnat_to_gnu_type (Etype (gnat_formal));
-      /* We treat a conversion between aggregate types as if it is an
-        unchecked conversion.  */
-      bool unchecked_convert_p
-       = (Nkind (gnat_actual) == N_Unchecked_Type_Conversion
+      /* We must suppress conversions that can cause the creation of a
+        temporary in the Out or In Out case because we need the real
+        object in this case, either to pass its address if it's passed
+        by reference or as target of the back copy done after the call
+        if it uses the copy-in copy-out mechanism.  We do it in the In
+        case too, except for an unchecked conversion because it alone
+        can cause the actual to be misaligned and the addressability
+        test is applied to the real object.  */
+      bool suppress_type_conversion
+       = ((Nkind (gnat_actual) == N_Unchecked_Type_Conversion
+           && Ekind (gnat_formal) != E_In_Parameter)
           || (Nkind (gnat_actual) == N_Type_Conversion
               && Is_Composite_Type (Underlying_Type (Etype (gnat_formal)))));
-      Node_Id gnat_name = (unchecked_convert_p
+      Node_Id gnat_name = (suppress_type_conversion
                           ? Expression (gnat_actual) : gnat_actual);
-      tree gnu_name = gnat_to_gnu (gnat_name);
-      tree gnu_name_type = gnat_to_gnu_type (Etype (gnat_name));
-      tree gnu_formal
-       = (present_gnu_tree (gnat_formal)
-          ? get_gnu_tree (gnat_formal) : NULL_TREE);
+      tree gnu_name = gnat_to_gnu (gnat_name), gnu_name_type;
       tree gnu_actual;
 
       /* If it's possible we may need to use this expression twice, make sure
-        than any side-effects are handled via SAVE_EXPRs. Likewise if we need
+        that any side-effects are handled via SAVE_EXPRs.  Likewise if we need
         to force side-effects before the call.
-
         ??? This is more conservative than we need since we don't need to do
-        this for pass-by-ref with no conversion. If we are passing a
-        non-addressable Out or In Out parameter by reference, pass the address
-        of a copy and set up to copy back out after the call.  */
+        this for pass-by-ref with no conversion.  */
       if (Ekind (gnat_formal) != E_In_Parameter)
+       gnu_name = gnat_stabilize_reference (gnu_name, true);
+
+      /* If we are passing a non-addressable parameter by reference, pass the
+        address of a copy.  In the Out or In Out case, set up to copy back
+        out after the call.  */
+      if (gnu_formal
+         && (DECL_BY_REF_P (gnu_formal)
+             || (TREE_CODE (gnu_formal) == PARM_DECL
+                 && (DECL_BY_COMPONENT_PTR_P (gnu_formal)
+                     || (DECL_BY_DESCRIPTOR_P (gnu_formal)))))
+         && (gnu_name_type = gnat_to_gnu_type (Etype (gnat_name)))
+         && !addressable_p (gnu_name, gnu_name_type))
        {
-         gnu_name = gnat_stabilize_reference (gnu_name, true);
-         if (!addressable_p (gnu_name)
-             && gnu_formal
-             && (DECL_BY_REF_P (gnu_formal)
-                 || (TREE_CODE (gnu_formal) == PARM_DECL
-                     && (DECL_BY_COMPONENT_PTR_P (gnu_formal)
-                         || (DECL_BY_DESCRIPTOR_P (gnu_formal))))))
+         tree gnu_copy = gnu_name, gnu_temp;
+
+         /* If the type is by_reference, a copy is not allowed.  */
+         if (Is_By_Reference_Type (Etype (gnat_formal)))
+           post_error
+             ("misaligned actual cannot be passed by reference", gnat_actual);
+
+         /* For users of Starlet we issue a warning because the
+            interface apparently assumes that by-ref parameters
+            outlive the procedure invocation.  The code still
+            will not work as intended, but we cannot do much
+            better since other low-level parts of the back-end
+            would allocate temporaries at will because of the
+            misalignment if we did not do so here.  */
+         else if (Is_Valued_Procedure (Entity (Name (gnat_node))))
            {
-             tree gnu_copy = gnu_name;
-             tree gnu_temp;
-
-             /* Remove any unpadding on the actual and make a copy.  But if
-                the actual is a left-justified modular type, first convert
-                to it.  */
-             if (TREE_CODE (gnu_name) == COMPONENT_REF
-                 && ((TREE_CODE (TREE_TYPE (TREE_OPERAND (gnu_name, 0)))
-                      == RECORD_TYPE)
-                     && (TYPE_IS_PADDING_P
-                         (TREE_TYPE (TREE_OPERAND (gnu_name, 0))))))
-               gnu_name = gnu_copy = TREE_OPERAND (gnu_name, 0);
-             else if (TREE_CODE (gnu_name_type) == RECORD_TYPE
-                      && (TYPE_LEFT_JUSTIFIED_MODULAR_P (gnu_name_type)))
-               gnu_name = convert (gnu_name_type, gnu_name);
-
-             gnu_actual = save_expr (gnu_name);
-
-             /* Since we're going to take the address of the SAVE_EXPR, we
-                don't want it to be marked as unchanging. So set
-                TREE_ADDRESSABLE.  */
-             gnu_temp = skip_simple_arithmetic (gnu_actual);
-             if (TREE_CODE (gnu_temp) == SAVE_EXPR)
-               {
-                 TREE_ADDRESSABLE (gnu_temp) = 1;
-                 TREE_READONLY (gnu_temp) = 0;
-               }
+             post_error
+               ("?possible violation of implicit assumption", gnat_actual);
+             post_error_ne
+               ("?made by pragma Import_Valued_Procedure on &", gnat_actual,
+                Entity (Name (gnat_node)));
+             post_error_ne ("?because of misalignment of &", gnat_actual,
+                            gnat_formal);
+           }
 
-             /* Set up to move the copy back to the original.  */
-             gnu_temp = build (MODIFY_EXPR, TREE_TYPE (gnu_copy),
-                               gnu_copy, gnu_actual);
-             annotate_with_node (gnu_temp, gnat_actual);
+         /* Remove any unpadding from the object and reset the copy.  */
+         if (TREE_CODE (gnu_name) == COMPONENT_REF
+             && ((TREE_CODE (TREE_TYPE (TREE_OPERAND (gnu_name, 0)))
+                  == RECORD_TYPE)
+                 && (TYPE_IS_PADDING_P
+                     (TREE_TYPE (TREE_OPERAND (gnu_name, 0))))))
+           gnu_name = gnu_copy = TREE_OPERAND (gnu_name, 0);
+
+         /* Otherwise convert to the nominal type of the object if it's
+            a record type.  There are several cases in which we need to
+            make the temporary using this type instead of the actual type
+            of the object if they are distinct, because the expectations
+            of the callee would otherwise not be met:
+              - if it's a justified modular type,
+              - if the actual type is a packed version of it.  */
+         else if (TREE_CODE (gnu_name_type) == RECORD_TYPE
+                  && (TYPE_JUSTIFIED_MODULAR_P (gnu_name_type)
+                      || larger_record_type_p (gnu_name_type,
+                                               TREE_TYPE (gnu_name))))
+           gnu_name = convert (gnu_name_type, gnu_name);
+
+         /* Make a SAVE_EXPR to both properly account for potential side
+            effects and handle the creation of a temporary copy.  Special
+            code in gnat_gimplify_expr ensures that the same temporary is
+            used as the object and copied back after the call if needed.  */
+         gnu_name = build1 (SAVE_EXPR, TREE_TYPE (gnu_name), gnu_name);
+         TREE_SIDE_EFFECTS (gnu_name) = 1;
+         TREE_INVARIANT (gnu_name) = 1;
+
+         /* Set up to move the copy back to the original.  */
+         if (Ekind (gnat_formal) != E_In_Parameter)
+           {
+             gnu_temp = build_binary_op (MODIFY_EXPR, NULL_TREE, gnu_copy,
+                                         gnu_name);
+             set_expr_location_from_node (gnu_temp, gnat_actual);
              append_to_statement_list (gnu_temp, &gnu_after_list);
            }
        }
 
+      /* Start from the real object and build the actual.  */
+      gnu_actual = gnu_name;
+
       /* If this was a procedure call, we may not have removed any padding.
         So do it here for the part we will use as an input, if any.  */
-      gnu_actual = gnu_name;
       if (Ekind (gnat_formal) != E_Out_Parameter
          && TREE_CODE (TREE_TYPE (gnu_actual)) == RECORD_TYPE
          && TYPE_IS_PADDING_P (TREE_TYPE (gnu_actual)))
        gnu_actual = convert (get_unpadded_type (Etype (gnat_actual)),
                              gnu_actual);
 
-      /* Unless this is an In parameter, we must remove any LJM building
-        from GNU_NAME.  */
-      if (Ekind (gnat_formal) != E_In_Parameter
-         && TREE_CODE (gnu_name) == CONSTRUCTOR
-         && TREE_CODE (TREE_TYPE (gnu_name)) == RECORD_TYPE
-         && TYPE_LEFT_JUSTIFIED_MODULAR_P (TREE_TYPE (gnu_name)))
-       gnu_name = convert (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (gnu_name))),
-                           gnu_name);
-
-      if (Ekind (gnat_formal) != E_Out_Parameter
-         && !unchecked_convert_p
-         && Do_Range_Check (gnat_actual))
-       gnu_actual = emit_range_check (gnu_actual, Etype (gnat_formal));
-
-      /* Do any needed conversions.  We need only check for unchecked
-        conversion since normal conversions will be handled by just
-        converting to the formal type.  */
-      if (unchecked_convert_p)
+      /* Do any needed conversions for the actual and make sure that it is
+        in range of the formal's type.  */
+      if (suppress_type_conversion)
        {
+         /* Put back the conversion we suppressed above in the computation
+            of the real object.  Note that we treat a conversion between
+            aggregate types as if it is an unchecked conversion here.  */
          gnu_actual
            = unchecked_convert (gnat_to_gnu_type (Etype (gnat_actual)),
                                 gnu_actual,
@@ -1705,31 +2258,52 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
                                  == N_Unchecked_Type_Conversion)
                                 && No_Truncation (gnat_actual));
 
-         /* One we've done the unchecked conversion, we still must ensure that
-            the object is in range of the formal's type.  */
          if (Ekind (gnat_formal) != E_Out_Parameter
              && Do_Range_Check (gnat_actual))
-           gnu_actual = emit_range_check (gnu_actual,
-                                          Etype (gnat_formal));
+           gnu_actual = emit_range_check (gnu_actual, Etype (gnat_formal));
+       }
+      else
+       {
+         if (Ekind (gnat_formal) != E_Out_Parameter
+             && Do_Range_Check (gnat_actual))
+           gnu_actual = emit_range_check (gnu_actual, Etype (gnat_formal));
+
+         /* We may have suppressed a conversion to the Etype of the actual
+            since the parent is a procedure call.  So put it back here.
+            ??? We use the reverse order compared to the case above because
+            of an awkward interaction with the check and actually don't put
+            back the conversion at all if a check is emitted.  This is also
+            done for the conversion to the formal's type just below.  */
+         if (TREE_CODE (gnu_actual) != SAVE_EXPR)
+           gnu_actual = convert (gnat_to_gnu_type (Etype (gnat_actual)),
+                                 gnu_actual);
        }
-      else if (TREE_CODE (gnu_actual) != SAVE_EXPR)
-       /* We may have suppressed a conversion to the Etype of the actual since
-          the parent is a procedure call.  So add the conversion here.  */
-       gnu_actual = convert (gnat_to_gnu_type (Etype (gnat_actual)),
-                             gnu_actual);
 
       if (TREE_CODE (gnu_actual) != SAVE_EXPR)
        gnu_actual = convert (gnu_formal_type, gnu_actual);
 
+      /* Unless this is an In parameter, we must remove any justified modular
+        building from GNU_NAME to get an lvalue.  */
+      if (Ekind (gnat_formal) != E_In_Parameter
+         && TREE_CODE (gnu_name) == CONSTRUCTOR
+         && TREE_CODE (TREE_TYPE (gnu_name)) == RECORD_TYPE
+         && TYPE_JUSTIFIED_MODULAR_P (TREE_TYPE (gnu_name)))
+       gnu_name = convert (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (gnu_name))),
+                           gnu_name);
+
       /* If we have not saved a GCC object for the formal, it means it is an
-        OUT parameter not passed by reference and that does not need to be
+        Out parameter not passed by reference and that does not need to be
         copied in. Otherwise, look at the PARM_DECL to see if it is passed by
         reference. */
       if (gnu_formal
-         && TREE_CODE (gnu_formal) == PARM_DECL && DECL_BY_REF_P (gnu_formal))
+         && TREE_CODE (gnu_formal) == PARM_DECL
+         && DECL_BY_REF_P (gnu_formal))
        {
          if (Ekind (gnat_formal) != E_In_Parameter)
            {
+             /* In Out or Out parameters passed by reference don't use the
+                copy-in copy-out mechanism so the address of the real object
+                must be passed to the function.  */
              gnu_actual = gnu_name;
 
              /* If we have a padded type, be sure we've removed padding.  */
@@ -1738,27 +2312,29 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
                  && TREE_CODE (gnu_actual) != SAVE_EXPR)
                gnu_actual = convert (get_unpadded_type (Etype (gnat_actual)),
                                      gnu_actual);
-           }
 
-         /* Otherwise, if we have a non-addressable COMPONENT_REF of a
-            variable-size type see if it's doing a unpadding operation.  If
-            so, remove that operation since we have no way of allocating the
-            required temporary.  */
-         if (TREE_CODE (gnu_actual) == COMPONENT_REF
-             && !TREE_CONSTANT (TYPE_SIZE (TREE_TYPE (gnu_actual)))
-             && (TREE_CODE (TREE_TYPE (TREE_OPERAND (gnu_actual, 0)))
-                 == RECORD_TYPE)
-             && TYPE_IS_PADDING_P (TREE_TYPE
-                                   (TREE_OPERAND (gnu_actual, 0)))
-             && !addressable_p (gnu_actual))
-           gnu_actual = TREE_OPERAND (gnu_actual, 0);
+             /* If we have the constructed subtype of an aliased object
+                with an unconstrained nominal subtype, the type of the
+                actual includes the template, although it is formally
+                constrained.  So we need to convert it back to the real
+                constructed subtype to retrieve the constrained part
+                and takes its address.  */
+             if (TREE_CODE (TREE_TYPE (gnu_actual)) == RECORD_TYPE
+                 && TYPE_CONTAINS_TEMPLATE_P (TREE_TYPE (gnu_actual))
+                 && TREE_CODE (gnu_actual) != SAVE_EXPR
+                 && Is_Constr_Subt_For_UN_Aliased (Etype (gnat_actual))
+                 && Is_Array_Type (Etype (gnat_actual)))
+               gnu_actual = convert (gnat_to_gnu_type (Etype (gnat_actual)),
+                                     gnu_actual);
+           }
 
          /* The symmetry of the paths to the type of an entity is broken here
             since arguments don't know that they will be passed by ref. */
          gnu_formal_type = TREE_TYPE (get_gnu_tree (gnat_formal));
          gnu_actual = build_unary_op (ADDR_EXPR, gnu_formal_type, gnu_actual);
        }
-      else if (gnu_formal && TREE_CODE (gnu_formal) == PARM_DECL
+      else if (gnu_formal
+              && TREE_CODE (gnu_formal) == PARM_DECL
               && DECL_BY_COMPONENT_PTR_P (gnu_formal))
        {
          gnu_formal_type = TREE_TYPE (get_gnu_tree (gnat_formal));
@@ -1782,7 +2358,8 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
                                build_unary_op (ADDR_EXPR, NULL_TREE,
                                                gnu_actual));
        }
-      else if (gnu_formal && TREE_CODE (gnu_formal) == PARM_DECL
+      else if (gnu_formal
+              && TREE_CODE (gnu_formal) == PARM_DECL
               && DECL_BY_DESCRIPTOR_P (gnu_formal))
        {
          /* If arg is 'Null_Parameter, pass zero descriptor.  */
@@ -1799,7 +2376,7 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
       else
        {
          tree gnu_actual_size = TYPE_SIZE (TREE_TYPE (gnu_actual));
-         
+
          if (Ekind (gnat_formal) != E_In_Parameter)
            gnu_name_list = tree_cons (NULL_TREE, gnu_name, gnu_name_list);
 
@@ -1821,20 +2398,61 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
                                            integer_zero_node),
                                   false);
          else
-           gnu_actual
-             = convert (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (gnu_formal)),
-                        gnu_actual);
+           gnu_actual = convert (DECL_ARG_TYPE (gnu_formal), gnu_actual);
        }
 
       gnu_actual_list = tree_cons (NULL_TREE, gnu_actual, gnu_actual_list);
     }
 
-  gnu_subprog_call = build (CALL_EXPR, TREE_TYPE (gnu_subprog_type),
-                           gnu_subprog_addr, nreverse (gnu_actual_list),
-                           NULL_TREE);
+  gnu_subprog_call = build_call_list (TREE_TYPE (gnu_subprog_type),
+                                     gnu_subprog_addr,
+                                     nreverse (gnu_actual_list));
+  set_expr_location_from_node (gnu_subprog_call, gnat_node);
+
+  /* If we return by passing a target, the result is the target after the
+     call.  We must not emit the call directly here because this might be
+     evaluated as part of an expression with conditions to control whether
+     the call should be emitted or not.  */
+  if (TYPE_RETURNS_BY_TARGET_PTR_P (gnu_subprog_type))
+    {
+      /* Conceptually, what we need is a COMPOUND_EXPR with the call followed
+        by the target object converted to the proper type.  Doing so would
+        potentially be very inefficient, however, as this expresssion might
+        end up wrapped into an outer SAVE_EXPR later on, which would incur a
+        pointless temporary copy of the whole object.
+
+        What we do instead is build a COMPOUND_EXPR returning the address of
+        the target, and then dereference.  Wrapping the COMPOUND_EXPR into a
+        SAVE_EXPR later on then only incurs a pointer copy.  */
+
+      tree gnu_result_type
+       = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (gnu_subprog_type)));
+
+      /* Build and return
+        (result_type) *[gnu_subprog_call (&gnu_target, ...), &gnu_target]  */
+
+      tree gnu_target_address
+       = build_unary_op (ADDR_EXPR, NULL_TREE, gnu_target);
+      set_expr_location_from_node (gnu_target_address, gnat_node);
+
+      gnu_result
+       = build2 (COMPOUND_EXPR, TREE_TYPE (gnu_target_address),
+                 gnu_subprog_call, gnu_target_address);
+
+      gnu_result
+       = unchecked_convert (gnu_result_type,
+                            build_unary_op (INDIRECT_REF, NULL_TREE,
+                                            gnu_result),
+                            false);
+
+      *gnu_result_type_p = gnu_result_type;
+      return gnu_result;
+    }
 
-  /* If it is a function call, the result is the call expression.  */
-  if (Nkind (gnat_node) == N_Function_Call)
+  /* If it is a function call, the result is the call expression unless
+     a target is specified, in which case we copy the result into the target
+     and return the assignment statement.  */
+  else if (Nkind (gnat_node) == N_Function_Call)
     {
       gnu_result = gnu_subprog_call;
 
@@ -1844,7 +2462,12 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
          || TYPE_RETURNS_BY_REF_P (gnu_subprog_type))
        gnu_result = build_unary_op (INDIRECT_REF, NULL_TREE, gnu_result);
 
-      *gnu_result_type_p = get_unpadded_type (Etype (gnat_node));
+      if (gnu_target)
+       gnu_result = build_binary_op (MODIFY_EXPR, NULL_TREE,
+                                     gnu_target, gnu_result);
+      else
+       *gnu_result_type_p = get_unpadded_type (Etype (gnat_node));
+
       return gnu_result;
     }
 
@@ -1862,7 +2485,7 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
        {
          tree gnu_name;
 
-         gnu_subprog_call = protect_multiple_eval (gnu_subprog_call);
+         gnu_subprog_call = save_expr (gnu_subprog_call);
          gnu_name_list = nreverse (gnu_name_list);
 
          /* If any of the names had side-effects, ensure they are all
@@ -1875,9 +2498,9 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
        }
 
       if (Nkind (Name (gnat_node)) == N_Explicit_Dereference)
-       gnat_formal = First_Formal (Etype (Name (gnat_node)));
+       gnat_formal = First_Formal_With_Extras (Etype (Name (gnat_node)));
       else
-       gnat_formal = First_Formal (Entity (Name (gnat_node)));
+       gnat_formal = First_Formal_With_Extras (Entity (Name (gnat_node)));
 
       for (gnat_actual = First_Actual (gnat_node);
           Present (gnat_actual);
@@ -1894,7 +2517,7 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
                               (get_gnu_tree (gnat_formal))))))))
            && Ekind (gnat_formal) != E_In_Parameter)
          {
-           /* Get the value to assign to this OUT or IN OUT parameter.  It is
+           /* Get the value to assign to this Out or In Out parameter.  It is
               either the result of the function if there is only a single such
               parameter or the appropriate field from the record returned.  */
            tree gnu_result
@@ -1902,8 +2525,7 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
                : build_component_ref (gnu_subprog_call, NULL_TREE,
                                       TREE_PURPOSE (scalar_return_list),
                                       false);
-           bool unchecked_conversion = (Nkind (gnat_actual)
-                                        == N_Unchecked_Type_Conversion);
+
            /* If the actual is a conversion, get the inner expression, which
               will be the real destination, and convert the result to the
               type of the actual parameter.  */
@@ -1917,16 +2539,30 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
                                               (TREE_TYPE (gnu_result))),
                                    gnu_result);
 
-           /* If the result is a type conversion, do it.  */
+           /* If the actual is a type conversion, the real target object is
+              denoted by the inner Expression and we need to convert the
+              result to the associated type.
+              We also need to convert our gnu assignment target to this type
+              if the corresponding GNU_NAME was constructed from the GNAT
+              conversion node and not from the inner Expression.  */
            if (Nkind (gnat_actual) == N_Type_Conversion)
-             gnu_result
-               = convert_with_check
-                 (Etype (Expression (gnat_actual)), gnu_result,
-                  Do_Overflow_Check (gnat_actual),
-                  Do_Range_Check (Expression (gnat_actual)),
-                  Float_Truncate (gnat_actual));
+             {
+               gnu_result
+                 = convert_with_check
+                   (Etype (Expression (gnat_actual)), gnu_result,
+                    Do_Overflow_Check (gnat_actual),
+                    Do_Range_Check (Expression (gnat_actual)),
+                    Float_Truncate (gnat_actual));
+
+               if (!Is_Composite_Type (Underlying_Type (Etype (gnat_formal))))
+                 gnu_actual = convert (TREE_TYPE (gnu_result), gnu_actual);
+             }
 
-           else if (unchecked_conversion)
+           /* Unchecked conversions as actuals for Out parameters are not
+              allowed in user code because they are not variables, but do
+              occur in front-end expansions.  The associated GNU_NAME is
+              always obtained from the inner expression in such cases.  */
+           else if (Nkind (gnat_actual) == N_Unchecked_Type_Conversion)
              gnu_result = unchecked_convert (TREE_TYPE (gnu_actual),
                                              gnu_result,
                                              No_Truncation (gnat_actual));
@@ -1940,20 +2576,17 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
                      && TREE_CONSTANT (TYPE_SIZE (TREE_TYPE (gnu_result)))))
                  gnu_result = convert (TREE_TYPE (gnu_actual), gnu_result);
              }
-               
+
            gnu_result = build_binary_op (MODIFY_EXPR, NULL_TREE,
                                          gnu_actual, gnu_result);
-           annotate_with_node (gnu_result, gnat_actual);
+           set_expr_location_from_node (gnu_result, gnat_actual);
            append_to_statement_list (gnu_result, &gnu_before_list);
            scalar_return_list = TREE_CHAIN (scalar_return_list);
            gnu_name_list = TREE_CHAIN (gnu_name_list);
          }
        }
   else
-    {
-      annotate_with_node (gnu_subprog_call, gnat_node);
-      append_to_statement_list (gnu_subprog_call, &gnu_before_list);
-    }
+    append_to_statement_list (gnu_subprog_call, &gnu_before_list);
 
   append_to_statement_list (gnu_after_list, &gnu_before_list);
   return gnu_before_list;
@@ -1970,7 +2603,7 @@ Handled_Sequence_Of_Statements_to_gnu (Node_Id gnat_node)
   /* If just annotating, ignore all EH and cleanups.  */
   bool gcc_zcx = (!type_annotate_only
                  && Present (Exception_Handlers (gnat_node))
-                 && Exception_Mechanism == GCC_ZCX);
+                 && Exception_Mechanism == Back_End_Exceptions);
   bool setjmp_longjmp
     = (!type_annotate_only && Present (Exception_Handlers (gnat_node))
        && Exception_Mechanism == Setjmp_Longjmp);
@@ -2001,11 +2634,6 @@ Handled_Sequence_Of_Statements_to_gnu (Node_Id gnat_node)
       gnat_pushlevel ();
     }
 
-  /* If we are to call a function when exiting this block add a cleanup
-     to the binding level we made above.  */
-  if (at_end)
-    add_cleanup (build_call_0_expr (gnat_to_gnu (At_End_Proc (gnat_node))));
-
   /* If using setjmp_longjmp, make the variables for the setjmp buffer and save
      area for address of previous buffer.  Do this first since we need to have
      the setjmp buf known for any decls in this block.  */
@@ -2016,17 +2644,33 @@ Handled_Sequence_Of_Statements_to_gnu (Node_Id gnat_node)
                                          build_call_0_expr (get_jmpbuf_decl),
                                          false, false, false, false, NULL,
                                          gnat_node);
+      DECL_ARTIFICIAL (gnu_jmpsave_decl) = 1;
+
+      /* The __builtin_setjmp receivers will immediately reinstall it.  Now
+        because of the unstructured form of EH used by setjmp_longjmp, there
+        might be forward edges going to __builtin_setjmp receivers on which
+        it is uninitialized, although they will never be actually taken.  */
+      TREE_NO_WARNING (gnu_jmpsave_decl) = 1;
       gnu_jmpbuf_decl = create_var_decl (get_identifier ("JMP_BUF"),
                                         NULL_TREE, jmpbuf_type,
                                         NULL_TREE, false, false, false, false,
                                         NULL, gnat_node);
+      DECL_ARTIFICIAL (gnu_jmpbuf_decl) = 1;
 
       set_block_jmpbuf_decl (gnu_jmpbuf_decl);
 
       /* When we exit this block, restore the saved value.  */
-      add_cleanup (build_call_1_expr (set_jmpbuf_decl, gnu_jmpsave_decl));
+      add_cleanup (build_call_1_expr (set_jmpbuf_decl, gnu_jmpsave_decl),
+                  End_Label (gnat_node));
     }
 
+  /* If we are to call a function when exiting this block, add a cleanup
+     to the binding level we made above.  Note that add_cleanup is FIFO
+     so we must register this cleanup after the EH cleanup just above.  */
+  if (at_end)
+    add_cleanup (build_call_0_expr (gnat_to_gnu (At_End_Proc (gnat_node))),
+                End_Label (gnat_node));
+
   /* Now build the tree for the declarations and statements inside this block.
      If this is SJLJ, set our jmp_buf as the current buffer.  */
   start_stmt_group ();
@@ -2036,7 +2680,6 @@ Handled_Sequence_Of_Statements_to_gnu (Node_Id gnat_node)
                                 build_unary_op (ADDR_EXPR, NULL_TREE,
                                                 gnu_jmpbuf_decl)));
 
-
   if (Present (First_Real_Statement (gnat_node)))
     process_decls (Statements (gnat_node), Empty,
                   First_Real_Statement (gnat_node), true, true);
@@ -2091,7 +2734,7 @@ Handled_Sequence_Of_Statements_to_gnu (Node_Id gnat_node)
         defer abortion.  */
       gnu_expr = build_call_1_expr (raise_nodefer_decl,
                                    TREE_VALUE (gnu_except_ptr_stack));
-      annotate_with_node (gnu_expr, gnat_node);
+      set_expr_location_from_node (gnu_expr, gnat_node);
 
       if (gnu_else_ptr)
        *gnu_else_ptr = gnu_expr;
@@ -2114,12 +2757,12 @@ Handled_Sequence_Of_Statements_to_gnu (Node_Id gnat_node)
       gnu_handler = end_stmt_group ();
 
       /* This block is now "if (setjmp) ... <handlers> else <block>".  */
-      gnu_result = build (COND_EXPR, void_type_node,
-                         (build_call_1_expr
-                          (setjmp_decl,
-                           build_unary_op (ADDR_EXPR, NULL_TREE,
-                                           gnu_jmpbuf_decl))),
-                         gnu_handler, gnu_inner_block);
+      gnu_result = build3 (COND_EXPR, void_type_node,
+                          (build_call_1_expr
+                           (setjmp_decl,
+                            build_unary_op (ADDR_EXPR, NULL_TREE,
+                                            gnu_jmpbuf_decl))),
+                          gnu_handler, gnu_inner_block);
     }
   else if (gcc_zcx)
     {
@@ -2134,8 +2777,8 @@ Handled_Sequence_Of_Statements_to_gnu (Node_Id gnat_node)
       gnu_handlers = end_stmt_group ();
 
       /* Now make the TRY_CATCH_EXPR for the block.  */
-      gnu_result = build (TRY_CATCH_EXPR, void_type_node,
-                         gnu_inner_block, gnu_handlers);
+      gnu_result = build2 (TRY_CATCH_EXPR, void_type_node,
+                          gnu_inner_block, gnu_handlers);
     }
   else
     gnu_result = gnu_inner_block;
@@ -2193,8 +2836,15 @@ Exception_Handler_to_gnu_sjlj (Node_Id gnat_node)
       else if (Nkind (gnat_temp) == N_Identifier
               || Nkind (gnat_temp) == N_Expanded_Name)
        {
-         tree gnu_expr
-           = gnat_to_gnu_entity (Entity (gnat_temp), NULL_TREE, 0);
+         Entity_Id gnat_ex_id = Entity (gnat_temp);
+         tree gnu_expr;
+
+         /* Exception may be a renaming. Recover original exception which is
+            the one elaborated and registered.  */
+         if (Present (Renamed_Object (gnat_ex_id)))
+           gnat_ex_id = Renamed_Object (gnat_ex_id);
+
+         gnu_expr = gnat_to_gnu_entity (gnat_ex_id, NULL_TREE, 0);
 
          this_choice
            = build_binary_op
@@ -2217,19 +2867,18 @@ Exception_Handler_to_gnu_sjlj (Node_Id gnat_node)
                = build_binary_op
                  (TRUTH_ORIF_EXPR, integer_type_node,
                   build_binary_op (EQ_EXPR, integer_type_node, gnu_comp,
-                                   build_int_cst (TREE_TYPE (gnu_comp),
-                                                  'V', 0)),
+                                   build_int_cst (TREE_TYPE (gnu_comp), 'V')),
                   this_choice);
            }
        }
       else
-       abort ();
+       gcc_unreachable ();
 
       gnu_choice = build_binary_op (TRUTH_ORIF_EXPR, integer_type_node,
                                    gnu_choice, this_choice);
     }
 
-  return build (COND_EXPR, void_type_node, gnu_choice, gnu_body, NULL_TREE);
+  return build3 (COND_EXPR, void_type_node, gnu_choice, gnu_body, NULL_TREE);
 }
 \f
 /* Subroutine of gnat_to_gnu to translate gnat_node, an N_Exception_Handler,
@@ -2249,24 +2898,22 @@ Exception_Handler_to_gnu_zcx (Node_Id gnat_node)
      handler can catch, with special cases for others and all others cases.
 
      Each exception type is actually identified by a pointer to the exception
-     id, with special value zero for "others" and one for "all others". Beware
-     that these special values are known and used by the personality routine to
-     identify the corresponding specific kinds of handlers.
-
-     ??? For initial time frame reasons, the others and all_others cases have
-     been handled using specific type trees, but this somehow hides information
-     from the back-end, which expects NULL to be passed for catch all and
-     end_cleanup to be used for cleanups.
+     id, or to a dummy object for "others" and "all others".
 
-     Care should be taken to ensure that the control flow impact of such
-     clauses is rendered in some way. lang_eh_type_covers is doing the trick
+     Care should be taken to ensure that the control flow impact of "others"
+     and "all others" is known to GCC. lang_eh_type_covers is doing the trick
      currently.  */
   for (gnat_temp = First (Exception_Choices (gnat_node));
        gnat_temp; gnat_temp = Next (gnat_temp))
     {
       if (Nkind (gnat_temp) == N_Others_Choice)
-       gnu_etype = (All_Others (gnat_temp) ? integer_one_node
-                    : integer_zero_node);
+       {
+         tree gnu_expr
+           = All_Others (gnat_temp) ? all_others_decl : others_decl;
+
+         gnu_etype
+           = build_unary_op (ADDR_EXPR, NULL_TREE, gnu_expr);
+       }
       else if (Nkind (gnat_temp) == N_Identifier
               || Nkind (gnat_temp) == N_Expanded_Name)
        {
@@ -2284,14 +2931,14 @@ Exception_Handler_to_gnu_zcx (Node_Id gnat_node)
             by the personality routine.  */
        }
       else
-       abort ();
+       gcc_unreachable ();
 
       /* The GCC interface expects NULL to be passed for catch all handlers, so
         it would be quite tempting to set gnu_etypes_list to NULL if gnu_etype
         is integer_zero_node.  It would not work, however, because GCC's
         notion of "catch all" is stronger than our notion of "others".  Until
         we correctly use the cleanup interface as well, doing that would
-        prevent the "all others" handlers from beeing seen, because nothing
+        prevent the "all others" handlers from being seen, because nothing
         can be caught beyond a catch all from GCC's point of view.  */
       gnu_etypes_list = tree_cons (NULL_TREE, gnu_etype, gnu_etypes_list);
     }
@@ -2316,7 +2963,7 @@ Exception_Handler_to_gnu_zcx (Node_Id gnat_node)
 
      We use a local variable to retrieve the incoming value at handler entry
      time, and reuse it to feed the end_handler hook's argument at exit.  */
-  gnu_current_exc_ptr = build (EXC_PTR_EXPR, ptr_type_node);
+  gnu_current_exc_ptr = build0 (EXC_PTR_EXPR, ptr_type_node);
   gnu_incoming_exc_ptr = create_var_decl (get_identifier ("EXPTR"), NULL_TREE,
                                          ptr_type_node, gnu_current_exc_ptr,
                                          false, false, false, false, NULL,
@@ -2325,12 +2972,14 @@ Exception_Handler_to_gnu_zcx (Node_Id gnat_node)
   add_stmt_with_node (build_call_1_expr (begin_handler_decl,
                                         gnu_incoming_exc_ptr),
                      gnat_node);
-  add_cleanup (build_call_1_expr (end_handler_decl, gnu_incoming_exc_ptr));
+  /* ??? We don't seem to have an End_Label at hand to set the location.  */
+  add_cleanup (build_call_1_expr (end_handler_decl, gnu_incoming_exc_ptr),
+              Empty);
   add_stmt_list (Statements (gnat_node));
   gnat_poplevel ();
 
-  return build (CATCH_EXPR, void_type_node, gnu_etypes_list,
-               end_stmt_group ());
+  return build2 (CATCH_EXPR, void_type_node, gnu_etypes_list,
+                end_stmt_group ());
 }
 \f
 /* Subroutine of gnat_to_gnu to generate code for an N_Compilation unit.  */
@@ -2354,19 +3003,22 @@ Compilation_Unit_to_gnu (Node_Id gnat_node)
   push_stack (&gnu_elab_proc_stack, NULL_TREE, gnu_elab_proc_decl);
 
   DECL_ELABORATION_PROC_P (gnu_elab_proc_decl) = 1;
-  allocate_struct_function (gnu_elab_proc_decl);
+  allocate_struct_function (gnu_elab_proc_decl, false);
   Sloc_to_locus (Sloc (gnat_unit_entity), &cfun->function_end_locus);
-  cfun = 0;
+  set_cfun (NULL);
 
-      /* For a body, first process the spec if there is one. */
+  /* For a body, first process the spec if there is one. */
   if (Nkind (Unit (gnat_node)) == N_Package_Body
       || (Nkind (Unit (gnat_node)) == N_Subprogram_Body
              && !Acts_As_Spec (gnat_node)))
-    add_stmt (gnat_to_gnu (Library_Unit (gnat_node)));
+    {
+      add_stmt (gnat_to_gnu (Library_Unit (gnat_node)));
+      finalize_from_with_types ();
+    }
 
   process_inlined_subprograms (gnat_node);
 
-  if (type_annotate_only)
+  if (type_annotate_only && gnat_node == Cunit (Main_Unit))
     {
       elaborate_all_entities (gnat_node);
 
@@ -2383,6 +3035,7 @@ Compilation_Unit_to_gnu (Node_Id gnat_node)
   /* Process any pragmas and actions following the unit.  */
   add_stmt_list (Pragmas_After (Aux_Decls_Node (gnat_node)));
   add_stmt_list (Actions (Aux_Decls_Node (gnat_node)));
+  finalize_from_with_types ();
 
   /* Save away what we've made so far and record this potential elaboration
      procedure.  */
@@ -2398,6 +3051,11 @@ Compilation_Unit_to_gnu (Node_Id gnat_node)
   /* Generate elaboration code for this unit, if necessary, and say whether
      we did or not.  */
   pop_stack (&gnu_elab_proc_stack);
+
+  /* Invalidate the global renaming pointers.  This is necessary because
+     stabilization of the renamed entities may create SAVE_EXPRs which
+     have been tied to a specific elaboration routine just above.  */
+  invalidate_global_renaming_pointers ();
 }
 \f
 /* This function is the driver of the GNAT to GCC tree transformation
@@ -2406,7 +3064,7 @@ Compilation_Unit_to_gnu (Node_Id gnat_node)
    If this is an expression, return the GCC equivalent of the expression.  If
    it is a statement, return the statement.  In the case when called for a
    statement, it may also add statements to the current statement group, in
-   which case anything it returns is to be interpreted as occuring after
+   which case anything it returns is to be interpreted as occurring after
    anything `it already added.  */
 
 tree
@@ -2434,27 +3092,43 @@ gnat_to_gnu (Node_Id gnat_node)
       && Nkind (gnat_node) != N_Identifier
       && !Compile_Time_Known_Value (gnat_node))
     return build1 (NULL_EXPR, get_unpadded_type (Etype (gnat_node)),
-                  build_call_raise (CE_Range_Check_Failed));
-
-  /* If this is a Statement and we are at top level, it must be part of
-     the elaboration procedure, so mark us as being in that procedure
-     and push our context.  */
-  if (!current_function_decl
-      && ((IN (Nkind (gnat_node), N_Statement_Other_Than_Procedure_Call)
-          && Nkind (gnat_node) != N_Null_Statement)
-         || Nkind (gnat_node) == N_Procedure_Call_Statement
-         || Nkind (gnat_node) == N_Label
-         || Nkind (gnat_node) == N_Implicit_Label_Declaration
-         || Nkind (gnat_node) == N_Handled_Sequence_Of_Statements
-         || ((Nkind (gnat_node) == N_Raise_Constraint_Error
-              || Nkind (gnat_node) == N_Raise_Storage_Error
-              || Nkind (gnat_node) == N_Raise_Program_Error)
-             && (Ekind (Etype (gnat_node)) == E_Void))))
+                  build_call_raise (CE_Range_Check_Failed, gnat_node,
+                                    N_Raise_Constraint_Error));
+
+  /* If this is a Statement and we are at top level, it must be part of the
+     elaboration procedure, so mark us as being in that procedure and push our
+     context.
+
+     If we are in the elaboration procedure, check if we are violating a a
+     No_Elaboration_Code restriction by having a statement there.  */
+  if ((IN (Nkind (gnat_node), N_Statement_Other_Than_Procedure_Call)
+       && Nkind (gnat_node) != N_Null_Statement)
+      || Nkind (gnat_node) == N_Procedure_Call_Statement
+      || Nkind (gnat_node) == N_Label
+      || Nkind (gnat_node) == N_Implicit_Label_Declaration
+      || Nkind (gnat_node) == N_Handled_Sequence_Of_Statements
+      || ((Nkind (gnat_node) == N_Raise_Constraint_Error
+          || Nkind (gnat_node) == N_Raise_Storage_Error
+          || Nkind (gnat_node) == N_Raise_Program_Error)
+         && (Ekind (Etype (gnat_node)) == E_Void)))
     {
-      current_function_decl = TREE_VALUE (gnu_elab_proc_stack);
-      start_stmt_group ();
-      gnat_pushlevel ();
-      went_into_elab_proc = true;
+      if (!current_function_decl)
+       {
+         current_function_decl = TREE_VALUE (gnu_elab_proc_stack);
+         start_stmt_group ();
+         gnat_pushlevel ();
+         went_into_elab_proc = true;
+       }
+
+      /* Don't check for a possible No_Elaboration_Code restriction violation
+        on N_Handled_Sequence_Of_Statements, as we want to signal an error on
+        every nested real statement instead.  This also avoids triggering
+        spurious errors on dummy (empty) sequences created by the front-end
+        for package bodies in some cases.  */
+
+      if (current_function_decl == TREE_VALUE (gnu_elab_proc_stack)
+         && Nkind (gnat_node) != N_Handled_Sequence_Of_Statements)
+       Check_Elaboration_Code_Allowed (gnat_node);
     }
 
   switch (Nkind (gnat_node))
@@ -2475,11 +3149,11 @@ gnat_to_gnu (Node_Id gnat_node)
        tree gnu_type;
 
        /* Get the type of the result, looking inside any padding and
-          left-justified modular types.  Then get the value in that type.  */
+          justified modular types.  Then get the value in that type.  */
        gnu_type = gnu_result_type = get_unpadded_type (Etype (gnat_node));
 
        if (TREE_CODE (gnu_type) == RECORD_TYPE
-           && TYPE_LEFT_JUSTIFIED_MODULAR_P (gnu_type))
+           && TYPE_JUSTIFIED_MODULAR_P (gnu_type))
          gnu_type = TREE_TYPE (TYPE_FIELDS (gnu_type));
 
        gnu_result = UI_To_gnu (Intval (gnat_node), gnu_type);
@@ -2489,8 +3163,7 @@ gnat_to_gnu (Node_Id gnat_node)
           of the subtype, but that causes problems with subtypes whose usage
           will raise Constraint_Error and with biased representation, so
           we don't.  */
-       if (TREE_CONSTANT_OVERFLOW (gnu_result))
-         abort ();
+       gcc_assert (!TREE_OVERFLOW (gnu_result));
       }
       break;
 
@@ -2504,8 +3177,9 @@ gnat_to_gnu (Node_Id gnat_node)
       if (Present (Entity (gnat_node)))
        gnu_result = DECL_INITIAL (get_gnu_tree (Entity (gnat_node)));
       else
-       gnu_result = build_int_cst (gnu_result_type,
-                                   Char_Literal_Value (gnat_node), 0);
+       gnu_result
+         = build_int_cst_type
+             (gnu_result_type, UI_To_CC (Char_Literal_Value (gnat_node)));
       break;
 
     case N_Real_Literal:
@@ -2516,14 +3190,13 @@ gnat_to_gnu (Node_Id gnat_node)
          gnu_result_type = get_unpadded_type (Etype (gnat_node));
          gnu_result = UI_To_gnu (Corresponding_Integer_Value (gnat_node),
                                  gnu_result_type);
-         if (TREE_CONSTANT_OVERFLOW (gnu_result))
-           abort ();
+         gcc_assert (!TREE_OVERFLOW (gnu_result));
        }
 
       /* We should never see a Vax_Float type literal, since the front end
          is supposed to transform these using appropriate conversions */
       else if (Vax_Float (Underlying_Type (Etype (gnat_node))))
-       abort ();
+       gcc_unreachable ();
 
       else
         {
@@ -2557,13 +3230,11 @@ gnat_to_gnu (Node_Id gnat_node)
                                     gnu_result,
                                     UI_To_gnu (Denominator (ur_realval),
                                                gnu_result_type));
-             else if (Rbase (ur_realval) != 2)
-               abort ();
-
              else
                {
                  REAL_VALUE_TYPE tmp;
 
+                 gcc_assert (Rbase (ur_realval) == 2);
                  real_ldexp (&tmp, &TREE_REAL_CST (gnu_result),
                              - UI_To_Int (Denominator (ur_realval)));
                  gnu_result = build_real (gnu_result_type, tmp);
@@ -2586,8 +3257,12 @@ gnat_to_gnu (Node_Id gnat_node)
        {
          String_Id gnat_string = Strval (gnat_node);
          int length = String_Length (gnat_string);
-         char *string = (char *) alloca (length + 1);
          int i;
+         char *string;
+         if (length >= ALLOCA_THRESHOLD)
+             string = xmalloc (length + 1); /* in case of large strings */
+          else
+             string = (char *) alloca (length + 1);
 
          /* Build the string with the characters in the literal.  Note
             that Ada strings are 1-origin.  */
@@ -2603,6 +3278,9 @@ gnat_to_gnu (Node_Id gnat_node)
          /* Strings in GCC don't normally have types, but we want
             this to not be converted to the array type.  */
          TREE_TYPE (gnu_result) = gnu_result_type;
+
+         if (length >= ALLOCA_THRESHOLD) /* free if heap-allocated */
+             free (string);
        }
       else
        {
@@ -2617,9 +3295,10 @@ gnat_to_gnu (Node_Id gnat_node)
          for (i = 0; i < length; i++)
            {
              gnu_list
-               = tree_cons (gnu_idx, build_int_cst
-                            (TREE_TYPE (gnu_result_type),
-                             Get_String_Char (gnat_string, i + 1), 0),
+               = tree_cons (gnu_idx,
+                            build_int_cst (TREE_TYPE (gnu_result_type),
+                                           Get_String_Char (gnat_string,
+                                                            i + 1)),
                             gnu_list);
 
              gnu_idx = int_const_binop (PLUS_EXPR, gnu_idx, integer_one_node,
@@ -2704,7 +3383,7 @@ gnat_to_gnu (Node_Id gnat_node)
     case N_Object_Renaming_Declaration:
       gnat_temp = Defining_Entity (gnat_node);
 
-      /* Don't do anything if this renaming is handled by the front end or if
+      /* Don't do anything if this renaming is handled by the front end or if
         we are just annotating types and this object has a composite or task
         type, don't elaborate it.  We return the result in case it has any
         SAVE_EXPRs in it that need to be evaluated here.  */
@@ -2788,9 +3467,7 @@ gnat_to_gnu (Node_Id gnat_node)
        for (i = 0, gnu_type = TREE_TYPE (gnu_array_object);
             i < ndim; i++, gnu_type = TREE_TYPE (gnu_type))
          {
-           if (TREE_CODE (gnu_type) != ARRAY_TYPE)
-             abort ();
-
+           gcc_assert (TREE_CODE (gnu_type) == ARRAY_TYPE);
            gnat_temp = gnat_expr_array[i];
            gnu_expr = gnat_to_gnu (gnat_temp);
 
@@ -2811,65 +3488,73 @@ gnat_to_gnu (Node_Id gnat_node)
 
     case N_Slice:
       {
-        tree gnu_type;
-        Node_Id gnat_range_node = Discrete_Range (gnat_node);
+       tree gnu_type;
+       Node_Id gnat_range_node = Discrete_Range (gnat_node);
 
-        gnu_result = gnat_to_gnu (Prefix (gnat_node));
-        gnu_result_type = get_unpadded_type (Etype (gnat_node));
+       gnu_result = gnat_to_gnu (Prefix (gnat_node));
+       gnu_result_type = get_unpadded_type (Etype (gnat_node));
 
        /* Do any implicit dereferences of the prefix and do any needed
           range check.  */
-        gnu_result = maybe_implicit_deref (gnu_result);
-        gnu_result = maybe_unconstrained_array (gnu_result);
-        gnu_type = TREE_TYPE (gnu_result);
-        if (Do_Range_Check (gnat_range_node))
-          {
-            /* Get the bounds of the slice. */
+       gnu_result = maybe_implicit_deref (gnu_result);
+       gnu_result = maybe_unconstrained_array (gnu_result);
+       gnu_type = TREE_TYPE (gnu_result);
+       if (Do_Range_Check (gnat_range_node))
+         {
+           /* Get the bounds of the slice.  */
            tree gnu_index_type
              = TYPE_INDEX_TYPE (TYPE_DOMAIN (gnu_result_type));
-            tree gnu_min_expr = TYPE_MIN_VALUE (gnu_index_type);
-            tree gnu_max_expr = TYPE_MAX_VALUE (gnu_index_type);
-            tree gnu_expr_l, gnu_expr_h, gnu_expr_type;
-
-            /* Check to see that the minimum slice value is in range */
-            gnu_expr_l
-             = emit_index_check
-               (gnu_result, gnu_min_expr,
-                TYPE_MIN_VALUE (TYPE_INDEX_TYPE (TYPE_DOMAIN (gnu_type))),
-                TYPE_MAX_VALUE (TYPE_INDEX_TYPE (TYPE_DOMAIN (gnu_type))));
-
-            /* Check to see that the maximum slice value is in range */
-            gnu_expr_h
-             = emit_index_check
-               (gnu_result, gnu_max_expr,
-                TYPE_MIN_VALUE (TYPE_INDEX_TYPE (TYPE_DOMAIN (gnu_type))),
-                TYPE_MAX_VALUE (TYPE_INDEX_TYPE (TYPE_DOMAIN (gnu_type))));
-
-            /* Derive a good type to convert everything too */
-            gnu_expr_type = get_base_type (TREE_TYPE (gnu_expr_l));
-
-            /* Build a compound expression that does the range checks */
-            gnu_expr
-              = build_binary_op (COMPOUND_EXPR, gnu_expr_type,
-                                 convert (gnu_expr_type, gnu_expr_h),
-                                 convert (gnu_expr_type, gnu_expr_l));
-
-            /* Build a conditional expression that returns the range checks
-               expression if the slice range is not null (max >= min) or
-               returns the min if the slice range is null */
-            gnu_expr
-              = fold (build (COND_EXPR, gnu_expr_type,
-                            build_binary_op (GE_EXPR, gnu_expr_type,
-                                             convert (gnu_expr_type,
-                                                      gnu_max_expr),
-                                             convert (gnu_expr_type,
-                                                      gnu_min_expr)),
-                            gnu_expr, gnu_min_expr));
-          }
-        else
-          gnu_expr = TYPE_MIN_VALUE (TYPE_DOMAIN (gnu_result_type));
+           tree gnu_min_expr = TYPE_MIN_VALUE (gnu_index_type);
+           tree gnu_max_expr = TYPE_MAX_VALUE (gnu_index_type);
+           /* Get the permitted bounds.  */
+           tree gnu_base_index_type
+             = TYPE_INDEX_TYPE (TYPE_DOMAIN (gnu_type));
+           tree gnu_base_min_expr = TYPE_MIN_VALUE (gnu_base_index_type);
+           tree gnu_base_max_expr = TYPE_MAX_VALUE (gnu_base_index_type);
+           tree gnu_expr_l, gnu_expr_h, gnu_expr_type;
+
+           /* Check to see that the minimum slice value is in range.  */
+           gnu_expr_l = emit_index_check (gnu_result,
+                                          gnu_min_expr,
+                                          gnu_base_min_expr,
+                                          gnu_base_max_expr);
+
+           /* Check to see that the maximum slice value is in range.  */
+           gnu_expr_h = emit_index_check (gnu_result,
+                                          gnu_max_expr,
+                                          gnu_base_min_expr,
+                                          gnu_base_max_expr);
+
+           /* Derive a good type to convert everything to.  */
+           gnu_expr_type = get_base_type (TREE_TYPE (gnu_expr_l));
+
+           /* Build a compound expression that does the range checks and
+              returns the low bound.  */
+           gnu_expr = build_binary_op (COMPOUND_EXPR, gnu_expr_type,
+                                       convert (gnu_expr_type, gnu_expr_h),
+                                       convert (gnu_expr_type, gnu_expr_l));
+
+          /* Build a conditional expression that does the range check and
+             returns the low bound if the slice is not empty (max >= min),
+             and returns the naked low bound otherwise (max < min), unless
+             it is non-constant and the high bound is; this prevents VRP
+             from inferring bogus ranges on the unlikely path.  */
+           gnu_expr = fold_build3 (COND_EXPR, gnu_expr_type,
+                                   build_binary_op (GE_EXPR, gnu_expr_type,
+                                                    convert (gnu_expr_type,
+                                                             gnu_max_expr),
+                                                    convert (gnu_expr_type,
+                                                             gnu_min_expr)),
+                                   gnu_expr,
+                                   TREE_CODE (gnu_min_expr) != INTEGER_CST
+                                   && TREE_CODE (gnu_max_expr) == INTEGER_CST
+                                   ? gnu_max_expr : gnu_min_expr);
+         }
+       else
+         /* Simply return the naked low bound.  */
+         gnu_expr = TYPE_MIN_VALUE (TYPE_DOMAIN (gnu_result_type));
 
-        gnu_result = build_binary_op (ARRAY_RANGE_REF, gnu_result_type,
+       gnu_result = build_binary_op (ARRAY_RANGE_REF, gnu_result_type,
                                      gnu_result, gnu_expr);
       }
       break;
@@ -2914,7 +3599,7 @@ gnat_to_gnu (Node_Id gnat_node)
                                       NULL_TREE, gnu_prefix);
        else
          {
-           gnu_field = gnat_to_gnu_entity (gnat_field, NULL_TREE, 0);
+           gnu_field = gnat_to_gnu_field_decl (gnat_field);
 
            /* If there are discriminants, the prefix might be
                evaluated more than once, which is a problem if it has
@@ -2923,7 +3608,7 @@ gnat_to_gnu (Node_Id gnat_node)
                                   ? Designated_Type (Etype
                                                      (Prefix (gnat_node)))
                                   : Etype (Prefix (gnat_node))))
-             gnu_prefix = gnat_stabilize_reference (gnu_prefix, 0);
+             gnu_prefix = gnat_stabilize_reference (gnu_prefix, false);
 
            gnu_result
              = build_component_ref (gnu_prefix, NULL_TREE, gnu_field,
@@ -2931,9 +3616,7 @@ gnat_to_gnu (Node_Id gnat_node)
                                      == N_Attribute_Reference));
          }
 
-       if (!gnu_result)
-         abort ();
-
+       gcc_assert (gnu_result);
        gnu_result_type = get_unpadded_type (Etype (gnat_node));
       }
       break;
@@ -2973,6 +3656,8 @@ gnat_to_gnu (Node_Id gnat_node)
        /* ??? It is wrong to evaluate the type now, but there doesn't
           seem to be any other practical way of doing it.  */
 
+       gcc_assert (!Expansion_Delayed (gnat_node));
+
        gnu_aggr_type = gnu_result_type
          = get_unpadded_type (Etype (gnat_node));
 
@@ -2984,24 +3669,12 @@ gnat_to_gnu (Node_Id gnat_node)
        if (Null_Record_Present (gnat_node))
          gnu_result = gnat_build_constructor (gnu_aggr_type, NULL_TREE);
 
-       else if (TREE_CODE (gnu_aggr_type) == RECORD_TYPE)
+       else if (TREE_CODE (gnu_aggr_type) == RECORD_TYPE
+                || TREE_CODE (gnu_aggr_type) == UNION_TYPE)
          gnu_result
-           = assoc_to_constructor (First (Component_Associations (gnat_node)),
+           = assoc_to_constructor (Etype (gnat_node),
+                                   First (Component_Associations (gnat_node)),
                                    gnu_aggr_type);
-       else if (TREE_CODE (gnu_aggr_type) == UNION_TYPE)
-         {
-           /* The first element is the discrimant, which we ignore.  The
-              next is the field we're building.  Convert the expression
-              to the type of the field and then to the union type.  */
-           Node_Id gnat_assoc
-             = Next (First (Component_Associations (gnat_node)));
-           Entity_Id gnat_field = Entity (First (Choices (gnat_assoc)));
-           tree gnu_field_type
-             = TREE_TYPE (gnat_to_gnu_entity (gnat_field, NULL_TREE, 0));
-
-           gnu_result = convert (gnu_field_type,
-                                 gnat_to_gnu (Expression (gnat_assoc)));
-         }
        else if (TREE_CODE (gnu_aggr_type) == ARRAY_TYPE)
          gnu_result = pos_to_constructor (First (Expressions (gnat_node)),
                                           gnu_aggr_type,
@@ -3016,14 +3689,19 @@ gnat_to_gnu (Node_Id gnat_node)
                            (Next
                             (First (Component_Associations (gnat_node))))));
        else
-         abort ();
+         gcc_unreachable ();
 
        gnu_result = convert (gnu_result_type, gnu_result);
       }
       break;
 
     case N_Null:
-      gnu_result = null_pointer_node;
+      if (TARGET_VTABLE_USES_DESCRIPTORS
+         && Ekind (Etype (gnat_node)) == E_Access_Subprogram_Type
+         && Is_Dispatch_Table_Entity (Etype (gnat_node)))
+       gnu_result = null_fdesc_node;
+      else
+       gnu_result = null_pointer_node;
       gnu_result_type = get_unpadded_type (Etype (gnat_node));
       break;
 
@@ -3047,7 +3725,6 @@ gnat_to_gnu (Node_Id gnat_node)
 
       /* If the result is a pointer type, see if we are improperly
         converting to a stricter alignment.  */
-
       if (STRICT_ALIGNMENT && POINTER_TYPE_P (gnu_result_type)
          && IN (Ekind (Etype (gnat_node)), Access_Kind))
        {
@@ -3057,11 +3734,18 @@ gnat_to_gnu (Node_Id gnat_node)
 
          if (align != 0 && align < oalign && !TYPE_ALIGN_OK (gnu_obj_type))
            post_error_ne_tree_2
-             ("?source alignment (^) < alignment of & (^)",
+             ("?source alignment (^) '< alignment of & (^)",
               gnat_node, Designated_Type (Etype (gnat_node)),
               size_int (align / BITS_PER_UNIT), oalign / BITS_PER_UNIT);
        }
 
+      /* If we are converting a descriptor to a function pointer, first
+        build the pointer.  */
+      if (TARGET_VTABLE_USES_DESCRIPTORS
+         && TREE_TYPE (gnu_result) == fdesc_type_node
+         && POINTER_TYPE_P (gnu_result_type))
+       gnu_result = build_unary_op (ADDR_EXPR, NULL_TREE, gnu_result);
+
       gnu_result = unchecked_convert (gnu_result_type, gnu_result,
                                      No_Truncation (gnat_node));
       break;
@@ -3090,7 +3774,7 @@ gnat_to_gnu (Node_Id gnat_node)
            gnu_high = TYPE_MAX_VALUE (gnu_range_type);
          }
        else
-         abort ();
+         gcc_unreachable ();
 
        gnu_result_type = get_unpadded_type (Etype (gnat_node));
 
@@ -3161,6 +3845,7 @@ gnat_to_gnu (Node_Id gnat_node)
     case N_And_Then: case N_Or_Else:
       {
        enum tree_code code = gnu_codes[Nkind (gnat_node)];
+       bool ignore_lhs_overflow = false;
        tree gnu_type;
 
        gnu_lhs = gnat_to_gnu (Left_Opnd (gnat_node));
@@ -3170,7 +3855,7 @@ gnat_to_gnu (Node_Id gnat_node)
        /* If this is a comparison operator, convert any references to
           an unconstrained array value into a reference to the
           actual array.  */
-       if (TREE_CODE_CLASS (code) == '<')
+       if (TREE_CODE_CLASS (code) == tcc_comparison)
          {
            gnu_lhs = maybe_unconstrained_array (gnu_lhs);
            gnu_rhs = maybe_unconstrained_array (gnu_rhs);
@@ -3209,17 +3894,28 @@ gnat_to_gnu (Node_Id gnat_node)
          }
 
        /* For right shifts, the type says what kind of shift to do,
-          so we may need to choose a different type.  */
+          so we may need to choose a different type.  In this case,
+          we have to ignore integer overflow lest it propagates all
+          the way down and causes a CE to be explicitly raised.  */
        if (Nkind (gnat_node) == N_Op_Shift_Right
            && !TYPE_UNSIGNED (gnu_type))
-         gnu_type = gnat_unsigned_type (gnu_type);
+         {
+           gnu_type = gnat_unsigned_type (gnu_type);
+           ignore_lhs_overflow = true;
+         }
        else if (Nkind (gnat_node) == N_Op_Shift_Right_Arithmetic
                 && TYPE_UNSIGNED (gnu_type))
-         gnu_type = gnat_signed_type (gnu_type);
+         {
+           gnu_type = gnat_signed_type (gnu_type);
+           ignore_lhs_overflow = true;
+         }
 
        if (gnu_type != gnu_result_type)
          {
+           tree gnu_old_lhs = gnu_lhs;
            gnu_lhs = convert (gnu_type, gnu_lhs);
+           if (TREE_CODE (gnu_lhs) == INTEGER_CST && ignore_lhs_overflow)
+             TREE_OVERFLOW (gnu_lhs) = TREE_OVERFLOW (gnu_old_lhs);
            gnu_rhs = convert (gnu_type, gnu_rhs);
          }
 
@@ -3266,7 +3962,9 @@ gnat_to_gnu (Node_Id gnat_node)
       /* This case can apply to a boolean or a modular type.
         Fall through for a boolean operand since GNU_CODES is set
         up to handle this.  */
-      if (IN (Ekind (Etype (gnat_node)), Modular_Integer_Kind))
+      if (Is_Modular_Integer_Type (Etype (gnat_node))
+         || (Ekind (Etype (gnat_node)) == E_Private_Type
+             && Is_Modular_Integer_Type (Full_View (Etype (gnat_node)))))
        {
          gnu_expr = gnat_to_gnu (Right_Opnd (gnat_node));
          gnu_result_type = get_unpadded_type (Etype (gnat_node));
@@ -3294,6 +3992,7 @@ gnat_to_gnu (Node_Id gnat_node)
       {
        tree gnu_init = 0;
        tree gnu_type;
+       bool ignore_init_type = false;
 
        gnat_temp = Expression (gnat_node);
 
@@ -3309,6 +4008,7 @@ gnat_to_gnu (Node_Id gnat_node)
            Entity_Id gnat_desig_type
              = Designated_Type (Underlying_Type (Etype (gnat_node)));
 
+           ignore_init_type = Has_Constrained_Partial_View (gnat_desig_type);
            gnu_init = gnat_to_gnu (Expression (gnat_temp));
 
            gnu_init = maybe_unconstrained_array (gnu_init);
@@ -3331,12 +4031,13 @@ gnat_to_gnu (Node_Id gnat_node)
              }
          }
        else
-         abort ();
+         gcc_unreachable ();
 
        gnu_result_type = get_unpadded_type (Etype (gnat_node));
        return build_allocator (gnu_type, gnu_init, gnu_result_type,
                                Procedure_To_Call (gnat_node),
-                               Storage_Pool (gnat_node), gnat_node);
+                               Storage_Pool (gnat_node), gnat_node,
+                               ignore_init_type);
       }
       break;
 
@@ -3355,26 +4056,33 @@ gnat_to_gnu (Node_Id gnat_node)
 
     case N_Assignment_Statement:
       /* Get the LHS and RHS of the statement and convert any reference to an
-        unconstrained array into a reference to the underlying array.  */
+        unconstrained array into a reference to the underlying array.
+        If we are not to do range checking and the RHS is an N_Function_Call,
+        pass the LHS to the call function.  */
       gnu_lhs = maybe_unconstrained_array (gnat_to_gnu (Name (gnat_node)));
-      gnu_rhs
-       = maybe_unconstrained_array (gnat_to_gnu (Expression (gnat_node)));
-
-      /* If range check is needed, emit code to generate it */
-      if (Do_Range_Check (Expression (gnat_node)))
-       gnu_rhs = emit_range_check (gnu_rhs, Etype (Name (gnat_node)));
-
-      /* If either side's type has a size that overflows, convert this
-        into raise of Storage_Error: execution shouldn't have gotten
-        here anyway.  */
-      if ((TREE_CODE (TYPE_SIZE (TREE_TYPE (gnu_lhs))) == INTEGER_CST
-          && TREE_OVERFLOW (TYPE_SIZE (TREE_TYPE (gnu_lhs))))
-         || (TREE_CODE (TYPE_SIZE (TREE_TYPE (gnu_rhs))) == INTEGER_CST
-             && TREE_OVERFLOW (TYPE_SIZE (TREE_TYPE (gnu_rhs)))))
-       gnu_result = build_call_raise (SE_Object_Too_Large);
+
+      /* If the type has a size that overflows, convert this into raise of
+        Storage_Error: execution shouldn't have gotten here anyway.  */
+      if (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (gnu_lhs))) == INTEGER_CST
+          && TREE_OVERFLOW (TYPE_SIZE_UNIT (TREE_TYPE (gnu_lhs))))
+       gnu_result = build_call_raise (SE_Object_Too_Large, gnat_node,
+                                      N_Raise_Storage_Error);
+      else if (Nkind (Expression (gnat_node)) == N_Function_Call
+              && !Do_Range_Check (Expression (gnat_node)))
+       gnu_result = call_to_gnu (Expression (gnat_node),
+                                 &gnu_result_type, gnu_lhs);
       else
-       gnu_result
-         = build_binary_op (MODIFY_EXPR, NULL_TREE, gnu_lhs, gnu_rhs);
+       {
+         gnu_rhs
+           = maybe_unconstrained_array (gnat_to_gnu (Expression (gnat_node)));
+
+         /* If range check is needed, emit code to generate it */
+         if (Do_Range_Check (Expression (gnat_node)))
+           gnu_rhs = emit_range_check (gnu_rhs, Etype (Name (gnat_node)));
+
+         gnu_result
+           = build_binary_op (MODIFY_EXPR, NULL_TREE, gnu_lhs, gnu_rhs);
+       }
       break;
 
     case N_If_Statement:
@@ -3382,9 +4090,9 @@ gnat_to_gnu (Node_Id gnat_node)
        tree *gnu_else_ptr;     /* Point to put next "else if" or "else". */
 
        /* Make the outer COND_EXPR.  Avoid non-determinism.  */
-       gnu_result = build (COND_EXPR, void_type_node,
-                           gnat_to_gnu (Condition (gnat_node)),
-                           NULL_TREE, NULL_TREE);
+       gnu_result = build3 (COND_EXPR, void_type_node,
+                            gnat_to_gnu (Condition (gnat_node)),
+                            NULL_TREE, NULL_TREE);
        COND_EXPR_THEN (gnu_result)
          = build_stmt_group (Then_Statements (gnat_node), false);
        TREE_SIDE_EFFECTS (gnu_result) = 1;
@@ -3397,13 +4105,13 @@ gnat_to_gnu (Node_Id gnat_node)
          for (gnat_temp = First (Elsif_Parts (gnat_node));
               Present (gnat_temp); gnat_temp = Next (gnat_temp))
            {
-             gnu_expr = build (COND_EXPR, void_type_node,
-                               gnat_to_gnu (Condition (gnat_temp)),
-                               NULL_TREE, NULL_TREE);
+             gnu_expr = build3 (COND_EXPR, void_type_node,
+                                gnat_to_gnu (Condition (gnat_temp)),
+                                NULL_TREE, NULL_TREE);
              COND_EXPR_THEN (gnu_expr)
                = build_stmt_group (Then_Statements (gnat_temp), false);
              TREE_SIDE_EFFECTS (gnu_expr) = 1;
-             annotate_with_node (gnu_expr, gnat_temp);
+             set_expr_location_from_node (gnu_expr, gnat_temp);
              *gnu_else_ptr = gnu_expr;
              gnu_else_ptr = &COND_EXPR_ELSE (gnu_expr);
            }
@@ -3434,12 +4142,12 @@ gnat_to_gnu (Node_Id gnat_node)
 
     case N_Exit_Statement:
       gnu_result
-       = build (EXIT_STMT, void_type_node,
-                (Present (Condition (gnat_node))
-                 ? gnat_to_gnu (Condition (gnat_node)) : NULL_TREE),
-                (Present (Name (gnat_node))
-                 ? get_gnu_tree (Entity (Name (gnat_node)))
-                 : TREE_VALUE (gnu_loop_label_stack)));
+       = build2 (EXIT_STMT, void_type_node,
+                 (Present (Condition (gnat_node))
+                  ? gnat_to_gnu (Condition (gnat_node)) : NULL_TREE),
+                 (Present (Name (gnat_node))
+                  ? get_gnu_tree (Entity (Name (gnat_node)))
+                  : TREE_VALUE (gnu_loop_label_stack)));
       break;
 
     case N_Return_Statement:
@@ -3447,7 +4155,9 @@ gnat_to_gnu (Node_Id gnat_node)
        /* The gnu function type of the subprogram currently processed.  */
        tree gnu_subprog_type = TREE_TYPE (current_function_decl);
        /* The return value from the subprogram.  */
-       tree gnu_ret_val = 0;
+       tree gnu_ret_val = NULL_TREE;
+       /* The place to put the return value.  */
+       tree gnu_lhs;
 
        /* If we are dealing with a "return;" from an Ada procedure with
           parameters passed by copy in copy out, we need to return a record
@@ -3470,6 +4180,7 @@ gnat_to_gnu (Node_Id gnat_node)
 
        else if (TYPE_CI_CO_LIST (gnu_subprog_type))
          {
+           gnu_lhs = DECL_RESULT (current_function_decl);
            if (list_length (TYPE_CI_CO_LIST (gnu_subprog_type)) == 1)
              gnu_ret_val = TREE_VALUE (TYPE_CI_CO_LIST (gnu_subprog_type));
            else
@@ -3485,53 +4196,74 @@ gnat_to_gnu (Node_Id gnat_node)
 
        else if (Present (Expression (gnat_node)))
          {
-           gnu_ret_val = gnat_to_gnu (Expression (gnat_node));
-
-           /* Do not remove the padding from GNU_RET_VAL if the inner
-              type is self-referential since we want to allocate the fixed
-              size in that case.  */
-           if (TREE_CODE (gnu_ret_val) == COMPONENT_REF
-               && (TREE_CODE (TREE_TYPE (TREE_OPERAND (gnu_ret_val, 0)))
-                   == RECORD_TYPE)
-               && (TYPE_IS_PADDING_P
-                   (TREE_TYPE (TREE_OPERAND (gnu_ret_val, 0))))
-               && (CONTAINS_PLACEHOLDER_P
-                   (TYPE_SIZE (TREE_TYPE (gnu_ret_val)))))
-             gnu_ret_val = TREE_OPERAND (gnu_ret_val, 0);
-
-           if (TYPE_RETURNS_BY_REF_P (gnu_subprog_type)
-               || By_Ref (gnat_node))
-             gnu_ret_val = build_unary_op (ADDR_EXPR, NULL_TREE, gnu_ret_val);
-
-           else if (TYPE_RETURNS_UNCONSTRAINED_P (gnu_subprog_type))
+           /* If the current function returns by target pointer and we
+              are doing a call, pass that target to the call.  */
+           if (TYPE_RETURNS_BY_TARGET_PTR_P (gnu_subprog_type)
+               && Nkind (Expression (gnat_node)) == N_Function_Call)
              {
-               gnu_ret_val = maybe_unconstrained_array (gnu_ret_val);
-
-               /* We have two cases: either the function returns with
-                  depressed stack or not.  If not, we allocate on the
-                  secondary stack.  If so, we allocate in the stack frame.
-                  if no copy is needed, the front end will set By_Ref,
-                  which we handle in the case above.  */
-               if (TYPE_RETURNS_STACK_DEPRESSED (gnu_subprog_type))
-                 gnu_ret_val
-                   = build_allocator (TREE_TYPE (gnu_ret_val), gnu_ret_val,
-                                      TREE_TYPE (gnu_subprog_type), 0, -1,
-                                      gnat_node);
+               gnu_lhs
+                 = build_unary_op (INDIRECT_REF, NULL_TREE,
+                                   DECL_ARGUMENTS (current_function_decl));
+               gnu_result = call_to_gnu (Expression (gnat_node),
+                                         &gnu_result_type, gnu_lhs);
+             }
+           else
+             {
+               gnu_ret_val = gnat_to_gnu (Expression (gnat_node));
+
+               if (TYPE_RETURNS_BY_TARGET_PTR_P (gnu_subprog_type))
+                 /* The original return type was unconstrained so dereference
+                    the TARGET pointer in the actual return value's type. */
+                 gnu_lhs
+                   = build_unary_op (INDIRECT_REF, TREE_TYPE (gnu_ret_val),
+                                     DECL_ARGUMENTS (current_function_decl));
                else
+                 gnu_lhs = DECL_RESULT (current_function_decl);
+
+               /* Do not remove the padding from GNU_RET_VAL if the inner
+                  type is self-referential since we want to allocate the fixed
+                  size in that case.  */
+               if (TREE_CODE (gnu_ret_val) == COMPONENT_REF
+                   && (TREE_CODE (TREE_TYPE (TREE_OPERAND (gnu_ret_val, 0)))
+                       == RECORD_TYPE)
+                   && (TYPE_IS_PADDING_P
+                       (TREE_TYPE (TREE_OPERAND (gnu_ret_val, 0))))
+                   && (CONTAINS_PLACEHOLDER_P
+                       (TYPE_SIZE (TREE_TYPE (gnu_ret_val)))))
+                 gnu_ret_val = TREE_OPERAND (gnu_ret_val, 0);
+
+               if (TYPE_RETURNS_BY_REF_P (gnu_subprog_type)
+                   || By_Ref (gnat_node))
                  gnu_ret_val
-                   = build_allocator (TREE_TYPE (gnu_ret_val), gnu_ret_val,
-                                      TREE_TYPE (gnu_subprog_type),
-                                      Procedure_To_Call (gnat_node),
-                                      Storage_Pool (gnat_node), gnat_node);
+                   = build_unary_op (ADDR_EXPR, NULL_TREE, gnu_ret_val);
+
+               else if (TYPE_RETURNS_UNCONSTRAINED_P (gnu_subprog_type))
+                 {
+                   gnu_ret_val = maybe_unconstrained_array (gnu_ret_val);
+                   gnu_ret_val
+                     = build_allocator (TREE_TYPE (gnu_ret_val),
+                                        gnu_ret_val,
+                                        TREE_TYPE (gnu_subprog_type),
+                                        Procedure_To_Call (gnat_node),
+                                        Storage_Pool (gnat_node),
+                                        gnat_node, false);
+                 }
              }
          }
+       else
+         /* If the Ada subprogram is a regular procedure, just return.  */
+         gnu_lhs = NULL_TREE;
+
+       if (TYPE_RETURNS_BY_TARGET_PTR_P (gnu_subprog_type))
+         {
+           if (gnu_ret_val)
+             gnu_result = build_binary_op (MODIFY_EXPR, NULL_TREE,
+                                           gnu_lhs, gnu_ret_val);
+           add_stmt_with_node (gnu_result, gnat_node);
+           gnu_lhs = NULL_TREE;
+         }
 
-       gnu_result =  build1 (RETURN_EXPR, void_type_node,
-                             (gnu_ret_val
-                              ? build (MODIFY_EXPR, TREE_TYPE (gnu_ret_val),
-                                       DECL_RESULT (current_function_decl),
-                                       gnu_ret_val)
-                              : NULL_TREE));
+       gnu_result = build_return_expr (gnu_lhs, gnu_ret_val);
       }
       break;
 
@@ -3548,7 +4280,7 @@ gnat_to_gnu (Node_Id gnat_node)
       /* Unless there is a freeze node, declare the subprogram.  We consider
         this a "definition" even though we're not generating code for
         the subprogram because we will be making the corresponding GCC
-        node here.  */
+        node here. */
 
       if (No (Freeze_Node (Defining_Entity (Specification (gnat_node)))))
        gnat_to_gnu_entity (Defining_Entity (Specification (gnat_node)),
@@ -3558,22 +4290,37 @@ gnat_to_gnu (Node_Id gnat_node)
 
     case N_Abstract_Subprogram_Declaration:
       /* This subprogram doesn't exist for code generation purposes, but we
-        have to elaborate the types of any parameters, unless they are
-        imported types (nothing to generate in this case).  */
+        have to elaborate the types of any parameters and result, unless
+        they are imported types (nothing to generate in this case).  */
+
+      /* Process the parameter types first.  */
+
       for (gnat_temp
-          = First_Formal (Defining_Entity (Specification (gnat_node)));
+          = First_Formal_With_Extras
+             (Defining_Entity (Specification (gnat_node)));
           Present (gnat_temp);
           gnat_temp = Next_Formal_With_Extras (gnat_temp))
        if (Is_Itype (Etype (gnat_temp))
            && !From_With_Type (Etype (gnat_temp)))
          gnat_to_gnu_entity (Etype (gnat_temp), NULL_TREE, 0);
 
+
+      /* Then the result type, set to Standard_Void_Type for procedures.  */
+
+      {
+       Entity_Id gnat_temp_type
+         = Etype (Defining_Entity (Specification (gnat_node)));
+
+       if (Is_Itype (gnat_temp_type) && !From_With_Type (gnat_temp_type))
+         gnat_to_gnu_entity (Etype (gnat_temp_type), NULL_TREE, 0);
+      }
+
       gnu_result = alloc_stmt_list ();
       break;
 
     case N_Defining_Program_Unit_Name:
       /* For a child unit identifier go up a level to get the
-         specificaton.  We get this when we try to find the spec of
+         specification.  We get this when we try to find the spec of
         a child unit package that is the compilation unit being compiled. */
       gnu_result = gnat_to_gnu (Parent (gnat_node));
       break;
@@ -3585,7 +4332,7 @@ gnat_to_gnu (Node_Id gnat_node)
 
     case N_Function_Call:
     case N_Procedure_Call_Statement:
-      gnu_result = call_to_gnu (gnat_node, &gnu_result_type);
+      gnu_result = call_to_gnu (gnat_node, &gnu_result_type, NULL_TREE);
       break;
 
     /*************************/
@@ -3654,7 +4401,6 @@ gnat_to_gnu (Node_Id gnat_node)
       /* This is not called for the main unit, which is handled in function
         gigi above.  */
       start_stmt_group ();
-      current_stmt_group->global = current_stmt_group;
       gnat_pushlevel ();
 
       Compilation_Unit_to_gnu (gnat_node);
@@ -3681,12 +4427,11 @@ gnat_to_gnu (Node_Id gnat_node)
       /* If there is an At_End procedure attached to this node, and the EH
         mechanism is SJLJ, we must have at least a corresponding At_End
         handler, unless the No_Exception_Handlers restriction is set.  */
-      if (!type_annotate_only
-         && Exception_Mechanism == Setjmp_Longjmp
-         && Present (At_End_Proc (gnat_node))
-         && !Present (Exception_Handlers (gnat_node))
-         && !No_Exception_Handlers_Set())
-       abort ();
+      gcc_assert (type_annotate_only
+                 || Exception_Mechanism != Setjmp_Longjmp
+                 || No (At_End_Proc (gnat_node))
+                 || Present (Exception_Handlers (gnat_node))
+                 || No_Exception_Handlers_Set ());
 
       gnu_result = Handled_Sequence_Of_Statements_to_gnu (gnat_node);
       break;
@@ -3694,11 +4439,41 @@ gnat_to_gnu (Node_Id gnat_node)
     case N_Exception_Handler:
       if (Exception_Mechanism == Setjmp_Longjmp)
        gnu_result = Exception_Handler_to_gnu_sjlj (gnat_node);
-      else if (Exception_Mechanism == GCC_ZCX)
+      else if (Exception_Mechanism == Back_End_Exceptions)
        gnu_result = Exception_Handler_to_gnu_zcx (gnat_node);
       else
-       abort ();
+       gcc_unreachable ();
+
+      break;
 
+    case N_Push_Constraint_Error_Label:
+      push_exception_label_stack (&gnu_constraint_error_label_stack,
+                                 Exception_Label (gnat_node));
+      break;
+
+    case N_Push_Storage_Error_Label:
+      push_exception_label_stack (&gnu_storage_error_label_stack,
+                                 Exception_Label (gnat_node));
+      break;
+
+    case N_Push_Program_Error_Label:
+      push_exception_label_stack (&gnu_program_error_label_stack,
+                                 Exception_Label (gnat_node));
+      break;
+
+    case N_Pop_Constraint_Error_Label:
+      gnu_constraint_error_label_stack
+       = TREE_CHAIN (gnu_constraint_error_label_stack);
+      break;
+
+    case N_Pop_Storage_Error_Label:
+      gnu_storage_error_label_stack
+       = TREE_CHAIN (gnu_storage_error_label_stack);
+      break;
+
+    case N_Pop_Program_Error_Label:
+      gnu_program_error_label_stack
+       = TREE_CHAIN (gnu_program_error_label_stack);
       break;
 
     /*******************************/
@@ -3738,7 +4513,7 @@ gnat_to_gnu (Node_Id gnat_node)
         equivalent for GNAT_TEMP.  When the object is frozen,
         gnat_to_gnu_entity will do the right thing. */
       save_gnu_tree (Entity (Name (gnat_node)),
-                    gnat_to_gnu (Expression (gnat_node)), true);
+                     gnat_to_gnu (Expression (gnat_node)), true);
       break;
 
     case N_Enumeration_Representation_Clause:
@@ -3752,47 +4527,102 @@ gnat_to_gnu (Node_Id gnat_node)
       if (!type_annotate_only)
        {
          tree gnu_template = gnat_to_gnu (Asm_Template (gnat_node));
-         tree gnu_input_list = NULL_TREE, gnu_output_list = NULL_TREE;
-         tree gnu_clobber_list = NULL_TREE;
+         tree gnu_inputs = NULL_TREE, gnu_outputs = NULL_TREE;
+         tree gnu_clobbers = NULL_TREE, tail;
+         bool allows_mem, allows_reg, fake;
+         int ninputs, noutputs, i;
+         const char **oconstraints;
+         const char *constraint;
          char *clobber;
 
-         /* First process inputs, then outputs, then clobbers.  */
-         Setup_Asm_Inputs (gnat_node);
-         while (Present (gnat_temp = Asm_Input_Value ()))
+         /* First retrieve the 3 operand lists built by the front-end.  */
+         Setup_Asm_Outputs (gnat_node);
+         while (Present (gnat_temp = Asm_Output_Variable ()))
            {
              tree gnu_value = gnat_to_gnu (gnat_temp);
              tree gnu_constr = build_tree_list (NULL_TREE, gnat_to_gnu
-                                                (Asm_Input_Constraint ()));
+                                                (Asm_Output_Constraint ()));
 
-             gnu_input_list
-               = tree_cons (gnu_constr, gnu_value, gnu_input_list);
-             Next_Asm_Input ();
+             gnu_outputs = tree_cons (gnu_constr, gnu_value, gnu_outputs);
+             Next_Asm_Output ();
            }
 
-         Setup_Asm_Outputs (gnat_node);
-         while (Present (gnat_temp = Asm_Output_Variable ()))
+         Setup_Asm_Inputs (gnat_node);
+         while (Present (gnat_temp = Asm_Input_Value ()))
            {
              tree gnu_value = gnat_to_gnu (gnat_temp);
              tree gnu_constr = build_tree_list (NULL_TREE, gnat_to_gnu
-                                                (Asm_Output_Constraint ()));
+                                                (Asm_Input_Constraint ()));
 
-             gnu_output_list
-               = tree_cons (gnu_constr, gnu_value, gnu_output_list);
-             Next_Asm_Output ();
+             gnu_inputs = tree_cons (gnu_constr, gnu_value, gnu_inputs);
+             Next_Asm_Input ();
            }
 
          Clobber_Setup (gnat_node);
          while ((clobber = Clobber_Get_Next ()))
-           gnu_clobber_list
+           gnu_clobbers
              = tree_cons (NULL_TREE,
                           build_string (strlen (clobber) + 1, clobber),
-                          gnu_clobber_list);
+                          gnu_clobbers);
+
+          /* Then perform some standard checking and processing on the
+            operands.  In particular, mark them addressable if needed.  */
+         gnu_outputs = nreverse (gnu_outputs);
+         noutputs = list_length (gnu_outputs);
+         gnu_inputs = nreverse (gnu_inputs);
+         ninputs = list_length (gnu_inputs);
+         oconstraints
+           = (const char **) alloca (noutputs * sizeof (const char *));
+
+         for (i = 0, tail = gnu_outputs; tail; ++i, tail = TREE_CHAIN (tail))
+           {
+             tree output = TREE_VALUE (tail);
+             constraint
+               = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
+             oconstraints[i] = constraint;
+
+             if (parse_output_constraint (&constraint, i, ninputs, noutputs,
+                                          &allows_mem, &allows_reg, &fake))
+               {
+                 /* If the operand is going to end up in memory,
+                    mark it addressable.  Note that we don't test
+                    allows_mem like in the input case below; this
+                    is modelled on the C front-end.  */
+                 if (!allows_reg
+                     && !gnat_mark_addressable (output))
+                   output = error_mark_node;
+               }
+             else
+               output = error_mark_node;
+
+             TREE_VALUE (tail) = output;
+           }
+
+         for (i = 0, tail = gnu_inputs; tail; ++i, tail = TREE_CHAIN (tail))
+           {
+             tree input = TREE_VALUE (tail);
+             constraint
+               = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
+
+             if (parse_input_constraint (&constraint, i, ninputs, noutputs,
+                                         0, oconstraints,
+                                         &allows_mem, &allows_reg))
+               {
+                 /* If the operand is going to end up in memory,
+                    mark it addressable.  */
+                 if (!allows_reg && allows_mem
+                     && !gnat_mark_addressable (input))
+                   input = error_mark_node;
+               }
+             else
+               input = error_mark_node;
+
+             TREE_VALUE (tail) = input;
+           }
 
-         gnu_input_list = nreverse (gnu_input_list);
-         gnu_output_list = nreverse (gnu_output_list);
-         gnu_result = build (ASM_EXPR,  void_type_node,
-                             gnu_template, gnu_output_list,
-                             gnu_input_list, gnu_clobber_list);
+         gnu_result = build4 (ASM_EXPR,  void_type_node,
+                              gnu_template, gnu_outputs,
+                              gnu_inputs, gnu_clobbers);
          ASM_VOLATILE_P (gnu_result) = Is_Asm_Volatile (gnat_node);
        }
       else
@@ -3822,9 +4652,13 @@ gnat_to_gnu (Node_Id gnat_node)
       if (!type_annotate_only)
        {
          tree gnu_ptr = gnat_to_gnu (Expression (gnat_node));
+         tree gnu_ptr_type = TREE_TYPE (gnu_ptr);
          tree gnu_obj_type;
+         tree gnu_actual_obj_type = 0;
          tree gnu_obj_size;
-         int align;
+         unsigned int align;
+         unsigned int default_allocator_alignment
+           = get_target_default_allocator_alignment () * BITS_PER_UNIT;
 
          /* If this is a thin pointer, we must dereference it to create
             a fat pointer, then go back below to a thin pointer.  The
@@ -3847,7 +4681,22 @@ gnat_to_gnu (Node_Id gnat_node)
                         gnu_ptr);
 
          gnu_obj_type = TREE_TYPE (TREE_TYPE (gnu_ptr));
-         gnu_obj_size = TYPE_SIZE_UNIT (gnu_obj_type);
+
+         if (Present (Actual_Designated_Subtype (gnat_node)))
+           {
+             gnu_actual_obj_type
+               = gnat_to_gnu_type (Actual_Designated_Subtype (gnat_node));
+
+             if (TYPE_FAT_OR_THIN_POINTER_P (gnu_ptr_type))
+               gnu_actual_obj_type
+                 = build_unc_object_type_from_ptr (gnu_ptr_type,
+                     gnu_actual_obj_type,
+                     get_identifier ("DEALLOC"));
+           }
+         else
+           gnu_actual_obj_type = gnu_obj_type;
+
+         gnu_obj_size = TYPE_SIZE_UNIT (gnu_actual_obj_type);
          align = TYPE_ALIGN (gnu_obj_type);
 
          if (TREE_CODE (gnu_obj_type) == RECORD_TYPE
@@ -3856,14 +4705,47 @@ gnat_to_gnu (Node_Id gnat_node)
              tree gnu_char_ptr_type = build_pointer_type (char_type_node);
              tree gnu_pos = byte_position (TYPE_FIELDS (gnu_obj_type));
              tree gnu_byte_offset
-               = convert (gnu_char_ptr_type,
+               = convert (sizetype,
                           size_diffop (size_zero_node, gnu_pos));
+             gnu_byte_offset = fold_build1 (NEGATE_EXPR, sizetype, gnu_byte_offset);
 
              gnu_ptr = convert (gnu_char_ptr_type, gnu_ptr);
-             gnu_ptr = build_binary_op (MINUS_EXPR, gnu_char_ptr_type,
+             gnu_ptr = build_binary_op (POINTER_PLUS_EXPR, gnu_char_ptr_type,
                                         gnu_ptr, gnu_byte_offset);
            }
 
+         /* If the object was allocated from the default storage pool, the
+            alignement was greater than what the allocator provides, and this
+            is not a fat or thin pointer, what we have in gnu_ptr here is an
+            address dynamically adjusted to match the alignment requirement
+            (see build_allocator).  What we need to pass to free is the
+            initial allocator's return value, which has been stored just in
+            front of the block we have.  */
+
+         if (No (Procedure_To_Call (gnat_node))
+             && align > default_allocator_alignment
+             && ! TYPE_FAT_OR_THIN_POINTER_P (gnu_ptr_type))
+           {
+             /* We set GNU_PTR
+                as * (void **)((void *)GNU_PTR - (void *)sizeof(void *))
+                in two steps:  */
+
+             /* GNU_PTR (void *)
+                = (void *)GNU_PTR - (void *)sizeof (void *))  */
+             gnu_ptr
+               = build_binary_op
+                   (POINTER_PLUS_EXPR, ptr_void_type_node,
+                    convert (ptr_void_type_node, gnu_ptr),
+                    size_int (-POINTER_SIZE/BITS_PER_UNIT));
+
+             /* GNU_PTR (void *) = *(void **)GNU_PTR  */
+             gnu_ptr
+               = build_unary_op
+                   (INDIRECT_REF, NULL_TREE,
+                    convert (build_pointer_type (ptr_void_type_node),
+                             gnu_ptr));
+           }
+
          gnu_result = build_call_alloc_dealloc (gnu_ptr, gnu_obj_size, align,
                                                 Procedure_To_Call (gnat_node),
                                                 Storage_Pool (gnat_node),
@@ -3881,19 +4763,21 @@ gnat_to_gnu (Node_Id gnat_node)
        }
 
       gnu_result_type = get_unpadded_type (Etype (gnat_node));
-      gnu_result = build_call_raise (UI_To_Int (Reason (gnat_node)));
+      gnu_result
+       = build_call_raise (UI_To_Int (Reason (gnat_node)), gnat_node,
+                           Nkind (gnat_node));
 
       /* If the type is VOID, this is a statement, so we need to
         generate the code for the call.  Handle a Condition, if there
         is one.  */
       if (TREE_CODE (gnu_result_type) == VOID_TYPE)
        {
-         annotate_with_node (gnu_result, gnat_node);
+         set_expr_location_from_node (gnu_result, gnat_node);
 
          if (Present (Condition (gnat_node)))
-           gnu_result = build (COND_EXPR, void_type_node,
-                               gnat_to_gnu (Condition (gnat_node)),
-                               gnu_result, alloc_stmt_list ());
+           gnu_result = build3 (COND_EXPR, void_type_node,
+                                gnat_to_gnu (Condition (gnat_node)),
+                                gnu_result, alloc_stmt_list ());
        }
       else
        gnu_result = build1 (NULL_EXPR, gnu_result_type, gnu_result);
@@ -3903,7 +4787,7 @@ gnat_to_gnu (Node_Id gnat_node)
       /* If the result is a pointer type, see if we are either converting
          from a non-pointer or from a pointer to a type with a different
         alias set and warn if so.  If the result defined in the same unit as
-        this unchecked convertion, we can allow this because we can know to
+        this unchecked conversion, we can allow this because we can know to
         make that type have alias set 0.  */
       {
        tree gnu_source_type = gnat_to_gnu_type (Source_Type (gnat_node));
@@ -3927,6 +4811,27 @@ gnat_to_gnu (Node_Id gnat_node)
               ("\\?or use `pragma No_Strict_Aliasing (&);`",
                gnat_node, Target_Type (gnat_node));
          }
+
+       /* The No_Strict_Aliasing flag is not propagated to the back-end for
+          fat pointers so unconditionally warn in problematic cases.  */
+       else if (TYPE_FAT_POINTER_P (gnu_target_type))
+         {
+           tree array_type
+             = TREE_TYPE (TREE_TYPE (TYPE_FIELDS (gnu_target_type)));
+
+           if (get_alias_set (array_type) != 0
+               && (!TYPE_FAT_POINTER_P (gnu_source_type)
+                   || (get_alias_set (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (gnu_source_type))))
+                       != get_alias_set (array_type))))
+             {
+               post_error_ne
+                 ("?possible aliasing problem for type&",
+                  gnat_node, Target_Type (gnat_node));
+               post_error
+                 ("\\?use -fno-strict-aliasing switch for references",
+                  gnat_node);
+             }
+         }
       }
       gnu_result = alloc_stmt_list ();
       break;
@@ -3938,9 +4843,7 @@ gnat_to_gnu (Node_Id gnat_node)
     case N_Component_Association:
     case N_Task_Body:
     default:
-      if (!type_annotate_only)
-       abort ();
-
+      gcc_assert (type_annotate_only);
       gnu_result = alloc_stmt_list ();
     }
 
@@ -3954,24 +4857,29 @@ gnat_to_gnu (Node_Id gnat_node)
       current_function_decl = NULL_TREE;
     }
 
-  /* Set the location information into the result.  If we're supposed to
-     return something of void_type, it means we have something we're
-     elaborating for effect, so just return.  */
-  if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (gnu_result))))
-    annotate_with_node (gnu_result, gnat_node);
+  /* Set the location information on the result if it is a real expression.
+     References can be reused for multiple GNAT nodes and they would get
+     the location information of their last use.  Note that we may have
+     no result if we tried to build a CALL_EXPR node to a procedure with
+     no side-effects and optimization is enabled.  */
+  if (gnu_result && EXPR_P (gnu_result) && !REFERENCE_CLASS_P (gnu_result))
+    set_expr_location_from_node (gnu_result, gnat_node);
 
+  /* If we're supposed to return something of void_type, it means we have
+     something we're elaborating for effect, so just return.  */
   if (TREE_CODE (gnu_result_type) == VOID_TYPE)
     return gnu_result;
 
   /* If the result is a constant that overflows, raise constraint error.  */
   else if (TREE_CODE (gnu_result) == INTEGER_CST
-      && TREE_CONSTANT_OVERFLOW (gnu_result))
+      && TREE_OVERFLOW (gnu_result))
     {
       post_error ("Constraint_Error will be raised at run-time?", gnat_node);
 
       gnu_result
        = build1 (NULL_EXPR, gnu_result_type,
-                 build_call_raise (CE_Overflow_Check_Failed));
+                 build_call_raise (CE_Overflow_Check_Failed, gnat_node,
+                                   N_Raise_Constraint_Error));
     }
 
   /* If our result has side-effects and is of an unconstrained type,
@@ -3980,38 +4888,43 @@ gnat_to_gnu (Node_Id gnat_node)
   if (TREE_SIDE_EFFECTS (gnu_result)
       && (TREE_CODE (gnu_result_type) == UNCONSTRAINED_ARRAY_TYPE
          || CONTAINS_PLACEHOLDER_P (TYPE_SIZE (gnu_result_type))))
-    gnu_result = gnat_stabilize_reference (gnu_result, 0);
-
-  /* Now convert the result to the proper type.  If the type is void or if
-     we have no result, return error_mark_node to show we have no result.
-     If the type of the result is correct or if we have a label (which doesn't
-     have any well-defined type), return our result.  Also don't do the
-     conversion if the "desired" type involves a PLACEHOLDER_EXPR in its size
-     since those are the cases where the front end may have the type wrong due
-     to "instantiating" the unconstrained record with discriminant values
-     or if this is a FIELD_DECL.  If this is the Name of an assignment
-     statement or a parameter of a procedure call, return what we have since
-     the RHS has to be converted to our type there in that case, unless
-     GNU_RESULT_TYPE has a simpler size.  Similarly, if the two types are
-     record types with the same name, the expression type has integral mode,
-     and GNU_RESULT_TYPE BLKmode, don't convert.  This will be the case when
-     we are converting from a packable type to its actual type and we need
-     those conversions to be NOPs in order for assignments into these types to
-     work properly if the inner object is a bitfield and hence can't have
-     its address taken.  Finally, don't convert integral types that are the
-     operand of an unchecked conversion since we need to ignore those
-     conversions (for 'Valid).  Otherwise, convert the result to the proper
-     type.  */
+    gnu_result = gnat_stabilize_reference (gnu_result, false);
+
+  /* Now convert the result to the result type, unless we are in one of the
+     following cases:
+
+       1. If this is the Name of an assignment statement or a parameter of
+         a procedure call, return the result almost unmodified since the
+         RHS will have to be converted to our type in that case, unless
+         the result type has a simpler size.   Similarly, don't convert
+         integral types that are the operands of an unchecked conversion
+         since we need to ignore those conversions (for 'Valid).
+
+       2. If we have a label (which doesn't have any well-defined type), a
+         field or an error, return the result almost unmodified.  Also don't
+         do the conversion if the result type involves a PLACEHOLDER_EXPR in
+         its size since those are the cases where the front end may have the
+         type wrong due to "instantiating" the unconstrained record with
+         discriminant values.  Similarly, if the two types are record types
+         with the same name don't convert.  This will be the case when we are
+         converting from a packed version of a type to its original type and
+         we need those conversions to be NOPs in order for assignments into
+         these types to work properly.
+
+       3. If the type is void or if we have no result, return error_mark_node
+         to show we have no result.
+
+       4. Finally, if the type of the result is already correct.  */
 
   if (Present (Parent (gnat_node))
       && ((Nkind (Parent (gnat_node)) == N_Assignment_Statement
           && Name (Parent (gnat_node)) == gnat_node)
          || (Nkind (Parent (gnat_node)) == N_Procedure_Call_Statement
              && Name (Parent (gnat_node)) != gnat_node)
+         || Nkind (Parent (gnat_node)) == N_Parameter_Association
          || (Nkind (Parent (gnat_node)) == N_Unchecked_Type_Conversion
              && !AGGREGATE_TYPE_P (gnu_result_type)
-             && !AGGREGATE_TYPE_P (TREE_TYPE (gnu_result)))
-         || Nkind (Parent (gnat_node)) == N_Parameter_Association)
+             && !AGGREGATE_TYPE_P (TREE_TYPE (gnu_result))))
       && !(TYPE_SIZE (gnu_result_type)
           && TYPE_SIZE (TREE_TYPE (gnu_result))
           && (AGGREGATE_TYPE_P (gnu_result_type)
@@ -4024,17 +4937,16 @@ gnat_to_gnu (Node_Id gnat_node)
                   && (CONTAINS_PLACEHOLDER_P
                       (TYPE_SIZE (TREE_TYPE (gnu_result))))))
           && !(TREE_CODE (gnu_result_type) == RECORD_TYPE
-               && TYPE_LEFT_JUSTIFIED_MODULAR_P (gnu_result_type))))
+               && TYPE_JUSTIFIED_MODULAR_P (gnu_result_type))))
     {
-      /* In this case remove padding only if the inner object is of
-        self-referential size: in that case it must be an object of
-        unconstrained type with a default discriminant.  In other cases,
-        we want to avoid copying too much data.  */
+      /* Remove padding only if the inner object is of self-referential
+        size: in that case it must be an object of unconstrained type
+        with a default discriminant and we want to avoid copying too
+        much data.  */
       if (TREE_CODE (TREE_TYPE (gnu_result)) == RECORD_TYPE
          && TYPE_IS_PADDING_P (TREE_TYPE (gnu_result))
-         && CONTAINS_PLACEHOLDER_P (TYPE_SIZE
-                                    (TREE_TYPE (TYPE_FIELDS
-                                                (TREE_TYPE (gnu_result))))))
+         && CONTAINS_PLACEHOLDER_P (TYPE_SIZE (TREE_TYPE (TYPE_FIELDS
+                                    (TREE_TYPE (gnu_result))))))
        gnu_result = convert (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (gnu_result))),
                              gnu_result);
     }
@@ -4049,25 +4961,22 @@ gnat_to_gnu (Node_Id gnat_node)
           || ((TYPE_NAME (gnu_result_type)
                == TYPE_NAME (TREE_TYPE (gnu_result)))
               && TREE_CODE (gnu_result_type) == RECORD_TYPE
-              && TREE_CODE (TREE_TYPE (gnu_result)) == RECORD_TYPE
-              && TYPE_MODE (gnu_result_type) == BLKmode
-              && (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (gnu_result)))
-                  == MODE_INT)))
+              && TREE_CODE (TREE_TYPE (gnu_result)) == RECORD_TYPE))
     {
-      /* Remove any padding record, but do nothing more in this case.  */
+      /* Remove any padding.  */
       if (TREE_CODE (TREE_TYPE (gnu_result)) == RECORD_TYPE
          && TYPE_IS_PADDING_P (TREE_TYPE (gnu_result)))
        gnu_result = convert (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (gnu_result))),
                              gnu_result);
     }
 
-  else if (gnu_result == error_mark_node
-          || gnu_result_type == void_type_node)
-    gnu_result =  error_mark_node;
+  else if (gnu_result == error_mark_node || gnu_result_type == void_type_node)
+    gnu_result = error_mark_node;
+
   else if (gnu_result_type != TREE_TYPE (gnu_result))
     gnu_result = convert (gnu_result_type, gnu_result);
 
-  /* We don't need any NOP_EXPR or NON_LVALUE_EXPR on GNU_RESULT.  */
+  /* We don't need any NOP_EXPR or NON_LVALUE_EXPR on the result.  */
   while ((TREE_CODE (gnu_result) == NOP_EXPR
          || TREE_CODE (gnu_result) == NON_LVALUE_EXPR)
         && TREE_TYPE (TREE_OPERAND (gnu_result, 0)) == TREE_TYPE (gnu_result))
@@ -4076,12 +4985,26 @@ gnat_to_gnu (Node_Id gnat_node)
   return gnu_result;
 }
 \f
+/* Subroutine of above to push the exception label stack.  GNU_STACK is
+   a pointer to the stack to update and GNAT_LABEL, if present, is the
+   label to push onto the stack.  */
+
+static void
+push_exception_label_stack (tree *gnu_stack, Entity_Id gnat_label)
+{
+  tree gnu_label = (Present (gnat_label)
+                   ? gnat_to_gnu_entity (gnat_label, NULL_TREE, 0)
+                   : NULL_TREE);
+
+  *gnu_stack = tree_cons (NULL_TREE, gnu_label, *gnu_stack);
+}
+\f
 /* Record the current code position in GNAT_NODE.  */
 
 static void
 record_code_position (Node_Id gnat_node)
 {
-  tree stmt_stmt = build (STMT_STMT, void_type_node, NULL_TREE);
+  tree stmt_stmt = build1 (STMT_STMT, void_type_node, NULL_TREE);
 
   add_stmt_with_node (stmt_stmt, gnat_node);
   save_gnu_tree (gnat_node, stmt_stmt, true);
@@ -4098,8 +5021,8 @@ insert_code_for (Node_Id gnat_node)
 \f
 /* Start a new statement group chained to the previous group.  */
 
-static void
-start_stmt_group ()
+void
+start_stmt_group (void)
 {
   struct stmt_group *group = stmt_group_free_list;
 
@@ -4111,7 +5034,6 @@ start_stmt_group ()
 
   group->previous = current_stmt_group;
   group->stmt_list = group->block = group->cleanups = NULL_TREE;
-  group->global = current_stmt_group ? current_stmt_group->global : NULL;
   current_stmt_group = group;
 }
 
@@ -4121,27 +5043,6 @@ void
 add_stmt (tree gnu_stmt)
 {
   append_to_statement_list (gnu_stmt, &current_stmt_group->stmt_list);
-
-  /* If we're at top level, show everything in here is in use in case
-     any of it is shared by a subprogram.
-
-     ??? If this is a DECL_EXPR for a VAR_DECL or CONST_DECL, we must
-     walk the sizes and DECL_INITIAL since we won't be walking the
-     BIND_EXPR here.  This whole thing is a mess!  */
-  if (global_bindings_p ())
-    {
-      walk_tree (&gnu_stmt, mark_visited, NULL, NULL);
-      if (TREE_CODE (gnu_stmt) == DECL_EXPR
-         && (TREE_CODE (DECL_EXPR_DECL (gnu_stmt)) == VAR_DECL
-             || TREE_CODE (DECL_EXPR_DECL (gnu_stmt)) == CONST_DECL))
-       {
-         tree gnu_decl = DECL_EXPR_DECL (gnu_stmt);
-
-         walk_tree (&DECL_SIZE (gnu_decl), mark_visited, NULL, NULL);
-         walk_tree (&DECL_SIZE_UNIT (gnu_decl), mark_visited, NULL, NULL);
-         walk_tree (&DECL_INITIAL (gnu_decl), mark_visited, NULL, NULL);
-       }
-    }
 }
 
 /* Similar, but set the location of GNU_STMT to that of GNAT_NODE.  */
@@ -4150,7 +5051,7 @@ void
 add_stmt_with_node (tree gnu_stmt, Node_Id gnat_node)
 {
   if (Present (gnat_node))
-    annotate_with_node (gnu_stmt, gnat_node);
+    set_expr_location_from_node (gnu_stmt, gnat_node);
   add_stmt (gnu_stmt);
 }
 
@@ -4160,7 +5061,8 @@ add_stmt_with_node (tree gnu_stmt, Node_Id gnat_node)
 void
 add_decl_expr (tree gnu_decl, Entity_Id gnat_entity)
 {
-  struct stmt_group *save_stmt_group = current_stmt_group;
+  tree type = TREE_TYPE (gnu_decl);
+  tree gnu_stmt, gnu_init, gnu_lhs;
 
   /* If this is a variable that Gigi is to ignore, we may have been given
      an ERROR_MARK.  So test for it.  We also might have been given a
@@ -4168,59 +5070,64 @@ add_decl_expr (tree gnu_decl, Entity_Id gnat_entity)
      ignore a TYPE_DECL for an UNCONSTRAINED_ARRAY_TYPE.  */
   if (!DECL_P (gnu_decl)
       || (TREE_CODE (gnu_decl) == TYPE_DECL
-         && TREE_CODE (TREE_TYPE (gnu_decl)) == UNCONSTRAINED_ARRAY_TYPE))
+         && TREE_CODE (type) == UNCONSTRAINED_ARRAY_TYPE))
     return;
 
-  if (global_bindings_p ())
-    current_stmt_group = current_stmt_group->global;
-
-  add_stmt_with_node (build (DECL_EXPR, void_type_node, gnu_decl),
-                     gnat_entity);
+  gnu_stmt = build1 (DECL_EXPR, void_type_node, gnu_decl);
 
+  /* If we are global, we don't want to actually output the DECL_EXPR for
+     this decl since we already have evaluated the expressions in the
+     sizes and positions as globals and doing it again would be wrong.  */
   if (global_bindings_p ())
-    current_stmt_group = save_stmt_group;
-
-  /* If this is a DECL_EXPR for a variable with DECL_INITIAl set,
-     there are two cases we need to handle here.  */
-  if (TREE_CODE (gnu_decl) == VAR_DECL && DECL_INITIAL (gnu_decl))
     {
-      tree gnu_init = DECL_INITIAL (gnu_decl);
-      tree gnu_lhs = NULL_TREE;
-
-      /* If this is a DECL_EXPR for a variable with DECL_INITIAL set
-        and decl has a padded type, convert it to the unpadded type so the
-        assignment is done properly.  */
-      if (TREE_CODE (TREE_TYPE (gnu_decl)) == RECORD_TYPE
-         && TYPE_IS_PADDING_P (TREE_TYPE (gnu_decl)))
-       gnu_lhs
-         = convert (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (gnu_decl))), gnu_decl);
-
-      /* Otherwise, if this is going into memory and the initializer isn't
-        valid for the assembler and loader.  Gimplification could do this,
-        but would be run too late if -fno-unit-at-a-time.  */
-      else if (TREE_STATIC (gnu_decl)
-              && !initializer_constant_valid_p (gnu_init,
-                                                TREE_TYPE (gnu_decl)))
+      /* Mark everything as used to prevent node sharing with subprograms.
+        Note that walk_tree knows how to handle TYPE_DECL, but neither
+        VAR_DECL nor CONST_DECL.  This appears to be somewhat arbitrary.  */
+      walk_tree (&gnu_stmt, mark_visited, NULL, NULL);
+      if (TREE_CODE (gnu_decl) == VAR_DECL
+         || TREE_CODE (gnu_decl) == CONST_DECL)
+       {
+         walk_tree (&DECL_SIZE (gnu_decl), mark_visited, NULL, NULL);
+         walk_tree (&DECL_SIZE_UNIT (gnu_decl), mark_visited, NULL, NULL);
+         walk_tree (&DECL_INITIAL (gnu_decl), mark_visited, NULL, NULL);
+       }
+    }
+  else
+    add_stmt_with_node (gnu_stmt, gnat_entity);
+
+  /* If this is a variable and an initializer is attached to it, it must be
+     valid for the context.  Similar to init_const in create_var_decl_1.  */
+  if (TREE_CODE (gnu_decl) == VAR_DECL
+      && (gnu_init = DECL_INITIAL (gnu_decl)) != NULL_TREE
+      && (TYPE_MAIN_VARIANT (type) != TYPE_MAIN_VARIANT (TREE_TYPE (gnu_init))
+         || (TREE_STATIC (gnu_decl)
+             && !initializer_constant_valid_p (gnu_init,
+                                               TREE_TYPE (gnu_init)))))
+    {
+      /* If GNU_DECL has a padded type, convert it to the unpadded
+        type so the assignment is done properly.  */
+      if (TREE_CODE (type) == RECORD_TYPE && TYPE_IS_PADDING_P (type))
+       gnu_lhs = convert (TREE_TYPE (TYPE_FIELDS (type)), gnu_decl);
+      else
        gnu_lhs = gnu_decl;
 
-      if (gnu_lhs)
-       {
-         tree gnu_assign_stmt
-           = build_binary_op (MODIFY_EXPR, NULL_TREE,
-                              gnu_lhs, DECL_INITIAL (gnu_decl));
+      gnu_stmt = build_binary_op (MODIFY_EXPR, NULL_TREE, gnu_lhs, gnu_init);
 
-         DECL_INITIAL (gnu_decl) = 0;
+      DECL_INITIAL (gnu_decl) = NULL_TREE;
+      if (TREE_READONLY (gnu_decl))
+       {
          TREE_READONLY (gnu_decl) = 0;
-         annotate_with_locus (gnu_assign_stmt,
-                              DECL_SOURCE_LOCATION (gnu_decl));
-         add_stmt (gnu_assign_stmt);
+         DECL_READONLY_ONCE_ELAB (gnu_decl) = 1;
        }
+
+      add_stmt_with_node (gnu_stmt, gnat_entity);
     }
 }
 
-/* Utility function to mark nodes with TREE_VISITED.  Called from walk_tree.
-   We use this to indicate all variable sizes and positions in global types
-   may not be shared by any subprogram.  */
+/* Utility function to mark nodes with TREE_VISITED and types as having their
+   sized gimplified.  Called from walk_tree.  We use this to indicate all
+   variable sizes and positions in global types may not be shared by any
+   subprogram.  */
 
 static tree
 mark_visited (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
@@ -4233,25 +5140,34 @@ mark_visited (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
   else if (!TYPE_IS_DUMMY_P (*tp))
     TREE_VISITED (*tp) = 1;
 
+  if (TYPE_P (*tp))
+    TYPE_SIZES_GIMPLIFIED (*tp) = 1;
+
   return NULL_TREE;
 }
 
-/* Likewise, but to mark as unvisited.  */
+/* Utility function to unshare expressions wrapped up in a SAVE_EXPR.  */
 
 static tree
-mark_unvisited (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
-               void *data ATTRIBUTE_UNUSED)
+unshare_save_expr (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
+                  void *data ATTRIBUTE_UNUSED)
 {
-  TREE_VISITED (*tp) = 0;
+  tree t = *tp;
+
+  if (TREE_CODE (t) == SAVE_EXPR)
+    TREE_OPERAND (t, 0) = unshare_expr (TREE_OPERAND (t, 0));
 
   return NULL_TREE;
 }
 
-/* Add GNU_CLEANUP, a cleanup action, to the current code group.  */
+/* Add GNU_CLEANUP, a cleanup action, to the current code group and
+   set its location to that of GNAT_NODE if present.  */
 
 static void
-add_cleanup (tree gnu_cleanup)
+add_cleanup (tree gnu_cleanup, Node_Id gnat_node)
 {
+  if (Present (gnat_node))
+    set_expr_location_from_node (gnu_cleanup, gnat_node);
   append_to_statement_list (gnu_cleanup, &current_stmt_group->cleanups);
 }
 
@@ -4260,9 +5176,7 @@ add_cleanup (tree gnu_cleanup)
 void
 set_block_for_group (tree gnu_block)
 {
-  if (current_stmt_group->block)
-    abort ();
-
+  gcc_assert (!current_stmt_group->block);
   current_stmt_group->block = gnu_block;
 }
 
@@ -4270,8 +5184,8 @@ set_block_for_group (tree gnu_block)
    a STATEMENT_LIST, but may also be a BIND_EXPR or TRY_FINALLY_EXPR if
    BLOCK or cleanups were set.  */
 
-static tree
-end_stmt_group ()
+tree
+end_stmt_group (void)
 {
   struct stmt_group *group = current_stmt_group;
   tree gnu_retval = group->stmt_list;
@@ -4284,12 +5198,12 @@ end_stmt_group ()
     gnu_retval = alloc_stmt_list ();
 
   if (group->cleanups)
-    gnu_retval = build (TRY_FINALLY_EXPR, void_type_node, gnu_retval,
-                       group->cleanups);
+    gnu_retval = build2 (TRY_FINALLY_EXPR, void_type_node, gnu_retval,
+                        group->cleanups);
 
   if (current_stmt_group->block)
-    gnu_retval = build (BIND_EXPR, void_type_node, BLOCK_VARS (group->block),
-                       gnu_retval, group->block);
+    gnu_retval = build3 (BIND_EXPR, void_type_node, BLOCK_VARS (group->block),
+                        gnu_retval, group->block);
 
   /* Remove this group from the stack and add it to the free list.  */
   current_stmt_group = group->previous;
@@ -4361,42 +5275,13 @@ pop_stack (tree *gnu_stack_ptr)
   gnu_stack_free_list = gnu_node;
 }
 \f
-/* GNU_STMT is a statement.  We generate code for that statement.  */
-
-void
-gnat_expand_stmt (tree gnu_stmt)
-{
-#if 0
-  tree gnu_elmt, gnu_elmt_2;
-#endif
-
-  switch (TREE_CODE (gnu_stmt))
-    {
-#if 0
-    case USE_STMT:
-      /* First write a volatile ASM_INPUT to prevent anything from being
-        moved.  */
-      gnu_elmt = gen_rtx_ASM_INPUT (VOIDmode, "");
-      MEM_VOLATILE_P (gnu_elmt) = 1;
-      emit_insn (gnu_elmt);
-
-      gnu_elmt = expand_expr (TREE_OPERAND (gnu_stmt, 0), NULL_RTX, VOIDmode,
-                           modifier);
-      emit_insn (gen_rtx_USE (VOIDmode, ));
-      return target;
-#endif
-
-    default:
-      abort ();
-    }
-}
-\f
 /* Generate GIMPLE in place for the expression at *EXPR_P.  */
 
 int
 gnat_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p ATTRIBUTE_UNUSED)
 {
   tree expr = *expr_p;
+  tree op;
 
   if (IS_ADA_STMT (expr))
     return gnat_gimplify_stmt (expr_p);
@@ -4417,7 +5302,7 @@ gnat_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p ATTRIBUTE_UNUSED)
          TREE_NO_WARNING (*expr_p) = 1;
        }
 
-      append_to_statement_list (TREE_OPERAND (expr, 0), pre_p);
+      gimplify_and_add (TREE_OPERAND (expr, 0), pre_p);
       return GS_OK;
 
     case UNCONSTRAINED_ARRAY_REF:
@@ -4426,16 +5311,69 @@ gnat_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p ATTRIBUTE_UNUSED)
       *expr_p = TREE_OPERAND (*expr_p, 0);
       return GS_OK;
 
-    case COMPONENT_REF:
-      /* We have a kludge here.  If the FIELD_DECL is from a fat pointer
-        and is from an early dummy type, replace it with the proper
-        FIELD_DECL.  */
-      if (TYPE_FAT_POINTER_P (TREE_TYPE (TREE_OPERAND (*expr_p, 0)))
-         && DECL_ORIGINAL_FIELD (TREE_OPERAND (*expr_p, 1)))
+    case ADDR_EXPR:
+      op = TREE_OPERAND (expr, 0);
+
+      /* If we're taking the address of a constant CONSTRUCTOR, force it to
+        be put into static memory.  We know it's going to be readonly given
+        the semantics we have and it's required to be static memory in
+        the case when the reference is in an elaboration procedure.   */
+      if (TREE_CODE (op) == CONSTRUCTOR && TREE_CONSTANT (op))
+       {
+         tree new_var = create_tmp_var (TREE_TYPE (op), "C");
+
+         TREE_READONLY (new_var) = 1;
+         TREE_STATIC (new_var) = 1;
+         TREE_ADDRESSABLE (new_var) = 1;
+         DECL_INITIAL (new_var) = op;
+
+         TREE_OPERAND (expr, 0) = new_var;
+         recompute_tree_invariant_for_addr_expr (expr);
+         return GS_ALL_DONE;
+       }
+
+      /* If we are taking the address of a SAVE_EXPR, we are typically
+        processing a misaligned argument to be passed by reference in a
+        procedure call.  We just mark the operand as addressable + not
+        readonly here and let the common gimplifier code perform the
+        temporary creation, initialization, and "instantiation" in place of
+        the SAVE_EXPR in further operands, in particular in the copy back
+        code inserted after the call.  */
+      else if (TREE_CODE (op) == SAVE_EXPR)
        {
-         TREE_OPERAND (*expr_p, 1)
-           = DECL_ORIGINAL_FIELD (TREE_OPERAND (*expr_p, 1));
-         return GS_OK;
+         TREE_ADDRESSABLE (op) = 1;
+         TREE_READONLY (op) = 0;
+       }
+
+      /* We let the gimplifier process &COND_EXPR and expect it to yield the
+        address of the selected operand when it is addressable.  Besides, we
+        also expect addressable_p to only let COND_EXPRs where both arms are
+        addressable reach here.  */
+      else if (TREE_CODE (op) == COND_EXPR)
+       ;
+
+      /* Otherwise, if we are taking the address of something that is neither
+        reference, declaration, or constant, make a variable for the operand
+        here and then take its address.  If we don't do it this way, we may
+        confuse the gimplifier because it needs to know the variable is
+        addressable at this point.  This duplicates code in
+        internal_get_tmp_var, which is unfortunate.  */
+      else if (TREE_CODE_CLASS (TREE_CODE (op)) != tcc_reference
+              && TREE_CODE_CLASS (TREE_CODE (op)) != tcc_declaration
+              && TREE_CODE_CLASS (TREE_CODE (op)) != tcc_constant)
+       {
+         tree new_var = create_tmp_var (TREE_TYPE (op), "A");
+         tree mod = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (op), new_var, op);
+
+         TREE_ADDRESSABLE (new_var) = 1;
+
+         if (EXPR_HAS_LOCATION (op))
+           SET_EXPR_LOCUS (mod, EXPR_LOCUS (op));
+
+         gimplify_and_add (mod, pre_p);
+         TREE_OPERAND (expr, 0) = new_var;
+         recompute_tree_invariant_for_addr_expr (expr);
+         return GS_ALL_DONE;
        }
 
       /* ... fall through ... */
@@ -4458,14 +5396,11 @@ gnat_gimplify_stmt (tree *stmt_p)
       *stmt_p = STMT_STMT_STMT (stmt);
       return GS_OK;
 
-    case USE_STMT:
-      *stmt_p = NULL_TREE;
-      return GS_ALL_DONE;
-
     case LOOP_STMT:
       {
        tree gnu_start_label = create_artificial_label ();
        tree gnu_end_label = LOOP_STMT_LABEL (stmt);
+       tree t;
 
        /* Set to emit the statements of the loop.  */
        *stmt_p = NULL_TREE;
@@ -4480,31 +5415,32 @@ gnat_gimplify_stmt (tree *stmt_p)
                                  stmt_p);
 
        if (LOOP_STMT_TOP_COND (stmt))
-         append_to_statement_list (build (COND_EXPR, void_type_node,
-                                          LOOP_STMT_TOP_COND (stmt),
-                                          alloc_stmt_list (),
-                                          build1 (GOTO_EXPR,
-                                                  void_type_node,
-                                                  gnu_end_label)),
+         append_to_statement_list (build3 (COND_EXPR, void_type_node,
+                                           LOOP_STMT_TOP_COND (stmt),
+                                           alloc_stmt_list (),
+                                           build1 (GOTO_EXPR,
+                                                   void_type_node,
+                                                   gnu_end_label)),
                                    stmt_p);
 
        append_to_statement_list (LOOP_STMT_BODY (stmt), stmt_p);
 
        if (LOOP_STMT_BOT_COND (stmt))
-         append_to_statement_list (build (COND_EXPR, void_type_node,
-                                          LOOP_STMT_BOT_COND (stmt),
-                                          alloc_stmt_list (),
-                                          build1 (GOTO_EXPR,
-                                                  void_type_node,
-                                                  gnu_end_label)),
+         append_to_statement_list (build3 (COND_EXPR, void_type_node,
+                                           LOOP_STMT_BOT_COND (stmt),
+                                           alloc_stmt_list (),
+                                           build1 (GOTO_EXPR,
+                                                   void_type_node,
+                                                   gnu_end_label)),
                                    stmt_p);
 
        if (LOOP_STMT_UPDATE (stmt))
          append_to_statement_list (LOOP_STMT_UPDATE (stmt), stmt_p);
 
-       append_to_statement_list (build1 (GOTO_EXPR, void_type_node,
-                                         gnu_start_label),
-                                 stmt_p);
+       t = build1 (GOTO_EXPR, void_type_node, gnu_start_label);
+       set_expr_location (t, DECL_SOURCE_LOCATION (gnu_end_label));
+       append_to_statement_list (t, stmt_p);
+
        append_to_statement_list (build1 (LABEL_EXPR, void_type_node,
                                          gnu_end_label),
                                  stmt_p);
@@ -4516,57 +5452,42 @@ gnat_gimplify_stmt (tree *stmt_p)
         see if it needs to be conditional.  */
       *stmt_p = build1 (GOTO_EXPR, void_type_node, EXIT_STMT_LABEL (stmt));
       if (EXIT_STMT_COND (stmt))
-       *stmt_p = build (COND_EXPR, void_type_node,
-                        EXIT_STMT_COND (stmt), *stmt_p, alloc_stmt_list ());
+       *stmt_p = build3 (COND_EXPR, void_type_node,
+                         EXIT_STMT_COND (stmt), *stmt_p, alloc_stmt_list ());
       return GS_OK;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 \f
-/* Force references to each of the entities in packages GNAT_NODE with's
-   so that the debugging information for all of them are identical
-   in all clients.  Operate recursively on anything it with's, but check
-   that we aren't elaborating something more than once.  */
-
-/* The reason for this routine's existence is two-fold.
-   First, with some debugging formats, notably MDEBUG on SGI
-   IRIX, the linker will remove duplicate debugging information if two
-   clients have identical debugguing information.  With the normal scheme
-   of elaboration, this does not usually occur, since entities in with'ed
-   packages are elaborated on demand, and if clients have different usage
-   patterns, the normal case, then the order and selection of entities
-   will differ.  In most cases however, it seems that linkers do not know
-   how to eliminate duplicate debugging information, even if it is
-   identical, so the use of this routine would increase the total amount
-   of debugging information in the final executable.
-
-   Second, this routine is called in type_annotate mode, to compute DDA
-   information for types in withed units, for ASIS use  */
+/* Force references to each of the entities in packages withed by GNAT_NODE.
+   Operate recursively but check that we aren't elaborating something more
+   than once.
+
+   This routine is exclusively called in type_annotate mode, to compute DDA
+   information for types in withed units, for ASIS use.  */
 
 static void
 elaborate_all_entities (Node_Id gnat_node)
 {
   Entity_Id gnat_with_clause, gnat_entity;
 
-  /* Process each unit only once. As we trace the context of all relevant
+  /* Process each unit only once.  As we trace the context of all relevant
      units transitively, including generic bodies, we may encounter the
-     same generic unit repeatedly */
-
+     same generic unit repeatedly.  */
   if (!present_gnu_tree (gnat_node))
      save_gnu_tree (gnat_node, integer_zero_node, true);
 
-  /* Save entities in all context units. A body may have an implicit_with
+  /* Save entities in all context units.  A body may have an implicit_with
      on its own spec, if the context includes a child unit, so don't save
      the spec twice.  */
-
   for (gnat_with_clause = First (Context_Items (gnat_node));
        Present (gnat_with_clause);
        gnat_with_clause = Next (gnat_with_clause))
     if (Nkind (gnat_with_clause) == N_With_Clause
        && !present_gnu_tree (Library_Unit (gnat_with_clause))
-        && Library_Unit (gnat_with_clause) != Library_Unit (Cunit (Main_Unit)))
+       && Library_Unit (gnat_with_clause) != Library_Unit (Cunit (Main_Unit)))
       {
        elaborate_all_entities (Library_Unit (gnat_with_clause));
 
@@ -4589,23 +5510,23 @@ elaborate_all_entities (Node_Id gnat_node)
                  && !IN (Ekind (gnat_entity), Generic_Unit_Kind))
                gnat_to_gnu_entity (gnat_entity, NULL_TREE, 0);
           }
-        else if (Ekind (Entity (Name (gnat_with_clause))) == E_Generic_Package)
-           {
-            Node_Id gnat_body
+       else if (Ekind (Entity (Name (gnat_with_clause))) == E_Generic_Package)
+         {
+           Node_Id gnat_body
              = Corresponding_Body (Unit (Library_Unit (gnat_with_clause)));
 
-            /* Retrieve compilation unit node of generic body.  */
-            while (Present (gnat_body)
+           /* Retrieve compilation unit node of generic body.  */
+           while (Present (gnat_body)
                   && Nkind (gnat_body) != N_Compilation_Unit)
              gnat_body = Parent (gnat_body);
 
-            /* If body is available, elaborate its context.  */
-            if (Present (gnat_body))
-                elaborate_all_entities (gnat_body);
-           }
+           /* If body is available, elaborate its context.  */
+           if (Present (gnat_body))
+             elaborate_all_entities (gnat_body);
+         }
       }
 
-  if (Nkind (Unit (gnat_node)) == N_Package_Body && type_annotate_only)
+  if (Nkind (Unit (gnat_node)) == N_Package_Body)
     elaborate_all_entities (Library_Unit (gnat_node));
 }
 \f
@@ -4637,7 +5558,7 @@ process_freeze_entity (Node_Id gnat_node)
     = present_gnu_tree (gnat_entity) ? get_gnu_tree (gnat_entity) : 0;
 
   /* If this entity has an Address representation clause, GNU_OLD is the
-     address, so discard it here.  */
+     address, so discard it here. */
   if (Present (Address_Clause (gnat_entity)))
     gnu_old = 0;
 
@@ -4650,36 +5571,40 @@ process_freeze_entity (Node_Id gnat_node)
 
   /* Don't do anything for subprograms that may have been elaborated before
      their freeze nodes.  This can happen, for example because of an inner call
-     in an instance body.  */
+     in an instance body, or a previous compilation of a spec for inlining
+     purposes. */
   if (gnu_old
-       && TREE_CODE (gnu_old) == FUNCTION_DECL
-       && (Ekind (gnat_entity) == E_Function
-          || Ekind (gnat_entity) == E_Procedure))
+      && ((TREE_CODE (gnu_old) == FUNCTION_DECL
+          && (Ekind (gnat_entity) == E_Function
+              || Ekind (gnat_entity) == E_Procedure))
+         || (gnu_old
+             && TREE_CODE (TREE_TYPE (gnu_old)) == FUNCTION_TYPE
+             && Ekind (gnat_entity) == E_Subprogram_Type)))
     return;
 
-  /* If we have a non-dummy type old tree, we have nothing to do.   Unless
-     this is the public view of a private type whose full view was not
-     delayed, this node was never delayed as it should have been.
-     Also allow this to happen for concurrent types since we may have
-     frozen both the Corresponding_Record_Type and this type.  */
+  /* If we have a non-dummy type old tree, we have nothing to do, except
+     aborting if this is the public view of a private type whose full view was
+     not delayed, as this node was never delayed as it should have been.  We
+     let this happen for concurrent types and their Corresponding_Record_Type,
+     however, because each might legitimately be elaborated before it's own
+     freeze node, e.g. while processing the other.  */
   if (gnu_old
       && !(TREE_CODE (gnu_old) == TYPE_DECL
           && TYPE_IS_DUMMY_P (TREE_TYPE (gnu_old))))
     {
-      if (IN (Ekind (gnat_entity), Incomplete_Or_Private_Kind)
-         && Present (Full_View (gnat_entity))
-         && No (Freeze_Node (Full_View (gnat_entity))))
-       return;
-      else if (Is_Concurrent_Type (gnat_entity))
-       return;
-      else
-       abort ();
+      gcc_assert ((IN (Ekind (gnat_entity), Incomplete_Or_Private_Kind)
+                  && Present (Full_View (gnat_entity))
+                  && No (Freeze_Node (Full_View (gnat_entity))))
+                 || Is_Concurrent_Type (gnat_entity)
+                 || (IN (Ekind (gnat_entity), Record_Kind)
+                     && Is_Concurrent_Record_Type (gnat_entity)));
+      return;
     }
 
   /* Reset the saved tree, if any, and elaborate the object or type for real.
      If there is a full declaration, elaborate it and copy the type to
      GNAT_ENTITY.  Likewise if this is the record subtype corresponding to
-     a class wide type or subtype.  */
+     a class wide type or subtype. */
   if (gnu_old)
     {
       save_gnu_tree (gnat_entity, NULL_TREE, false);
@@ -4697,6 +5622,16 @@ process_freeze_entity (Node_Id gnat_node)
     {
       gnu_new = gnat_to_gnu_entity (Full_View (gnat_entity), NULL_TREE, 1);
 
+      /* Propagate back-annotations from full view to partial view.  */
+      if (Unknown_Alignment (gnat_entity))
+       Set_Alignment (gnat_entity, Alignment (Full_View (gnat_entity)));
+
+      if (Unknown_Esize (gnat_entity))
+       Set_Esize (gnat_entity, Esize (Full_View (gnat_entity)));
+
+      if (Unknown_RM_Size (gnat_entity))
+       Set_RM_Size (gnat_entity, RM_Size (Full_View (gnat_entity)));
+
       /* The above call may have defined this entity (the simplest example
         of this is when we have a private enumeral type since the bounds
         will have the public view.  */
@@ -4727,7 +5662,7 @@ process_inlined_subprograms (Node_Id gnat_node)
 
   /* If we can inline, generate RTL for all the inlined subprograms.
      Define the entity first so we set DECL_EXTERNAL.  */
-  if (optimize > 0 && !flag_no_inline)
+  if (optimize > 0 && !flag_really_no_inline)
     for (gnat_entity = First_Inlined_Subprogram (gnat_node);
         Present (gnat_entity);
         gnat_entity = Next_Inlined_Subprogram (gnat_entity))
@@ -4888,6 +5823,11 @@ emit_range_check (tree gnu_expr, Entity_Id gnat_range_type)
   tree gnu_high = TYPE_MAX_VALUE (gnu_range_type);
   tree gnu_compare_type = get_base_type (TREE_TYPE (gnu_expr));
 
+  /* If GNU_EXPR has GNAT_RANGE_TYPE as its base type, no check is needed.
+     This can for example happen when translating 'Val or 'Value.  */
+  if (gnu_compare_type == gnu_range_type)
+    return gnu_expr;
+
   /* If GNU_EXPR has an integral type that is narrower than GNU_RANGE_TYPE,
      we can't do anything since we might be truncating the bounds.  No
      check is needed in this case.  */
@@ -4901,7 +5841,7 @@ emit_range_check (tree gnu_expr, Entity_Id gnat_range_type)
 
   /* There's no good type to use here, so we might as well use
      integer_type_node. Note that the form of the check is
-        (not (expr >= lo)) or (not (expr >= hi))
+        (not (expr >= lo)) or (not (expr <= hi))
       the reason for this slightly convoluted form is that NaN's
       are not considered to be in range in the float case. */
   return emit_check
@@ -4967,7 +5907,7 @@ emit_index_check (tree gnu_array_object,
 \f
 /* GNU_COND contains the condition corresponding to an access, discriminant or
    range check of value GNU_EXPR.  Build a COND_EXPR that returns GNU_EXPR if
-   GNU_COND is false and raises a CONSTRAINT_ERROR if GNU_COND is true. 
+   GNU_COND is false and raises a CONSTRAINT_ERROR if GNU_COND is true.
    REASON is the code that says why the exception was raised.  */
 
 static tree
@@ -4976,23 +5916,23 @@ emit_check (tree gnu_cond, tree gnu_expr, int reason)
   tree gnu_call;
   tree gnu_result;
 
-  gnu_call = build_call_raise (reason);
+  gnu_call = build_call_raise (reason, Empty, N_Raise_Constraint_Error);
 
   /* Use an outer COMPOUND_EXPR to make sure that GNU_EXPR will get evaluated
      in front of the comparison in case it ends up being a SAVE_EXPR.  Put the
      whole thing inside its own SAVE_EXPR so the inner SAVE_EXPR doesn't leak
      out.  */
-  gnu_result = fold (build (COND_EXPR, TREE_TYPE (gnu_expr), gnu_cond,
-                           build (COMPOUND_EXPR, TREE_TYPE (gnu_expr),
-                                  gnu_call, gnu_expr),
-                           gnu_expr));
+  gnu_result = fold_build3 (COND_EXPR, TREE_TYPE (gnu_expr), gnu_cond,
+                           build2 (COMPOUND_EXPR, TREE_TYPE (gnu_expr),
+                                   gnu_call, gnu_expr),
+                           gnu_expr);
 
   /* If GNU_EXPR has side effects, make the outer COMPOUND_EXPR and
      protect it.  Otherwise, show GNU_RESULT has no side effects: we
      don't need to evaluate it just for the check.  */
   if (TREE_SIDE_EFFECTS (gnu_expr))
     gnu_result
-      = build (COMPOUND_EXPR, TREE_TYPE (gnu_expr), gnu_expr, gnu_result);
+      = build2 (COMPOUND_EXPR, TREE_TYPE (gnu_expr), gnu_expr, gnu_result);
   else
     TREE_SIDE_EFFECTS (gnu_result) = 0;
 
@@ -5016,7 +5956,6 @@ convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflowp,
   tree gnu_in_type = TREE_TYPE (gnu_expr);
   tree gnu_in_basetype = get_base_type (gnu_in_type);
   tree gnu_base_type = get_base_type (gnu_type);
-  tree gnu_ada_base_type = get_ada_base_type (gnu_type);
   tree gnu_result = gnu_expr;
 
   /* If we are not doing any checks, the output is an integral type, and
@@ -5108,28 +6047,71 @@ convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflowp,
 
   /* Now convert to the result base type.  If this is a non-truncating
      float-to-integer conversion, round.  */
-  if (INTEGRAL_TYPE_P (gnu_ada_base_type) && FLOAT_TYPE_P (gnu_in_basetype)
+  if (INTEGRAL_TYPE_P (gnu_base_type) && FLOAT_TYPE_P (gnu_in_basetype)
       && !truncatep)
     {
-      tree gnu_point_5 = build_real (gnu_in_basetype, dconstp5);
-      tree gnu_minus_point_5 = build_real (gnu_in_basetype, dconstmp5);
-      tree gnu_zero = convert (gnu_in_basetype, integer_zero_node);
-      tree gnu_saved_result = save_expr (gnu_result);
-      tree gnu_comp = build (GE_EXPR, integer_type_node,
-                            gnu_saved_result, gnu_zero);
-      tree gnu_adjust = build (COND_EXPR, gnu_in_basetype, gnu_comp,
-                              gnu_point_5, gnu_minus_point_5);
-
-      gnu_result
-       = build (PLUS_EXPR, gnu_in_basetype, gnu_saved_result, gnu_adjust);
+      REAL_VALUE_TYPE half_minus_pred_half, pred_half;
+      tree gnu_conv, gnu_zero, gnu_comp, gnu_saved_result, calc_type;
+      tree gnu_pred_half, gnu_add_pred_half, gnu_subtract_pred_half;
+      const struct real_format *fmt;
+
+      /* The following calculations depend on proper rounding to even
+         of each arithmetic operation. In order to prevent excess
+         precision from spoiling this property, use the widest hardware
+         floating-point type.
+
+         FIXME: For maximum efficiency, this should only be done for machines
+         and types where intermediates may have extra precision.  */
+
+      calc_type = longest_float_type_node;
+      /* FIXME: Should not have padding in the first place */
+      if (TREE_CODE (calc_type) == RECORD_TYPE
+              && TYPE_IS_PADDING_P (calc_type))
+        calc_type = TREE_TYPE (TYPE_FIELDS (calc_type));
+
+      /* Compute the exact value calc_type'Pred (0.5) at compile time. */
+      fmt = REAL_MODE_FORMAT (TYPE_MODE (calc_type));
+      real_2expN (&half_minus_pred_half, -(fmt->p) - 1, TYPE_MODE (calc_type));
+      REAL_ARITHMETIC (pred_half, MINUS_EXPR, dconsthalf,
+                       half_minus_pred_half);
+      gnu_pred_half = build_real (calc_type, pred_half);
+
+      /* If the input is strictly negative, subtract this value
+         and otherwise add it from the input. For 0.5, the result
+         is exactly between 1.0 and the machine number preceding 1.0
+         (for calc_type). Since the last bit of 1.0 is even, this 0.5
+         will round to 1.0, while all other number with an absolute
+         value less than 0.5 round to 0.0. For larger numbers exactly
+         halfway between integers, rounding will always be correct as
+         the true mathematical result will be closer to the higher
+         integer compared to the lower one. So, this constant works
+         for all floating-point numbers.
+
+         The reason to use the same constant with subtract/add instead
+         of a positive and negative constant is to allow the comparison
+         to be scheduled in parallel with retrieval of the constant and
+         conversion of the input to the calc_type (if necessary).
+      */
+
+      gnu_zero = convert (gnu_in_basetype, integer_zero_node);
+      gnu_saved_result = save_expr (gnu_result);
+      gnu_conv = convert (calc_type, gnu_saved_result);
+      gnu_comp = build2 (GE_EXPR, integer_type_node,
+                       gnu_saved_result, gnu_zero);
+      gnu_add_pred_half
+        = build2 (PLUS_EXPR, calc_type, gnu_conv, gnu_pred_half);
+      gnu_subtract_pred_half
+        = build2 (MINUS_EXPR, calc_type, gnu_conv, gnu_pred_half);
+      gnu_result = build3 (COND_EXPR, calc_type, gnu_comp,
+                          gnu_add_pred_half, gnu_subtract_pred_half);
     }
 
-  if (TREE_CODE (gnu_ada_base_type) == INTEGER_TYPE
-      && TYPE_HAS_ACTUAL_BOUNDS_P (gnu_ada_base_type)
+  if (TREE_CODE (gnu_base_type) == INTEGER_TYPE
+      && TYPE_HAS_ACTUAL_BOUNDS_P (gnu_base_type)
       && TREE_CODE (gnu_result) == UNCONSTRAINED_ARRAY_REF)
-    gnu_result = unchecked_convert (gnu_ada_base_type, gnu_result, false);
+    gnu_result = unchecked_convert (gnu_base_type, gnu_result, false);
   else
-    gnu_result = convert (gnu_ada_base_type, gnu_result);
+    gnu_result = convert (gnu_base_type, gnu_result);
 
   /* Finally, do the range check if requested.  Note that if the
      result type is a modular type, the range check is actually
@@ -5143,14 +6125,97 @@ convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflowp,
   return convert (gnu_type, gnu_result);
 }
 \f
-/* Return 1 if GNU_EXPR can be directly addressed.  This is the case unless
-   it is an expression involving computation or if it involves a bitfield
-   reference.  This returns the same as gnat_mark_addressable in most
-   cases.  */
+/* Return true if RECORD_TYPE, a record type, is larger than TYPE.  */
+
+static bool
+larger_record_type_p (tree record_type, tree type)
+{
+  tree rsize, size;
+
+  /* Padding types are not considered larger on their own.  */
+  if (TYPE_IS_PADDING_P (record_type))
+    return false;
+
+  rsize = TYPE_SIZE (record_type);
+  size = TYPE_SIZE (type);
+
+  if (!(TREE_CODE (rsize) == INTEGER_CST && TREE_CODE (size) == INTEGER_CST))
+    return false;
+
+  return tree_int_cst_lt (size, rsize) != 0;
+}
+
+/* Return true if GNU_EXPR can be directly addressed.  This is the case
+   unless it is an expression involving computation or if it involves a
+   reference to a bitfield or to an object not sufficiently aligned for
+   its type.  If GNU_TYPE is non-null, return true only if GNU_EXPR can
+   be directly addressed as an object of this type.
+
+   *** Notes on addressability issues in the Ada compiler ***
+
+   This predicate is necessary in order to bridge the gap between Gigi
+   and the middle-end about addressability of GENERIC trees.  A tree
+   is said to be addressable if it can be directly addressed, i.e. if
+   its address can be taken, is a multiple of the type's alignment on
+   strict-alignment architectures and returns the first storage unit
+   assigned to the object represented by the tree.
+
+   In the C family of languages, everything is in practice addressable
+   at the language level, except for bit-fields.  This means that these
+   compilers will take the address of any tree that doesn't represent
+   a bit-field reference and expect the result to be the first storage
+   unit assigned to the object.  Even in cases where this will result
+   in unaligned accesses at run time, nothing is supposed to be done
+   and the program is considered as erroneous instead (see PR c/18287).
+
+   The implicit assumptions made in the middle-end are in keeping with
+   the C viewpoint described above:
+     - the address of a bit-field reference is supposed to be never
+       taken; the compiler (generally) will stop on such a construct,
+     - any other tree is addressable if it is formally addressable,
+       i.e. if it is formally allowed to be the operand of ADDR_EXPR.
+
+   In Ada, the viewpoint is the opposite one: nothing is addressable
+   at the language level unless explicitly declared so.  This means
+   that the compiler will both make sure that the trees representing
+   references to addressable ("aliased" in Ada parlance) objects are
+   addressable and make no real attempts at ensuring that the trees
+   representing references to non-addressable objects are addressable.
+
+   In the first case, Ada is effectively equivalent to C and handing
+   down the direct result of applying ADDR_EXPR to these trees to the
+   middle-end works flawlessly.  In the second case, Ada cannot afford
+   to consider the program as erroneous if the address of trees that
+   are not addressable is requested for technical reasons, unlike C;
+   as a consequence, the Ada compiler must arrange for either making
+   sure that this address is not requested in the middle-end or for
+   compensating by inserting temporaries if it is requested in Gigi.
+
+   The first goal can be achieved because the middle-end should not
+   request the address of non-addressable trees on its own; the only
+   exception is for the invocation of low-level block operations like
+   memcpy, for which the addressability requirements are lower since
+   the type's alignment can be disregarded.  In practice, this means
+   that Gigi must make sure that such operations cannot be applied to
+   non-BLKmode bit-fields.
+
+   The second goal is achieved by means of the addressable_p predicate
+   and by inserting SAVE_EXPRs around trees deemed non-addressable.
+   They will be turned during gimplification into proper temporaries
+   whose address will be used in lieu of that of the original tree.  */
 
 static bool
-addressable_p (tree gnu_expr)
+addressable_p (tree gnu_expr, tree gnu_type)
 {
+  /* The size of the real type of the object must not be smaller than
+     that of the expected type, otherwise an indirect access in the
+     latter type would be larger than the object.  Only records need
+     to be considered in practice.  */
+  if (gnu_type
+      && TREE_CODE (gnu_type) == RECORD_TYPE
+      && larger_record_type_p (gnu_type, TREE_TYPE (gnu_expr)))
+    return false;
+
   switch (TREE_CODE (gnu_expr))
     {
     case VAR_DECL:
@@ -5164,41 +6229,58 @@ addressable_p (tree gnu_expr)
     case UNCONSTRAINED_ARRAY_REF:
     case INDIRECT_REF:
     case CONSTRUCTOR:
+    case STRING_CST:
+    case INTEGER_CST:
     case NULL_EXPR:
     case SAVE_EXPR:
+    case CALL_EXPR:
       return true;
 
+    case COND_EXPR:
+      /* We accept &COND_EXPR as soon as both operands are addressable and
+        expect the outcome to be the address of the selected operand.  */
+      return (addressable_p (TREE_OPERAND (gnu_expr, 1), NULL_TREE)
+             && addressable_p (TREE_OPERAND (gnu_expr, 2), NULL_TREE));
+
     case COMPONENT_REF:
       return (!DECL_BIT_FIELD (TREE_OPERAND (gnu_expr, 1))
-             && (!DECL_NONADDRESSABLE_P (TREE_OPERAND (gnu_expr, 1))
-                 || !flag_strict_aliasing)
-             && addressable_p (TREE_OPERAND (gnu_expr, 0)));
+             && (!STRICT_ALIGNMENT
+                 /* Even with DECL_BIT_FIELD cleared, we have to ensure that
+                    the field is sufficiently aligned, in case it is subject
+                    to a pragma Component_Alignment.  But we don't need to
+                    check the alignment of the containing record, as it is
+                    guaranteed to be not smaller than that of its most
+                    aligned field that is not a bit-field.  */
+                 || DECL_ALIGN (TREE_OPERAND (gnu_expr, 1))
+                      >= TYPE_ALIGN (TREE_TYPE (gnu_expr)))
+             && addressable_p (TREE_OPERAND (gnu_expr, 0), NULL_TREE));
 
     case ARRAY_REF:  case ARRAY_RANGE_REF:
     case REALPART_EXPR:  case IMAGPART_EXPR:
     case NOP_EXPR:
-      return addressable_p (TREE_OPERAND (gnu_expr, 0));
+      return addressable_p (TREE_OPERAND (gnu_expr, 0), NULL_TREE);
 
     case CONVERT_EXPR:
       return (AGGREGATE_TYPE_P (TREE_TYPE (gnu_expr))
-             && addressable_p (TREE_OPERAND (gnu_expr, 0)));
+             && addressable_p (TREE_OPERAND (gnu_expr, 0), NULL_TREE));
 
     case VIEW_CONVERT_EXPR:
       {
        /* This is addressable if we can avoid a copy.  */
        tree type = TREE_TYPE (gnu_expr);
        tree inner_type = TREE_TYPE (TREE_OPERAND (gnu_expr, 0));
-
        return (((TYPE_MODE (type) == TYPE_MODE (inner_type)
-                 && (TYPE_ALIGN (type) <= TYPE_ALIGN (inner_type)
+                 && (!STRICT_ALIGNMENT
+                     || TYPE_ALIGN (type) <= TYPE_ALIGN (inner_type)
                      || TYPE_ALIGN (inner_type) >= BIGGEST_ALIGNMENT))
                 || ((TYPE_MODE (type) == BLKmode
                      || TYPE_MODE (inner_type) == BLKmode)
-                    && (TYPE_ALIGN (type) <= TYPE_ALIGN (inner_type)
+                    && (!STRICT_ALIGNMENT
+                        || TYPE_ALIGN (type) <= TYPE_ALIGN (inner_type)
                         || TYPE_ALIGN (inner_type) >= BIGGEST_ALIGNMENT
                         || TYPE_ALIGN_OK (type)
                         || TYPE_ALIGN_OK (inner_type))))
-               && addressable_p (TREE_OPERAND (gnu_expr, 0)));
+               && addressable_p (TREE_OPERAND (gnu_expr, 0), NULL_TREE));
       }
 
     default:
@@ -5208,7 +6290,7 @@ addressable_p (tree gnu_expr)
 \f
 /* Do the processing for the declaration of a GNAT_ENTITY, a type.  If
    a separate Freeze node exists, delay the bulk of the processing.  Otherwise
-   make a GCC type for GNAT_ENTITY and set up the correspondance.  */
+   make a GCC type for GNAT_ENTITY and set up the correspondence.  */
 
 void
 process_type (Entity_Id gnat_entity)
@@ -5252,25 +6334,15 @@ process_type (Entity_Id gnat_entity)
      pointers.  */
   if (gnu_old)
     {
-      if (TREE_CODE (gnu_old) != TYPE_DECL
-         || !TYPE_IS_DUMMY_P (TREE_TYPE (gnu_old)))
-       {
-         /* If this was a withed access type, this is not an error
-            and merely indicates we've already elaborated the type
-            already. */
-         if (Is_Type (gnat_entity) && From_With_Type (gnat_entity))
-           return;
-
-         abort ();
-       }
+      gcc_assert (TREE_CODE (gnu_old) == TYPE_DECL
+                 && TYPE_IS_DUMMY_P (TREE_TYPE (gnu_old)));
 
       save_gnu_tree (gnat_entity, NULL_TREE, false);
     }
 
   /* Now fully elaborate the type.  */
   gnu_new = gnat_to_gnu_entity (gnat_entity, NULL_TREE, 1);
-  if (TREE_CODE (gnu_new) != TYPE_DECL)
-    abort ();
+  gcc_assert (TREE_CODE (gnu_new) == TYPE_DECL);
 
   /* If we have an old type and we've made pointers to this type,
      update those pointers.  */
@@ -5300,15 +6372,16 @@ process_type (Entity_Id gnat_entity)
     }
 }
 \f
-/* GNAT_ASSOC is the front of the Component_Associations of an N_Aggregate.
-   GNU_TYPE is the GCC type of the corresponding record.
+/* GNAT_ENTITY is the type of the resulting constructors,
+   GNAT_ASSOC is the front of the Component_Associations of an N_Aggregate,
+   and GNU_TYPE is the GCC type of the corresponding record.
 
    Return a CONSTRUCTOR to build the record.  */
 
 static tree
-assoc_to_constructor (Node_Id gnat_assoc, tree gnu_type)
+assoc_to_constructor (Entity_Id gnat_entity, Node_Id gnat_assoc, tree gnu_type)
 {
-  tree gnu_field, gnu_list, gnu_result;
+  tree gnu_list, gnu_result;
 
   /* We test for GNU_FIELD being empty in the case where a variant
      was the last thing since we don't take things off GNAT_ASSOC in
@@ -5319,13 +6392,23 @@ assoc_to_constructor (Node_Id gnat_assoc, tree gnu_type)
        gnat_assoc = Next (gnat_assoc))
     {
       Node_Id gnat_field = First (Choices (gnat_assoc));
-      tree gnu_field = gnat_to_gnu_entity (Entity (gnat_field), NULL_TREE, 0);
+      tree gnu_field = gnat_to_gnu_field_decl (Entity (gnat_field));
       tree gnu_expr = gnat_to_gnu (Expression (gnat_assoc));
 
       /* The expander is supposed to put a single component selector name
         in every record component association */
-      if (Next (gnat_field))
-       abort ();
+      gcc_assert (No (Next (gnat_field)));
+
+      /* Ignore fields that have Corresponding_Discriminants since we'll
+        be setting that field in the parent.  */
+      if (Present (Corresponding_Discriminant (Entity (gnat_field)))
+         && Is_Tagged_Type (Scope (Entity (gnat_field))))
+       continue;
+
+      /* Also ignore discriminants of Unchecked_Unions.  */
+      else if (Is_Unchecked_Union (gnat_entity)
+              && Ekind (Entity (gnat_field)) == E_Discriminant)
+       continue;
 
       /* Before assigning a value in an aggregate make sure range checks
         are done if required.  Then convert to the type of the field.  */
@@ -5340,10 +6423,15 @@ assoc_to_constructor (Node_Id gnat_assoc, tree gnu_type)
 
   gnu_result = extract_values (gnu_list, gnu_type);
 
-  /* Verify every enty in GNU_LIST was used.  */
-  for (gnu_field = gnu_list; gnu_field; gnu_field = TREE_CHAIN (gnu_field))
-    if (!TREE_ADDRESSABLE (gnu_field))
-      abort ();
+#ifdef ENABLE_CHECKING
+  {
+    tree gnu_field;
+
+    /* Verify every entry in GNU_LIST was used.  */
+    for (gnu_field = gnu_list; gnu_field; gnu_field = TREE_CHAIN (gnu_field))
+      gcc_assert (TREE_ADDRESSABLE (gnu_field));
+  }
+#endif
 
   return gnu_result;
 }
@@ -5420,7 +6508,8 @@ extract_values (tree values, tree record_type)
       else if (DECL_INTERNAL_P (field))
        {
          value = extract_values (values, TREE_TYPE (field));
-         if (TREE_CODE (value) == CONSTRUCTOR && !CONSTRUCTOR_ELTS (value))
+         if (TREE_CODE (value) == CONSTRUCTOR
+             && VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (value)))
            value = 0;
        }
       else
@@ -5498,37 +6587,40 @@ protect_multiple_eval (tree exp)
                                                 exp)));
 }
 \f
-/* This is equivalent to stabilize_reference in GCC's tree.c, but we know
-   how to handle our new nodes and we take an extra argument that says
-   whether to force evaluation of everything.  */
+/* This is equivalent to stabilize_reference in tree.c, but we know how to
+   handle our own nodes and we take extra arguments.  FORCE says whether to
+   force evaluation of everything.  We set SUCCESS to true unless we walk
+   through something we don't know how to stabilize.  */
 
 tree
-gnat_stabilize_reference (tree ref, bool force)
+maybe_stabilize_reference (tree ref, bool force, bool *success)
 {
   tree type = TREE_TYPE (ref);
   enum tree_code code = TREE_CODE (ref);
   tree result;
 
+  /* Assume we'll success unless proven otherwise.  */
+  *success = true;
+
   switch (code)
     {
+    case CONST_DECL:
     case VAR_DECL:
     case PARM_DECL:
     case RESULT_DECL:
       /* No action is needed in this case.  */
       return ref;
 
+    case ADDR_EXPR:
     case NOP_EXPR:
     case CONVERT_EXPR:
     case FLOAT_EXPR:
     case FIX_TRUNC_EXPR:
-    case FIX_FLOOR_EXPR:
-    case FIX_ROUND_EXPR:
-    case FIX_CEIL_EXPR:
     case VIEW_CONVERT_EXPR:
-    case ADDR_EXPR:
       result
        = build1 (code, type,
-                 gnat_stabilize_reference (TREE_OPERAND (ref, 0), force));
+                 maybe_stabilize_reference (TREE_OPERAND (ref, 0), force,
+                                            success));
       break;
 
     case INDIRECT_REF:
@@ -5539,45 +6631,75 @@ gnat_stabilize_reference (tree ref, bool force)
       break;
 
     case COMPONENT_REF:
-      result = build (COMPONENT_REF, type,
-                     gnat_stabilize_reference (TREE_OPERAND (ref, 0),
-                                               force),
+     result = build3 (COMPONENT_REF, type,
+                     maybe_stabilize_reference (TREE_OPERAND (ref, 0), force,
+                                                success),
                      TREE_OPERAND (ref, 1), NULL_TREE);
       break;
 
     case BIT_FIELD_REF:
-      result = build (BIT_FIELD_REF, type,
-                     gnat_stabilize_reference (TREE_OPERAND (ref, 0), force),
-                     gnat_stabilize_reference_1 (TREE_OPERAND (ref, 1),
-                                                    force),
-                     gnat_stabilize_reference_1 (TREE_OPERAND (ref, 2),
-                                                 force));
+      result = build3 (BIT_FIELD_REF, type,
+                      maybe_stabilize_reference (TREE_OPERAND (ref, 0), force,
+                                                 success),
+                      gnat_stabilize_reference_1 (TREE_OPERAND (ref, 1),
+                                                  force),
+                      gnat_stabilize_reference_1 (TREE_OPERAND (ref, 2),
+                                                  force));
       break;
 
     case ARRAY_REF:
     case ARRAY_RANGE_REF:
-      result = build (code, type,
-                     gnat_stabilize_reference (TREE_OPERAND (ref, 0), force),
-                     gnat_stabilize_reference_1 (TREE_OPERAND (ref, 1),
-                                                 force),
-                     NULL_TREE, NULL_TREE);
+      result = build4 (code, type,
+                      maybe_stabilize_reference (TREE_OPERAND (ref, 0), force,
+                                                 success),
+                      gnat_stabilize_reference_1 (TREE_OPERAND (ref, 1),
+                                                  force),
+                      NULL_TREE, NULL_TREE);
       break;
 
     case COMPOUND_EXPR:
-      result = build (COMPOUND_EXPR, type,
-                     gnat_stabilize_reference_1 (TREE_OPERAND (ref, 0),
-                                                 force),
-                     gnat_stabilize_reference (TREE_OPERAND (ref, 1),
-                                               force));
+      result = gnat_stabilize_reference_1 (ref, force);
+      break;
+
+    case CALL_EXPR:
+      /* This generates better code than the scheme in protect_multiple_eval
+        because large objects will be returned via invisible reference in
+        most ABIs so the temporary will directly be filled by the callee.  */
+      result = gnat_stabilize_reference_1 (ref, force);
+      break;
+
+    case CONSTRUCTOR:
+      /* Constructors with 1 element are used extensively to formally
+        convert objects to special wrapping types.  */
+      if (TREE_CODE (type) == RECORD_TYPE
+         && VEC_length (constructor_elt, CONSTRUCTOR_ELTS (ref)) == 1)
+       {
+         tree index
+           = VEC_index (constructor_elt, CONSTRUCTOR_ELTS (ref), 0)->index;
+         tree value
+           = VEC_index (constructor_elt, CONSTRUCTOR_ELTS (ref), 0)->value;
+         result
+           = build_constructor_single (type, index,
+                                       gnat_stabilize_reference_1 (value,
+                                                                   force));
+       }
+      else
+       {
+         *success = false;
+         return ref;
+       }
       break;
 
+    case ERROR_MARK:
+      ref = error_mark_node;
+
+      /* ...  Fallthru to failure ... */
+
       /* If arg isn't a kind of lvalue we recognize, make no change.
         Caller should recognize the error for an invalid lvalue.  */
     default:
+      *success = false;
       return ref;
-
-    case ERROR_MARK:
-      return error_mark_node;
     }
 
   TREE_READONLY (result) = TREE_READONLY (ref);
@@ -5597,6 +6719,17 @@ gnat_stabilize_reference (tree ref, bool force)
   return result;
 }
 
+/* Wrapper around maybe_stabilize_reference, for common uses without
+   lvalue restrictions and without need to examine the success
+   indication.  */
+
+static tree
+gnat_stabilize_reference (tree ref, bool force)
+{
+  bool dummy;
+  return maybe_stabilize_reference (ref, force, &dummy);
+}
+
 /* Similar to stabilize_reference_1 in tree.c, but supports an extra
    arg to force a SAVE_EXPR for everything.  */
 
@@ -5617,41 +6750,43 @@ gnat_stabilize_reference_1 (tree e, bool force)
 
   switch (TREE_CODE_CLASS (code))
     {
-    case 'x':
-    case 't':
-    case 'd':
-    case '<':
-    case 's':
-    case 'e':
-    case 'r':
+    case tcc_exceptional:
+    case tcc_type:
+    case tcc_declaration:
+    case tcc_comparison:
+    case tcc_statement:
+    case tcc_expression:
+    case tcc_reference:
+    case tcc_vl_exp:
       /* If this is a COMPONENT_REF of a fat pointer, save the entire
         fat pointer.  This may be more efficient, but will also allow
         us to more easily find the match for the PLACEHOLDER_EXPR.  */
       if (code == COMPONENT_REF
          && TYPE_FAT_POINTER_P (TREE_TYPE (TREE_OPERAND (e, 0))))
-       result = build (COMPONENT_REF, type,
-                       gnat_stabilize_reference_1 (TREE_OPERAND (e, 0),
-                                                   force),
-                       TREE_OPERAND (e, 1), TREE_OPERAND (e, 2));
+       result = build3 (COMPONENT_REF, type,
+                        gnat_stabilize_reference_1 (TREE_OPERAND (e, 0),
+                                                    force),
+                        TREE_OPERAND (e, 1), TREE_OPERAND (e, 2));
       else if (TREE_SIDE_EFFECTS (e) || force)
        return save_expr (e);
       else
        return e;
       break;
 
-    case 'c':
+    case tcc_constant:
       /* Constants need no processing.  In fact, we should never reach
         here.  */
       return e;
 
-    case '2':
+    case tcc_binary:
       /* Recursively stabilize each operand.  */
-      result = build (code, type,
-                     gnat_stabilize_reference_1 (TREE_OPERAND (e, 0), force),
-                     gnat_stabilize_reference_1 (TREE_OPERAND (e, 1), force));
+      result = build2 (code, type,
+                      gnat_stabilize_reference_1 (TREE_OPERAND (e, 0), force),
+                      gnat_stabilize_reference_1 (TREE_OPERAND (e, 1),
+                                                  force));
       break;
 
-    case '1':
+    case tcc_unary:
       /* Recursively stabilize each operand.  */
       result = build1 (code, type,
                       gnat_stabilize_reference_1 (TREE_OPERAND (e, 0),
@@ -5659,7 +6794,7 @@ gnat_stabilize_reference_1 (tree e, bool force)
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   TREE_READONLY (result) = TREE_READONLY (e);
@@ -5669,33 +6804,33 @@ gnat_stabilize_reference_1 (tree e, bool force)
   return result;
 }
 \f
-extern char *__gnat_to_canonical_file_spec (char *);
-
-/* Convert Sloc into *LOCUS (a location_t).  Return true if this Sloc
-   corresponds to a source code location and false if it doesn't.  In the
-   latter case, we don't update *LOCUS.  We also set the Gigi global variable
-   REF_FILENAME to the reference file name as given by sinput (i.e no
-   directory).  */
+/* Convert SLOC into LOCUS.  Return true if SLOC corresponds to a source code
+   location and false if it doesn't.  In the former case, set the Gigi global
+   variable REF_FILENAME to the simple debug file name as given by sinput.  */
 
 bool
 Sloc_to_locus (Source_Ptr Sloc, location_t *locus)
 {
-  /* If node not from source code, ignore.  */
-  if (Sloc < 0)
+  if (Sloc == No_Location)
     return false;
 
-  /* Use the identifier table to make a hashed, permanent copy of the filename,
-     since the name table gets reallocated after Gigi returns but before all
-     the debugging information is output. The __gnat_to_canonical_file_spec
-     call translates filenames from pragmas Source_Reference that contain host
-     style syntax not understood by gdb. */
-  locus->file
-    = IDENTIFIER_POINTER
-      (get_identifier
-       (__gnat_to_canonical_file_spec
-       (Get_Name_String (Full_Debug_Name (Get_Source_File_Index (Sloc))))));
-
-  locus->line = Get_Logical_Line_Number (Sloc);
+  if (Sloc <= Standard_Location)
+    {
+      *locus = BUILTINS_LOCATION;
+      return false;
+    }
+  else
+    {
+      Source_File_Index file = Get_Source_File_Index (Sloc);
+      Logical_Line_Number line = Get_Logical_Line_Number (Sloc);
+      Column_Number column = Get_Column_Number (Sloc);
+      struct line_map *map = &line_table->maps[file - 1];
+
+      /* Translate the location according to the line-map.h formula.  */
+      *locus = map->start_location
+               + ((line - map->to_line) << map->column_bits)
+               + (column & ((1 << map->column_bits) - 1));
+    }
 
   ref_filename
     = IDENTIFIER_POINTER
@@ -5705,18 +6840,18 @@ Sloc_to_locus (Source_Ptr Sloc, location_t *locus)
   return true;
 }
 
-/* Similar to annotate_with_locus, but start with the Sloc of GNAT_NODE and
+/* Similar to set_expr_location, but start with the Sloc of GNAT_NODE and
    don't do anything if it doesn't correspond to a source location.  */
 
 static void
-annotate_with_node (tree node, Node_Id gnat_node)
+set_expr_location_from_node (tree node, Node_Id gnat_node)
 {
   location_t locus;
 
   if (!Sloc_to_locus (Sloc (gnat_node), &locus))
     return;
 
-  annotate_with_locus (node, locus);
+  set_expr_location (node, locus);
 }
 \f
 /* Post an error message.  MSG is the error message, properly annotated.
@@ -5831,19 +6966,11 @@ post_error_ne_tree_2 (const char *msg,
   Error_Msg_Uint_2 = UI_From_Int (num);
   post_error_ne_tree (msg, node, ent, t);
 }
-
-/* Set the node for a second '&' in the error message.  */
-
-void
-set_second_error_entity (Entity_Id e)
-{
-  Error_Msg_Node_2 = e;
-}
 \f
 /* Initialize the table that maps GNAT codes to GCC codes for simple
    binary and unary operations.  */
 
-void
+static void
 init_code_table (void)
 {
   gnu_codes[N_And_Then] = TRUTH_ANDIF_EXPR;
@@ -5873,4 +7000,20 @@ init_code_table (void)
   gnu_codes[N_Op_Shift_Right_Arithmetic] = RSHIFT_EXPR;
 }
 
+/* Return a label to branch to for the exception type in KIND or NULL_TREE
+   if none.  */
+
+tree
+get_exception_label (char kind)
+{
+  if (kind == N_Raise_Constraint_Error)
+    return TREE_VALUE (gnu_constraint_error_label_stack);
+  else if (kind == N_Raise_Storage_Error)
+    return TREE_VALUE (gnu_storage_error_label_stack);
+  else if (kind == N_Raise_Program_Error)
+    return TREE_VALUE (gnu_program_error_label_stack);
+  else
+    return NULL_TREE;
+}
+
 #include "gt-ada-trans.h"