[Ada] Various typo fixes and reformatting of comments
[platform/upstream/gcc.git] / gcc / tree-nested.c
index dc63ef6..de168df 100644 (file)
@@ -1,5 +1,5 @@
 /* Nested function decomposition for GIMPLE.
-   Copyright (C) 2004-2013 Free Software Foundation, Inc.
+   Copyright (C) 2004-2020 Free Software Foundation, Inc.
 
    This file is part of GCC.
 
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
+#include "backend.h"
+#include "target.h"
+#include "rtl.h"
 #include "tree.h"
-#include "tm_p.h"
-#include "function.h"
-#include "tree-dump.h"
-#include "tree-inline.h"
 #include "gimple.h"
-#include "tree-iterator.h"
-#include "bitmap.h"
+#include "memmodel.h"
+#include "tm_p.h"
+#include "stringpool.h"
 #include "cgraph.h"
+#include "fold-const.h"
+#include "stor-layout.h"
+#include "dumpfile.h"
+#include "tree-inline.h"
+#include "gimplify.h"
+#include "gimple-iterator.h"
+#include "gimple-walk.h"
 #include "tree-cfg.h"
-#include "expr.h"      /* FIXME: For STACK_SAVEAREA_MODE and SAVE_NONLOCAL.  */
+#include "explow.h"
 #include "langhooks.h"
-#include "pointer-set.h"
 #include "gimple-low.h"
+#include "gomp-constants.h"
+#include "diagnostic.h"
 
 
 /* The object of this pass is to lower the representation of a set of nested
@@ -83,9 +90,9 @@ struct nesting_info
   struct nesting_info *inner;
   struct nesting_info *next;
 
-  struct pointer_map_t *field_map;
-  struct pointer_map_t *var_map;
-  struct pointer_set_t *mem_refs;
+  hash_map<tree, tree> *field_map;
+  hash_map<tree, tree> *var_map;
+  hash_set<tree *> *mem_refs;
   bitmap suppress_expansion;
 
   tree context;
@@ -97,8 +104,10 @@ struct nesting_info
   tree chain_decl;
   tree nl_goto_field;
 
+  bool thunk_p;
   bool any_parm_remapped;
   bool any_tramp_created;
+  bool any_descr_created;
   char static_chain_added;
 };
 
@@ -151,43 +160,30 @@ create_tmp_var_for (struct nesting_info *info, tree type, const char *prefix)
   DECL_CONTEXT (tmp_var) = info->context;
   DECL_CHAIN (tmp_var) = info->new_local_var_chain;
   DECL_SEEN_IN_BIND_EXPR_P (tmp_var) = 1;
-  if (TREE_CODE (type) == COMPLEX_TYPE
-      || TREE_CODE (type) == VECTOR_TYPE)
-    DECL_GIMPLE_REG_P (tmp_var) = 1;
 
   info->new_local_var_chain = tmp_var;
 
   return tmp_var;
 }
 
+/* Like build_simple_mem_ref, but set TREE_THIS_NOTRAP on the result.  */
+
+static tree
+build_simple_mem_ref_notrap (tree ptr)
+{
+  tree t = build_simple_mem_ref (ptr);
+  TREE_THIS_NOTRAP (t) = 1;
+  return t;
+}
+
 /* Take the address of EXP to be used within function CONTEXT.
    Mark it for addressability as necessary.  */
 
 tree
-build_addr (tree exp, tree context)
+build_addr (tree exp)
 {
-  tree base = exp;
-  tree save_context;
-  tree retval;
-
-  while (handled_component_p (base))
-    base = TREE_OPERAND (base, 0);
-
-  if (DECL_P (base))
-    TREE_ADDRESSABLE (base) = 1;
-
-  /* Building the ADDR_EXPR will compute a set of properties for
-     that ADDR_EXPR.  Those properties are unfortunately context
-     specific, i.e., they are dependent on CURRENT_FUNCTION_DECL.
-
-     Temporarily set CURRENT_FUNCTION_DECL to the desired context,
-     build the ADDR_EXPR, then restore CURRENT_FUNCTION_DECL.  That
-     way the properties are for the ADDR_EXPR are computed properly.  */
-  save_context = current_function_decl;
-  current_function_decl = context;
-  retval = build_fold_addr_expr (exp);
-  current_function_decl = save_context;
-  return retval;
+  mark_addressable (exp);
+  return build_fold_addr_expr (exp);
 }
 
 /* Insert FIELD into TYPE, sorted by alignment requirements.  */
@@ -208,7 +204,7 @@ insert_field_into_struct (tree type, tree field)
 
   /* Set correct alignment for frame struct type.  */
   if (TYPE_ALIGN (type) < DECL_ALIGN (field))
-    TYPE_ALIGN (type) = DECL_ALIGN (field);
+    SET_TYPE_ALIGN (type, DECL_ALIGN (field));
 }
 
 /* Build or return the RECORD_TYPE that describes the frame state that is
@@ -235,8 +231,15 @@ get_frame_type (struct nesting_info *info)
       free (name);
 
       info->frame_type = type;
-      info->frame_decl = create_tmp_var_for (info, type, "FRAME");
+
+      /* Do not put info->frame_decl on info->new_local_var_chain,
+        so that we can declare it in the lexical blocks, which
+        makes sure virtual regs that end up appearing in its RTL
+        expression get substituted in instantiate_virtual_regs.  */
+      info->frame_decl = create_tmp_var_raw (type, "FRAME");
+      DECL_CONTEXT (info->frame_decl) = info->context;
       DECL_NONLOCAL_FRAME (info->frame_decl) = 1;
+      DECL_SEEN_IN_BIND_EXPR_P (info->frame_decl) = 1;
 
       /* ??? Always make it addressable for now, since it is meant to
         be pointed to by the static chain pointer.  This pessimizes
@@ -246,26 +249,29 @@ get_frame_type (struct nesting_info *info)
         local frame structure in the first place.  */
       TREE_ADDRESSABLE (info->frame_decl) = 1;
     }
+
   return type;
 }
 
-/* Return true if DECL should be referenced by pointer in the non-local
-   frame structure.  */
+/* Return true if DECL should be referenced by pointer in the non-local frame
+   structure.  */
 
 static bool
 use_pointer_in_frame (tree decl)
 {
   if (TREE_CODE (decl) == PARM_DECL)
     {
-      /* It's illegal to copy TREE_ADDRESSABLE, impossible to copy variable
-         sized decls, and inefficient to copy large aggregates.  Don't bother
-         moving anything but scalar variables.  */
+      /* It's illegal to copy TREE_ADDRESSABLE, impossible to copy variable-
+        sized DECLs, and inefficient to copy large aggregates.  Don't bother
+        moving anything but scalar parameters.  */
       return AGGREGATE_TYPE_P (TREE_TYPE (decl));
     }
   else
     {
-      /* Variable sized types make things "interesting" in the frame.  */
-      return DECL_SIZE (decl) == NULL || !TREE_CONSTANT (DECL_SIZE (decl));
+      /* Variable-sized DECLs can only come from OMP clauses at this point
+        since the gimplifier has already turned the regular variables into
+        pointers.  Do the same as the gimplifier.  */
+      return !DECL_SIZE (decl) || TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST;
     }
 }
 
@@ -276,45 +282,72 @@ static tree
 lookup_field_for_decl (struct nesting_info *info, tree decl,
                       enum insert_option insert)
 {
-  void **slot;
+  gcc_checking_assert (decl_function_context (decl) == info->context);
 
   if (insert == NO_INSERT)
     {
-      slot = pointer_map_contains (info->field_map, decl);
-      return slot ? (tree) *slot : NULL_TREE;
+      tree *slot = info->field_map->get (decl);
+      return slot ? *slot : NULL_TREE;
     }
 
-  slot = pointer_map_insert (info->field_map, decl);
+  tree *slot = &info->field_map->get_or_insert (decl);
   if (!*slot)
     {
+      tree type = get_frame_type (info);
       tree field = make_node (FIELD_DECL);
       DECL_NAME (field) = DECL_NAME (decl);
 
       if (use_pointer_in_frame (decl))
        {
          TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
-         DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
+         SET_DECL_ALIGN (field, TYPE_ALIGN (TREE_TYPE (field)));
          DECL_NONADDRESSABLE_P (field) = 1;
        }
       else
        {
           TREE_TYPE (field) = TREE_TYPE (decl);
           DECL_SOURCE_LOCATION (field) = DECL_SOURCE_LOCATION (decl);
-          DECL_ALIGN (field) = DECL_ALIGN (decl);
+          SET_DECL_ALIGN (field, DECL_ALIGN (decl));
           DECL_USER_ALIGN (field) = DECL_USER_ALIGN (decl);
           TREE_ADDRESSABLE (field) = TREE_ADDRESSABLE (decl);
           DECL_NONADDRESSABLE_P (field) = !TREE_ADDRESSABLE (decl);
           TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (decl);
+
+         /* Declare the transformation and adjust the original DECL.  For a
+            variable or for a parameter when not optimizing, we make it point
+            to the field in the frame directly.  For a parameter, we don't do
+            it when optimizing because the variable tracking pass will already
+            do the job,  */
+         if (VAR_P (decl) || !optimize)
+           {
+             tree x
+               = build3 (COMPONENT_REF, TREE_TYPE (field), info->frame_decl,
+                         field, NULL_TREE);
+
+             /* If the next declaration is a PARM_DECL pointing to the DECL,
+                we need to adjust its VALUE_EXPR directly, since chains of
+                VALUE_EXPRs run afoul of garbage collection.  This occurs
+                in Ada for Out parameters that aren't copied in.  */
+             tree next = DECL_CHAIN (decl);
+             if (next
+                 && TREE_CODE (next) == PARM_DECL
+                 && DECL_HAS_VALUE_EXPR_P (next)
+                 && DECL_VALUE_EXPR (next) == decl)
+               SET_DECL_VALUE_EXPR (next, x);
+
+             SET_DECL_VALUE_EXPR (decl, x);
+             DECL_HAS_VALUE_EXPR_P (decl) = 1;
+           }
        }
 
-      insert_field_into_struct (get_frame_type (info), field);
+      insert_field_into_struct (type, field);
       *slot = field;
 
       if (TREE_CODE (decl) == PARM_DECL)
        info->any_parm_remapped = true;
     }
 
-  return (tree) *slot;
+  return *slot;
 }
 
 /* Build or return the variable that holds the static chain within
@@ -379,7 +412,7 @@ get_chain_field (struct nesting_info *info)
       field = make_node (FIELD_DECL);
       DECL_NAME (field) = get_identifier ("__chain");
       TREE_TYPE (field) = type;
-      DECL_ALIGN (field) = TYPE_ALIGN (type);
+      SET_DECL_ALIGN (field, TYPE_ALIGN (type));
       DECL_NONADDRESSABLE_P (field) = 1;
 
       insert_field_into_struct (get_frame_type (info), field);
@@ -401,7 +434,7 @@ get_chain_field (struct nesting_info *info)
 
 static tree
 init_tmp_var_with_call (struct nesting_info *info, gimple_stmt_iterator *gsi,
-                       gimple call)
+                       gcall *call)
 {
   tree t;
 
@@ -422,7 +455,7 @@ static tree
 init_tmp_var (struct nesting_info *info, tree exp, gimple_stmt_iterator *gsi)
 {
   tree t;
-  gimple stmt;
+  gimple *stmt;
 
   t = create_tmp_var_for (info, TREE_TYPE (exp), NULL);
   stmt = gimple_build_assign (t, exp);
@@ -453,7 +486,7 @@ static tree
 save_tmp_var (struct nesting_info *info, tree exp, gimple_stmt_iterator *gsi)
 {
   tree t;
-  gimple stmt;
+  gimple *stmt;
 
   t = create_tmp_var_for (info, TREE_TYPE (exp), NULL);
   stmt = gimple_build_assign (exp, t);
@@ -492,7 +525,7 @@ get_trampoline_type (struct nesting_info *info)
   t = build_array_type (char_type_node, t);
   t = build_decl (DECL_SOURCE_LOCATION (info->context),
                  FIELD_DECL, get_identifier ("__data"), t);
-  DECL_ALIGN (t) = align;
+  SET_DECL_ALIGN (t, align);
   DECL_USER_ALIGN (t) = 1;
 
   trampoline_type = make_node (RECORD_TYPE);
@@ -504,6 +537,70 @@ get_trampoline_type (struct nesting_info *info)
   return trampoline_type;
 }
 
+/* Build or return the type used to represent a nested function descriptor.  */
+
+static GTY(()) tree descriptor_type;
+
+static tree
+get_descriptor_type (struct nesting_info *info)
+{
+  /* The base alignment is that of a function.  */
+  const unsigned align = FUNCTION_ALIGNMENT (FUNCTION_BOUNDARY);
+  tree t;
+
+  if (descriptor_type)
+    return descriptor_type;
+
+  t = build_index_type (integer_one_node);
+  t = build_array_type (ptr_type_node, t);
+  t = build_decl (DECL_SOURCE_LOCATION (info->context),
+                 FIELD_DECL, get_identifier ("__data"), t);
+  SET_DECL_ALIGN (t, MAX (TYPE_ALIGN (ptr_type_node), align));
+  DECL_USER_ALIGN (t) = 1;
+
+  descriptor_type = make_node (RECORD_TYPE);
+  TYPE_NAME (descriptor_type) = get_identifier ("__builtin_descriptor");
+  TYPE_FIELDS (descriptor_type) = t;
+  layout_type (descriptor_type);
+  DECL_CONTEXT (t) = descriptor_type;
+
+  return descriptor_type;
+}
+
+/* Given DECL, a nested function, find or create an element in the
+   var map for this function.  */
+
+static tree
+lookup_element_for_decl (struct nesting_info *info, tree decl,
+                        enum insert_option insert)
+{
+  if (insert == NO_INSERT)
+    {
+      tree *slot = info->var_map->get (decl);
+      return slot ? *slot : NULL_TREE;
+    }
+
+  tree *slot = &info->var_map->get_or_insert (decl);
+  if (!*slot)
+    *slot = build_tree_list (NULL_TREE, NULL_TREE);
+
+  return (tree) *slot;
+} 
+
+/* Given DECL, a nested function, create a field in the non-local
+   frame structure for this function.  */
+
+static tree
+create_field_for_decl (struct nesting_info *info, tree decl, tree type)
+{
+  tree field = make_node (FIELD_DECL);
+  DECL_NAME (field) = DECL_NAME (decl);
+  TREE_TYPE (field) = type;
+  TREE_ADDRESSABLE (field) = 1;
+  insert_field_into_struct (get_frame_type (info), field);
+  return field;
+}
+
 /* Given DECL, a nested function, find or create a field in the non-local
    frame structure for a trampoline for this function.  */
 
