Fortran (re-)allocation on assignment and gfortran warnings - fortran

A simple code:
program main
integer, allocatable :: A(:,:)
integer :: B(3,4)
B=1
A = B !A will get allocated, with the same shape and bounds as B
end program main
Compiling the above code with: gfortran-8 -std=f2008 -fcheck=all -Wall -Wextra -fbounds-check -fimplicit-none array.f90
I got the following warning:
Warning: ‘a.offset’ may be used uninitialized in this function
Warning: ‘a.dim[0].lbound’ may be used uninitialized in this function
Warning: ‘a.dim[0].ubound’ may be used uninitialized in this function [-Wmaybe-uninitialized]
Is there somebody having an idea of why I got these warnings?

This is a well known GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77504 that has been reported in many duplicates to the bugzilla (even by myself) - see the Duplicates section for the other incarnations.
As far as I understand it the actual code generated by the compiler should work correctly and it is just an incorrect warning. As Steve pointed out in the comment, use -Wno-maybe-uninitialized to hide this warning. I have included it into my build scripts as well.

Related

Bound checking for empty arrays --- behavior of various compilers

Update 20210914: Absoft support confirms that the behavior of af95 / af90 described below is unintended and indeed a bug. Absoft developers will work to resolve it. The other compilers act correctly in this regard. Thank #Vladimir F for the answer, comments, and suggestions.
I have the impression that Fortran is cool with arrays of size 0. However, with Absoft Pro 21.0, I encountered a (strange) error involving such arrays. In contrast, gfortran, ifort, nagfor, pgfortran, sunf95, and g95 are all happy with the same piece of code.
Below is a minimal working example.
! testempty.f90
!!!!!! A module that offends AF90/AF95 !!!!!!!!!!!!!!!!!!!!!!!!
module empty_mod
implicit none
private
public :: foo
contains
subroutine foo(n)
implicit none
integer, intent(in) :: n
integer :: a(0)
integer :: b(n - 1)
call bar(a) ! AF90/AF95 is happy with this line.
call bar(b) ! AF90/AF95 is angry with this line.
end subroutine foo
subroutine bar(x)
implicit none
integer, intent(out) :: x(:)
x = 1 ! BAR(B) annoys AF90/AF95 regardless of this line.
end subroutine bar
end module empty_mod
!!!!!! Module ends !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!! Main program !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
program testempty
use empty_mod, only : foo
implicit none
call foo(2) ! AF90/AF95 is happy with this line.
call foo(1) ! AF90/AF95 is angry with this line.
write (*, *) 'Succeed!' ! Declare victory when arriving here.
end program testempty
!!!!!! Main program ends !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Name this piece of code as testempty.f90. Then run
$ af95 -no-pie -et -Rb -g -O0 -o atest testempty.f90
$ ./atest
This is what happened on my machine (Ubuntu 20.04, linux 5.4.0-77-generic, x86_64):
./atest
? FORTRAN Runtime Error:
? Subscript 1 is out of range for dimension 1 for array
? B with bounds 1:
? File testempty.f90; Line 19
? atest, run-time exception on Mon Sep 13 14:08:41 2021
? Program counter: 000000001004324B
? Signal SIGABRT, Abort
? Traceback follows
OBJECT PC ROUTINE LINE SOURCE
libpthread.so.0 000000001004324B raise N/A N/A
atest 00000000004141F3 __abs_f90rerr N/A N/A
atest 000000000041CA81 _BOUNDS_ERROR N/A N/A
atest 00000000004097B4 __FOO.in.EMPTY_MO N/A N/A
atest 000000000040993A MAIN__ 40 testempty.f90
atest 000000000042A209 main N/A N/A
libc.so.6 000000000FD0C0B3 __libc_start_main N/A N/A
atest 000000000040956E _start N/A N/A
So af95 was annoyed by call bar(b). With af90, the result was the same.
I tested the same code using gfortran, ifort, nagfor, pgfortran, sunf95, and g95. All of them were quite happy with the code even though I imposed bound checking explicitly. Below is the Makefile for the tests.
# This Makefile tests the following compilers on empty arrays.
#
# af95: Absoft 64-bit Pro Fortran 21.0.0
# gfortran: GNU Fortran (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
# ifort: ifort (IFORT) 2021.2.0 20210228
# nagfor: NAG Fortran Compiler Release 7.0(Yurakucho) Build 7036
# pgfortran: pgfortran (aka nvfortran) 21.3-0 LLVM 64-bit x86-64
# sunf95: Oracle Developer Studio 12.6
# g95: G95 (GCC 4.0.3 (g95 0.94!) Jan 17 2013)
#
# Tested on Ubuntu 20.04 with Linux 5.4.0-77-generic x86_64
.PHONY: test clean
test:
make -s gtest
make -s itest
make -s ntest
make -s ptest
make -s stest
make -s 9test
make -s atest
gtest: FC = gfortran -Wall -Wextra -fcheck=all
itest: FC = ifort -warn all -check all
ntest: FC = nagfor -C
ptest: FC = pgfortran -C -Mbounds
stest: FC = sunf95 -w3 -xcheck=%all -C
9test: FC = g95 -Wall -Wextra -fbounds-check
atest: FC = af95 -no-pie -et -Rb
%test: testempty.f90
$(FC) -g -O0 -o $# $<
./$#
clean:
rm -f *.o *.mod *.dbg *test
Questions:
Is the behavior of af95/af90 standard-conforming?
Does my code contain anything that violates the Fortran standards?
In general, is it considered dangerous to involve empty arrays in Fortran code? Sometimes they are inevitable given the fact the data sizes are often undecidable before runtime.
By "standards", I mean 2003, 2008, and 2018.
Thank you very much for any comments or criticism.
(The same question is posed on Fortran Discourse, and I hope it does not violate the rules here.)
The program looks OK to me. Zero-sized arrays are perfectly possible in Fortran although I admit I normally do not have automatic ones - but that is just a coincidence.
I think it is a compiler bug in the Absoft compiler or its array bounds checker.

