https://gcc.gnu.org/g:9906a9863d65386ee4045333eb26a2569783abb5
commit r14-10560-g9906a9863d65386ee4045333eb26a2569783abb5 Author: Paul Thomas <pa...@gcc.gnu.org> Date: Thu Jul 18 08:51:35 2024 +0100 Fortran: Suppress bogus used uninitialized warnings [PR108889]. 2024-07-18 Paul Thomas <pa...@gcc.gnu.org> gcc/fortran PR fortran/108889 * gfortran.h: Add bit field 'allocated_in_scope' to gfc_symbol. * trans-array.cc (gfc_array_allocate): Set 'allocated_in_scope' after allocation if not a component reference. (gfc_alloc_allocatable_for_assignment): If 'allocated_in_scope' not set, not a component ref and not allocated, set the array bounds and offset to give zero length in all dimensions. Then set allocated_in_scope. gcc/testsuite/ PR fortran/108889 * gfortran.dg/pr108889.f90: New test. (cherry picked from commit c3aa339ea50f050caf7ed2e497f5499ec2d7b9cc) Diff: --- gcc/fortran/gfortran.h | 4 ++++ gcc/fortran/trans-array.cc | 43 ++++++++++++++++++++++++++++++++++ gcc/testsuite/gfortran.dg/pr108889.f90 | 43 ++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+) diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index de3d9e25911b..fbdf00590bc2 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -1946,6 +1946,10 @@ typedef struct gfc_symbol /* Set if this should be passed by value, but is not a VALUE argument according to the Fortran standard. */ unsigned pass_as_value:1; + /* Set if an allocatable array variable has been allocated in the current + scope. Used in the suppression of uninitialized warnings in reallocation + on assignment. */ + unsigned allocated_in_scope:1; /* Reference counter, used for memory management. diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc index 761f0a425078..d5d9c730826e 100644 --- a/gcc/fortran/trans-array.cc +++ b/gcc/fortran/trans-array.cc @@ -6561,6 +6561,8 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg, else gfc_add_expr_to_block (&se->pre, set_descriptor); + expr->symtree->n.sym->allocated_in_scope = 1; + return true; } @@ -10932,6 +10934,8 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop, stmtblock_t realloc_block; stmtblock_t alloc_block; stmtblock_t fblock; + stmtblock_t loop_pre_block; + gfc_ref *ref; gfc_ss *rss; gfc_ss *lss; gfc_array_info *linfo; @@ -11132,6 +11136,45 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop, array1, build_int_cst (TREE_TYPE (array1), 0)); cond_null= gfc_evaluate_now (cond_null, &fblock); + /* If the data is null, set the descriptor bounds and offset. This suppresses + the maybe used uninitialized warning and forces the use of malloc because + the size is zero in all dimensions. Note that this block is only executed + if the lhs is unallocated and is only applied once in any namespace. + Component references are not subject to the warnings. */ + for (ref = expr1->ref; ref; ref = ref->next) + if (ref->type == REF_COMPONENT) + break; + + if (!expr1->symtree->n.sym->allocated_in_scope && !ref) + { + gfc_start_block (&loop_pre_block); + for (n = 0; n < expr1->rank; n++) + { + gfc_conv_descriptor_lbound_set (&loop_pre_block, desc, + gfc_rank_cst[n], + gfc_index_one_node); + gfc_conv_descriptor_ubound_set (&loop_pre_block, desc, + gfc_rank_cst[n], + gfc_index_zero_node); + gfc_conv_descriptor_stride_set (&loop_pre_block, desc, + gfc_rank_cst[n], + gfc_index_zero_node); + } + + tmp = gfc_conv_descriptor_offset (desc); + gfc_add_modify (&loop_pre_block, tmp, gfc_index_zero_node); + + tmp = fold_build2_loc (input_location, EQ_EXPR, + logical_type_node, array1, + build_int_cst (TREE_TYPE (array1), 0)); + tmp = build3_v (COND_EXPR, tmp, + gfc_finish_block (&loop_pre_block), + build_empty_stmt (input_location)); + gfc_prepend_expr_to_block (&loop->pre, tmp); + + expr1->symtree->n.sym->allocated_in_scope = 1; + } + tmp = build3_v (COND_EXPR, cond_null, build1_v (GOTO_EXPR, jump_label1), build_empty_stmt (input_location)); diff --git a/gcc/testsuite/gfortran.dg/pr108889.f90 b/gcc/testsuite/gfortran.dg/pr108889.f90 new file mode 100644 index 000000000000..7fd4e3882a48 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr108889.f90 @@ -0,0 +1,43 @@ +! { dg-do compile } +! { dg-options "-Wall -fdump-tree-original" } +! +! Contributed by Tobias Burnus <bur...@gcc.gnu.org> +! +program main + implicit none + + type :: struct + real, allocatable :: var(:) + end type struct + + type(struct) :: single + real, allocatable :: ref1(:), ref2(:), ref3(:), ref4(:) + + ref2 = [1,2,3,4,5] ! Warnings here + + single%var = ref2 ! No warnings for components + ref1 = single%var ! Warnings here + ref1 = [1,2,3,4,5] ! Should not add to tree dump count + + allocate (ref3(5)) + ref3 = single%var ! No warnings following allocation + + call set_ref4 + + call test (ref1) + call test (ref2) + call test (ref3) + call test (ref4) + +contains + subroutine test (arg) + real, allocatable :: arg(:) + if (size(arg) /= size(single%var)) stop 1 + if (lbound(arg, 1) /= 1) stop 2 + if (any (arg /= single%var)) stop 3 + end + subroutine set_ref4 + ref4 = single%var ! Warnings in contained scope + end +end +! { df-final { scan-tree-dump-times "ubound = 0" 3 "original" } } \ No newline at end of file