Janne Blomqvist wrote:
On Fri, Dec 28, 2012 at 12:31 AM, Tobias Burnus <bur...@net-b.de> wrote:
a) The Fortran standard only defines LOGICAL(kind=C_Bool) as being
interoperable with C - no other LOGICAL type. That matches GCC: With gcc
(the C compiler) only _Bool is a BOOLEAN_TYPE with TYPE_PRECISION == 1.
Hence, this patch rejects other logical kinds as dummy argument/result
variable in BIND(C) procedures if -std=f2003/f2008/f2008ts is specified
(using -pedantic, one gets a warning).
Sorry, I don't understand, what is the -pedantic warning about if it's
already rejected? Or do you mean std=gnu -pedantic?
The latter. Actually, I use "gfc_notify_std(GFC_STD_GNU, ..." and just
observed the -pedantic result. (I have to admit that I never quite
understood - and still don't - what -pedantic exactly does.)
b) As GNU extension, other logical kinds are accepted in BIND(C) procedures;
however, as the main use of "LOGICAL(kind=4)" (for BIND(C) procedures) is to
handle logical expressions which use C's int, one has to deal with all
integer values and not only 0 and 1. Hence, a normal integer type is used
internally in that case. That has been done to avoid surprises of users and
hard to trace bugs.
Does this actually work robustly?
I think it does in the sense that it mitigates the problems related to
LOGICAL(kind=4) and BIND(C) procedures. No, if one thinks of it as full
cure for the problem. The only way to ensure this is to turn all of
gfortran's LOGICALs into integers - and even that won't prevent issues
related to interoperability with C's _Bool as that one expects only 0
and 1. Thus, either C<->Fortran or Fortran <-> Fortran
logical(kind=C_Bool) could still lead to problems.
E.g. if you have a logical but really integer under the covers, what happens if you
equivalence it with a "normal" logical variable.
Well, equivalencing of actual arguments / result variables is not
allowed (I think, not checked). Besides, if you have equivalenced two
variables, if you have set one, you may not access the other, e.g.:
logical :: A
integer :: B
equivalence (A,B)
A = .true.
B = 1
if (A) ...
is invalid as "A" is not defined, even if A = .true. and B = 1 have
exactly the same storage size and bit patterns and, hence, in practice
"A" would be a well defined .true.
Or pass it as an argument to a procedure expecting a normal logical etc.
If the value is only 1 or 0, there shouldn't be any problems. Only if
one uses in turn ".not. dummy" there might be one.
The idea of the patch was only to mitigate the problems - a full cure is
not possible (cf. above). I think the most likely problematic code is
if (.not. c_function())
which is fixed by the patch. And the hope is that fold-converting to a
type-precision=1, Boolean-type logical fixes most of the remaining issues.
I think the current solution which only affects non-C_BOOL-kind actual
arguments and result variables of BIND(C) procedures is a good compromise.
* * *
But if others do not like this approach, one could turn the
gfc_notify_std into a gfc_error are completely reject logicals with
kinds /= C_Bool for dummy arguments/result variables in BIND(C)
procedures. Would you prefer that approach?
(Doing so will break user code (e.g. Open MPI) and make users unhappy
but it will be a tad safer as the current patch.)
Tobias