OSDN Git Service

* gigi.h (standard_datatypes): Add ADT_fdesc_type and ADT_null_fdesc.
[pf3gnuchains/gcc-fork.git] / gcc / ada / trans.c
index b19f2f5..4dc5202 100644 (file)
@@ -6,7 +6,7 @@
  *                                                                          *
  *                          C Implementation File                           *
  *                                                                          *
- *          Copyright (C) 1992-2006, 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- *
 #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;
@@ -82,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
@@ -137,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 unshare_save_expr (tree *, int *, void *);
-static tree end_stmt_group (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 *);
@@ -164,14 +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 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);
-
+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.  */
@@ -181,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;
@@ -203,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 ();
@@ -215,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.  */
@@ -222,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);
@@ -243,6 +329,7 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name,
     gnat_init_gcc_eh ();
 
   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. */
@@ -274,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
@@ -283,32 +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;
 
-  /* 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"));
+  switch (Nkind (gnat_parent))
+    {
+    case N_Reference:
+      return 1;
+
+    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;
+
+      /* ... 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;
+    }
+
+  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
@@ -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 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.  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
@@ -389,12 +585,12 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
      enclosing block, but we have no way of testing that right now.
 
      ??? 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
+     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
@@ -404,8 +600,7 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
   /* 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
@@ -429,9 +624,15 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
               && (! DECL_RENAMING_GLOBAL_P (gnu_result)
                   || global_bindings_p ()))
        gnu_result = renamed_obj;
-      else
+
+      /* 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;
     }
@@ -448,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;
@@ -483,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.  */
@@ -497,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;
@@ -612,6 +852,53 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
       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 ... */
 
     case Attr_Access:
@@ -638,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:
@@ -664,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);
          }
 
@@ -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 (build2 (CEIL_DIV_EXPR, bitsizetype,
-                                           gnu_result, bitsize_unit_node)));
+                             fold_build2 (CEIL_DIV_EXPR, bitsizetype,
+                                          gnu_result, bitsize_unit_node));
       break;
 
     case Attr_Alignment:
@@ -839,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));
@@ -862,38 +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);
 
        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
@@ -901,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;
       }
 
@@ -1100,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 (build2 (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;
@@ -1172,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,33 +1584,31 @@ Case_Statement_to_gnu (Node_Id gnat_node)
              gcc_unreachable ();
            }
 
-         /* 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 translated 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++;
-          }
+         /* 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
-         containing the Case statement.  */
-
-       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)));
-       }
+      /* 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.  */
+      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. */
@@ -1253,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.  */
@@ -1298,7 +1685,7 @@ Loop_Statement_to_gnu (Node_Id gnat_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);
+         set_expr_location_from_node (gnu_cond_expr, gnat_loop_spec);
        }
 
       /* Open a new nesting level that will surround the loop to declare the
@@ -1333,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);
     }
 
@@ -1431,9 +1818,6 @@ establish_gnat_vms_condition_handler (void)
 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;
   /* Defining identifier of a parameter to the subprogram.  */
   Entity_Id gnat_param;
   /* The defining identifier for the subprogram body. Note that if a
@@ -1449,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.  */
@@ -1457,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
@@ -1478,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,
@@ -1497,7 +1882,7 @@ 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.  */
@@ -1507,7 +1892,7 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
     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))
          ;
@@ -1518,7 +1903,6 @@ 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.
@@ -1527,9 +1911,9 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
      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.  */
+     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 ();
@@ -1537,11 +1921,35 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
   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.  */