@@ -511,29 +608,47 @@ static tree
 lookup_tramp_for_decl (struct nesting_info *info, tree decl,
                       enum insert_option insert)
 {
-  void **slot;
+  tree elt, field;
 
-  if (insert == NO_INSERT)
+  elt = lookup_element_for_decl (info, decl, insert);
+  if (!elt)
+    return NULL_TREE;
+
+  field = TREE_PURPOSE (elt);
+
+  if (!field && insert == INSERT)
     {
-      slot = pointer_map_contains (info->var_map, decl);
-      return slot ? (tree) *slot : NULL_TREE;
+      field = create_field_for_decl (info, decl, get_trampoline_type (info));
+      TREE_PURPOSE (elt) = field;
+      info->any_tramp_created = true;
     }
 
-  slot = pointer_map_insert (info->var_map, decl);
-  if (!*slot)
-    {
-      tree field = make_node (FIELD_DECL);
-      DECL_NAME (field) = DECL_NAME (decl);
-      TREE_TYPE (field) = get_trampoline_type (info);
-      TREE_ADDRESSABLE (field) = 1;
+  return field;
+}
 
-      insert_field_into_struct (get_frame_type (info), field);
-      *slot = field;
+/* Given DECL, a nested function, find or create a field in the non-local
+   frame structure for a descriptor for this function.  */
 
-      info->any_tramp_created = true;
+static tree
+lookup_descr_for_decl (struct nesting_info *info, tree decl,
+                      enum insert_option insert)
+{
+  tree elt, field;
+
+  elt = lookup_element_for_decl (info, decl, insert);
+  if (!elt)
+    return NULL_TREE;
+
+  field = TREE_VALUE (elt);
+
+  if (!field && insert == INSERT)
+    {
+      field = create_field_for_decl (info, decl, get_descriptor_type (info));
+      TREE_VALUE (elt) = field;
+      info->any_descr_created = true;
     }
 
-  return (tree) *slot;
+  return field;
 }
 
 /* Build or return the field within the non-local frame state that holds
@@ -558,7 +673,9 @@ get_nl_goto_field (struct nesting_info *info)
       else
        type = lang_hooks.types.type_for_mode (Pmode, 1);
 
-      size = GET_MODE_SIZE (STACK_SAVEAREA_MODE (SAVE_NONLOCAL));
+      scalar_int_mode mode
+       = as_a <scalar_int_mode> (STACK_SAVEAREA_MODE (SAVE_NONLOCAL));
+      size = GET_MODE_SIZE (mode);
       size = size / GET_MODE_SIZE (Pmode);
       size = size + 1;
 
@@ -568,7 +685,7 @@ get_nl_goto_field (struct nesting_info *info)
       field = make_node (FIELD_DECL);
       DECL_NAME (field) = get_identifier ("__nl_goto_buf");
       TREE_TYPE (field) = type;
-      DECL_ALIGN (field) = TYPE_ALIGN (type);
+      SET_DECL_ALIGN (field, TYPE_ALIGN (type));
       TREE_ADDRESSABLE (field) = 1;
 
       insert_field_into_struct (get_frame_type (info), field);
@@ -608,7 +725,7 @@ walk_function (walk_stmt_fn callback_stmt, walk_tree_fn callback_op,
 /* Invoke CALLBACK on a GIMPLE_OMP_FOR's init, cond, incr and pre-body.  */
 
 static void
-walk_gimple_omp_for (gimple for_stmt,
+walk_gimple_omp_for (gomp_for *for_stmt,
                     walk_stmt_fn callback_stmt, walk_tree_fn callback_op,
                     struct nesting_info *info)
 {
@@ -696,7 +813,7 @@ walk_all_functions (walk_stmt_fn callback_stmt, walk_tree_fn callback_op,
 static bool
 check_for_nested_with_variably_modified (tree fndecl, tree orig_fndecl)
 {
-  struct cgraph_node *cgn = cgraph_get_node (fndecl);
+  struct cgraph_node *cgn = cgraph_node::get (fndecl);
   tree arg;
 
   for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
@@ -720,11 +837,12 @@ static struct nesting_info *
 create_nesting_tree (struct cgraph_node *cgn)
 {
   struct nesting_info *info = XCNEW (struct nesting_info);
-  info->field_map = pointer_map_create ();
-  info->var_map = pointer_map_create ();
-  info->mem_refs = pointer_set_create ();
+  info->field_map = new hash_map<tree, tree>;
+  info->var_map = new hash_map<tree, tree>;
+  info->mem_refs = new hash_set<tree *>;
   info->suppress_expansion = BITMAP_ALLOC (&nesting_info_bitmap_obstack);
   info->context = cgn->decl;
+  info->thunk_p = cgn->thunk.thunk_p;
 
   for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
     {
@@ -754,17 +872,19 @@ get_static_chain (struct nesting_info *info, tree target_context,
 
   if (info->context == target_context)
     {
-      x = build_addr (info->frame_decl, target_context);
+      x = build_addr (info->frame_decl);
+      info->static_chain_added |= 1;
     }
   else
     {
       x = get_chain_decl (info);
+      info->static_chain_added |= 2;
 
       for (i = info->outer; i->context != target_context; i = i->outer)
        {
          tree field = get_chain_field (i);
 
-         x = build_simple_mem_ref (x);
+         x = build_simple_mem_ref_notrap (x);
          x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
          x = init_tmp_var (info, x, gsi);
        }
@@ -790,21 +910,23 @@ get_frame_field (struct nesting_info *info, tree target_context,
       /* Make sure frame_decl gets created.  */
       (void) get_frame_type (info);
       x = info->frame_decl;
+      info->static_chain_added |= 1;
     }
   else
     {
       x = get_chain_decl (info);
+      info->static_chain_added |= 2;
 
       for (i = info->outer; i->context != target_context; i = i->outer)
        {
          tree field = get_chain_field (i);
 
-         x = build_simple_mem_ref (x);
+         x = build_simple_mem_ref_notrap (x);
          x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
          x = init_tmp_var (info, x, gsi);
        }
 
-      x = build_simple_mem_ref (x);
+      x = build_simple_mem_ref_notrap (x);
     }
 
   x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
@@ -816,7 +938,7 @@ static void note_nonlocal_vla_type (struct nesting_info *info, tree type);
 /* A subroutine of convert_nonlocal_reference_op.  Create a local variable
    in the nested function with DECL_VALUE_EXPR set to reference the true
    variable in the parent function.  This is used both for debug info
-   and in OpenMP lowering.  */
+   and in OMP lowering.  */
 
 static tree
 get_nonlocal_debug_decl (struct nesting_info *info, tree decl)
@@ -824,12 +946,11 @@ get_nonlocal_debug_decl (struct nesting_info *info, tree decl)
   tree target_context;
   struct nesting_info *i;
   tree x, field, new_decl;
-  void **slot;
 
-  slot = pointer_map_insert (info->var_map, decl);
+  tree *slot = &info->var_map->get_or_insert (decl);
 
   if (*slot)
-    return (tree) *slot;
+    return *slot;
 
   target_context = decl_function_context (decl);
 
@@ -840,23 +961,25 @@ get_nonlocal_debug_decl (struct nesting_info *info, tree decl)
       (void) get_frame_type (info);
       x = info->frame_decl;
       i = info;
+      info->static_chain_added |= 1;
     }
   else
     {
       x = get_chain_decl (info);
+      info->static_chain_added |= 2;
       for (i = info->outer; i->context != target_context; i = i->outer)
        {
          field = get_chain_field (i);
-         x = build_simple_mem_ref (x);
+         x = build_simple_mem_ref_notrap (x);
          x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
        }
-      x = build_simple_mem_ref (x);
+      x = build_simple_mem_ref_notrap (x);
     }
 
   field = lookup_field_for_decl (i, decl, INSERT);
   x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
   if (use_pointer_in_frame (decl))
-    x = build_simple_mem_ref (x);
+    x = build_simple_mem_ref_notrap (x);
 
   /* ??? We should be remapping types as well, surely.  */
   new_decl = build_decl (DECL_SOURCE_LOCATION (decl),
@@ -871,7 +994,7 @@ get_nonlocal_debug_decl (struct nesting_info *info, tree decl)
   DECL_SEEN_IN_BIND_EXPR_P (new_decl) = 1;
   if ((TREE_CODE (decl) == PARM_DECL
        || TREE_CODE (decl) == RESULT_DECL
-       || TREE_CODE (decl) == VAR_DECL)
+       || VAR_P (decl))
       && DECL_BY_REFERENCE (decl))
     DECL_BY_REFERENCE (new_decl) = 1;
 
@@ -916,37 +1039,48 @@ convert_nonlocal_reference_op (tree *tp, int *walk_subtrees, void *data)
       /* FALLTHRU */
 
     case PARM_DECL:
-      if (decl_function_context (t) != info->context)
-       {
-         tree x;
-         wi->changed = true;
+      {
+       tree x, target_context = decl_function_context (t);
 
-         x = get_nonlocal_debug_decl (info, t);
-         if (!bitmap_bit_p (info->suppress_expansion, DECL_UID (t)))
-           {
-             tree target_context = decl_function_context (t);
-             struct nesting_info *i;
-             for (i = info->outer; i->context != target_context; i = i->outer)
-               continue;
-             x = lookup_field_for_decl (i, t, INSERT);
-             x = get_frame_field (info, target_context, x, &wi->gsi);
-             if (use_pointer_in_frame (t))
-               {
-                 x = init_tmp_var (info, x, &wi->gsi);
-                 x = build_simple_mem_ref (x);
-               }
-           }
+       if (info->context == target_context)
+         break;
 
-         if (wi->val_only)
-           {
-             if (wi->is_lhs)
-               x = save_tmp_var (info, x, &wi->gsi);
-             else
+       wi->changed = true;
+
+       if (bitmap_bit_p (info->suppress_expansion, DECL_UID (t)))
+         x = get_nonlocal_debug_decl (info, t);
+       else
+         {
+           struct nesting_info *i = info;
+           while (i && i->context != target_context)
+             i = i->outer;
+           /* If none of the outer contexts is the target context, this means
+              that the VAR or PARM_DECL is referenced in a wrong context.  */
+           if (!i)
+             internal_error ("%s from %s referenced in %s",
+                             IDENTIFIER_POINTER (DECL_NAME (t)),
+                             IDENTIFIER_POINTER (DECL_NAME (target_context)),
+                             IDENTIFIER_POINTER (DECL_NAME (info->context)));
+
+           x = lookup_field_for_decl (i, t, INSERT);
+           x = get_frame_field (info, target_context, x, &wi->gsi);
+           if (use_pointer_in_frame (t))
+             {
                x = init_tmp_var (info, x, &wi->gsi);
-           }
+               x = build_simple_mem_ref_notrap (x);
+             }
+         }
 
-         *tp = x;
-       }
+       if (wi->val_only)
+         {
+           if (wi->is_lhs)
+             x = save_tmp_var (info, x, &wi->gsi);
+           else
+             x = init_tmp_var (info, x, &wi->gsi);
+         }
+
+       *tp = x;
+      }
       break;
 
     case LABEL_DECL:
@@ -1051,7 +1185,7 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
 {
   struct nesting_info *const info = (struct nesting_info *) wi->info;
   bool need_chain = false, need_stmts = false;
-  tree clause, decl;
+  tree clause, decl, *pdecl;
   int dummy;
   bitmap new_suppress;
 
@@ -1060,11 +1194,23 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
 
   for (clause = *pclauses; clause ; clause = OMP_CLAUSE_CHAIN (clause))
     {
+      pdecl = NULL;
       switch (OMP_CLAUSE_CODE (clause))
        {
        case OMP_CLAUSE_REDUCTION:
+       case OMP_CLAUSE_IN_REDUCTION:
+       case OMP_CLAUSE_TASK_REDUCTION:
          if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause))
            need_stmts = true;
+         if (TREE_CODE (OMP_CLAUSE_DECL (clause)) == MEM_REF)
+           {
+             pdecl = &TREE_OPERAND (OMP_CLAUSE_DECL (clause), 0);
+             if (TREE_CODE (*pdecl) == POINTER_PLUS_EXPR)
+               pdecl = &TREE_OPERAND (*pdecl, 0);
+             if (TREE_CODE (*pdecl) == INDIRECT_REF
+                 || TREE_CODE (*pdecl) == ADDR_EXPR)
+               pdecl = &TREE_OPERAND (*pdecl, 0);
+           }
          goto do_decl_clause;
 
        case OMP_CLAUSE_LASTPRIVATE:
@@ -1072,19 +1218,37 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
            need_stmts = true;
          goto do_decl_clause;
 
+       case OMP_CLAUSE_LINEAR:
+         if (OMP_CLAUSE_LINEAR_GIMPLE_SEQ (clause))
+           need_stmts = true;
+         wi->val_only = true;
+         wi->is_lhs = false;
+         convert_nonlocal_reference_op (&OMP_CLAUSE_LINEAR_STEP (clause),
+                                        &dummy, wi);
+         goto do_decl_clause;
+
        case OMP_CLAUSE_PRIVATE:
        case OMP_CLAUSE_FIRSTPRIVATE:
        case OMP_CLAUSE_COPYPRIVATE:
        case OMP_CLAUSE_SHARED:
+       case OMP_CLAUSE_TO_DECLARE:
+       case OMP_CLAUSE_LINK:
+       case OMP_CLAUSE_USE_DEVICE_PTR:
+       case OMP_CLAUSE_USE_DEVICE_ADDR:
+       case OMP_CLAUSE_IS_DEVICE_PTR:
        do_decl_clause:
-         decl = OMP_CLAUSE_DECL (clause);
-         if (TREE_CODE (decl) == VAR_DECL
+         if (pdecl == NULL)
+           pdecl = &OMP_CLAUSE_DECL (clause);
+         decl = *pdecl;
+         if (VAR_P (decl)
              && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
            break;
          if (decl_function_context (decl) != info->context)
            {
+             if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_SHARED)
+               OMP_CLAUSE_SHARED_READONLY (clause) = 0;
              bitmap_set_bit (new_suppress, DECL_UID (decl));
-             OMP_CLAUSE_DECL (clause) = get_nonlocal_debug_decl (info, decl);
+             *pdecl = get_nonlocal_debug_decl (info, decl);
              if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_PRIVATE)
                need_chain = true;
            }
@@ -1097,10 +1261,93 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
        case OMP_CLAUSE_FINAL:
        case OMP_CLAUSE_IF:
        case OMP_CLAUSE_NUM_THREADS:
+       case OMP_CLAUSE_DEPEND:
+       case OMP_CLAUSE_DEVICE:
+       case OMP_CLAUSE_NUM_TEAMS:
+       case OMP_CLAUSE_THREAD_LIMIT:
+       case OMP_CLAUSE_SAFELEN:
+       case OMP_CLAUSE_SIMDLEN:
+       case OMP_CLAUSE_PRIORITY:
+       case OMP_CLAUSE_GRAINSIZE:
+       case OMP_CLAUSE_NUM_TASKS:
+       case OMP_CLAUSE_HINT:
+       case OMP_CLAUSE_NUM_GANGS:
+       case OMP_CLAUSE_NUM_WORKERS:
+       case OMP_CLAUSE_VECTOR_LENGTH:
+       case OMP_CLAUSE_GANG:
+       case OMP_CLAUSE_WORKER:
+       case OMP_CLAUSE_VECTOR:
+       case OMP_CLAUSE_ASYNC:
+       case OMP_CLAUSE_WAIT:
+         /* Several OpenACC clauses have optional arguments.  Check if they
+            are present.  */
+         if (OMP_CLAUSE_OPERAND (clause, 0))
+           {
+             wi->val_only = true;
+             wi->is_lhs = false;
+             convert_nonlocal_reference_op (&OMP_CLAUSE_OPERAND (clause, 0),
+                                            &dummy, wi);
+           }
+
+         /* The gang clause accepts two arguments.  */
+         if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_GANG
+             && OMP_CLAUSE_GANG_STATIC_EXPR (clause))
+           {
+               wi->val_only = true;
+               wi->is_lhs = false;
+               convert_nonlocal_reference_op
+                 (&OMP_CLAUSE_GANG_STATIC_EXPR (clause), &dummy, wi);
+           }
+         break;
+
+       case OMP_CLAUSE_DIST_SCHEDULE:
+         if (OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (clause) != NULL)
+           {
+             wi->val_only = true;
+             wi->is_lhs = false;
+             convert_nonlocal_reference_op (&OMP_CLAUSE_OPERAND (clause, 0),
+                                            &dummy, wi);
+           }
+         break;
+
+       case OMP_CLAUSE_MAP:
+       case OMP_CLAUSE_TO:
+       case OMP_CLAUSE_FROM:
+         if (OMP_CLAUSE_SIZE (clause))
+           {
+             wi->val_only = true;
+             wi->is_lhs = false;
+             convert_nonlocal_reference_op (&OMP_CLAUSE_SIZE (clause),
+                                            &dummy, wi);
+           }
+         if (DECL_P (OMP_CLAUSE_DECL (clause)))
+           goto do_decl_clause;
          wi->val_only = true;
          wi->is_lhs = false;
-         convert_nonlocal_reference_op (&OMP_CLAUSE_OPERAND (clause, 0),
-                                        &dummy, wi);
+         walk_tree (&OMP_CLAUSE_DECL (clause), convert_nonlocal_reference_op,
+                    wi, NULL);
+         break;
+
+       case OMP_CLAUSE_ALIGNED:
+         if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
+           {
+             wi->val_only = true;
+             wi->is_lhs = false;
+             convert_nonlocal_reference_op
+               (&OMP_CLAUSE_ALIGNED_ALIGNMENT (clause), &dummy, wi);
+           }
+         /* FALLTHRU */
+       case OMP_CLAUSE_NONTEMPORAL:
+         /* Like do_decl_clause, but don't add any suppression.  */
+         decl = OMP_CLAUSE_DECL (clause);
+         if (VAR_P (decl)
+             && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
+           break;
+         if (decl_function_context (decl) != info->context)
+           {
+             OMP_CLAUSE_DECL (clause) = get_nonlocal_debug_decl (info, decl);
+             need_chain = true;
+           }
          break;
 
        case OMP_CLAUSE_NOWAIT:
@@ -1108,10 +1355,47 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
        case OMP_CLAUSE_DEFAULT:
        case OMP_CLAUSE_COPYIN:
        case OMP_CLAUSE_COLLAPSE:
+       case OMP_CLAUSE_TILE:
        case OMP_CLAUSE_UNTIED:
        case OMP_CLAUSE_MERGEABLE:
+       case OMP_CLAUSE_PROC_BIND:
+       case OMP_CLAUSE_NOGROUP:
+       case OMP_CLAUSE_THREADS:
+       case OMP_CLAUSE_SIMD:
+       case OMP_CLAUSE_DEFAULTMAP:
+       case OMP_CLAUSE_ORDER:
+       case OMP_CLAUSE_SEQ:
+       case OMP_CLAUSE_INDEPENDENT:
+       case OMP_CLAUSE_AUTO:
+       case OMP_CLAUSE_IF_PRESENT:
+       case OMP_CLAUSE_FINALIZE:
+       case OMP_CLAUSE__CONDTEMP_:
+       case OMP_CLAUSE__SCANTEMP_:
          break;
 
+         /* The following clause belongs to the OpenACC cache directive, which
+            is discarded during gimplification.  */
+       case OMP_CLAUSE__CACHE_:
+         /* The following clauses are only allowed in the OpenMP declare simd
+            directive, so not seen here.  */
+       case OMP_CLAUSE_UNIFORM:
+       case OMP_CLAUSE_INBRANCH:
+       case OMP_CLAUSE_NOTINBRANCH:
+         /* The following clauses are only allowed on OpenMP cancel and
+            cancellation point directives, which at this point have already
+            been lowered into a function call.  */
+       case OMP_CLAUSE_FOR:
+       case OMP_CLAUSE_PARALLEL:
+       case OMP_CLAUSE_SECTIONS:
+       case OMP_CLAUSE_TASKGROUP:
+         /* The following clauses are only added during OMP lowering; nested
+            function decomposition happens before that.  */
+       case OMP_CLAUSE__LOOPTEMP_:
+       case OMP_CLAUSE__REDUCTEMP_:
+       case OMP_CLAUSE__SIMDUID_:
+       case OMP_CLAUSE__GRIDDIM_:
+       case OMP_CLAUSE__SIMT_:
+         /* Anything else.  */
        default:
          gcc_unreachable ();
        }
@@ -1124,12 +1408,17 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
       switch (OMP_CLAUSE_CODE (clause))
        {
        case OMP_CLAUSE_REDUCTION:
+       case OMP_CLAUSE_IN_REDUCTION:
+       case OMP_CLAUSE_TASK_REDUCTION:
          if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause))
            {
              tree old_context
                = DECL_CONTEXT (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause));
              DECL_CONTEXT (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause))
                = info->context;
+             if (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clause))
+               DECL_CONTEXT (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clause))
+                 = info->context;
              walk_body (convert_nonlocal_reference_stmt,
                         convert_nonlocal_reference_op, info,
                         &OMP_CLAUSE_REDUCTION_GIMPLE_INIT (clause));
@@ -1138,6 +1427,9 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
                         &OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (clause));
              DECL_CONTEXT (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause))
                = old_context;
+             if (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clause))
+               DECL_CONTEXT (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clause))
+                 = old_context;
            }
          break;
 
