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

2019-05-16 Thread 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 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

2019-05-15 Thread Janne Blomqvist
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

2019-05-15 Thread Jakub Jelinek
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

2019-05-12 Thread Thomas König
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

2019-05-12 Thread 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
>  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

2019-05-12 Thread Janne Blomqvist
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

2019-05-12 Thread Thomas Koenig

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

2019-05-12 Thread Janne Blomqvist
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

2019-05-12 Thread Thomas Koenig

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

2019-05-11 Thread Jakub Jelinek
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

2019-05-11 Thread Janne Blomqvist
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