For the code implicit none integer, allocatable :: v(:) character(len=1), allocatable :: a(:) a = ["a"] print*, a v = [10,20] print*,v end gfortran -Wall -Wextra xgfortran_warn.f90 gives many incorrect warnings: xgfortran_warn.f90:4:9: 4 | a = ["a"] | ^ Warning: 'a.offset' is used uninitialized [-Wuninitialized] xgfortran_warn.f90:3:37: 3 | character(len=1), allocatable :: a(:) | ^ note: 'a' declared here xgfortran_warn.f90:4:9: 4 | a = ["a"] | ^ Warning: 'a.dim[0].lbound' is used uninitialized [-Wuninitialized] xgfortran_warn.f90:3:37: 3 | character(len=1), allocatable :: a(:) | ^ note: 'a' declared here xgfortran_warn.f90:4:9: 4 | a = ["a"] | ^ Warning: 'a.dim[0].ubound' is used uninitialized [-Wuninitialized] xgfortran_warn.f90:3:37: 3 | character(len=1), allocatable :: a(:) | ^ note: 'a' declared here xgfortran_warn.f90:4:9: 4 | a = ["a"] | ^ Warning: 'a.dim[0].lbound' may be used uninitialized [-Wmaybe-uninitialized] xgfortran_warn.f90:3:37: 3 | character(len=1), allocatable :: a(:) | ^ note: 'a' declared here xgfortran_warn.f90:4:9: 4 | a = ["a"] | ^ Warning: 'a.dim[0].ubound' may be used uninitialized [-Wmaybe-uninitialized] xgfortran_warn.f90:3:37: 3 | character(len=1), allocatable :: a(:) | ^ note: 'a' declared here xgfortran_warn.f90:4:9: 4 | a = ["a"] | ^ Warning: 'a.dim[0].ubound' may be used uninitialized [-Wmaybe-uninitialized] xgfortran_warn.f90:3:37: 3 | character(len=1), allocatable :: a(:) | ^ note: 'a' declared here xgfortran_warn.f90:4:9: 4 | a = ["a"] | ^ Warning: 'a.dim[0].lbound' may be used uninitialized [-Wmaybe-uninitialized] xgfortran_warn.f90:3:37: 3 | character(len=1), allocatable :: a(:) | ^ note: 'a' declared here The output is the same for gfortran 12.0.1 20220213 on Windows from equation.com and gfortran-11 on WSL2. The code combines two codes from a Fortran Discourse discussion https://fortran-lang.discourse.group/t/gfortran-uninitialized-warnings/3838 .
I see that the report is a duplicate of some reports listed at https://fortran-lang.discourse.group/t/gfortran-uninitialized-warnings/3838/4 56670 – Allocatable-length character var causes bogus warning with -Wuninitialized 1 91442 – Wrong "may be used uninitialized" warning with allocation on assignment 77504 – [10/11/12/13 Regression] "is used uninitialized" with allocatable string and array constructors
*** Bug 106108 has been marked as a duplicate of this bug. ***
Removed 'diagnostic' keyword. This is much worse than just a bad diagnostic. Consider a much shorter testcase. program foo integer, allocatable :: i(:) i = [1,1] if (any(i /= 1)) stop end program foo % gfortran11 -Wall -c a.f90 |& grep -i warn Warning: 'i.offset' is used uninitialized [-Wuninitialized] Warning: 'i.dim[0].lbound' is used uninitialized [-Wuninitialized] Warning: 'i.dim[0].ubound' is used uninitialized [-Wuninitialized] Warning: 'i.dim[0].lbound' may be used uninitialized [-Wmaybe-uninitialized] Warning: 'i.dim[0].ubound' may be used uninitialized [-Wmaybe-uninitialized] Warning: 'i.dim[0].ubound' may be used uninitialized [-Wmaybe-uninitialized] Warning: 'i.dim[0].lbound' may be used uninitialized [-Wmaybe-uninitialized] With the patch that follows, I get % gfcx -Wall -c a.f90 |& grep -i warn Warning: 'i.offset' is used uninitialized [-Wuninitialized] Warning: 'i.dim[0].lbound' is used uninitialized [-Wuninitialized] Warning: 'i.dim[0].ubound' is used uninitialized [-Wuninitialized] so 4 of the rogue warnings are no longer issued. diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc index 05134952db4..793e6a21e6d 100644 --- a/gcc/fortran/trans-array.cc +++ b/gcc/fortran/trans-array.cc @@ -10734,27 +10734,27 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop, /* If the lhs shape is not the same as the rhs jump to setting the bounds and doing the reallocation....... */ - for (n = 0; n < expr1->rank; n++) + if (expr1->shape) { - /* Check the shape. */ - lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[n]); - ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[n]); - tmp = fold_build2_loc (input_location, MINUS_EXPR, - gfc_array_index_type, - loop->to[n], loop->from[n]); - tmp = fold_build2_loc (input_location, PLUS_EXPR, - gfc_array_index_type, - tmp, lbound); - tmp = fold_build2_loc (input_location, MINUS_EXPR, - gfc_array_index_type, - tmp, ubound); - cond = fold_build2_loc (input_location, NE_EXPR, - logical_type_node, - tmp, gfc_index_zero_node); - tmp = build3_v (COND_EXPR, cond, - build1_v (GOTO_EXPR, jump_label1), - build_empty_stmt (input_location)); - gfc_add_expr_to_block (&fblock, tmp); + for (n = 0; n < expr1->rank; n++) + { + /* Check the shape. */ + lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[n]); + ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[n]); + tmp = fold_build2_loc (input_location, MINUS_EXPR, + gfc_array_index_type, + loop->to[n], loop->from[n]); + tmp = fold_build2_loc (input_location, PLUS_EXPR, + gfc_array_index_type, tmp, lbound); + tmp = fold_build2_loc (input_location, MINUS_EXPR, + gfc_array_index_type, tmp, ubound); + cond = fold_build2_loc (input_location, NE_EXPR, + logical_type_node, tmp, gfc_index_zero_node); + tmp = build3_v (COND_EXPR, cond, + build1_v (GOTO_EXPR, jump_label1), + build_empty_stmt (input_location)); + gfc_add_expr_to_block (&fblock, tmp); + } } /* ...else if the element lengths are not the same also go to So, what's the problem. The scalarizer is broken, which was originally written before (re)allocation of the LHS was introduced to Fortran. The above is not valid Fortran 95. The LHS and RHS of the assignment must be conformable. This means that, if an error had not been emitted, then the LHS and RHS have the same array descriptor. This leads to two problems. The first is the scalarizer appears to write the descriptors into the intermediate representation (IR). % gfortran11 -Wall -c a.f90 -fdump-tree-original % more a.f90.005t.original (NOte inline annotations) void foo () { struct array01_integer(kind=4) i; i.data = 0B; i.dtype = {.elem_len=4, .rank=1, .type=1}; { *** This is the descriptor for the RHS integer(kind=4)[0:] * restrict D.3943; integer(kind=8) D.3944; integer(kind=8) D.3945; integer(kind=8) D.3946; static integer(kind=4) A.0[2] = {1, 1}; integer(kind=8) D.3949; *** end RHS *** This is the descriptor for the LHS D.3943 = (integer(kind=4)[0:] * restrict) i.data; D.3944 = i.offset; D.3945 = i.dim[0].lbound; D.3946 = i.dim[0].ubound; *** end LHS D.3943 is a validate expression. D.3944, D.3945, and D.3946 are the cause of 3 warnings; and in fact, these are the three that remain after my patch above is applied. Due to the complexity of scalarization, I have been unable to find where the code is added to the IR. Now, when (re)allocation on assignment was introduced, it seems the checking assumed that LHS had already been allocated (i.e., it has a proper descriptor). So, the descriptor for the LHS was used to build the information need to determine if reallocation was need. Fortunately, an initially unallocated allocated has its expr->shape pointer set to NULL. I use this in the above patch to block the use of the LHS descriptor.
I am closing this PR, since it is fixed on mainline by pr108889 and will be backported in due course. Paul