@@ -1147,6 +1439,12 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
                     &OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (clause));
          break;
 
+       case OMP_CLAUSE_LINEAR:
+         walk_body (convert_nonlocal_reference_stmt,
+                    convert_nonlocal_reference_op, info,
+                    &OMP_CLAUSE_LINEAR_GIMPLE_SEQ (clause));
+         break;
+
        default:
          break;
        }
@@ -1182,33 +1480,17 @@ note_nonlocal_vla_type (struct nesting_info *info, tree type)
       if (domain)
        {
          t = TYPE_MIN_VALUE (domain);
-         if (t && (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL)
+         if (t && (VAR_P (t) || TREE_CODE (t) == PARM_DECL)
              && decl_function_context (t) != info->context)
            get_nonlocal_debug_decl (info, t);
          t = TYPE_MAX_VALUE (domain);
-         if (t && (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL)
+         if (t && (VAR_P (t) || TREE_CODE (t) == PARM_DECL)
              && decl_function_context (t) != info->context)
            get_nonlocal_debug_decl (info, t);
        }
     }
 }
 
-/* Create nonlocal debug decls for nonlocal VLA array bounds for VLAs
-   in BLOCK.  */
-
-static void
-note_nonlocal_block_vlas (struct nesting_info *info, tree block)
-{
-  tree var;
-
-  for (var = BLOCK_VARS (block); var; var = DECL_CHAIN (var))
-    if (TREE_CODE (var) == VAR_DECL
-       && variably_modified_type_p (TREE_TYPE (var), NULL)
-       && DECL_HAS_VALUE_EXPR_P (var)
-       && decl_function_context (var) != info->context)
-      note_nonlocal_vla_type (info, TREE_TYPE (var));
-}
-
 /* Callback for walk_gimple_stmt.  Rewrite all references to VAR and
    PARM_DECLs that belong to outer functions.  This handles statements
    that are not handled via the standard recursion done in
@@ -1223,7 +1505,7 @@ convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
   struct nesting_info *info = (struct nesting_info *) wi->info;
   tree save_local_var_chain;
   bitmap save_suppress;
-  gimple stmt = gsi_stmt (*gsi);
+  gimple *stmt = gsi_stmt (*gsi);
 
   switch (gimple_code (stmt))
     {
@@ -1233,11 +1515,25 @@ convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
        {
          wi->val_only = true;
          wi->is_lhs = false;
-         *handled_ops_p = true;
+         *handled_ops_p = false;
          return NULL_TREE;
        }
       break;
 
+    case GIMPLE_OMP_TEAMS:
+      if (!gimple_omp_teams_host (as_a <gomp_teams *> (stmt)))
+       {
+         save_suppress = info->suppress_expansion;
+         convert_nonlocal_omp_clauses (gimple_omp_teams_clauses_ptr (stmt),
+                                       wi);
+         walk_body (convert_nonlocal_reference_stmt,
+                    convert_nonlocal_reference_op, info,
+                    gimple_omp_body_ptr (stmt));
+         info->suppress_expansion = save_suppress;
+         break;
+       }
+      /* FALLTHRU */
+
     case GIMPLE_OMP_PARALLEL:
     case GIMPLE_OMP_TASK:
       save_suppress = info->suppress_expansion;