@@ -1566,7 +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
-       (build_return_expr (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 ();
@@ -1574,14 +1982,12 @@ 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);
 
@@ -1593,9 +1999,10 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
     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
@@ -1649,7 +2056,8 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
 
       {
        tree call_expr
-         = build_call_raise (PE_Stubbed_Subprogram_Called, gnat_node);
+         = build_call_raise (PE_Stubbed_Subprogram_Called, gnat_node,
+                             N_Raise_Program_Error);
 
        if (Nkind (gnat_node) == N_Function_Call && !gnu_target)
          {
@@ -1713,7 +2121,7 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
 
   /* 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);
@@ -1724,124 +2132,125 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
        = (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_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 (!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;
-             tree gnu_temp;
-
-             /* If the type is by_reference, a copy is not allowed.  */
-             if (Is_By_Reference_Type (Etype (gnat_formal)))
-               post_error
-                 ("misaligned & cannot be passed by reference", gnat_actual);
+       gnu_name = gnat_stabilize_reference (gnu_name, true);
 
-             /* 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.  */
+      /* 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))
+       {
+         tree gnu_copy = gnu_name, gnu_temp;
 
-             else if (Is_Valued_Procedure (Entity (Name (gnat_node))))
-               {
-                 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);
-               }
+         /* 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))))
+           {
+             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);
+           }
 
-             /* Remove any unpadding on the actual and make a copy.  But if
-                the actual is a 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_JUSTIFIED_MODULAR_P (gnu_name_type)))
-               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 actual and copied back after the call.  */
-             gnu_actual = save_expr (gnu_name);
-
-             /* Set up to move the copy back to the original.  */
-             gnu_temp = build_binary_op (MODIFY_EXPR, NULL_TREE,
-                                         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);
-
-             /* Account for next statement just below.  */
-             gnu_name = gnu_actual;
            }
        }
 
+      /* 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_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,
@@ -1849,31 +2258,52 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
                                  == 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.  */
@@ -1898,32 +2328,13 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
                                      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);
-
-         /* For In parameters, gnu_actual might still not be addressable at
-            this point and we need the creation of a temporary copy since
-            this is to be passed by ref.  Resorting to save_expr to force a
-            SAVE_EXPR temporary creation here is not guaranteed to work
-            because the actual might be invariant or readonly without side
-            effects, so we let the gimplifier process this case.  */
-
          /* 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));
@@ -1947,7 +2358,8 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
                                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.  */
@@ -1992,18 +2404,49 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
       gnu_actual_list = tree_cons (NULL_TREE, gnu_actual, gnu_actual_list);
     }
 
-  gnu_subprog_call = build3 (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, we emit the call and return the target
-     as our result.  */
+  /* 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))
     {
-      add_stmt_with_node (gnu_subprog_call, gnat_node);
-      *gnu_result_type_p
+      /* 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)));
-      return unchecked_convert (*gnu_result_type_p, gnu_target, false);
+
+      /* 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 unless
@@ -2074,7 +2517,7 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
                               (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
@@ -2099,9 +2542,8 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
            /* 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
+              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)
              {
@@ -2112,15 +2554,13 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
                     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);
+               if (!Is_Composite_Type (Underlying_Type (Etype (gnat_formal))))
+                 gnu_actual = convert (TREE_TYPE (gnu_result), gnu_actual);
              }
 
-           /* Unchecked conversions as actuals for out parameters are not
+           /* 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
+              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),
@@ -2139,17 +2579,14 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
 
            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;
@@ -2207,6 +2644,8 @@ 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
@@ -2216,18 +2655,21 @@ Handled_Sequence_Of_Statements_to_gnu (Node_Id gnat_node)
                                         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))));
+    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.  */
@@ -2292,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;
@@ -2530,7 +2972,9 @@ 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 ();
 
@@ -2559,15 +3003,18 @@ 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. */
   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);
 
@@ -2588,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.  */
@@ -2644,7 +3092,8 @@ 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, gnat_node));
+                  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
@@ -2714,7 +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.  */
-       gcc_assert (!TREE_CONSTANT_OVERFLOW (gnu_result));
+       gcc_assert (!TREE_OVERFLOW (gnu_result));
       }
       break;
 
@@ -2729,10 +3178,8 @@ gnat_to_gnu (Node_Id gnat_node)
        gnu_result = DECL_INITIAL (get_gnu_tree (Entity (gnat_node)));
       else
        gnu_result
