aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authorTobias Burnus <tobias@codesourcery.com>2023-02-25 11:55:08 +0100
committerTobias Burnus <tobias@codesourcery.com>2023-02-25 11:55:42 +0100
commitd3e427f684b0cd7cedbe7b93a06f455e562c5901 (patch)
treef3c68b810b06cc09a7c1e5ebe27b5cf90844e3ba /gcc/fortran
parent4341106354c6a463ce3628a4ef9c1a1d37193b59 (diff)
downloadgcc-d3e427f684b0cd7cedbe7b93a06f455e562c5901.zip
gcc-d3e427f684b0cd7cedbe7b93a06f455e562c5901.tar.gz
gcc-d3e427f684b0cd7cedbe7b93a06f455e562c5901.tar.bz2
Fortran: Skip bound conv in gfc_conv_gfc_desc_to_cfi_desc with intent(out) ptr [PR108621]
When the dummy argument of the bind(C) proc is 'pointer, intent(out)', the conversion of the GFC to the CFI bounds can be skipped: it is not needed and avoids issues with noninit memory. Note that the 'cfi->base_addr = gfc->addr' assignment is kept as the C code of a user might assume that a nullified pointer arrives as NULL (or even a specific value). For instance, gfortran.dg/c-interop/section-{1,2}.f90 assumes the value NULL. Note 2: The PR is about a may-be-uninitialized warning with intent(out). In the PR's testcase, the pointer was nullified and should not have produced that warning. That is a diagnostic issue, now tracked as PR middle-end/108906 as the issue in principle still exists (e.g. with 'intent(inout)'). [But no longer for intent(out).] Note 3: With undefined pointers and no 'intent', accessing uninit memory is unavoidable on the caller side as the compiler cannot know what the C function does (but this usage determines whether the pointer is permitted be undefined or whether the bounds must be gfc-to-cfi converted). gcc/fortran/ChangeLog: PR fortran/108621 * trans-expr.cc (gfc_conv_gfc_desc_to_cfi_desc): Skip setting of bounds of CFI desc for 'pointer,intent(out)'. gcc/testsuite/ChangeLog: PR fortran/108621 * gfortran.dg/c-interop/fc-descriptor-pr108621.f90: New test.
Diffstat (limited to 'gcc/fortran')
-rw-r--r--gcc/fortran/trans-expr.cc6
1 files changed, 6 insertions, 0 deletions
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index e85b53f..045c8b0 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -5673,6 +5673,9 @@ gfc_conv_gfc_desc_to_cfi_desc (gfc_se *parmse, gfc_expr *e, gfc_symbol *fsym)
gfc_add_modify (&block, tmp,
build_int_cst (TREE_TYPE (tmp), attr));
+ /* The cfi-base_addr assignment could be skipped for 'pointer, intent(out)'.
+ That is very sensible for undefined pointers, but the C code might assume
+ that the pointer retains the value, in particular, if it was NULL. */
if (e->rank == 0)
{
tmp = gfc_get_cfi_desc_base_addr (cfi);
@@ -5695,6 +5698,9 @@ gfc_conv_gfc_desc_to_cfi_desc (gfc_se *parmse, gfc_expr *e, gfc_symbol *fsym)
gfc_add_modify (&block, tmp2, fold_convert (TREE_TYPE (tmp2), tmp));
}
+ if (fsym->attr.pointer && fsym->attr.intent == INTENT_OUT)
+ goto done;
+
/* When allocatable + intent out, free the cfi descriptor. */
if (fsym->attr.allocatable && fsym->attr.intent == INTENT_OUT)
{