Strange behavior of "gfortran -Wconversion"

Consider the following code.
! test.f90
program test
use iso_fortran_env, only: INT64, REAL64
print *, real(0_INT64, REAL64)
print *, real(1000_INT64, REAL64)
print *, real(huge(0_INT64), REAL64)
end program test
When compiling it with gfortran in the following way:
$ gfortran -Wconversion -std=f2008 test.f90
I got the following warning:
test.f90:5:18:
5 | print *, real(huge(0_INT64), REAL64)
| 1
Warning: Change of value in conversion from ‘INTEGER(8)’ to ‘REAL(8)’ at (1) [-Wconversion]
Note that gfortran is happy with the first two conversions, but not the last one.
Question: Is the warning illustrated above an expected behavior of gfortran? I thought that NO warning should be produced in any of the three cases, since the conversion is done explicitly by REAL( , INT64).
Here is the version information of my gfortran:
$ gfortran --version
GNU Fortran (Ubuntu 9.3.0-10ubuntu2) 9.3.0
As a reference, ifort 19.1.127 compiles test.f90 without any complaint:
$ ifort -warn all -stand f08 test.f90
Thank you very much for any comments or critics.
Answer by #dave_thompson_085 in the comments:
“0 and 1000 can be represented exactly in REAL64 (and even in REAL32). HUGE(INT64) is 9223372036854775807 and it cannot. REAL64 has 53 bits for the 'mantissa' (really, significand), and after subtracting the sign and adding the hidden bit this supports just under 16 decimal digits of magnitude. 9223372036854775807 is 19 decimal digits. This is not a diagnostic required by the standard, so it's up to each 'processor' (compiler) what to do about it.”
Thank you very much, #dave_thompson_085.

Compiling with gfortran and ifort

I am trying to compile a large group of codes for solving a physics problem. I usually use gfortran. There is no compile time error. My gfortran compiler statement is
gfortran -fdefault-real-8 -O -Waliasing -Wampersand -Wconversion -Wsurprising -Wintrinsics-std -Wintrinsic-shadow -Wline-truncation -Wreal-q-constant
When executed, I get a runtime error
Program received signal SIGBUS: Access to an undefined portion of a memory object.
But this runtime error does not occur, when I compile with the debugging flag -g or with Intel compiler ifort.
Even with gfortran without the -g flag, sometime this error does not occur! I know that this can be caused by some undefined array or unallocated array or something like this. My problem is that I can not seem to find out where is problem as apparently, I have no compile-time error.
So, is there a compiler flag for gfortran or for ifort which can help me detect this error?
Thanks
Madhurjya

How to deal with warnings about tail-padded arrays in C++?

I'm writing a C++ application which uses a C library that defines a tail-padded structure in one of its headers. Without going into too much details, it looks somewhat like this:
struct MyStruct {
// ... other members
// The last member, a tail-padding array
MyType myBuffer[];
}
I use -Wall -Wextra -Wpedantic -Werror with g++ and -std=c++0x.
Unfortunately, g++ gives me a warning about that array:
error: ISO C++ forbids zero-size array 'myBuffer' [-Wpedantic]
What is the right way to deal with this?
I know I can suppress the warning by adding a pragma to the header myself:
#pragma GCC diagnostic ignored "-Wpedantic"
But that doesn't feel right. What do you guys suggest?
You could
Remove the zero-sized array.
Build without -Wpedantic (possibly only for that file).
Build without -Werror and ignore the warning.
Build the code as C.

Unexpected output from Clang

I've been testing out clang-llvm to see if it is worth it to mention to my school's IT department to add it to the machines we students program on. For all of our assignments, we are required to compile using g++ -Wall -W -pedantic-errors *.cpp, so I just converted the command to clang++ -Wall -W -pedantic-errors. I got some output that I wasn't expecting:
Attempting to compile...
In file included from test_library.cpp:6:
In file included from ./test_library.h:64:
In file included from ./library.h:167:
./library.hpp:20:23: warning: unused variable 'e' [-Wunused-variable]
catch(Exception & e)
^
Whereas the GCC compiler does not give an error about unused variables in the catch block. Is there anything I can do so that Clang does not freak out about unused variables in try/catch blocks while keeping the command similar to the g++ one?
Clang-LLVM(v2.7) GNU GCC(v4.4.4) Fedora 13
I kinda agree with Mike, but for getting-off-the-ground's sake, try this:
clang++ -Wall -W -pedantic-errors -Wno-unused-variable
I haven't used llvm much but I think the point of the [-Wunused-variable] in the diagnostic is to tell you that you can shut that warning up with -Wno-unused-variable.
What's wrong with catching exception with "catch(Exception &)" if you are not using the variable? You compilers AND your code reviewers will be happier.