@@ -1270,7 +1566,8 @@ convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
     case GIMPLE_OMP_FOR:
       save_suppress = info->suppress_expansion;
       convert_nonlocal_omp_clauses (gimple_omp_for_clauses_ptr (stmt), wi);
-      walk_gimple_omp_for (stmt, convert_nonlocal_reference_stmt,
+      walk_gimple_omp_for (as_a <gomp_for *> (stmt),
+                          convert_nonlocal_reference_stmt,
                           convert_nonlocal_reference_op, info);
       walk_body (convert_nonlocal_reference_stmt,
                 convert_nonlocal_reference_op, info, gimple_omp_body_ptr (stmt));
@@ -1293,43 +1590,109 @@ convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       info->suppress_expansion = save_suppress;
       break;
 
-    case GIMPLE_OMP_TARGET:
+    case GIMPLE_OMP_TASKGROUP:
       save_suppress = info->suppress_expansion;
-      convert_nonlocal_omp_clauses (gimple_omp_target_clauses_ptr (stmt), wi);
+      convert_nonlocal_omp_clauses (gimple_omp_taskgroup_clauses_ptr (stmt), wi);
       walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
                 info, gimple_omp_body_ptr (stmt));
       info->suppress_expansion = save_suppress;
       break;
 
-    case GIMPLE_OMP_TEAMS:
+    case GIMPLE_OMP_TARGET:
+      if (!is_gimple_omp_offloaded (stmt))
+       {
+         save_suppress = info->suppress_expansion;
+         convert_nonlocal_omp_clauses (gimple_omp_target_clauses_ptr (stmt),
+                                       wi);
+         info->suppress_expansion = save_suppress;
+         walk_body (convert_nonlocal_reference_stmt,
+                    convert_nonlocal_reference_op, info,
+                    gimple_omp_body_ptr (stmt));
+         break;
+       }
       save_suppress = info->suppress_expansion;
-      convert_nonlocal_omp_clauses (gimple_omp_teams_clauses_ptr (stmt), wi);
+      if (convert_nonlocal_omp_clauses (gimple_omp_target_clauses_ptr (stmt),
+                                       wi))
+       {
+         tree c, decl;
+         decl = get_chain_decl (info);
+         c = build_omp_clause (gimple_location (stmt), OMP_CLAUSE_MAP);
+         OMP_CLAUSE_DECL (c) = decl;
+         OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TO);
+         OMP_CLAUSE_SIZE (c) = DECL_SIZE_UNIT (decl);
+         OMP_CLAUSE_CHAIN (c) = gimple_omp_target_clauses (stmt);
+         gimple_omp_target_set_clauses (as_a <gomp_target *> (stmt), c);
+       }
+
+      save_local_var_chain = info->new_local_var_chain;
+      info->new_local_var_chain = NULL;
+
       walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
                 info, gimple_omp_body_ptr (stmt));
+
+      if (info->new_local_var_chain)
+       declare_vars (info->new_local_var_chain,
+                     gimple_seq_first_stmt (gimple_omp_body (stmt)),
+                     false);
+      info->new_local_var_chain = save_local_var_chain;
       info->suppress_expansion = save_suppress;
       break;
 
     case GIMPLE_OMP_SECTION:
     case GIMPLE_OMP_MASTER:
-    case GIMPLE_OMP_TASKGROUP:
     case GIMPLE_OMP_ORDERED:
+    case GIMPLE_OMP_SCAN:
       walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
                 info, gimple_omp_body_ptr (stmt));
       break;
 
     case GIMPLE_BIND:
-      if (!optimize && gimple_bind_block (stmt))
-       note_nonlocal_block_vlas (info, gimple_bind_block (stmt));
+      {
+      gbind *bind_stmt = as_a <gbind *> (stmt);
+
+      for (tree var = gimple_bind_vars (bind_stmt); var; var = DECL_CHAIN (var))
+       if (TREE_CODE (var) == NAMELIST_DECL)
+         {
+           /* Adjust decls mentioned in NAMELIST_DECL.  */
+           tree decls = NAMELIST_DECL_ASSOCIATED_DECL (var);
+           tree decl;
+           unsigned int i;
+
+           FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (decls), i, decl)
+             {
+               if (VAR_P (decl)
+                   && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
+                 continue;
+               if (decl_function_context (decl) != info->context)
+                 CONSTRUCTOR_ELT (decls, i)->value
+                   = get_nonlocal_debug_decl (info, decl);
+             }
+         }
 
       *handled_ops_p = false;
       return NULL_TREE;
-
+      }
     case GIMPLE_COND:
       wi->val_only = true;
       wi->is_lhs = false;
       *handled_ops_p = false;
       return NULL_TREE;
 
+    case GIMPLE_ASSIGN:
+      if (gimple_clobber_p (stmt))
+       {
+         tree lhs = gimple_assign_lhs (stmt);
+         if (DECL_P (lhs)
+             && !(TREE_STATIC (lhs) || DECL_EXTERNAL (lhs))
+             && decl_function_context (lhs) != info->context)
+           {
+             gsi_replace (gsi, gimple_build_nop (), true);
+             break;
+           }
+       }
+      *handled_ops_p = false;
+      return NULL_TREE;
+
     default:
       /* For every other statement that we are not interested in
         handling here, let the walker traverse the operands.  */
@@ -1345,18 +1708,17 @@ convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
 
 /* A subroutine of convert_local_reference.  Create a local variable
    in the parent function with DECL_VALUE_EXPR set to reference the
-   field in FRAME.  This is used both for debug info and in OpenMP
+   field in FRAME.  This is used both for debug info and in OMP
    lowering.  */
 
 static tree
 get_local_debug_decl (struct nesting_info *info, tree decl, tree field)
 {
   tree x, new_decl;
-  void **slot;
 
-  slot = pointer_map_insert (info->var_map, decl);
+  tree *slot = &info->var_map->get_or_insert (decl);
   if (*slot)
-    return (tree) *slot;
+    return *slot;
 
   /* Make sure frame_decl gets created.  */
   (void) get_frame_type (info);
@@ -1375,7 +1737,7 @@ get_local_debug_decl (struct nesting_info *info, tree decl, tree field)
   DECL_SEEN_IN_BIND_EXPR_P (new_decl) = 1;
   if ((TREE_CODE (decl) == PARM_DECL
        || TREE_CODE (decl) == RESULT_DECL
-       || TREE_CODE (decl) == VAR_DECL)
+       || VAR_P (decl))
       && DECL_BY_REFERENCE (decl))
     DECL_BY_REFERENCE (new_decl) = 1;
 
@@ -1417,7 +1779,7 @@ convert_local_reference_op (tree *tp, int *walk_subtrees, void *data)
       /* FALLTHRU */
 
     case PARM_DECL:
-      if (decl_function_context (t) == info->context)
+      if (t != info->frame_decl && decl_function_context (t) == info->context)
        {
          /* If we copied a pointer to the frame, then the original decl
             is used unchanged in the parent function.  */
@@ -1431,8 +1793,9 @@ convert_local_reference_op (tree *tp, int *walk_subtrees, void *data)
            break;
          wi->changed = true;
 
-         x = get_local_debug_decl (info, t, field);
-         if (!bitmap_bit_p (info->suppress_expansion, DECL_UID (t)))
+         if (bitmap_bit_p (info->suppress_expansion, DECL_UID (t)))
+           x = get_local_debug_decl (info, t, field);
+         else
            x = get_frame_field (info, info->context, field, &wi->gsi);
 
          if (wi->val_only)
@@ -1520,7 +1883,7 @@ convert_local_reference_op (tree *tp, int *walk_subtrees, void *data)
         fold here, as the chain record type is not yet finalized.  */
       if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR
          && !DECL_P (TREE_OPERAND (TREE_OPERAND (t, 0), 0)))
-       pointer_set_insert (info->mem_refs, tp);
+       info->mem_refs->add (tp);
       wi->val_only = save_val_only;
       break;
 
