I have run into an issue in one of our large programs where a DATA statement is used to initialize the values within array slices of a 2-D array, but leaving some slices uninitialized. While I understand that one cannot use a data statement to initialize the whole array to some value and then another data statement for assigning specific values for certain elements of the array, I am a bit surprised that the /Qinit:snan /Qinit:arrays compiler switches do not set elements that were 'untouched' to signal NaN. The latter is what I had hoped for (and it would have allowed me to catch an error in the code). The current behavior left me with the false believe that I would be able to catch such issues.
Here is a simple example:
program Test_data_statement implicit none integer :: i real,dimension(3,3) :: rtab real,dimension(3,1) :: rlist data rtab / 6 * -777.7 / !first array value initialization with data statement; note that only 6 out of 9 array entries are initialized data rtab(1:3,2) / 0.21, 0.0, 0.23 / !second attempted data initialization of array slice (not conforming with Fortran standard) !data rtab(1:3,3) / 0.31, 0.0, 0.33 / !this array slice initialization via data statement would be valid (since slice not initialized above). write(*,*) 'rtab:' do i = 1,3 write(*,'(3(F9.2, 1X))') rtab(:,i) end do write(*,*) '' write(*,*) 'rlist:' write(*,'(3(F9.2, 1X))') rlist(:,1) read(*,*) end program Test_data_statement !Intel(R) Visual Fortran Compiler version 126.96.36.199 issues a warning message for line 9: !warning #6956: In this DATA statement, there are more variables than values assigned to the variables. [RTAB] !rtab: ! -777.70 -777.70 -777.70 ! -777.70 -777.70 -777.70 ! 0.00 0.00 0.00 !Q: why are these values not 'NaN' when using /Qinit:snan /Qinit:arrays command line switches? ! !rlist: ! NaN NaN NaN !gfortran (gcc version 9.3.0) issues an error for line 9: !Error: DATA statement at (1) has more variables than values
The code on line 10 shows an example of what was done in our original program at first, leading to unintended consequences. It would be useful if the compiler would issue an error or at least a warning about the repeated use of a DATA statement involving the same array elements. A warning is only stated that not all elements were initialized (for line 9).
Using the command line options /Qinit:snan /Qinit:arrays, I would have expected that the third line in the output for rtab would show NaN and not 0.0, similar to the output for rlist. Am I wrong about this expectation or is the compiler not supposed to honor the /Qinit:snan /Qinit:arrays flags in the context of DATA use?
full command line from VS:
/nologo /debug:full /Od /standard-semantics /warn:all /debug-parameters:all /Qinit:snan /Qinit:arrays /module:"x64\Debug\\" /object:"x64\Debug\\" /Fd"x64\Debug\vc160.pdb" /traceback /check:bounds /check:shape /check:uninit /libs:dll /threads /dbglibs /c
The compiler believes that you initialized the array, so it doesn't generate code to fill in just the elements you skipped over.
As you probably know the /Qinit options are a dirty fix to old/bad coding practices of the past. I appreciate the task of fixing can be too big a task but at lease aim to fix segments of code that you work on then the task gets smaller over time.
You are looking for a convenience from your compiler vendor to overcome code deficiencies, so you can petition your vendor to see if they appreciate your need.
For your actual code, given its size. legacy, etc., your choice may be limited but if some refactoring is possible and your compiler support allows, you can consider using IEEE facilities in the standard in conjunction with an indexing scheme. See a simple example below:
use, intrinsic :: ieee_arithmetic, only : ieee_value, ieee_quiet_nan integer :: i real :: x(9) integer, parameter :: nelem = 6 integer, parameter :: idx(size(x)) = [ [( 1, i=1,nelem )], [( 0, i=nelem+1,size(x) )] ] data x(1:nelem) / nelem * 42.0 / ! Aaray section initialization where ( idx == 0 ) x = ieee_value( x, ieee_quiet_nan ) print *, "x = ", x end
Here's the program response using 2 different compilers with standard option:
C:\Temp>ifort /standard-semantics p.f90 Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 188.8.131.52 Build 20200623 Copyright (C) 1985-2020 Intel Corporation. All rights reserved. Microsoft (R) Incremental Linker Version 14.26.28806.0 Copyright (C) Microsoft Corporation. All rights reserved. -out:p.exe -subsystem:console p.obj C:\Temp>p.exe x = 42.00000 42.00000 42.00000 42.00000 42.00000 42.00000 NaN NaN NaN C:\Temp>x86_64-w64-mingw32-gfortran.exe -std=f2018 p.f90 -o p.exe C:\Temp>p.exe x = 42.0000000 42.0000000 42.0000000 42.0000000 42.0000000 42.0000000 NaN NaN NaN C:\Temp>
By the way, can you confirm you are aware the use of DATA statement causes "implied SAVE" attribute and which can affect subprogram semantics, hinder multithreading, parallelization etc.?
Thanks to all for your replies.
I am aware of the implied SAVE with use of DATA statements. I also would not recommend using /Qinit:zero unless for good reasons in legacy code. My issue was simply that the use of /Qinit:snan in this case did not help (and essentially prevented) trapping of missed/erroneous initialization statements in the code and relying on /Qinit:snan in terms of detecting missed initializations is therefore not recommended in the case of arrays initialized by DATA, which may be good to know for others too. In cases of other scalar variables and arrays, it has been a useful feature offered by the Intel compiler.
I will replace such DATA statements from older code sections by other / better ways of data initialization. In the use case of our code, DATA was most often used to initialize, within a module declaration part, large tables of array values that are constants. In such a case, a better approach is to replace those initializations with PARAMETER statements for the arrays.