-         = force_fit_type
-           (build_int_cst
-             (gnu_result_type, UI_To_CC (Char_Literal_Value (gnat_node))),
-            false, false, false);
+         = build_int_cst_type
+             (gnu_result_type, UI_To_CC (Char_Literal_Value (gnat_node)));
       break;
 
     case N_Real_Literal:
@@ -2743,7 +3190,7 @@ 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);
-         gcc_assert (!TREE_CONSTANT_OVERFLOW (gnu_result));
+         gcc_assert (!TREE_OVERFLOW (gnu_result));
        }
 
       /* We should never see a Vax_Float type literal, since the front end
@@ -2810,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.  */
@@ -2827,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
        {
@@ -3034,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 (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, 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;
@@ -3234,7 +3696,12 @@ gnat_to_gnu (Node_Id gnat_node)
       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;
 
@@ -3258,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))
        {
@@ -3273,6 +3739,13 @@ gnat_to_gnu (Node_Id 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;
@@ -3442,11 +3915,7 @@ gnat_to_gnu (Node_Id gnat_node)
            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);
-               TREE_CONSTANT_OVERFLOW (gnu_lhs)
-                 = TREE_CONSTANT_OVERFLOW (gnu_old_lhs);
-             }
+             TREE_OVERFLOW (gnu_lhs) = TREE_OVERFLOW (gnu_old_lhs);
            gnu_rhs = convert (gnu_type, gnu_rhs);
          }
 
@@ -3493,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));
@@ -3594,7 +4065,8 @@ gnat_to_gnu (Node_Id gnat_node)
         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);
+       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),
@@ -3639,7 +4111,7 @@ gnat_to_gnu (Node_Id gnat_node)
              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);
            }
@@ -3768,26 +4240,13 @@ gnat_to_gnu (Node_Id gnat_node)
                else if (TYPE_RETURNS_UNCONSTRAINED_P (gnu_subprog_type))
                  {
                    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, false);
-                   else
-                     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);
+                   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);
                  }
              }
          }
@@ -3821,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)),
@@ -3838,7 +4297,7 @@ gnat_to_gnu (Node_Id gnat_node)
 
       for (gnat_temp
           = First_Formal_With_Extras
-              (Defining_Entity (Specification (gnat_node)));
+             (Defining_Entity (Specification (gnat_node)));
           Present (gnat_temp);
           gnat_temp = Next_Formal_With_Extras (gnat_temp))
        if (Is_Itype (Etype (gnat_temp))
@@ -3987,6 +4446,36 @@ gnat_to_gnu (Node_Id gnat_node)
 
       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;
+
     /*******************************/
     /* Chapter 12: Generic Units:  */
     /*******************************/
@@ -4024,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:
@@ -4167,7 +4656,9 @@ gnat_to_gnu (Node_Id gnat_node)
          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
@@ -4214,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),
@@ -4240,14 +4764,15 @@ 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)), gnat_node);
+       = 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 = build3 (COND_EXPR, void_type_node,
@@ -4332,11 +4857,13 @@ gnat_to_gnu (Node_Id gnat_node)
       current_function_decl = NULL_TREE;
     }
 
-  /* Set the location information into the result.  Note that we may have
+  /* 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))
-    annotate_with_node (gnu_result, gnat_node);
+  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.  */
@@ -4345,13 +4872,14 @@ gnat_to_gnu (Node_Id gnat_node)
 
   /* 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, gnat_node));
+                 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,
@@ -4362,36 +4890,41 @@ gnat_to_gnu (Node_Id gnat_node)
          || CONTAINS_PLACEHOLDER_P (TYPE_SIZE (gnu_result_type))))
     gnu_result = gnat_stabilize_reference (gnu_result, false);
 
-  /* 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.  */
+  /* 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)
@@ -4406,15 +4939,14 @@ gnat_to_gnu (Node_Id gnat_node)
           && !(TREE_CODE (gnu_result_type) == RECORD_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);
     }
@@ -4429,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))
@@ -4456,6 +4985,20 @@ 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
@@ -4478,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;
 
@@ -4508,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);
 }
 
@@ -4553,7 +5096,7 @@ add_decl_expr (tree gnu_decl, Entity_Id gnat_entity)
     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.  */ 