@@ -1555,7 +1918,7 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
 {
   struct nesting_info *const info = (struct nesting_info *) wi->info;
   bool need_frame = false, need_stmts = false;
-  tree clause, decl;
+  tree clause, decl, *pdecl;
   int dummy;
   bitmap new_suppress;
 
@@ -1564,11 +1927,23 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
 
   for (clause = *pclauses; clause ; clause = OMP_CLAUSE_CHAIN (clause))
     {
+      pdecl = NULL;
       switch (OMP_CLAUSE_CODE (clause))
        {
        case OMP_CLAUSE_REDUCTION:
+       case OMP_CLAUSE_IN_REDUCTION:
+       case OMP_CLAUSE_TASK_REDUCTION:
          if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause))
            need_stmts = true;
+         if (TREE_CODE (OMP_CLAUSE_DECL (clause)) == MEM_REF)
+           {
+             pdecl = &TREE_OPERAND (OMP_CLAUSE_DECL (clause), 0);
+             if (TREE_CODE (*pdecl) == POINTER_PLUS_EXPR)
+               pdecl = &TREE_OPERAND (*pdecl, 0);
+             if (TREE_CODE (*pdecl) == INDIRECT_REF
+                 || TREE_CODE (*pdecl) == ADDR_EXPR)
+               pdecl = &TREE_OPERAND (*pdecl, 0);
+           }
          goto do_decl_clause;
 
        case OMP_CLAUSE_LASTPRIVATE:
@@ -1576,13 +1951,29 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
            need_stmts = true;
          goto do_decl_clause;
 
+       case OMP_CLAUSE_LINEAR:
+         if (OMP_CLAUSE_LINEAR_GIMPLE_SEQ (clause))
+           need_stmts = true;
+         wi->val_only = true;
+         wi->is_lhs = false;
+         convert_local_reference_op (&OMP_CLAUSE_LINEAR_STEP (clause), &dummy,
+                                     wi);
+         goto do_decl_clause;
+
        case OMP_CLAUSE_PRIVATE:
        case OMP_CLAUSE_FIRSTPRIVATE:
        case OMP_CLAUSE_COPYPRIVATE:
        case OMP_CLAUSE_SHARED:
+       case OMP_CLAUSE_TO_DECLARE:
+       case OMP_CLAUSE_LINK:
+       case OMP_CLAUSE_USE_DEVICE_PTR:
+       case OMP_CLAUSE_USE_DEVICE_ADDR:
+       case OMP_CLAUSE_IS_DEVICE_PTR:
        do_decl_clause:
-         decl = OMP_CLAUSE_DECL (clause);
-         if (TREE_CODE (decl) == VAR_DECL
+         if (pdecl == NULL)
+           pdecl = &OMP_CLAUSE_DECL (clause);
+         decl = *pdecl;
+         if (VAR_P (decl)
              && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
            break;
          if (decl_function_context (decl) == info->context
@@ -1591,9 +1982,10 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
              tree field = lookup_field_for_decl (info, decl, NO_INSERT);
              if (field)
                {
+                 if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_SHARED)
+                   OMP_CLAUSE_SHARED_READONLY (clause) = 0;
                  bitmap_set_bit (new_suppress, DECL_UID (decl));
-                 OMP_CLAUSE_DECL (clause)
-                   = get_local_debug_decl (info, decl, field);
+                 *pdecl = get_local_debug_decl (info, decl, field);
                  need_frame = true;
                }
            }
@@ -1606,10 +1998,99 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
        case OMP_CLAUSE_FINAL:
        case OMP_CLAUSE_IF:
        case OMP_CLAUSE_NUM_THREADS:
+       case OMP_CLAUSE_DEPEND:
+       case OMP_CLAUSE_DEVICE:
+       case OMP_CLAUSE_NUM_TEAMS:
+       case OMP_CLAUSE_THREAD_LIMIT:
+       case OMP_CLAUSE_SAFELEN:
+       case OMP_CLAUSE_SIMDLEN:
+       case OMP_CLAUSE_PRIORITY:
+       case OMP_CLAUSE_GRAINSIZE:
+       case OMP_CLAUSE_NUM_TASKS:
+       case OMP_CLAUSE_HINT:
+       case OMP_CLAUSE_NUM_GANGS:
+       case OMP_CLAUSE_NUM_WORKERS:
+       case OMP_CLAUSE_VECTOR_LENGTH:
+       case OMP_CLAUSE_GANG:
+       case OMP_CLAUSE_WORKER:
+       case OMP_CLAUSE_VECTOR:
+       case OMP_CLAUSE_ASYNC:
+       case OMP_CLAUSE_WAIT:
+         /* Several OpenACC clauses have optional arguments.  Check if they
+            are present.  */
+         if (OMP_CLAUSE_OPERAND (clause, 0))
+           {
+             wi->val_only = true;
+             wi->is_lhs = false;
+             convert_local_reference_op (&OMP_CLAUSE_OPERAND (clause, 0),
+                                         &dummy, wi);
+           }
+
+         /* The gang clause accepts two arguments.  */
+         if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_GANG
+             && OMP_CLAUSE_GANG_STATIC_EXPR (clause))
+           {
+               wi->val_only = true;
+               wi->is_lhs = false;
+               convert_nonlocal_reference_op
+                 (&OMP_CLAUSE_GANG_STATIC_EXPR (clause), &dummy, wi);
+           }
+         break;
+
+       case OMP_CLAUSE_DIST_SCHEDULE:
+         if (OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (clause) != NULL)
+           {
+             wi->val_only = true;
+             wi->is_lhs = false;
+             convert_local_reference_op (&OMP_CLAUSE_OPERAND (clause, 0),
+                                         &dummy, wi);
+           }
+         break;
+
+       case OMP_CLAUSE_MAP:
+       case OMP_CLAUSE_TO:
+       case OMP_CLAUSE_FROM:
+         if (OMP_CLAUSE_SIZE (clause))
+           {
+             wi->val_only = true;
+             wi->is_lhs = false;
+             convert_local_reference_op (&OMP_CLAUSE_SIZE (clause),
+                                         &dummy, wi);
+           }
+         if (DECL_P (OMP_CLAUSE_DECL (clause)))
+           goto do_decl_clause;
          wi->val_only = true;
          wi->is_lhs = false;
-         convert_local_reference_op (&OMP_CLAUSE_OPERAND (clause, 0), &dummy,
-                                     wi);
+         walk_tree (&OMP_CLAUSE_DECL (clause), convert_local_reference_op,
+                    wi, NULL);
+         break;
+
+       case OMP_CLAUSE_ALIGNED:
+         if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
+           {
+             wi->val_only = true;
+             wi->is_lhs = false;
+             convert_local_reference_op
+               (&OMP_CLAUSE_ALIGNED_ALIGNMENT (clause), &dummy, wi);
+           }
+         /* FALLTHRU */
+       case OMP_CLAUSE_NONTEMPORAL:
+         /* Like do_decl_clause, but don't add any suppression.  */
+         decl = OMP_CLAUSE_DECL (clause);
+         if (VAR_P (decl)
+             && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
+           break;
+         if (decl_function_context (decl) == info->context
+             && !use_pointer_in_frame (decl))
+           {
+             tree field = lookup_field_for_decl (info, decl, NO_INSERT);
+             if (field)
+               {
+                 OMP_CLAUSE_DECL (clause)
+                   = get_local_debug_decl (info, decl, field);
+                 need_frame = true;
+               }
+           }
          break;
 
        case OMP_CLAUSE_NOWAIT:
@@ -1617,10 +2098,47 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
        case OMP_CLAUSE_DEFAULT:
        case OMP_CLAUSE_COPYIN:
        case OMP_CLAUSE_COLLAPSE:
+       case OMP_CLAUSE_TILE:
        case OMP_CLAUSE_UNTIED:
        case OMP_CLAUSE_MERGEABLE:
+       case OMP_CLAUSE_PROC_BIND:
+       case OMP_CLAUSE_NOGROUP:
+       case OMP_CLAUSE_THREADS:
+       case OMP_CLAUSE_SIMD:
+       case OMP_CLAUSE_DEFAULTMAP:
+       case OMP_CLAUSE_ORDER:
+       case OMP_CLAUSE_SEQ:
+       case OMP_CLAUSE_INDEPENDENT:
+       case OMP_CLAUSE_AUTO:
+       case OMP_CLAUSE_IF_PRESENT:
+       case OMP_CLAUSE_FINALIZE:
+       case OMP_CLAUSE__CONDTEMP_:
+       case OMP_CLAUSE__SCANTEMP_:
          break;
 
+         /* The following clause belongs to the OpenACC cache directive, which
+            is discarded during gimplification.  */
+       case OMP_CLAUSE__CACHE_:
+         /* The following clauses are only allowed in the OpenMP declare simd
+            directive, so not seen here.  */
+       case OMP_CLAUSE_UNIFORM:
+       case OMP_CLAUSE_INBRANCH:
+       case OMP_CLAUSE_NOTINBRANCH:
+         /* The following clauses are only allowed on OpenMP cancel and
+            cancellation point directives, which at this point have already
+            been lowered into a function call.  */
+       case OMP_CLAUSE_FOR:
+       case OMP_CLAUSE_PARALLEL:
+       case OMP_CLAUSE_SECTIONS:
+       case OMP_CLAUSE_TASKGROUP:
+         /* The following clauses are only added during OMP lowering; nested
+            function decomposition happens before that.  */
+       case OMP_CLAUSE__LOOPTEMP_:
+       case OMP_CLAUSE__REDUCTEMP_:
+       case OMP_CLAUSE__SIMDUID_:
+       case OMP_CLAUSE__GRIDDIM_:
+       case OMP_CLAUSE__SIMT_:
+         /* Anything else.  */
        default:
          gcc_unreachable ();
        }
@@ -1633,12 +2151,17 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
       switch (OMP_CLAUSE_CODE (clause))
        {
        case OMP_CLAUSE_REDUCTION:
+       case OMP_CLAUSE_IN_REDUCTION:
+       case OMP_CLAUSE_TASK_REDUCTION:
          if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause))
            {
              tree old_context
                = DECL_CONTEXT (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause));
              DECL_CONTEXT (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause))
                = info->context;
+             if (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clause))
+               DECL_CONTEXT (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clause))
+                 = info->context;
              walk_body (convert_local_reference_stmt,
                         convert_local_reference_op, info,
                         &OMP_CLAUSE_REDUCTION_GIMPLE_INIT (clause));
@@ -1647,6 +2170,9 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
                         &OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (clause));
              DECL_CONTEXT (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause))
                = old_context;
+             if (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clause))
+               DECL_CONTEXT (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clause))
+                 = old_context;
            }
          break;
 
@@ -1656,6 +2182,12 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
                     &OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (clause));
          break;
 
+       case OMP_CLAUSE_LINEAR:
+         walk_body (convert_local_reference_stmt,
+                    convert_local_reference_op, info,
+                    &OMP_CLAUSE_LINEAR_GIMPLE_SEQ (clause));
+         break;
+
        default:
          break;
        }
@@ -1675,42 +2207,72 @@ convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
   struct nesting_info *info = (struct nesting_info *) wi->info;
   tree save_local_var_chain;
   bitmap save_suppress;
-  gimple stmt = gsi_stmt (*gsi);
+  char save_static_chain_added;
+  bool frame_decl_added;
+  gimple *stmt = gsi_stmt (*gsi);
 
   switch (gimple_code (stmt))
     {
+    case GIMPLE_OMP_TEAMS:
+      if (!gimple_omp_teams_host (as_a <gomp_teams *> (stmt)))
+       {
+         save_suppress = info->suppress_expansion;
+         convert_local_omp_clauses (gimple_omp_teams_clauses_ptr (stmt), wi);
+         walk_body (convert_local_reference_stmt, convert_local_reference_op,
+                    info, gimple_omp_body_ptr (stmt));
+         info->suppress_expansion = save_suppress;
+         break;
+       }
+      /* FALLTHRU */
+
     case GIMPLE_OMP_PARALLEL:
     case GIMPLE_OMP_TASK:
       save_suppress = info->suppress_expansion;
+      frame_decl_added = false;
       if (convert_local_omp_clauses (gimple_omp_taskreg_clauses_ptr (stmt),
                                     wi))
        {
-         tree c;
+         tree c = build_omp_clause (gimple_location (stmt),
+                                    OMP_CLAUSE_SHARED);
          (void) get_frame_type (info);
-         c = build_omp_clause (gimple_location (stmt),
-                               OMP_CLAUSE_SHARED);
          OMP_CLAUSE_DECL (c) = info->frame_decl;
          OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
          gimple_omp_taskreg_set_clauses (stmt, c);
+         info->static_chain_added |= 4;
+         frame_decl_added = true;
        }
 
       save_local_var_chain = info->new_local_var_chain;
+      save_static_chain_added = info->static_chain_added;
       info->new_local_var_chain = NULL;
+      info->static_chain_added = 0;
 
       walk_body (convert_local_reference_stmt, convert_local_reference_op, info,
                 gimple_omp_body_ptr (stmt));
 
+      if ((info->static_chain_added & 4) != 0 && !frame_decl_added)
+       {
+         tree c = build_omp_clause (gimple_location (stmt),
+                                    OMP_CLAUSE_SHARED);
+         (void) get_frame_type (info);
+         OMP_CLAUSE_DECL (c) = info->frame_decl;
+         OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
+         info->static_chain_added |= 4;
+         gimple_omp_taskreg_set_clauses (stmt, c);
+       }
       if (info->new_local_var_chain)
        declare_vars (info->new_local_var_chain,
                      gimple_seq_first_stmt (gimple_omp_body (stmt)), false);
       info->new_local_var_chain = save_local_var_chain;
       info->suppress_expansion = save_suppress;
+      info->static_chain_added |= save_static_chain_added;
       break;
 
     case GIMPLE_OMP_FOR:
       save_suppress = info->suppress_expansion;
       convert_local_omp_clauses (gimple_omp_for_clauses_ptr (stmt), wi);
-      walk_gimple_omp_for (stmt, convert_local_reference_stmt,
+      walk_gimple_omp_for (as_a <gomp_for *> (stmt),
+                          convert_local_reference_stmt,
                           convert_local_reference_op, info);
       walk_body (convert_local_reference_stmt, convert_local_reference_op,
                 info, gimple_omp_body_ptr (stmt));
@@ -1733,26 +2295,71 @@ convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       info->suppress_expansion = save_suppress;
       break;
 
-    case GIMPLE_OMP_TARGET:
+    case GIMPLE_OMP_TASKGROUP:
       save_suppress = info->suppress_expansion;
-      convert_local_omp_clauses (gimple_omp_target_clauses_ptr (stmt), wi);
+      convert_local_omp_clauses (gimple_omp_taskgroup_clauses_ptr (stmt), wi);
       walk_body (convert_local_reference_stmt, convert_local_reference_op,
                 info, gimple_omp_body_ptr (stmt));
       info->suppress_expansion = save_suppress;
       break;
 
-    case GIMPLE_OMP_TEAMS:
+    case GIMPLE_OMP_TARGET:
+      if (!is_gimple_omp_offloaded (stmt))
+       {
+         save_suppress = info->suppress_expansion;
+         convert_local_omp_clauses (gimple_omp_target_clauses_ptr (stmt), wi);
+         info->suppress_expansion = save_suppress;
+         walk_body (convert_local_reference_stmt, convert_local_reference_op,
+                    info, gimple_omp_body_ptr (stmt));
+         break;
+       }
       save_suppress = info->suppress_expansion;
-      convert_local_omp_clauses (gimple_omp_teams_clauses_ptr (stmt), wi);
-      walk_body (convert_local_reference_stmt, convert_local_reference_op,
-                info, gimple_omp_body_ptr (stmt));
+      frame_decl_added = false;
+      if (convert_local_omp_clauses (gimple_omp_target_clauses_ptr (stmt), wi))
+       {
+         tree c = build_omp_clause (gimple_location (stmt), OMP_CLAUSE_MAP);
+         (void) get_frame_type (info);
+         OMP_CLAUSE_DECL (c) = info->frame_decl;
+         OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TOFROM);
+         OMP_CLAUSE_SIZE (c) = DECL_SIZE_UNIT (info->frame_decl);
+         OMP_CLAUSE_CHAIN (c) = gimple_omp_target_clauses (stmt);
+         gimple_omp_target_set_clauses (as_a <gomp_target *> (stmt), c);
+         info->static_chain_added |= 4;
+         frame_decl_added = true;
+       }
+
+      save_local_var_chain = info->new_local_var_chain;
+      save_static_chain_added = info->static_chain_added;
+      info->new_local_var_chain = NULL;
+      info->static_chain_added = 0;
+
+      walk_body (convert_local_reference_stmt, convert_local_reference_op, info,
+                gimple_omp_body_ptr (stmt));
+
+      if ((info->static_chain_added & 4) != 0 && !frame_decl_added)
+       {
+         tree c = build_omp_clause (gimple_location (stmt), OMP_CLAUSE_MAP);
+         (void) get_frame_type (info);
+         OMP_CLAUSE_DECL (c) = info->frame_decl;
+         OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TOFROM);
+         OMP_CLAUSE_SIZE (c) = DECL_SIZE_UNIT (info->frame_decl);
+         OMP_CLAUSE_CHAIN (c) = gimple_omp_target_clauses (stmt);
+         gimple_omp_target_set_clauses (as_a <gomp_target *> (stmt), c);
+         info->static_chain_added |= 4;
+       }
+
+      if (info->new_local_var_chain)
+       declare_vars (info->new_local_var_chain,
+                     gimple_seq_first_stmt (gimple_omp_body (stmt)), false);
+      info->new_local_var_chain = save_local_var_chain;
       info->suppress_expansion = save_suppress;
