Re: [PATCH] fortran: C++ support for generating C prototypes
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 and similar for others; > >std::complex 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 is > >passed in the end as std::complex &, 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 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 ret = fortran_fn_ (); it will work just fine, but for the arguments trying to void fortran_sub_ (__complex__ float); std::complex 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
Re: [PATCH] fortran: C++ support for generating C prototypes
On Wed, May 15, 2019 at 4:41 PM Jakub Jelinek wrote: > > 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 \n" > > + "#ifdef __cplusplus\n" > > + "#include \n" > > + "#define FLOAT_COMPLEX std::complex\n" > > + "#define DOUBLE_COMPLEX std::complex\n" > > + "#define LONG_DOUBLE_COMPLEX std::complex\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? Er, because originally I printed out these definitons as part of the other fprintf call where a comment was printed, and when I moved it to another location I forgot to remove the translation markers. Committed r271261 and r271264 as obvious. > 2) I don't think float _Complex is >passed the same as std::complex and similar for others; >std::complex 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 is >passed in the end as std::complex &, 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? -- Janne Blomqvist
Re: [PATCH] fortran: C++ support for generating C prototypes
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 \n" > + "#ifdef __cplusplus\n" > + "#include \n" > + "#define FLOAT_COMPLEX std::complex\n" > + "#define DOUBLE_COMPLEX std::complex\n" > + "#define LONG_DOUBLE_COMPLEX std::complex\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 and similar for others; std::complex 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 is passed in the end as std::complex &, while float _Complex the same as __complex__ float; and ditto for functions returning complex Jakub
Re: [PATCH] fortran: C++ support for generating C prototypes
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 😉
Re: [PATCH] fortran: C++ support for generating C prototypes
On Sun, May 12, 2019 at 10:36:09PM +0300, Janne Blomqvist wrote: > On Sun, May 12, 2019 at 11:29 AM Janne Blomqvist > wrote: > > > > On Sun, May 12, 2019 at 11:06 AM Thomas Koenig > > 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_ Jakub
Re: [PATCH] fortran: C++ support for generating C prototypes
On Sun, May 12, 2019 at 11:29 AM Janne Blomqvist wrote: > > On Sun, May 12, 2019 at 11:06 AM Thomas Koenig 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 trunk and 9? -- Janne Blomqvist 0001-Add-include-guards-for-generated-C-prototypes.patch Description: Binary data
Re: [PATCH] fortran: C++ support for generating C prototypes
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
Re: [PATCH] fortran: C++ support for generating C prototypes
On Sun, May 12, 2019 at 11:06 AM Thomas Koenig wrote: > > Am 12.05.19 um 00:02 schrieb Jakub Jelinek: > > Is it correct to use macros in user namespace? Shouldn't they be say __ > > prefixed, or even have __GFC_ or __GFORTRAN_ in them? > > I think Jakub has a point there -- something like __GFC_DOUBLE_COMPLEX > would probably be better. > > So, OK with that change. 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. Any opinions whether it should be committed to 9 as well? > (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. -- Janne Blomqvist
Re: [PATCH] fortran: C++ support for generating C prototypes
Am 12.05.19 um 00:02 schrieb Jakub Jelinek: Is it correct to use macros in user namespace? Shouldn't they be say __ prefixed, or even have __GFC_ or __GFORTRAN_ in them? I think Jakub has a point there -- something like __GFC_DOUBLE_COMPLEX would probably be better. So, OK with that change. (I thought for a second about guarding about double inclusion, but including prototypes twice is harmless, and this should be the user's responsibility). Regards Thomas
Re: [PATCH] fortran: C++ support for generating C prototypes
On Sun, May 12, 2019 at 12:47:04AM +0300, Janne Blomqvist wrote: > When generating C prototypes for Fortran procedures with the > -fc-prototypes and -fc-prototypes-external options, print a snippet > defining macros for complex types, and add C++ support by suppressing > mangling. > > fortran/ChangeLog: > > 2019-05-12 Janne Blomqvist > > * dump-parse-tree.c (get_c_type_name): Use macros for complex type > names. > * parse.c (gfc_parse_file): Define complex macros, add CPP support > when printing C prototypes. > > Ok for trunk? Is it correct to use macros in user namespace? Shouldn't they be say __ prefixed, or even have __GFC_ or __GFORTRAN_ in them? > --- a/gcc/fortran/dump-parse-tree.c > +++ b/gcc/fortran/dump-parse-tree.c > @@ -3143,11 +3143,11 @@ get_c_type_name (gfc_typespec *ts, gfc_array_spec > *as, const char **pre, > else if (strcmp (*type_name, "size_t") == 0) > *type_name = "ssize_t"; > else if (strcmp (*type_name, "float_complex") == 0) > - *type_name = "float complex"; > + *type_name = "FLOAT_COMPLEX"; > else if (strcmp (*type_name, "double_complex") == 0) > - *type_name = "double complex"; > + *type_name = "DOUBLE_COMPLEX"; > else if (strcmp (*type_name, "long_double_complex") == 0) > - *type_name = "long double complex"; > + *type_name = "LONG_DOUBLE_COMPLEX"; > > ret = T_OK; > } > @@ -3166,11 +3166,11 @@ get_c_type_name (gfc_typespec *ts, gfc_array_spec > *as, const char **pre, > else if (strcmp (*type_name, "size_t") == 0) > *type_name = "ssize_t"; > else if (strcmp (*type_name, "float_complex") == 0) > - *type_name = "float complex"; > + *type_name = "FLOAT_COMPLEX"; > else if (strcmp (*type_name, "double_complex") == 0) > - *type_name = "double complex"; > + *type_name = "DOUBLE_COMPLEX"; > else if (strcmp (*type_name, "long_double_complex") == 0) > - *type_name = "long double complex"; > + *type_name = "LONG_DOUBLE_COMPLEX"; > > ret = T_WARN; > break; > diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c > index 9d693595e20..8077da870b0 100644 > --- 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 \n" > + "#ifdef __cplusplus\n" > + "#include \n" > + "#define FLOAT_COMPLEX std::complex\n" > + "#define DOUBLE_COMPLEX std::complex\n" > + "#define LONG_DOUBLE_COMPLEX std::complex\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")); > +} > + > + /* First dump BIND(C) prototypes. */ >if (flag_c_prototypes) > { >for (gfc_current_ns = gfc_global_ns_list; gfc_current_ns; > @@ -6342,6 +6360,10 @@ done: >if (flag_c_prototypes_external) > gfc_dump_external_c_prototypes (stdout); > > + if (flag_c_prototypes || flag_c_prototypes_external) > +fprintf (stdout, > + _("\n#ifdef __cplusplus\n}\n#endif\n")); > + >/* Do the translation. */ >translate_all_program_units (gfc_global_ns_list); > > -- > 2.17.1 Jakub
[PATCH] fortran: C++ support for generating C prototypes
When generating C prototypes for Fortran procedures with the -fc-prototypes and -fc-prototypes-external options, print a snippet defining macros for complex types, and add C++ support by suppressing mangling. fortran/ChangeLog: 2019-05-12 Janne Blomqvist * dump-parse-tree.c (get_c_type_name): Use macros for complex type names. * parse.c (gfc_parse_file): Define complex macros, add CPP support when printing C prototypes. Ok for trunk? --- gcc/fortran/dump-parse-tree.c | 12 ++-- gcc/fortran/parse.c | 22 ++ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c index 54af5dfd50d..21305243522 100644 --- a/gcc/fortran/dump-parse-tree.c +++ b/gcc/fortran/dump-parse-tree.c @@ -3143,11 +3143,11 @@ get_c_type_name (gfc_typespec *ts, gfc_array_spec *as, const char **pre, else if (strcmp (*type_name, "size_t") == 0) *type_name = "ssize_t"; else if (strcmp (*type_name, "float_complex") == 0) - *type_name = "float complex"; + *type_name = "FLOAT_COMPLEX"; else if (strcmp (*type_name, "double_complex") == 0) - *type_name = "double complex"; + *type_name = "DOUBLE_COMPLEX"; else if (strcmp (*type_name, "long_double_complex") == 0) - *type_name = "long double complex"; + *type_name = "LONG_DOUBLE_COMPLEX"; ret = T_OK; } @@ -3166,11 +3166,11 @@ get_c_type_name (gfc_typespec *ts, gfc_array_spec *as, const char **pre, else if (strcmp (*type_name, "size_t") == 0) *type_name = "ssize_t"; else if (strcmp (*type_name, "float_complex") == 0) - *type_name = "float complex"; + *type_name = "FLOAT_COMPLEX"; else if (strcmp (*type_name, "double_complex") == 0) - *type_name = "double complex"; + *type_name = "DOUBLE_COMPLEX"; else if (strcmp (*type_name, "long_double_complex") == 0) - *type_name = "long double complex"; + *type_name = "LONG_DOUBLE_COMPLEX"; ret = T_WARN; break; diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c index 9d693595e20..8077da870b0 100644 --- 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 \n" +"#ifdef __cplusplus\n" +"#include \n" +"#define FLOAT_COMPLEX std::complex\n" +"#define DOUBLE_COMPLEX std::complex\n" +"#define LONG_DOUBLE_COMPLEX std::complex\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")); +} + + /* First dump BIND(C) prototypes. */ if (flag_c_prototypes) { for (gfc_current_ns = gfc_global_ns_list; gfc_current_ns; @@ -6342,6 +6360,10 @@ done: if (flag_c_prototypes_external) gfc_dump_external_c_prototypes (stdout); + if (flag_c_prototypes || flag_c_prototypes_external) +fprintf (stdout, +_("\n#ifdef __cplusplus\n}\n#endif\n")); + /* Do the translation. */ translate_all_program_units (gfc_global_ns_list); -- 2.17.1