Re: [PATCH] fortran: C++ support for generating C prototypes

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] fortran: C++ support for generating C prototypes

Thomas Koenig-6
Am 12.05.19 um 10:29 schrieb Janne Blomqvist:
> Thanks, committed as r271106. I prefixed the macros with __GFORTRAN_,
> as that seems clearer to users where those come from as gfc seems used
> mostly in the compiler internals.

Sounds good.

> Any opinions whether it should be committed to 9 as well?

Well, we just introduced this feature :-)  Your change makes it
more useful, and it's not like gcc-9 has a long history
with the current format.

So, OK from my side for gcc-9 as well.

I just hope that using this option will not keep people from
using the standard C interop feature...

Next task would be to generate prototypes for extended
C interop (but not today).

Regards

        Thomas
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] fortran: C++ support for generating C prototypes

Jakub Jelinek
On Sun, May 12, 2019 at 10:36:09PM +0300, Janne Blomqvist wrote:

> On Sun, May 12, 2019 at 11:29 AM Janne Blomqvist
> <[hidden email]> wrote:
> >
> > On Sun, May 12, 2019 at 11:06 AM Thomas Koenig <[hidden email]> wrote:
> > > (I thought for a second about guarding about double inclusion, but
> > > including prototypes twice is harmless, and this should be the
> > > user's responsibility).
> >
> > I thought about adding include guards as well, but the problem is that
> > we don't know which name the end user wants to save the output as.
>
> But, we can of course use the source file name instead of the usual
> header name for the include guard. Like in the attached patch. Ok for

There are many characters that can appear in filenames and can't appear in
macro names, /, <, >, :, ;, many others.  Either you need to replace them
all with _ but then you risk collisions, or add some way how to encode the
characters you can't put in directly (say _7b etc.), or instead use
_GFORTRAN_GUARD_<crc or sha256sum etc. of filename>

        Jakub
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] fortran: C++ support for generating C prototypes

Thomas König
In reply to this post by Thomas Koenig-6
Hi Janne,

I do not think we need to add header guards.

The headers, as we emit them, contain prototypes only, so repeated inclusions
Should be harmless.

So. the potential disadvantage would be a teeny bit of compilation time vs the chance of header macro collision and resulting wrong code.

Filenames can be duplicates,
and eventually the responsibility should be the user‘s.

Finally, I want people to read the comment about this not being recommended 😉
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] fortran: C++ support for generating C prototypes

Jakub Jelinek
In reply to this post by Thomas Koenig-6
On Sun, May 12, 2019 at 12:47:04AM +0300, Janne Blomqvist wrote:

> --- a/gcc/fortran/parse.c
> +++ b/gcc/fortran/parse.c
> @@ -6331,6 +6331,24 @@ done:
>        }
>  
>    /* Dump C prototypes.  */
> +  if (flag_c_prototypes || flag_c_prototypes_external)
> +    {
> +      fprintf (stdout,
> +       _("#include <stddef.h>\n"
> + "#ifdef __cplusplus\n"
> + "#include <complex>\n"
> + "#define FLOAT_COMPLEX std::complex<float>\n"
> + "#define DOUBLE_COMPLEX std::complex<double>\n"
> + "#define LONG_DOUBLE_COMPLEX std::complex<long double>\n"
> + "extern \"C\" {\n"
> + "#else\n"
> + "#define FLOAT_COMPLEX float _Complex\n"
> + "#define DOUBLE_COMPLEX double _Complex\n"
> + "#define LONG_DOUBLE_COMPLEX long double _Complex\n"
> + "#endif\n\n"));

Two more things:
1) why the _() around the code snippet?  Do you expect translators
   to translate the C snippets to something else or what?
2) I don't think float _Complex is
   passed the same as std::complex<float> and similar for others;
   std::complex<float> is in libstdc++ a C++ class with with
   __complex__ float as its sole non-static data member and with non-trivial
   constructors; which means it is passed/returned via a hidden reference;
   when the argument is actually FLOAT_COMPLEX * or FLOAT_COMPLEX &,
   you except for aliasing don't have to care that much, but if
   that complex argument has VALUE attribute in Fortran and so the
   C prototype would be FLOAT_COMPLEX, then std::complex<float> is
   passed in the end as std::complex<float> &, while float _Complex
   the same as __complex__ float; and ditto for functions returning
   complex

        Jakub
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] fortran: C++ support for generating C prototypes

Jakub Jelinek
On Wed, May 15, 2019 at 10:41:06PM +0300, Janne Blomqvist wrote:

> > 2) I don't think float _Complex is
> >    passed the same as std::complex<float> and similar for others;
> >    std::complex<float> is in libstdc++ a C++ class with with
> >    __complex__ float as its sole non-static data member and with non-trivial
> >    constructors; which means it is passed/returned via a hidden reference;
> >    when the argument is actually FLOAT_COMPLEX * or FLOAT_COMPLEX &,
> >    you except for aliasing don't have to care that much, but if
> >    that complex argument has VALUE attribute in Fortran and so the
> >    C prototype would be FLOAT_COMPLEX, then std::complex<float> is
> >    passed in the end as std::complex<float> &, while float _Complex
> >    the same as __complex__ float; and ditto for functions returning
> >    complex
>
> Ugh, I guess that's right. Any good way around it? Except print a
> warning in the header that passing std::complex<> by value doesn't
> work?

Perhaps we can use different macros for the two cases, define
__GFORTRAN_FLOAT_COMPLEX to std::complex<float> and
__GFORTRAN_FLOAT_COMPLEX_VALUE to __complex__ float and use the
former in the __GFORTRAN_FLOAT_COMPLEX * arguments and
the latter for VALUE dummy args and return value.

For the return value case, guess it will be fine, when one does
__complex__ float fortran_fn_ (void);
std::complex<float> ret = fortran_fn_ ();
it will work just fine, but for the arguments trying to
void fortran_sub_ (__complex__ float);
std::complex<float> f = 2.0f + 4.0fi;
fortran_sub_ (f);
will not work (but one will get at least errors).  One can use non-standard
fortran_sub_ (f.__rep ());

        Jakub