+     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))
@@ -4617,11 +5160,14 @@ unshare_save_expr (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
   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);
 }
 
@@ -4638,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;
@@ -4729,36 +5275,6 @@ 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:
-      gcc_unreachable ();
-    }
-}
-\f
 /* Generate GIMPLE in place for the expression at *EXPR_P.  */
 
 int
@@ -4786,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:
@@ -4829,6 +5345,13 @@ gnat_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p ATTRIBUTE_UNUSED)
          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
@@ -4853,19 +5376,6 @@ gnat_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p ATTRIBUTE_UNUSED)
          return GS_ALL_DONE;
        }
 
-      return GS_UNHANDLED;
-
-    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)))
-       {
-         TREE_OPERAND (*expr_p, 1)
-           = DECL_ORIGINAL_FIELD (TREE_OPERAND (*expr_p, 1));
-         return GS_OK;
-       }
-
       /* ... fall through ... */
 
     default:
@@ -4886,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;
@@ -4930,9 +5437,10 @@ gnat_gimplify_stmt (tree *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);
@@ -5050,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;
 
@@ -5064,14 +5572,14 @@ 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, 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))
-    || (gnu_old
-        && (TREE_CODE (TREE_TYPE (gnu_old)) == FUNCTION_TYPE
-        && Ekind (gnat_entity) == E_Subprogram_Type)))
+     purposes. */
+  if (gnu_old
+      && ((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, except
@@ -5096,7 +5604,7 @@ process_freeze_entity (Node_Id gnat_node)
   /* 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);
@@ -5315,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.  */
@@ -5403,16 +5916,16 @@ emit_check (tree gnu_cond, tree gnu_expr, int reason)
   tree gnu_call;
   tree gnu_result;
 
-  gnu_call = build_call_raise (reason, Empty);
+  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 (build3 (COND_EXPR, TREE_TYPE (gnu_expr), gnu_cond,
-                            build2 (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
@@ -5558,7 +6071,7 @@ convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflowp,
 
       /* 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);
+      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);
@@ -5612,13 +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 reference
-   to a bitfield or to a field not sufficiently aligned for its type.  */
+/* 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:
@@ -5632,48 +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))
              && (!STRICT_ALIGNMENT
-                 /* If the field was marked as "semantically" addressable
-                    in create_field_decl, we are guaranteed that it can
-                    be directly addressed.  */
-                 || !DECL_NONADDRESSABLE_P (TREE_OPERAND (gnu_expr, 1))
-                 /* Otherwise it can nevertheless be directly addressed
-                    if it has been sufficiently aligned in the record.  */
+                 /* 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)));
+             && 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:
@@ -5820,7 +6427,7 @@ assoc_to_constructor (Entity_Id gnat_entity, Node_Id gnat_assoc, tree gnu_type)
   {
     tree gnu_field;
 
-    /* Verify every enty in GNU_LIST was used.  */
+    /* 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));
   }
@@ -5980,18 +6587,13 @@ 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 extra arguments:
-
-   FORCE says whether to force evaluation of everything,
-
-   SUCCESS we set to true unless we walk through something we don't know how
-   to stabilize, or through something which is not an lvalue and LVALUES_ONLY
-   is true, in which cases we set to false.  */
+/* 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
-maybe_stabilize_reference (tree ref, bool force, bool lvalues_only,
-                          bool *success)
+maybe_stabilize_reference (tree ref, bool force, bool *success)
 {
   tree type = TREE_TYPE (ref);
   enum tree_code code = TREE_CODE (ref);
@@ -6002,6 +6604,7 @@ maybe_stabilize_reference (tree ref, bool force, bool lvalues_only,
 
   switch (code)
     {
+    case CONST_DECL:
     case VAR_DECL:
     case PARM_DECL:
     case RESULT_DECL:
@@ -6009,14 +6612,6 @@ maybe_stabilize_reference (tree ref, bool force, bool lvalues_only,
       return ref;
 
     case ADDR_EXPR:
-      /*  A standalone ADDR_EXPR is never an lvalue, and this one can't
-         be nested inside an outer INDIRECT_REF, since INDIREC_REF goes
-         straight to stabilize_1.  */
-      if (lvalues_only)
-       goto failure;
-
-      /* ... Fallthru ... */
-
     case NOP_EXPR:
     case CONVERT_EXPR:
     case FLOAT_EXPR:
@@ -6025,7 +6620,7 @@ maybe_stabilize_reference (tree ref, bool force, bool lvalues_only,
       result
        = build1 (code, type,
                  maybe_stabilize_reference (TREE_OPERAND (ref, 0), force,
-                                            lvalues_only, success));
+                                            success));
       break;
 
     case INDIRECT_REF:
@@ -6038,14 +6633,14 @@ maybe_stabilize_reference (tree ref, bool force, bool lvalues_only,
     case COMPONENT_REF:
      result = build3 (COMPONENT_REF, type,
                      maybe_stabilize_reference (TREE_OPERAND (ref, 0), force,
-                                                lvalues_only, success),
+                                                success),
                      TREE_OPERAND (ref, 1), NULL_TREE);
       break;
 
     case BIT_FIELD_REF:
       result = build3 (BIT_FIELD_REF, type,
                       maybe_stabilize_reference (TREE_OPERAND (ref, 0), force,
-                                                 lvalues_only, success),
+                                                 success),
                       gnat_stabilize_reference_1 (TREE_OPERAND (ref, 1),
                                                   force),
                       gnat_stabilize_reference_1 (TREE_OPERAND (ref, 2),
@@ -6056,18 +6651,43 @@ maybe_stabilize_reference (tree ref, bool force, bool lvalues_only,
     case ARRAY_RANGE_REF:
       result = build4 (code, type,
                       maybe_stabilize_reference (TREE_OPERAND (ref, 0), force,
-                                                 lvalues_only, success),
+                                                 success),
                       gnat_stabilize_reference_1 (TREE_OPERAND (ref, 1),
                                                   force),
                       NULL_TREE, NULL_TREE);
       break;
 
     case COMPOUND_EXPR:
-      result = build2 (COMPOUND_EXPR, type,
-                      gnat_stabilize_reference_1 (TREE_OPERAND (ref, 0),
-                                                  force),
-                      maybe_stabilize_reference (TREE_OPERAND (ref, 1), force,
-                                                 lvalues_only, success));
+      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:
@@ -6078,7 +6698,6 @@ maybe_stabilize_reference (tree ref, bool force, bool lvalues_only,
       /* If arg isn't a kind of lvalue we recognize, make no change.
         Caller should recognize the error for an invalid lvalue.  */
     default:
-    failure:
       *success = false;
       return ref;
     }
@@ -6104,11 +6723,11 @@ maybe_stabilize_reference (tree ref, bool force, bool lvalues_only,
    lvalue restrictions and without need to examine the success
    indication.  */
 
-tree
+static tree
 gnat_stabilize_reference (tree ref, bool force)
 {
-  bool stabilized;
-  return maybe_stabilize_reference (ref, force, false, &stabilized);
+  bool dummy;
+  return maybe_stabilize_reference (ref, force, &dummy);
 }
 
 /* Similar to stabilize_reference_1 in tree.c, but supports an extra
@@ -6138,6 +6757,7 @@ gnat_stabilize_reference_1 (tree e, bool force)
     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.  */
@@ -6184,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
@@ -6220,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.
@@ -6350,7 +6970,7 @@ post_error_ne_tree_2 (const char *msg,
 /* 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;
@@ -6380,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"