1

For language interoperability, I want to detect the size of integral type used for enums by the C compiler at configure time. I've already had a look at the following questions:

Specifically, I wish to get rid of the compiler warning by gfortran for source like the following:

SUBROUTINE fwrap(another_int)
  IMPLICIT NONE
  INTEGER, INTENT(in) :: another_int
  ENUM, BIND(c)
    ENUMERATOR :: enu_a, enu_b
  END ENUM
  INTEGER, PARAMETER :: enu_type_kind = KIND(enu_a)
  INTERFACE
    SUBROUTINE wrapped_c(enu) BIND(C, name='wrapped_c')
      IMPORT:: enu_type_kind
      INTEGER(enu_type_kind), VALUE :: enu
    END SUBROUTINE wrapped_c
  END INTERFACE

  IF (another_int < 0_enu_type_kind .OR. &
       another_int > enu_b) &
       CALL abort()
  CALL wrapped_c(INT(another_int, enu_type_kind))
END SUBROUTINE fwrap

Compiler invocation (gfortran 11.1):

$ gfortran -c -o enum-warn.o  -Wall -Wextra -Wconversion -Wstrict-overflow enum-warn.f90
enum-warn.f90:9:28:

    9 |     SUBROUTINE wrapped_c(enu) BIND(C, name='wrapped_c')
      |                            1
Warning: Variable 'enu' at (1) is a dummy argument of the BIND(C) procedure 'wrapped_c' but may not be C interoperable [https://gcc.gnu.org/onlinedocs/gfortran/Error-and-Warning-Options.html#index-Wc-binding-type-Wc-binding-type]

And if I knew that all enums are passed as C int on a platform, I could just substitute c_int for enu_type_kind in the above (which does not raise the warning). I'm not particularly interested in C code that uses __attribute__((packed)) because I'm aiming for portable code, while still getting as few warnings as possible.

TJahns
  • 197
  • 1
  • 9
  • This warning seems problematic if not even buggy. I'd ignore it and ask gfortran devs about the exact meaning here. Steve might be around. – Vladimir F Героям слава Oct 12 '21 at 19:59
  • `by the C compiler at configure time` what is configure time? – 0___________ Oct 12 '21 at 20:05
  • If you use a C `int`, it will probably map to a fortran `INTEGER`. So, if you cast an `enum` to an `int`: `enum myenum xval; fortran_func((int) xval);` then that should be okay. Or, `int ival = xval; fortran_func(ival);` The C compiler will flag these only if the conversion can't be done safely as it knows both sizes. The fortran compiler can't know the size for the C `enum` so it _has_ to warn about it. `gfortran` probably has a command line option for this but casting to / using `int` may be the best way to go – Craig Estey Oct 12 '21 at 20:58
  • @CraigEstey There is a concept of a companion C processor (compiler). So the Fortran compiler should be able to know the C enum size. Alas, the only enums in Fortran are the `bind(C)` ones, there are no non-`bind(C)` enums, they are there precisely to match what C would do. Also, there is no reason to speculate wheter `int` matches `integer`. That's what we have `integer(c_int)` for. It seems to me that the warning is just triggered by a situatiin the compiler writer dis not anticipate. – Vladimir F Героям слава Oct 12 '21 at 21:45
  • In particular, gfortran appears to raise this warning whenever it sees a kind constant that does not come from the `iso_c_binding` module. Probably even when it is a result of `kind()` applied on an entity that is known to be interoperable. I do not believe in code obfuscation just to silence warnings that could be ignored instead. – Vladimir F Героям слава Oct 12 '21 at 21:48
  • @VladimirF My fortran usage stopped with Fortran IV, but I thought I could answer this based on my knowledge/usage of C `enum`--Good to know about `integer(c_int)`. In my [C] code, I pass around an `enum` as an `int` if I have an intermediate function that must just pass the enum as opaque. That is, libA defines the enum and libB does _not_ have the definition and we call: `libAf1(xval) --> libBf2(xval) --> libAf3(xval)`. Also, if the enum had to go into a `struct` that was part of a network protocol, I'd probably use `int32_t` [or equiv] there to ensure all clients matched up. – Craig Estey Oct 12 '21 at 21:59
  • @VladimirF By configure-time I mean that the software in question uses autoconf and I can probe the compiler to create macros in response. It's not as simple as using constants from iso_c_binding directly, i.e. doing `INTEGER, PARAMETER :: some_kind = c_int` in Fortran also takes care of the warning. I'm still kind of wondering if I chose the right way to derive the kind parameter, that's why I didn't file a report to gfortran maintainers yet. – TJahns Oct 12 '21 at 22:24
  • 2
    @VladimirF, it looks like a false-positive. The Fortran standard guarantees that the type of an enum is interoperable. The problem here is that the import statement is simply importing a kind type parameter, which does not convey information about its connection to an enum type. As a working around, the warning might be suppressed with -Wno-c-binding-type option (I have not tried it). Yes, a bug should be reported to GCC. – steve Oct 13 '21 at 04:24
  • I tried something else, chaning the interface block to `SUBROUTINE wrapped_c(enu) BIND(C, name='wrapped_c') IMPORT:: enu_a INTEGER(KIND(enu_a)), VALUE :: enu END SUBROUTINE wrapped_c ` gives the same warning. – TJahns Oct 13 '21 at 11:34
  • 1
    [GCC Bug report filed](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102727) – TJahns Oct 13 '21 at 11:51

0 Answers0