All, The attached patch generates special initializers for derived-type c_ptr and c_funptr symbols so they are handled correctly by the translation phase. Previously, an EXPR_STRUCTURE expression was generated for both types, as c_ptr and c_funptr are structure types with a c_address field. The c_address field never had its backend_decl generated, because it is typically handled specially.
With the patch, the trunk compiler does not exhibit the bugs in the mentioned PRs (82972, 83088, 85851). I did encounter some issues building and regression testing the trunk compiler which I am certain are unrelated. The current trunk fails to bootstrap for me so I am using an older revision which appears to have some testcase issues. The issues are attached at the bottom of this e-mail for reference. In any case, the changelog is here, and the patch is attached. Aside from the issues mentioned below the compile bootstraps and regression tests successfully. Does this look OK for trunk? Furthermore, this patch comes a bit late as the PRs were submitted before 8.1 was released; is it appropriate to backport this to 7-branch and/or 8-branch? >From b6fbe8e429d5c98675741234e2ac5cc6810df3c5 Mon Sep 17 00:00:00 2001 From: Fritz Reese <fritzore...@gmail.com> Date: Fri, 22 Jun 2018 16:11:02 -0400 Subject: [PATCH] PR fortran/82972 Fix -finit-derived for c_ptr and c_funptr in programs which use iso_c_binding. gcc/fortran/ * expr.c (component_initializer): Assign init expr to c->initializer. (generate_isocbinding_initializer): New. (gfc_generate_initializer): Call generate_isocbinding_initializer to generate initializers for c_ptr and c_funptr with -finit-derived. gcc/testsuite/ * gfortran.dg/init_flag_17.f90: New testcase. --- gcc/fortran/expr.c | 33 +++++++++++++++++++++++++++++- gcc/testsuite/gfortran.dg/init_flag_17.f90 | 28 +++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gfortran.dg/init_flag_17.f90 ======= TEST ISSUES ======= $ gfortran --version GNU Fortran (GCC) 8.0.0 20180110 (experimental) ... $ make -sk check-fortran ... FAIL: gfortran.dg/pr68078.f90 -O0 execution test FAIL: gfortran.fortran-torture/compile/pr83081.f90, -O3 -g (internal compiler error) ... In the first case (pr68078) the process appears to occasionally run out of stack memory due to the setrlimit(), causing it to receive SIGSEGV. $ cd gcc/testsuite/gfortran.dg $ gfortran pr68078.f90 set_vm_limit.c -o pr68078 $ i=0; time while ./a.out >/dev/null; do echo attempt $i; i=$(($i+1)) ; done attempt 0 attempt 1 attempt 2 attempt 3 attempt 4 attempt 5 attempt 6 attempt 7 attempt 8 attempt 9 attempt 10 Segmentation fault (core dumped) real 0m0.104s user 0m0.007s sys 0m0.023s The second case appears positively unrelated (and only occurs with -O3): $ gfortran -c -O3 pr83081.f90 during GIMPLE pass: pcom pr83081.f90:4:0: Subroutine SPLIFT (X,Y,YP,YPP,N,IERR,ISX,A1,B1,AN,BN) internal compiler error: in probability_in, at profile-count.h:1038 0x6f47ee profile_count::probability_in(profile_count) const /data/midas/foreese/src/gcc-trunk/gcc/profile-count.h:1038 0x6f47ee tree_transform_and_unroll_loop(loop*, unsigned int, edge_def*, tree_niter_desc*, void (*)(loop*, void*), void*) /data/midas/foreese/src/gcc-trunk/gcc/tree-ssa-loop-manip.c:1382 0xe36716 tree_predictive_commoning_loop /data/midas/foreese/src/gcc-trunk/gcc/tree-predcom.c:3278 0xe37e7d tree_predictive_commoning() /data/midas/foreese/src/gcc-trunk/gcc/tree-predcom.c:3312 Please submit a full bug report, with preprocessed source if appropriate. Please include the complete backtrace with any bug report. See <https://gcc.gnu.org/bugs/> for instructions. ======= END TEST ISSUES =======
From b6fbe8e429d5c98675741234e2ac5cc6810df3c5 Mon Sep 17 00:00:00 2001 From: Fritz Reese <fritzore...@gmail.com> Date: Fri, 22 Jun 2018 16:11:02 -0400 Subject: [PATCH] PR fortran/82972 Fix -finit-derived for c_ptr and c_funptr in programs which use iso_c_binding. gcc/fortran/ * expr.c (component_initializer): Assign init expr to c->initializer. (generate_isocbinding_initializer): New. (gfc_generate_initializer): Call generate_isocbinding_initializer to generate initializers for c_ptr and c_funptr with -finit-derived. gcc/testsuite/ * gfortran.dg/init_flag_17.f90: New testcase. --- gcc/fortran/expr.c | 33 +++++++++++++++++++++++++++++- gcc/testsuite/gfortran.dg/init_flag_17.f90 | 28 +++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gfortran.dg/init_flag_17.f90 diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c index 45ccc184fc1..ad549911cd1 100644 --- a/gcc/fortran/expr.c +++ b/gcc/fortran/expr.c @@ -4476,7 +4476,7 @@ component_initializer (gfc_typespec *ts, gfc_component *c, bool generate) gfc_apply_init (&c->ts, &c->attr, init); } - return init; + return (c->initializer = init); } @@ -4488,6 +4488,33 @@ gfc_default_initializer (gfc_typespec *ts) return gfc_generate_initializer (ts, false); } +/* Generate an initializer expression for an iso_c_binding type + such as c_[fun]ptr. The appropriate initializer is c_null_[fun]ptr. */ + +static gfc_expr * +generate_isocbinding_initializer (gfc_symbol *derived) +{ + /* The initializers have already been built into the c_null_[fun]ptr symbols + from gen_special_c_interop_ptr. */ + + gfc_symtree *npsym = NULL; + if (0 == strcmp(derived->name, "c_ptr")) + gfc_find_sym_tree("c_null_ptr", gfc_current_ns, true, &npsym); + else if (0 == strcmp(derived->name, "c_funptr")) + gfc_find_sym_tree("c_null_funptr", gfc_current_ns, true, &npsym); + else + gfc_internal_error ("generate_isocbinding_initializer(): bad iso_c_binding" + " type, expected %<c_ptr%> or %<c_funptr%>"); + if (npsym) + { + gfc_expr *init = gfc_copy_expr(npsym->n.sym->value); + init->symtree = npsym; + init->ts.is_iso_c = true; + return init; + } + + return NULL; +} /* Get or generate an expression for a default initializer of a derived type. If -finit-derived is specified, generate default initialization expressions @@ -4498,8 +4525,12 @@ gfc_generate_initializer (gfc_typespec *ts, bool generate) { gfc_expr *init, *tmp; gfc_component *comp; + generate = flag_init_derived && generate; + if (ts->u.derived->ts.is_iso_c && generate) + return generate_isocbinding_initializer(ts->u.derived); + /* See if we have a default initializer in this, but not in nested types (otherwise we could use gfc_has_default_initializer()). We don't need to check if we are going to generate them. */ diff --git a/gcc/testsuite/gfortran.dg/init_flag_17.f90 b/gcc/testsuite/gfortran.dg/init_flag_17.f90 new file mode 100644 index 00000000000..401830fccbc --- /dev/null +++ b/gcc/testsuite/gfortran.dg/init_flag_17.f90 @@ -0,0 +1,28 @@ +! { dg-do compile } +! { dg-options "-finit-derived -finit-local-zero -fdump-tree-original" } +! +! PR fortran/82972 +! +! Make sure we do not ICE when generating initializers for c_ptr and c_funptr +! components of derived types (and make sure they are properly initialized to +! zero). +! + +program init_flag_17 + use iso_c_binding + implicit none + + type :: ty + type(c_ptr) :: ptr ! = c_null_ptr + type(c_funptr) :: fptr ! = c_null_funptr + end type + + type(ty) :: t + + print *, t%ptr + print *, t%fptr + +end program + +! { dg-final { scan-tree-dump "\.ptr=0" "original" } } +! { dg-final { scan-tree-dump "\.fptr=0" "original" } } -- 2.12.2