static gfc_actual_arglist *pdt_param_list;
static bool generating_copy_helper;
+static hash_set<gfc_symbol *> seen_derived_types;
/* Forward declaration of structure_alloc_comps for wrapper generator. */
static tree structure_alloc_comps (gfc_symbol *, tree, tree, int, int, int,
bool saved_generating = generating_copy_helper;
generating_copy_helper = true;
+ /* When generating a wrapper, we need a fresh type tracking state to
+ avoid inheriting the parent context's seen_derived_types, which would
+ cause infinite recursion when the wrapper tries to handle the same
+ recursive type. Save elements, clear the set, generate wrapper, then
+ restore elements. */
+ vec<gfc_symbol *> saved_symbols = vNULL;
+ for (hash_set<gfc_symbol *>::iterator it = seen_derived_types.begin ();
+ it != seen_derived_types.end (); ++it)
+ saved_symbols.safe_push (*it);
+ seen_derived_types.empty ();
+
der_type_ptr = build_pointer_type (comp_type);
dest_typed = fold_convert (der_type_ptr, dest_parm);
src_typed = fold_convert (der_type_ptr, src_parm);
0, purpose, caf_mode, NULL, false);
gfc_add_expr_to_block (&block, body);
+ /* Restore saved symbols. */
+ seen_derived_types.empty ();
+ for (unsigned i = 0; i < saved_symbols.length (); i++)
+ seen_derived_types.add (saved_symbols[i]);
+ saved_symbols.release ();
generating_copy_helper = saved_generating;
body = gfc_finish_block (&block);
int caf_dereg_mode;
symbol_attribute *attr;
bool deallocate_called;
- static hash_set<gfc_symbol *> seen_derived_types;
gfc_init_block (&fnblock);
false, false, NULL_TREE, NULL_TREE);
gfc_add_expr_to_block (&fnblock, tmp);
}
- /* Special case: recursive allocatable array components require runtime
- helper to avoid compile-time infinite recursion. Generate a call to
- _gfortran_cfi_deep_copy_array with an element copy wrapper. */
+ /* Special case: recursive allocatable array components require
+ runtime helpers to avoid compile-time infinite recursion. Generate
+ a call to _gfortran_cfi_deep_copy_array with an element copy
+ wrapper. When inside a wrapper, reuse current_function_decl. */
else if (c->attr.allocatable && c->as && cmp_has_alloc_comps && same_type
&& purpose == COPY_ALLOC_COMP && !c->attr.proc_pointer
&& !c->attr.codimension && !caf_in_coarray (caf_mode)
tree alloc_expr;
int comp_rank;
- /* Get the element type from ctype (which is already the component type).
- For arrays, we need the element type, not the array type. */
+ /* Get the element type from ctype (already the component
+ type). For arrays we need the element type, not the array
+ type. */
elem_type = ctype;
if (GFC_DESCRIPTOR_TYPE_P (ctype))
elem_type = gfc_get_element_type (ctype);
comp_rank);
gfc_add_expr_to_block (&fnblock, alloc_expr);
- /* Generate or reuse the element copy helper. Inside an existing helper
- we can reuse the current function to prevent recursive generation. */
+ /* Generate or reuse the element copy helper. Inside an
+ existing helper we can reuse the current function to
+ prevent recursive generation. */
if (inside_wrapper)
- copy_wrapper = gfc_build_addr_expr (NULL_TREE, current_function_decl);
+ copy_wrapper
+ = gfc_build_addr_expr (NULL_TREE, current_function_decl);
else
- copy_wrapper = generate_element_copy_wrapper (c->ts.u.derived,
- elem_type,
- purpose, caf_mode);
+ copy_wrapper
+ = generate_element_copy_wrapper (c->ts.u.derived, elem_type,
+ purpose, caf_mode);
copy_wrapper = fold_convert (helper_ptr_type, copy_wrapper);
/* Build addresses of descriptors. */
dest_addr = gfc_build_addr_expr (pvoid_type_node, dcmp);
src_addr = gfc_build_addr_expr (pvoid_type_node, comp);
- /* Build call: _gfortran_cfi_deep_copy_array (&dcmp, &comp, wrapper). */
+ /* Build call: _gfortran_cfi_deep_copy_array (&dcmp, &comp,
+ wrapper). */
call = build_call_expr_loc (input_location,
gfor_fndecl_cfi_deep_copy_array, 3,
- dest_addr, src_addr, copy_wrapper);
+ dest_addr, src_addr,
+ copy_wrapper);
gfc_add_expr_to_block (&fnblock, call);
}
else if (c->attr.allocatable && !c->attr.proc_pointer
- && (add_when_allocated != NULL_TREE || !cmp_has_alloc_comps || !c->as
- || c->attr.codimension || caf_in_coarray (caf_mode)))
+ && (add_when_allocated != NULL_TREE
+ || !cmp_has_alloc_comps
+ || !c->as
+ || c->attr.codimension
+ || caf_in_coarray (caf_mode)))
{
rank = c->as ? c->as->rank : 0;
if (c->attr.codimension)
else
image_index = integer_zero_node;
- /* Create a temporary if value is not already a pointer, or if it's an
- address of a constant (which is invalid in C). */
- bool need_tmp = !POINTER_TYPE_P (TREE_TYPE (value));
- if (POINTER_TYPE_P (TREE_TYPE (value))
- && TREE_CODE (value) == ADDR_EXPR
- && TREE_CONSTANT (TREE_OPERAND (value, 0)))
- need_tmp = true;
-
- if (need_tmp)
- {
- tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
- if (POINTER_TYPE_P (TREE_TYPE (value)))
- gfc_add_modify (&block, tmp,
- fold_convert (TREE_TYPE (tmp),
- build_fold_indirect_ref (value)));
- else
- gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), value));
- value = gfc_build_addr_expr (NULL_TREE, tmp);
+ /* Ensure VALUE names addressable storage: taking the address of a
+ constant is invalid in C, and scalars need a temporary as well. */
+ if (!POINTER_TYPE_P (TREE_TYPE (value)))
+ {
+ tree elem
+ = fold_convert (TREE_TYPE (TREE_TYPE (atom)), value);
+ elem = gfc_trans_force_lval (&block, elem);
+ value = gfc_build_addr_expr (NULL_TREE, elem);
+ }
+ else if (TREE_CODE (value) == ADDR_EXPR
+ && TREE_CONSTANT (TREE_OPERAND (value, 0)))
+ {
+ tree elem
+ = fold_convert (TREE_TYPE (TREE_TYPE (atom)),
+ build_fold_indirect_ref (value));
+ elem = gfc_trans_force_lval (&block, elem);
+ value = gfc_build_addr_expr (NULL_TREE, elem);
}
gfc_init_se (&argse, NULL);
--- /dev/null
+! { dg-do compile }
+!
+! PR fortran/121628
+! Test that derived types with multiple recursive allocatable array
+! components compile without ICE. This was broken by the initial deep-copy
+! patch which caused infinite compile-time recursion due to seen_derived_types
+! persisting across wrapper generation.
+!
+! The fix saves and restores seen_derived_types when generating element
+! copy wrappers to prevent inheriting parent context state.
+!
+
+program alloc_comp_deep_copy_7
+ implicit none
+
+ type :: nested_t
+ type(nested_t), allocatable :: children(:)
+ type(nested_t), allocatable :: relatives(:)
+ end type nested_t
+
+ type(nested_t) :: a
+
+end program alloc_comp_deep_copy_7
-# Makefile.in generated by automake 1.15.1 from Makefile.am.
+# Makefile.in generated by automake 1.15 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2017 Free Software Foundation, Inc.
+# Copyright (C) 1994-2014 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@LIBGFOR_MINIMAL_FALSE@ runtime/fpu.lo runtime/main.lo \
@LIBGFOR_MINIMAL_FALSE@ runtime/pause.lo runtime/stop.lo
am__objects_3 = runtime/bounds.lo runtime/compile_options.lo \
- runtime/deep_copy.lo runtime/memory.lo runtime/string.lo runtime/select.lo \
- $(am__objects_1) $(am__objects_2)
+ runtime/deep_copy.lo runtime/memory.lo runtime/string.lo \
+ runtime/select.lo $(am__objects_1) $(am__objects_2)
am__objects_4 = generated/matmul_i1.lo generated/matmul_i2.lo \
generated/matmul_i4.lo generated/matmul_i8.lo \
generated/matmul_i16.lo generated/matmul_r4.lo \
@IEEE_SUPPORT_TRUE@ieee/ieee_exceptions.F90 \
@IEEE_SUPPORT_TRUE@ieee/ieee_features.F90
-gfor_src = runtime/bounds.c runtime/compile_options.c runtime/deep_copy.c \
- runtime/memory.c runtime/string.c runtime/select.c $(am__append_6) \
- $(am__append_7)
+gfor_src = runtime/bounds.c runtime/compile_options.c \
+ runtime/deep_copy.c runtime/memory.c runtime/string.c \
+ runtime/select.c $(am__append_6) $(am__append_7)
i_matmul_c = \
generated/matmul_i1.c \
generated/matmul_i2.c \
@AMDEP_TRUE@@am__include@ @am__quote@runtime/$(DEPDIR)/bounds.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@runtime/$(DEPDIR)/compile_options.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@runtime/$(DEPDIR)/convert_char.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@runtime/$(DEPDIR)/deep_copy.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@runtime/$(DEPDIR)/environ.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@runtime/$(DEPDIR)/error.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@runtime/$(DEPDIR)/fpu.Plo@am__quote@
-# generated automatically by aclocal 1.15.1 -*- Autoconf -*-
+# generated automatically by aclocal 1.15 -*- Autoconf -*-
-# Copyright (C) 1996-2017 Free Software Foundation, Inc.
+# Copyright (C) 1996-2014 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
If you have problems, you may need to regenerate the build system entirely.
To do so, use the procedure documented by the package, typically 'autoreconf'.])])
-# Copyright (C) 2002-2017 Free Software Foundation, Inc.
+# Copyright (C) 2002-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
[am__api_version='1.15'
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
dnl require some minimum version. Point them to the right macro.
-m4_if([$1], [1.15.1], [],
+m4_if([$1], [1.15], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
])
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
-[AM_AUTOMAKE_VERSION([1.15.1])dnl
+[AM_AUTOMAKE_VERSION([1.15])dnl
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
-# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+# Copyright (C) 2001-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# AM_CONDITIONAL -*- Autoconf -*-
-# Copyright (C) 1997-2017 Free Software Foundation, Inc.
+# Copyright (C) 1997-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
Usually this means the macro was only invoked conditionally.]])
fi])])
-# Copyright (C) 1999-2017 Free Software Foundation, Inc.
+# Copyright (C) 1999-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# Generate code to set up dependency tracking. -*- Autoconf -*-
-# Copyright (C) 1999-2017 Free Software Foundation, Inc.
+# Copyright (C) 1999-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# Do all the work for Automake. -*- Autoconf -*-
-# Copyright (C) 1996-2017 Free Software Foundation, Inc.
+# Copyright (C) 1996-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
done
echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
-# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+# Copyright (C) 2001-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
# From Jim Meyering
-# Copyright (C) 1996-2017 Free Software Foundation, Inc.
+# Copyright (C) 1996-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# Check to see how 'make' treats includes. -*- Autoconf -*-
-# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+# Copyright (C) 2001-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
-# Copyright (C) 1997-2017 Free Software Foundation, Inc.
+# Copyright (C) 1997-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# Helper functions for option handling. -*- Autoconf -*-
-# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+# Copyright (C) 2001-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
AC_DEFUN([_AM_IF_OPTION],
[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
-# Copyright (C) 1999-2017 Free Software Foundation, Inc.
+# Copyright (C) 1999-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# For backward compatibility.
AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
-# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+# Copyright (C) 2001-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# Check to make sure that the build environment is sane. -*- Autoconf -*-
-# Copyright (C) 1996-2017 Free Software Foundation, Inc.
+# Copyright (C) 1996-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
rm -f conftest.file
])
-# Copyright (C) 2009-2017 Free Software Foundation, Inc.
+# Copyright (C) 2009-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
])
-# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+# Copyright (C) 2001-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
AC_SUBST([INSTALL_STRIP_PROGRAM])])
-# Copyright (C) 2006-2017 Free Software Foundation, Inc.
+# Copyright (C) 2006-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# Check how to create a tarball. -*- Autoconf -*-
-# Copyright (C) 2004-2017 Free Software Foundation, Inc.
+# Copyright (C) 2004-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
extern void *xrealloc (void *, size_t);
internal_proto(xrealloc);
-/* deep_copy.c - Runtime helper for recursive allocatable array components */
-
-struct CFI_cdesc_t;
extern void cfi_deep_copy_array (gfc_array_void *,
gfc_array_void *,
void (*copy_element) (void *, void *));