@@ -1829,6 +1829,7 @@ typedef struct gfc_symbol
gfc_array_spec *as;
struct gfc_symbol *result; /* function result symbol */
gfc_component *components; /* Derived type components */
+ gfc_omp_namelist *omp_allocated, *omp_allocated_end;
/* Defined only for Cray pointees; points to their pointer. */
struct gfc_symbol *cp_pointer;
@@ -6057,6 +6057,7 @@ gfc_match_omp_allocate (void)
new_st.op = EXEC_OMP_ALLOCATE;
new_st.ext.omp_clauses = c;
+ new_st.resolved_sym = NULL;
gfc_free_expr (allocator);
return MATCH_YES;
}
@@ -9548,6 +9549,34 @@ gfc_resolve_oacc_routines (gfc_namespace *ns)
}
}
+static void
+prepare_omp_allocated_var_list_for_cleanup (gfc_omp_namelist *cn, locus loc)
+{
+ gfc_symbol *proc = cn->sym->ns->proc_name;
+ gfc_omp_namelist *p, *n;
+
+ for (n = cn; n; n = n->next)
+ {
+ if (n->sym->attr.allocatable && !n->sym->attr.save
+ && !n->sym->attr.result && !proc->attr.is_main_program)
+ {
+ p = gfc_get_omp_namelist ();
+ p->sym = n->sym;
+ p->expr = gfc_copy_expr (n->expr);
+ p->where = loc;
+ p->next = NULL;
+ if (proc->omp_allocated == NULL)
+ proc->omp_allocated_end = proc->omp_allocated = p;
+ else
+ {
+ proc->omp_allocated_end->next = p;
+ proc->omp_allocated_end = p;
+ }
+
+ }
+ }
+}
+
static void
check_allocate_directive_restrictions (gfc_symbol *sym, gfc_expr *omp_al,
gfc_namespace *ns, locus loc)
@@ -9678,6 +9707,7 @@ gfc_resolve_omp_allocate (gfc_code *code, gfc_namespace *ns)
code->loc);
}
}
+ prepare_omp_allocated_var_list_for_cleanup (cn, code->loc);
}
@@ -4588,6 +4588,26 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
}
}
+ /* Generate a dummy allocate pragma with free kind so that cleanup
+ of those variables which were allocated using the allocate statement
+ associated with an allocate clause happens correctly. */
+
+ if (proc_sym->omp_allocated)
+ {
+ gfc_clear_new_st ();
+ new_st.op = EXEC_OMP_ALLOCATE;
+ gfc_omp_clauses *c = gfc_get_omp_clauses ();
+ c->lists[OMP_LIST_ALLOCATOR] = proc_sym->omp_allocated;
+ new_st.ext.omp_clauses = c;
+ /* This is just a hacky way to convey to handler that we are
+ dealing with cleanup here. Saves us from using another field
+ for it. */
+ new_st.resolved_sym = proc_sym->omp_allocated->sym;
+ gfc_add_init_cleanup (block, NULL,
+ gfc_trans_omp_directive (&new_st));
+ gfc_free_omp_clauses (c);
+ proc_sym->omp_allocated = NULL;
+ }
/* Initialize the INTENT(OUT) derived type dummy arguments. This
should be done here so that the offsets and lbounds of arrays
@@ -5019,6 +5019,12 @@ gfc_trans_omp_allocate (gfc_code *code)
OMP_ALLOCATE_CLAUSES (stmt) = gfc_trans_omp_clauses (&block, clauses,
code->loc, false,
true);
+ if (code->next == NULL && code->block == NULL
+ && code->resolved_sym != NULL)
+ OMP_ALLOCATE_KIND_FREE (stmt) = 1;
+ else
+ OMP_ALLOCATE_KIND_ALLOCATE (stmt) = 1;
+
gfc_add_expr_to_block (&block, stmt);
gfc_merge_block_scope (&block);
return gfc_finish_block (&block);
@@ -69,4 +69,5 @@ end type
allocate(pii, parr(5))
end subroutine
-! { dg-final { scan-tree-dump-times "#pragma omp allocate" 6 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp allocate \\(kind=allocate\\)" 6 "original" } }
+! { dg-final { scan-tree-dump "#pragma omp allocate \\(kind=free\\)" "original" } }
@@ -1257,6 +1257,9 @@ struct GTY(()) tree_base {
EXPR_LOCATION_WRAPPER_P in
NON_LVALUE_EXPR, VIEW_CONVERT_EXPR
+ OMP_ALLOCATE_KIND_ALLOCATE in
+ OMP_ALLOCATE
+
private_flag:
TREE_PRIVATE in
@@ -1283,6 +1286,9 @@ struct GTY(()) tree_base {
ENUM_IS_OPAQUE in
ENUMERAL_TYPE
+ OMP_ALLOCATE_KIND_FREE in
+ OMP_ALLOCATE
+
protected_flag:
TREE_PROTECTED in
@@ -3541,6 +3541,10 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags,
case OMP_ALLOCATE:
pp_string (pp, "#pragma omp allocate ");
+ if (OMP_ALLOCATE_KIND_ALLOCATE (node))
+ pp_string (pp, "(kind=allocate) ");
+ else if (OMP_ALLOCATE_KIND_FREE (node))
+ pp_string (pp, "(kind=free) ");
dump_omp_clauses (pp, OMP_ALLOCATE_CLAUSES (node), spc, flags);
break;
@@ -1467,6 +1467,10 @@ class auto_suppress_location_wrappers
TREE_OPERAND (OACC_UPDATE_CHECK (NODE), 0)
#define OMP_ALLOCATE_CLAUSES(NODE) TREE_OPERAND (OMP_ALLOCATE_CHECK (NODE), 0)
+#define OMP_ALLOCATE_KIND_ALLOCATE(NODE) \
+ (OMP_ALLOCATE_CHECK (NODE)->base.public_flag)
+#define OMP_ALLOCATE_KIND_FREE(NODE) \
+ (OMP_ALLOCATE_CHECK (NODE)->base.private_flag)
#define OMP_PARALLEL_BODY(NODE) TREE_OPERAND (OMP_PARALLEL_CHECK (NODE), 0)
#define OMP_PARALLEL_CLAUSES(NODE) TREE_OPERAND (OMP_PARALLEL_CHECK (NODE), 1)