Message ID | trinity-40b5eb30-1e93-481c-8dac-ba523821704c-1605392105473@3c-app-gmx-bs60 |
---|---|
State | New |
Headers | show |
Series | [v1] PR fortran/48958 - Add runtime diagnostics for SIZE intrinsic function | expand |
Hi Harald,
> Feedback, such as comments for improvement, are welcome.
It feels a bit strange to have a check for an allocatable
behind -fcheck=pointer, but I'm not sure that introducing
a special check option would really be worth it.
Regarding pointers: They are usually not nullified (unless
they are global). What do people think about adding a
NULL initializer to their data components when -fcheck=pointer is in
force?
On the other hand, for code like
module p
contains
subroutine foo
real, pointer, dimension(:) :: pp
print *,pp
end subroutine foo
end module p
we at least get a warning already.
Regarding size(x%re): You would have to chase the refs to find
the allocatable components.
However, I think your patch already makes the situation better for
the user, so I'd say it is good for trunk already; later improvements
are always possible.
Best regards
Thomas
Hi Thomas, thanks for the comments. > It feels a bit strange to have a check for an allocatable > behind -fcheck=pointer, but I'm not sure that introducing > a special check option would really be worth it. Yes, I thought about that. There's already a discrepancy between the GFC_RTCHECK_* in libgfortran.h, which has #define GFC_RTCHECK_DO (1<<3) #define GFC_RTCHECK_POINTER (1<<4) #define GFC_RTCHECK_MEM (1<<5) without the latter being documented, and gfortran.texi, which has [...] GFC_RTCHECK_DO (16), GFC_RTCHECK_POINTER (32), [...] -fcheck=mem should be checking memory allocations for things other than allocate (according to invoke.texi), like temporaries. -fcheck=pointer says: Enable generation of run-time checks for pointers and allocatables. So that is at least consistent. (Note to self: submit patch for obvious documentation fixes). > Regarding pointers: They are usually not nullified (unless > they are global). What do people think about adding a > NULL initializer to their data components when -fcheck=pointer is in > force? I was surprised when looking at the dump-tree difference of integer, pointer :: a(:) vs. integer, pointer :: a(:) => NULL() The latter has the expected: static struct array01_integer(kind=4) a = {.data=0B}; while the former has: struct array01_integer(kind=4) a; a.span = 0; Why setting .span at all, and not setting a.data = 0B ? > Regarding size(x%re): You would have to chase the refs to find > the allocatable components. I was probably too tired and drifted off from the subject. This is a more generic issue and not related to size(). > However, I think your patch already makes the situation better for > the user, so I'd say it is good for trunk already; later improvements > are always possible. Yes. Will commit soon. Thanks again, Harald
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c index e0afc10d105..d17b623924c 100644 --- a/gcc/fortran/trans-intrinsic.c +++ b/gcc/fortran/trans-intrinsic.c @@ -7929,6 +7929,35 @@ gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr) && strcmp (e->ref->u.c.component->name, "_data") == 0) sym = e->symtree->n.sym; + if ((gfc_option.rtcheck & GFC_RTCHECK_POINTER) + && e + && (e->expr_type == EXPR_VARIABLE || e->expr_type == EXPR_FUNCTION)) + { + symbol_attribute attr; + char *msg; + + attr = gfc_expr_attr (e); + if (attr.allocatable) + msg = xasprintf ("Allocatable argument '%s' is not allocated", + e->symtree->n.sym->name); + else if (attr.pointer) + msg = xasprintf ("Pointer argument '%s' is not associated", + e->symtree->n.sym->name); + else + goto end_arg_check; + + argse.descriptor_only = 1; + gfc_conv_expr_descriptor (&argse, actual->expr); + tree temp = gfc_conv_descriptor_data_get (argse.expr); + tree cond = fold_build2_loc (input_location, EQ_EXPR, + logical_type_node, temp, + fold_convert (TREE_TYPE (temp), + null_pointer_node)); + gfc_trans_runtime_check (true, false, cond, &argse.pre, &e->where, msg); + free (msg); + } + end_arg_check: + argse.data_not_needed = 1; if (gfc_is_class_array_function (e)) { diff --git a/gcc/testsuite/gfortran.dg/pr48958.f90 b/gcc/testsuite/gfortran.dg/pr48958.f90 new file mode 100644 index 00000000000..2b109374f40 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr48958.f90 @@ -0,0 +1,25 @@ +! { dg-do run } +! { dg-options "-fcheck=pointer -fdump-tree-original" } +! { dg-shouldfail "Fortran runtime error: Allocatable argument 'a' is not allocated" } +! { dg-output "At line 13 .*" } +! PR48958 - Add runtime diagnostics for SIZE intrinsic function + +program p + integer :: n + integer, allocatable :: a(:) + integer, pointer :: b(:) + class(*), allocatable :: c(:) + integer :: d(10) + print *, size (a) + print *, size (b) + print *, size (c) + print *, size (d) + print *, size (f(n)) +contains + function f (n) + integer, intent(in) :: n + real, allocatable :: f(:) + end function f +end + +! { dg-final { scan-tree-dump-times "_gfortran_runtime_error_at" 4 "original" } }