+      info->static_chain_added |= save_static_chain_added;
       break;
 
     case GIMPLE_OMP_SECTION:
     case GIMPLE_OMP_MASTER:
-    case GIMPLE_OMP_TASKGROUP:
     case GIMPLE_OMP_ORDERED:
+    case GIMPLE_OMP_SCAN:
       walk_body (convert_local_reference_stmt, convert_local_reference_op,
                 info, gimple_omp_body_ptr (stmt));
       break;
@@ -1767,7 +2374,8 @@ convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       if (gimple_clobber_p (stmt))
        {
          tree lhs = gimple_assign_lhs (stmt);
-         if (!use_pointer_in_frame (lhs)
+         if (DECL_P (lhs)
+             && !use_pointer_in_frame (lhs)
              && lookup_field_for_decl (info, lhs, NO_INSERT))
            {
              gsi_replace (gsi, gimple_build_nop (), true);
@@ -1777,6 +2385,38 @@ convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       *handled_ops_p = false;
       return NULL_TREE;
 
+    case GIMPLE_BIND:
+      for (tree var = gimple_bind_vars (as_a <gbind *> (stmt));
+          var;
+          var = DECL_CHAIN (var))
+       if (TREE_CODE (var) == NAMELIST_DECL)
+         {
+           /* Adjust decls mentioned in NAMELIST_DECL.  */
+           tree decls = NAMELIST_DECL_ASSOCIATED_DECL (var);
+           tree decl;
+           unsigned int i;
+
+           FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (decls), i, decl)
+             {
+               if (VAR_P (decl)
+                   && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
+                 continue;
+               if (decl_function_context (decl) == info->context
+                   && !use_pointer_in_frame (decl))
+                 {
+                   tree field = lookup_field_for_decl (info, decl, NO_INSERT);
+                   if (field)
+                     {
+                       CONSTRUCTOR_ELT (decls, i)->value
+                         = get_local_debug_decl (info, decl, field);
+                     }
+                 }
+             }
+         }
+
+      *handled_ops_p = false;
+      return NULL_TREE;
+
     default:
       /* For every other statement that we are not interested in
         handling here, let the walker traverse the operands.  */
@@ -1800,9 +2440,8 @@ convert_nl_goto_reference (gimple_stmt_iterator *gsi, bool *handled_ops_p,
 {
   struct nesting_info *const info = (struct nesting_info *) wi->info, *i;
   tree label, new_label, target_context, x, field;
-  void **slot;
-  gimple call;
-  gimple stmt = gsi_stmt (*gsi);
+  gcall *call;
+  gimple *stmt = gsi_stmt (*gsi);
 
   if (gimple_code (stmt) != GIMPLE_GOTO)
     {
@@ -1834,7 +2473,7 @@ convert_nl_goto_reference (gimple_stmt_iterator *gsi, bool *handled_ops_p,
      (hairy target-specific) non-local goto receiver code to be generated
      when we expand rtl.  Enter this association into var_map so that we
      can insert the new label into the IL during a second pass.  */
-  slot = pointer_map_insert (i->var_map, label);
+  tree *slot = &i->var_map->get_or_insert (label);
   if (*slot == NULL)
     {
       new_label = create_artificial_label (UNKNOWN_LOCATION);
@@ -1842,15 +2481,15 @@ convert_nl_goto_reference (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       *slot = new_label;
     }
   else
-    new_label = (tree) *slot;
+    new_label = *slot;
 
   /* Build: __builtin_nl_goto(new_label, &chain->nl_goto_field).  */
   field = get_nl_goto_field (i);
   x = get_frame_field (info, target_context, field, gsi);
-  x = build_addr (x, target_context);
+  x = build_addr (x);
   x = gsi_gimplify_val (info, x, gsi);
   call = gimple_build_call (builtin_decl_implicit (BUILT_IN_NONLOCAL_GOTO),
-                           2, build_addr (new_label, target_context), x);
+                           2, build_addr (new_label), x);
   gsi_replace (gsi, call, false);
 
   /* We have handled all of STMT's operands, no need to keep going.  */
@@ -1872,10 +2511,9 @@ convert_nl_goto_receiver (gimple_stmt_iterator *gsi, bool *handled_ops_p,
   struct nesting_info *const info = (struct nesting_info *) wi->info;
   tree label, new_label;
   gimple_stmt_iterator tmp_gsi;
-  void **slot;
-  gimple stmt = gsi_stmt (*gsi);
+  glabel *stmt = dyn_cast <glabel *> (gsi_stmt (*gsi));
 
-  if (gimple_code (stmt) != GIMPLE_LABEL)
+  if (!stmt)
     {
       *handled_ops_p = false;
       return NULL_TREE;
@@ -1883,7 +2521,7 @@ convert_nl_goto_receiver (gimple_stmt_iterator *gsi, bool *handled_ops_p,
 
   label = gimple_label_label (stmt);
 
-  slot = pointer_map_contains (info->var_map, label);
+  tree *slot = info->var_map->get (label);
   if (!slot)
     {
       *handled_ops_p = false;
@@ -1896,7 +2534,7 @@ convert_nl_goto_receiver (gimple_stmt_iterator *gsi, bool *handled_ops_p,
   gsi_prev (&tmp_gsi);
   if (gsi_end_p (tmp_gsi) || gimple_stmt_may_fallthru (gsi_stmt (tmp_gsi)))
     {
-      gimple stmt = gimple_build_goto (label);
+      gimple *stmt = gimple_build_goto (label);
       gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
     }
 
@@ -1919,7 +2557,8 @@ convert_tramp_reference_op (tree *tp, int *walk_subtrees, void *data)
   struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
   struct nesting_info *const info = (struct nesting_info *) wi->info, *i;
   tree t = *tp, decl, target_context, x, builtin;
-  gimple call;
+  bool descr;
+  gcall *call;
 
   *walk_subtrees = 0;
   switch (TREE_CODE (t))
@@ -1953,16 +2592,26 @@ convert_tramp_reference_op (tree *tp, int *walk_subtrees, void *data)
         we need to insert the trampoline.  */
       for (i = info; i->context != target_context; i = i->outer)
        continue;
-      x = lookup_tramp_for_decl (i, decl, INSERT);
+
+      /* Decide whether to generate a descriptor or a trampoline. */
+      descr = FUNC_ADDR_BY_DESCRIPTOR (t) && !flag_trampolines;
+
+      if (descr)
+       x = lookup_descr_for_decl (i, decl, INSERT);
+      else
+       x = lookup_tramp_for_decl (i, decl, INSERT);
 
       /* Compute the address of the field holding the trampoline.  */
       x = get_frame_field (info, target_context, x, &wi->gsi);
-      x = build_addr (x, target_context);
+      x = build_addr (x);
       x = gsi_gimplify_val (info, x, &wi->gsi);
 
       /* Do machine-specific ugliness.  Normally this will involve
         computing extra alignment, but it can really be anything.  */
-      builtin = builtin_decl_implicit (BUILT_IN_ADJUST_TRAMPOLINE);
+      if (descr)
+       builtin = builtin_decl_implicit (BUILT_IN_ADJUST_DESCRIPTOR);
+      else
+       builtin = builtin_decl_implicit (BUILT_IN_ADJUST_TRAMPOLINE);
       call = gimple_build_call (builtin, 1, x);
       x = init_tmp_var_with_call (info, &wi->gsi, call);
 
@@ -1993,7 +2642,7 @@ convert_tramp_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
                              struct walk_stmt_info *wi)
 {
   struct nesting_info *info = (struct nesting_info *) wi->info;
-  gimple stmt = gsi_stmt (*gsi);
+  gimple *stmt = gsi_stmt (*gsi);
 
   switch (gimple_code (stmt))
     {
@@ -2008,27 +2657,80 @@ convert_tramp_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
        break;
       }
 
+    case GIMPLE_OMP_TEAMS:
+      if (!gimple_omp_teams_host (as_a <gomp_teams *> (stmt)))
+       {
+         *handled_ops_p = false;
+         return NULL_TREE;
+       }
+      goto do_parallel;
+
+    case GIMPLE_OMP_TARGET:
+      if (!is_gimple_omp_offloaded (stmt))
+       {
+         *handled_ops_p = false;
+         return NULL_TREE;
+       }
+      /* FALLTHRU */
     case GIMPLE_OMP_PARALLEL:
     case GIMPLE_OMP_TASK:
+    do_parallel:
       {
-       tree save_local_var_chain;
+       tree save_local_var_chain = info->new_local_var_chain;
         walk_gimple_op (stmt, convert_tramp_reference_op, wi);
-       save_local_var_chain = info->new_local_var_chain;
        info->new_local_var_chain = NULL;
+       char save_static_chain_added = info->static_chain_added;
+       info->static_chain_added = 0;
         walk_body (convert_tramp_reference_stmt, convert_tramp_reference_op,
                   info, gimple_omp_body_ptr (stmt));
        if (info->new_local_var_chain)
          declare_vars (info->new_local_var_chain,
                        gimple_seq_first_stmt (gimple_omp_body (stmt)),
                        false);
+       for (int i = 0; i < 2; i++)
+         {
+           tree c, decl;
+           if ((info->static_chain_added & (1 << i)) == 0)
+             continue;
+           decl = i ? get_chain_decl (info) : info->frame_decl;
+           /* Don't add CHAIN.* or FRAME.* twice.  */
+           for (c = gimple_omp_taskreg_clauses (stmt);
+                c;
+                c = OMP_CLAUSE_CHAIN (c))
+             if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
+                  || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
+                 && OMP_CLAUSE_DECL (c) == decl)
+               break;
+           if (c == NULL && gimple_code (stmt) != GIMPLE_OMP_TARGET)
+             {
+               c = build_omp_clause (gimple_location (stmt),
+                                     i ? OMP_CLAUSE_FIRSTPRIVATE
+                                     : OMP_CLAUSE_SHARED);
+               OMP_CLAUSE_DECL (c) = decl;
+               OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
+               gimple_omp_taskreg_set_clauses (stmt, c);
+             }
+           else if (c == NULL)
+             {
+               c = build_omp_clause (gimple_location (stmt),
+                                     OMP_CLAUSE_MAP);
+               OMP_CLAUSE_DECL (c) = decl;
+               OMP_CLAUSE_SET_MAP_KIND (c,
+                                        i ? GOMP_MAP_TO : GOMP_MAP_TOFROM);
+               OMP_CLAUSE_SIZE (c) = DECL_SIZE_UNIT (decl);
+               OMP_CLAUSE_CHAIN (c) = gimple_omp_target_clauses (stmt);
+               gimple_omp_target_set_clauses (as_a <gomp_target *> (stmt),
+                                              c);
+             }
+         }
        info->new_local_var_chain = save_local_var_chain;
+       info->static_chain_added |= save_static_chain_added;
       }
       break;
 
     default:
       *handled_ops_p = false;
       return NULL_TREE;
-      break;
     }
 
   *handled_ops_p = true;
@@ -2049,7 +2751,7 @@ convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p,
   tree decl, target_context;
   char save_static_chain_added;
   int i;
-  gimple stmt = gsi_stmt (*gsi);
+  gimple *stmt = gsi_stmt (*gsi);
 
   switch (gimple_code (stmt))
     {
@@ -2062,12 +2764,33 @@ convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       target_context = decl_function_context (decl);
       if (target_context && DECL_STATIC_CHAIN (decl))
        {
-         gimple_call_set_chain (stmt, get_static_chain (info, target_context,
-                                                        &wi->gsi));
+         struct nesting_info *i = info;
+         while (i && i->context != target_context)
+           i = i->outer;
+         /* If none of the outer contexts is the target context, this means
+            that the function is called in a wrong context.  */
+         if (!i)
+           internal_error ("%s from %s called in %s",
+                           IDENTIFIER_POINTER (DECL_NAME (decl)),
+                           IDENTIFIER_POINTER (DECL_NAME (target_context)),
+                           IDENTIFIER_POINTER (DECL_NAME (info->context)));
+
+         gimple_call_set_chain (as_a <gcall *> (stmt),
+                                get_static_chain (info, target_context,
+                                                  &wi->gsi));
          info->static_chain_added |= (1 << (info->context != target_context));
        }
       break;
 
+    case GIMPLE_OMP_TEAMS:
+      if (!gimple_omp_teams_host (as_a <gomp_teams *> (stmt)))
+       {
+         walk_body (convert_gimple_call, NULL, info,
+                    gimple_omp_body_ptr (stmt));
+         break;
+       }
+      /* FALLTHRU */
+
     case GIMPLE_OMP_PARALLEL:
     case GIMPLE_OMP_TASK:
       save_static_chain_added = info->static_chain_added;
@@ -2100,6 +2823,42 @@ convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       info->static_chain_added |= save_static_chain_added;
       break;
 
+    case GIMPLE_OMP_TARGET:
+      if (!is_gimple_omp_offloaded (stmt))
+       {
+         walk_body (convert_gimple_call, NULL, info, gimple_omp_body_ptr (stmt));
+         break;
+       }
+      save_static_chain_added = info->static_chain_added;
+      info->static_chain_added = 0;
+      walk_body (convert_gimple_call, NULL, info, gimple_omp_body_ptr (stmt));
+      for (i = 0; i < 2; i++)
+       {
+         tree c, decl;
+         if ((info->static_chain_added & (1 << i)) == 0)
+           continue;
+         decl = i ? get_chain_decl (info) : info->frame_decl;
+         /* Don't add CHAIN.* or FRAME.* twice.  */
+         for (c = gimple_omp_target_clauses (stmt);
+              c;
+              c = OMP_CLAUSE_CHAIN (c))
+           if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+               && OMP_CLAUSE_DECL (c) == decl)
+             break;
+         if (c == NULL)
+           {
+             c = build_omp_clause (gimple_location (stmt), OMP_CLAUSE_MAP);
+             OMP_CLAUSE_DECL (c) = decl;
+             OMP_CLAUSE_SET_MAP_KIND (c, i ? GOMP_MAP_TO : GOMP_MAP_TOFROM);
+             OMP_CLAUSE_SIZE (c) = DECL_SIZE_UNIT (decl);
+             OMP_CLAUSE_CHAIN (c) = gimple_omp_target_clauses (stmt);
+             gimple_omp_target_set_clauses (as_a <gomp_target *> (stmt),
+                                            c);
+           }
+       }
+      info->static_chain_added |= save_static_chain_added;
+      break;
+
     case GIMPLE_OMP_FOR:
       walk_body (convert_gimple_call, NULL, info,
                 gimple_omp_for_pre_body_ptr (stmt));
@@ -2107,11 +2866,10 @@ convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p,
     case GIMPLE_OMP_SECTIONS:
     case GIMPLE_OMP_SECTION:
     case GIMPLE_OMP_SINGLE:
-    case GIMPLE_OMP_TARGET:
-    case GIMPLE_OMP_TEAMS:
     case GIMPLE_OMP_MASTER:
     case GIMPLE_OMP_TASKGROUP:
     case GIMPLE_OMP_ORDERED:
+    case GIMPLE_OMP_SCAN:
     case GIMPLE_OMP_CRITICAL:
       walk_body (convert_gimple_call, NULL, info, gimple_omp_body_ptr (stmt));
       break;
@@ -2137,11 +2895,23 @@ convert_all_function_calls (struct nesting_info *root)
   struct nesting_info *n;
 
   /* First, optimistically clear static_chain for all decls that haven't
-     used the static chain already for variable access.  */
+     used the static chain already for variable access.  But always create
+     it if not optimizing.  This makes it possible to reconstruct the static
+     nesting tree at run time and thus to resolve up-level references from
+     within the debugger.  */
   FOR_EACH_NEST_INFO (n, root)
     {
+      if (n->thunk_p)
+       continue;
       tree decl = n->context;
-      if (!n->outer || (!n->chain_decl && !n->chain_field))
+      if (!optimize)
+       {
+         if (n->inner)
+           (void) get_frame_type (n);
+         if (n->outer)
+           (void) get_chain_decl (n);
+       }
+      else if (!n->outer || (!n->chain_decl && !n->chain_field))
        {
          DECL_STATIC_CHAIN (decl) = 0;
          if (dump_file && (dump_flags & TDF_DETAILS))
@@ -2153,6 +2923,14 @@ convert_all_function_calls (struct nesting_info *root)
       chain_count += DECL_STATIC_CHAIN (decl);
     }
 
+  FOR_EACH_NEST_INFO (n, root)
+    if (n->thunk_p)
+      {
+       tree decl = n->context;
+       tree alias = cgraph_node::get (decl)->thunk.alias;
+       DECL_STATIC_CHAIN (decl) = DECL_STATIC_CHAIN (alias);
+      }
+
   /* Walk the functions and perform transformations.  Note that these
      transformations can induce new uses of the static chain, which in turn
      require re-examining all users of the decl.  */
@@ -2172,12 +2950,22 @@ convert_all_function_calls (struct nesting_info *root)
 
       FOR_EACH_NEST_INFO (n, root)
        {
+         if (n->thunk_p)
+           continue;
          tree decl = n->context;
          walk_function (convert_tramp_reference_stmt,
                         convert_tramp_reference_op, n);
          walk_function (convert_gimple_call, NULL, n);
          chain_count += DECL_STATIC_CHAIN (decl);
        }
+
+      FOR_EACH_NEST_INFO (n, root)
+       if (n->thunk_p)
+         {
+           tree decl = n->context;
+           tree alias = cgraph_node::get (decl)->thunk.alias;
+           DECL_STATIC_CHAIN (decl) = DECL_STATIC_CHAIN (alias);
+         }
     }
   while (chain_count != old_chain_count);
 
@@ -2198,7 +2986,7 @@ static tree
 nesting_copy_decl (tree decl, copy_body_data *id)
 {
   struct nesting_copy_body_data *nid = (struct nesting_copy_body_data *) id;
-  void **slot = pointer_map_contains (nid->root->var_map, decl);
+  tree *slot = nid->root->var_map->get (decl);
 
   if (slot)
     return (tree) *slot;
@@ -2211,7 +2999,7 @@ nesting_copy_decl (tree decl, copy_body_data *id)
       return new_decl;
     }
 
-  if (TREE_CODE (decl) == VAR_DECL
+  if (VAR_P (decl)
       || TREE_CODE (decl) == PARM_DECL
       || TREE_CODE (decl) == RESULT_DECL)
     return decl;
@@ -2227,15 +3015,14 @@ contains_remapped_vars (tree *tp, int *walk_subtrees, void *data)
 {
   struct nesting_info *root = (struct nesting_info *) data;
   tree t = *tp;
-  void **slot;
 
   if (DECL_P (t))
     {
       *walk_subtrees = 0;
-      slot = pointer_map_contains (root->var_map, t);
+      tree *slot = root->var_map->get (t);
 
       if (slot)
-       return (tree) *slot;
+       return *slot;
     }
   return NULL;
 }
@@ -2255,7 +3042,7 @@ remap_vla_decls (tree block, struct nesting_info *root)
     remap_vla_decls (subblock, root);
 
   for (var = BLOCK_VARS (block); var; var = DECL_CHAIN (var))
-    if (TREE_CODE (var) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (var))
+    if (VAR_P (var) && DECL_HAS_VALUE_EXPR_P (var))
       {
        val = DECL_VALUE_EXPR (var);
        type = TREE_TYPE (var);
@@ -2265,7 +3052,7 @@ remap_vla_decls (tree block, struct nesting_info *root)
              && variably_modified_type_p (type, NULL)))
          continue;
 
-       if (pointer_map_contains (root->var_map, TREE_OPERAND (val, 0))
+       if (root->var_map->get (TREE_OPERAND (val, 0))
            || walk_tree (&type, contains_remapped_vars, root, NULL))
          break;
       }
@@ -2275,15 +3062,14 @@ remap_vla_decls (tree block, struct nesting_info *root)
 
   memset (&id, 0, sizeof (id));
   id.cb.copy_decl = nesting_copy_decl;
-  id.cb.decl_map = pointer_map_create ();
+  id.cb.decl_map = new hash_map<tree, tree>;
   id.root = root;
 
   for (; var; var = DECL_CHAIN (var))
-    if (TREE_CODE (var) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (var))
+    if (VAR_P (var) && DECL_HAS_VALUE_EXPR_P (var))
       {
        struct nesting_info *i;
        tree newt, context;
-       void **slot;
 
        val = DECL_VALUE_EXPR (var);
        type = TREE_TYPE (var);
@@ -2293,7 +3079,7 @@ remap_vla_decls (tree block, struct nesting_info *root)
              && variably_modified_type_p (type, NULL)))
          continue;
 
-       slot = pointer_map_contains (root->var_map, TREE_OPERAND (val, 0));
+       tree *slot = root->var_map->get (TREE_OPERAND (val, 0));
        if (!slot && !walk_tree (&type, contains_remapped_vars, root, NULL))
          continue;
 
@@ -2336,65 +3122,151 @@ remap_vla_decls (tree block, struct nesting_info *root)
          SET_DECL_VALUE_EXPR (var, val);
       }
 
-  pointer_map_destroy (id.cb.decl_map);
+  delete id.cb.decl_map;
+}
+
+/* Fixup VLA decls in BLOCK and subblocks if remapped variables are
+   involved.  */
+
+static void
+fixup_vla_decls (tree block)
+{
+  for (tree var = BLOCK_VARS (block); var; var = DECL_CHAIN (var))
+    if (VAR_P (var) && DECL_HAS_VALUE_EXPR_P (var))
+      {
+       tree val = DECL_VALUE_EXPR (var);
+
+       if (!(TREE_CODE (val) == INDIRECT_REF
+             && VAR_P (TREE_OPERAND (val, 0))
+             && DECL_HAS_VALUE_EXPR_P (TREE_OPERAND (val, 0))))
+         continue;
+
+       /* Fully expand value expressions.  This avoids having debug variables
+          only referenced from them and that can be swept during GC.  */
+       val = build1 (INDIRECT_REF, TREE_TYPE (val),
+                     DECL_VALUE_EXPR (TREE_OPERAND (val, 0)));
+       SET_DECL_VALUE_EXPR (var, val);
+      }
+
+  for (tree sub = BLOCK_SUBBLOCKS (block); sub; sub = BLOCK_CHAIN (sub))
+    fixup_vla_decls (sub);
 }
 
 /* Fold the MEM_REF *E.  */
-static bool
-fold_mem_refs (const void *e, void *data ATTRIBUTE_UNUSED)
+bool
+fold_mem_refs (tree *const &e, void *data ATTRIBUTE_UNUSED)
 {
   tree *ref_p = CONST_CAST2 (tree *, const tree *, (const tree *)e);
   *ref_p = fold (*ref_p);
   return true;
 }
 
-/* Do "everything else" to clean up or complete state collected by the
-   various walking passes -- lay out the types and decls, generate code
-   to initialize the frame decl, store critical expressions in the
-   struct function for rtl to find.  */
+/* Given DECL, a nested function, build an initialization call for FIELD,
+   the trampoline or descriptor for DECL, using FUNC as the function.  */
+
+static gcall *
+build_init_call_stmt (struct nesting_info *info, tree decl, tree field,
+                     tree func)
+{
+  tree arg1, arg2, arg3, x;
+
+  gcc_assert (DECL_STATIC_CHAIN (decl));
+  arg3 = build_addr (info->frame_decl);
+
+  arg2 = build_addr (decl);
+
+  x = build3 (COMPONENT_REF, TREE_TYPE (field),
+             info->frame_decl, field, NULL_TREE);
+  arg1 = build_addr (x);
+
+  return gimple_build_call (func, 3, arg1, arg2, arg3);
+}
+
+/* Do "everything else" to clean up or complete state collected by the various
+   walking passes -- create a field to hold the frame base address, lay out the
+   types and decls, generate code to initialize the frame decl, store critical
+   expressions in the struct function for rtl to find.  */
 
 static void
 finalize_nesting_tree_1 (struct nesting_info *root)
 {
-  gimple_seq stmt_list;
-  gimple stmt;
+  gimple_seq stmt_list = NULL;
+  gimple *stmt;
   tree context = root->context;
   struct function *sf;
 
-  stmt_list = NULL;
+  if (root->thunk_p)
+    return;
 
   /* If we created a non-local frame type or decl, we need to lay them
      out at this time.  */
   if (root->frame_type)
     {
+      /* Debugging information needs to compute the frame base address of the
+        parent frame out of the static chain from the nested frame.
+
+        The static chain is the address of the FRAME record, so one could
+        imagine it would be possible to compute the frame base address just
+        adding a constant offset to this address.  Unfortunately, this is not
+        possible: if the FRAME object has alignment constraints that are
+        stronger than the stack, then the offset between the frame base and
+        the FRAME object will be dynamic.
+
+        What we do instead is to append a field to the FRAME object that holds
+        the frame base address: then debug info just has to fetch this
+        field.  */
+
+      /* Debugging information will refer to the CFA as the frame base
+        address: we will do the same here.  */
+      const tree frame_addr_fndecl
+        = builtin_decl_explicit (BUILT_IN_DWARF_CFA);
+
+      /* Create a field in the FRAME record to hold the frame base address for
+        this stack frame.  Since it will be used only by the debugger, put it
+        at the end of the record in order not to shift all other offsets.  */
+      tree fb_decl = make_node (FIELD_DECL);
+
+      DECL_NAME (fb_decl) = get_identifier ("FRAME_BASE.PARENT");
+      TREE_TYPE (fb_decl) = ptr_type_node;
+      TREE_ADDRESSABLE (fb_decl) = 1;
+      DECL_CONTEXT (fb_decl) = root->frame_type;
+      TYPE_FIELDS (root->frame_type) = chainon (TYPE_FIELDS (root->frame_type),
+                                               fb_decl);
+
       /* In some cases the frame type will trigger the -Wpadded warning.
         This is not helpful; suppress it. */
       int save_warn_padded = warn_padded;
-      tree *adjust;
-
       warn_padded = 0;
       layout_type (root->frame_type);
       warn_padded = save_warn_padded;
       layout_decl (root->frame_decl, 0);
 
-      /* Remove root->frame_decl from root->new_local_var_chain, so
-        that we can declare it also in the lexical blocks, which
-        helps ensure virtual regs that end up appearing in its RTL
-        expression get substituted in instantiate_virtual_regs().  */
-      for (adjust = &root->new_local_var_chain;
-          *adjust != root->frame_decl;
-          adjust = &DECL_CHAIN (*adjust))
-       gcc_assert (DECL_CHAIN (*adjust));
-      *adjust = DECL_CHAIN (*adjust);
-
-      DECL_CHAIN (root->frame_decl) = NULL_TREE;
+      /* Initialize the frame base address field.  If the builtin we need is
+        not available, set it to NULL so that debugging information does not
+        reference junk.  */
+      tree fb_ref = build3 (COMPONENT_REF, TREE_TYPE (fb_decl),
+                           root->frame_decl, fb_decl, NULL_TREE);
+      tree fb_tmp;
+
+      if (frame_addr_fndecl != NULL_TREE)
+       {
+         gcall *fb_gimple = gimple_build_call (frame_addr_fndecl, 1,
+                                               integer_zero_node);
+         gimple_stmt_iterator gsi = gsi_last (stmt_list);
+
+         fb_tmp = init_tmp_var_with_call (root, &gsi, fb_gimple);
+       }
+      else
+       fb_tmp = build_int_cst (TREE_TYPE (fb_ref), 0);
+      gimple_seq_add_stmt (&stmt_list,
+                          gimple_build_assign (fb_ref, fb_tmp));
+
       declare_vars (root->frame_decl,
                    gimple_seq_first_stmt (gimple_body (context)), true);
     }
 
-  /* If any parameters were referenced non-locally, then we need to
-     insert a copy.  Likewise, if any variables were referenced by
-     pointer, we need to initialize the address.  */
+  /* If any parameters were referenced non-locally, then we need to insert
+     a copy or a pointer.  */
   if (root->any_parm_remapped)
     {
       tree p;
@@ -2407,14 +3279,10 @@ finalize_nesting_tree_1 (struct nesting_info *root)
            continue;
 
          if (use_pointer_in_frame (p))
-           x = build_addr (p, context);
+           x = build_addr (p);
          else
            x = p;
 
-         y = build3 (COMPONENT_REF, TREE_TYPE (field),
-                     root->frame_decl, field, NULL_TREE);
-         stmt = gimple_build_assign (y, x);
-         gimple_seq_add_stmt (&stmt_list, stmt);
          /* If the assignment is from a non-register the stmt is
             not valid gimple.  Make it so by using a temporary instead.  */
          if (!is_gimple_reg (x)
@@ -2422,8 +3290,12 @@ finalize_nesting_tree_1 (struct nesting_info *root)
            {
              gimple_stmt_iterator gsi = gsi_last (stmt_list);
              x = init_tmp_var (root, x, &gsi);
-             gimple_assign_set_rhs1 (stmt, x);
            }
+
+         y = build3 (COMPONENT_REF, TREE_TYPE (field),
+                     root->frame_decl, field, NULL_TREE);
+         stmt = gimple_build_assign (y, x);
+         gimple_seq_add_stmt (&stmt_list, stmt);
        }
     }
 
@@ -2443,23 +3315,32 @@ finalize_nesting_tree_1 (struct nesting_info *root)
       struct nesting_info *i;
       for (i = root->inner; i ; i = i->next)
        {
-         tree arg1, arg2, arg3, x, field;
+         tree field, x;
 
          field = lookup_tramp_for_decl (root, i->context, NO_INSERT);
          if (!field)
            continue;
 
-         gcc_assert (DECL_STATIC_CHAIN (i->context));
-         arg3 = build_addr (root->frame_decl, context);
+         x = builtin_decl_implicit (BUILT_IN_INIT_TRAMPOLINE);
+         stmt = build_init_call_stmt (root, i->context, field, x);
+         gimple_seq_add_stmt (&stmt_list, stmt);
+       }
+    }
 
-         arg2 = build_addr (i->context, context);
+  /* If descriptors were created, then we need to initialize them.  */
+  if (root->any_descr_created)
+    {
+      struct nesting_info *i;
+      for (i = root->inner; i ; i = i->next)
+       {
+         tree field, x;
 
-         x = build3 (COMPONENT_REF, TREE_TYPE (field),
-                     root->frame_decl, field, NULL_TREE);
-         arg1 = build_addr (x, context);
+         field = lookup_descr_for_decl (root, i->context, NO_INSERT);
+         if (!field)
+           continue;
 
-         x = builtin_decl_implicit (BUILT_IN_INIT_TRAMPOLINE);
-         stmt = gimple_build_call (x, 3, arg1, arg2, arg3);
+         x = builtin_decl_implicit (BUILT_IN_INIT_DESCRIPTOR);
+         stmt = build_init_call_stmt (root, i->context, field, x);
          gimple_seq_add_stmt (&stmt_list, stmt);
        }
     }
@@ -2467,9 +3348,9 @@ finalize_nesting_tree_1 (struct nesting_info *root)
   /* If we created initialization statements, insert them.  */
   if (stmt_list)
     {
-      gimple bind;
+      gbind *bind;
       annotate_all_with_location (stmt_list, DECL_SOURCE_LOCATION (context));
-      bind = gimple_seq_first_stmt (gimple_body (context));
+      bind = gimple_seq_first_stmt_as_a_bind (gimple_body (context));
       gimple_seq_add_seq (&stmt_list, gimple_bind_body (bind));
       gimple_bind_set_body (bind, stmt_list);
     }
@@ -2498,7 +3379,7 @@ finalize_nesting_tree_1 (struct nesting_info *root)
   if (root->debug_var_chain)
     {
       tree debug_var;
-      gimple scope;
+      gbind *scope;
 
       remap_vla_decls (DECL_INITIAL (root->context), root);
 
@@ -2515,7 +3396,7 @@ finalize_nesting_tree_1 (struct nesting_info *root)
 
          memset (&id, 0, sizeof (id));
          id.cb.copy_decl = nesting_copy_decl;
-         id.cb.decl_map = pointer_map_create ();
+         id.cb.decl_map = new hash_map<tree, tree>;
          id.root = root;
 
          for (; debug_var; debug_var = DECL_CHAIN (debug_var))
@@ -2550,10 +3431,10 @@ finalize_nesting_tree_1 (struct nesting_info *root)
                  TYPE_NAME (newt) = remap_decl (TYPE_NAME (newt), &id.cb);
              }
 
-         pointer_map_destroy (id.cb.decl_map);
+         delete id.cb.decl_map;
        }
 
-      scope = gimple_seq_first_stmt (gimple_body (root->context));
+      scope = gimple_seq_first_stmt_as_a_bind (gimple_body (root->context));
       if (gimple_bind_block (scope))
        declare_vars (root->debug_var_chain, scope, true);
       else
@@ -2561,9 +3442,11 @@ finalize_nesting_tree_1 (struct nesting_info *root)
          = chainon (BLOCK_VARS (DECL_INITIAL (root->context)),
                     root->debug_var_chain);
     }
+  else
+    fixup_vla_decls (DECL_INITIAL (root->context));
 
   /* Fold the rewritten MEM_REF trees.  */
-  pointer_set_traverse (root->mem_refs, fold_mem_refs, NULL);
+  root->mem_refs->traverse<void *, fold_mem_refs> (NULL);
 
   /* Dump the translated tree function.  */
   if (dump_file)
@@ -2586,14 +3469,15 @@ finalize_nesting_tree (struct nesting_info *root)
 static void
 unnest_nesting_tree_1 (struct nesting_info *root)
 {
-  struct cgraph_node *node = cgraph_get_node (root->context);
+  struct cgraph_node *node = cgraph_node::get (root->context);
 
   /* For nested functions update the cgraph to reflect unnesting.
      We also delay finalizing of these functions up to this point.  */
   if (node->origin)
     {
-       cgraph_unnest_node (node);
-       cgraph_finalize_function (root->context, true);
+       node->unnest ();
+       if (!root->thunk_p)
+        cgraph_node::finalize_function (root->context, true);
     }
 }
 
@@ -2616,9 +3500,9 @@ free_nesting_tree (struct nesting_info *root)
   do
     {
       next = iter_nestinfo_next (node);
-      pointer_map_destroy (node->var_map);
-      pointer_map_destroy (node->field_map);
-      pointer_set_destroy (node->mem_refs);
+      delete node->var_map;
+      delete node->field_map;
+      delete node->mem_refs;
       free (node);
       node = next;
     }
@@ -2633,7 +3517,8 @@ gimplify_all_functions (struct cgraph_node *root)
   if (!gimple_body (root->decl))
     gimplify_function_tree (root->decl);
   for (iter = root->nested; iter; iter = iter->next_nested)
-    gimplify_all_functions (iter);
+    if (!iter->thunk.thunk_p)
+      gimplify_all_functions (iter);
 }
 
 /* Main entry point for this pass.  Process FNDECL and all of its nested
@@ -2646,13 +3531,13 @@ lower_nested_functions (tree fndecl)
   struct nesting_info *root;
 
   /* If there are no nested functions, there's nothing to do.  */
-  cgn = cgraph_get_node (fndecl);
+  cgn = cgraph_node::get (fndecl);
   if (!cgn->nested)
     return;
 
   gimplify_all_functions (cgn);
 
-  dump_file = dump_begin (TDI_nested, &dump_flags);
+  set_dump_file (dump_begin (TDI_nested, &dump_flags));
   if (dump_file)
     fprintf (dump_file, "\n;; Function %s\n\n",
             lang_hooks.decl_printable_name (fndecl, 2));
@@ -2679,7 +3564,7 @@ lower_nested_functions (tree fndecl)
   if (dump_file)
     {
       dump_end (TDI_nested, dump_file);
-      dump_file = NULL;
+      set_dump_file (NULL);
     }
 }