https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103828

--- Comment #2 from Francois-Xavier Coudert <fxcoudert at gcc dot gnu.org> ---
So, even modifying gfc_sym_type() in trans-types.c to emit the proper type does
not fix the issue. Why? Because the rug is pulled under our feet later. Turns
out there is a function that deals with this, much later in the front-end:
gfc_conv_scalar_char_value()

But that function is really wrong. It's called in generate_local_decl(), which
says:

       /* Modify the tree type for scalar character dummy arguments of bind(c)
         procedures if they are passed by value.  The tree type for them will
         be promoted to INTEGER_TYPE for the middle end, which appears to be
         what C would do with characters passed by-value.  The value attribute
         implies the dummy is a scalar.  */

and gfc_conv_scalar_char_value() does this:

       /* This becomes the nominal_type in
         function.c:assign_parm_find_data_types.  */
       TREE_TYPE (sym->backend_decl) = unsigned_char_type_node;
       /* This becomes the passed_type in
         function.c:assign_parm_find_data_types.  C promotes char to
         integer for argument passing.  */
       DECL_ARG_TYPE (sym->backend_decl) = unsigned_type_node;

But this is completely wrong. In C, `char` arguments are only promoted to `int`
when the destination type is unknown, i.e., in unprototyped functions (K&R
style) or variadic arguments. C interoperability only interoperates with
prototyped C functions, so this promotion should not happen, and `char` should
be passed as `char`!

I am attaching the patch under testing.

Reply via email to