Patchwork [Fortran] Add -Wc-binding-type warning

login
register
mail settings
Submitter Tobias Burnus
Date March 3, 2012, 2:23 p.m.
Message ID <4F522945.6010001@net-b.de>
Download mbox | patch
Permalink /patch/144425/
State New
Headers show

Comments

Tobias Burnus - March 3, 2012, 2:23 p.m.
GNU Fortran warns by default for code like the following:

interface
   subroutine sub (n)  bind (C)
     integer :: n
   end subroutine sub
end interface

Namely, it prints:

Warning: Variable 'n' at (1) is a parameter to the BIND(C) procedure 
'sub' but may not be C interoperable


That's on one hand correct: There is no defined relation between Fortran 
default kinds (or any kind number) and the C types. Thus, the proper way 
is to use the parameters defined in ISO_C_BINDING, such as "c_int".

On the other hand, "integer" and "int" is the same on many (but not on 
all systems) and, thus, many users simply use the default type.

Compiling interfaces with hundreds of such definitions clutters the 
screen with those warnings and makes it difficult to spot other warnings.

Thus, this patch adds a warning flag for this purpose - and it also 
excludes those warnings from the default setting. That's a bit in line 
with Fortran 2008 and TS 29113, which remove more and more constraints 
and force the users to ensure themselves that the variables are 
interoperable. However, keeping it as default warning is also fine with me.

Build and regtested on x86-64-linux.
OK?

Tobias
Steve Kargl - March 3, 2012, 3:54 p.m.
On Sat, Mar 03, 2012 at 03:23:01PM +0100, Tobias Burnus wrote:
> GNU Fortran warns by default for code like the following:
> 
> interface
>   subroutine sub (n)  bind (C)
>     integer :: n
>   end subroutine sub
> end interface
> 
> Namely, it prints:
> 
> Warning: Variable 'n' at (1) is a parameter to the BIND(C) procedure 
> 'sub' but may not be C interoperable
> 
> That's on one hand correct: There is no defined relation between Fortran 
> default kinds (or any kind number) and the C types. Thus, the proper way 
> is to use the parameters defined in ISO_C_BINDING, such as "c_int".
> 
> On the other hand, "integer" and "int" is the same on many (but not on 
> all systems) and, thus, many users simply use the default type.
> 
> Compiling interfaces with hundreds of such definitions clutters the 
> screen with those warnings and makes it difficult to spot other warnings.
> 
> Thus, this patch adds a warning flag for this purpose - and it also 
> excludes those warnings from the default setting. That's a bit in line 
> with Fortran 2008 and TS 29113, which remove more and more constraints 
> and force the users to ensure themselves that the variables are 
> interoperable. However, keeping it as default warning is also fine with me.
> 
> Build and regtested on x86-64-linux.
> OK?
> 

OK.

Patch

2012-03-03  Tobias Burnus  <burnus@net-b.de>

	* lang.opt (Wc-binding-type): New flag.
	* options.c (gfc_init_options, gfc_handle_option): Handle it.
	* invoke.texi (Wc-binding-type): Document it.
	* gfortran.h (gfc_option_t): Add warn_c_binding_type.
	* decl.c (verify_bind_c_sym): Handle -Wc-binding-type.
	* symbol.c (gfc_set_default_type, verify_bind_c_derived_type):
	Ditto.

2012-03-03  Tobias Burnus  <burnus@net-b.de>

	* gfortran.dg/bind_c_dts_4.f03: Add dg-options -Wc-binding-type.
	* gfortran.dg/bind_c_implicit_vars.f03: Ditto.
	* gfortran.dg/bind_c_usage_8.f03: Ditto.
	* gfortran.dg/c_kind_tests_2.f03: Ditto.
	* gfortran.dg/class_30.f90: Remove dg-warning line.
	* gfortran.dg/bind_c_usage_25.f90: New.

diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index bdb8c39..75b8a89 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -3930,7 +3930,7 @@  verify_bind_c_sym (gfc_symbol *tmp_sym, gfc_typespec *ts,
     {
       tmp_sym = tmp_sym->result;
       /* Make sure it wasn't an implicitly typed result.  */
-      if (tmp_sym->attr.implicit_type)
+      if (tmp_sym->attr.implicit_type && gfc_option.warn_c_binding_type)
 	{
 	  gfc_warning ("Implicitly declared BIND(C) function '%s' at "
                        "%L may not be C interoperable", tmp_sym->name,
@@ -3951,7 +3951,7 @@  verify_bind_c_sym (gfc_symbol *tmp_sym, gfc_typespec *ts,
       if (gfc_verify_c_interop (&(tmp_sym->ts)) != SUCCESS)
 	{
 	  /* See if we're dealing with a sym in a common block or not.	*/
-	  if (is_in_common == 1)
+	  if (is_in_common == 1 && gfc_option.warn_c_binding_type)
 	    {
 	      gfc_warning ("Variable '%s' in common block '%s' at %L "
                            "may not be a C interoperable "
@@ -3965,7 +3965,7 @@  verify_bind_c_sym (gfc_symbol *tmp_sym, gfc_typespec *ts,
                 gfc_error ("Type declaration '%s' at %L is not C "
                            "interoperable but it is BIND(C)",
                            tmp_sym->name, &(tmp_sym->declared_at));
-              else
+              else if (gfc_option.warn_c_binding_type)
                 gfc_warning ("Variable '%s' at %L "
                              "may not be a C interoperable "
                              "kind but it is bind(c)",
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index a5edd13..1c242b4 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -2200,6 +2201,7 @@  typedef struct
   int warn_aliasing;
   int warn_ampersand;
   int gfc_warn_conversion;
+  int warn_c_binding_type;
   int warn_conversion_extra;
   int warn_function_elimination;
   int warn_implicit_interface;
diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi
index 1f6de84..38ebfe9 100644
--- a/gcc/fortran/invoke.texi
+++ b/gcc/fortran/invoke.texi
@@ -142,7 +142,7 @@  by type.  Explanations are in the following sections.
 @xref{Error and Warning Options,,Options to request or suppress errors
 and warnings}.
 @gccoptlist{-Waliasing -Wall -Wampersand -Warray-bounds
--Wcharacter-truncation @gol
+-Wc-binding-type -Wcharacter-truncation @gol
 -Wconversion -Wfunction-elimination -Wimplicit-interface @gol
 -Wimplicit-procedure -Wintrinsic-shadow -Wintrinsics-std @gol
 -Wline-truncation -Wno-align-commons -Wno-tabs -Wreal-q-constant @gol
@@ -773,6 +773,14 @@  Warn about array temporaries generated by the compiler.  The information
 generated by this warning is sometimes useful in optimization, in order to
 avoid such temporaries.
 
+@item -Wc-binding-type
+@opindex @code{Wc-binding-type}
+@cindex warning, C binding type
+Warn if the a variable might not be C interoperable.  In particular, warn if 
+the variable has been declared using an intrinsic type with default kind
+instead of using a kind parameter defined for C interoperability in the
+intrinsic @code{ISO_C_Binding} module.
+
 @item -Wcharacter-truncation
 @opindex @code{Wcharacter-truncation}
 @cindex warnings, character truncation
diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt
index 56c589c..7e160a0 100644
--- a/gcc/fortran/lang.opt
+++ b/gcc/fortran/lang.opt
@@ -210,6 +210,10 @@  Warray-temporaries
 Fortran Warning
 Warn about creation of array temporaries
 
+Wc-binding-type
+Fortran Warning
+Warn if the type of a variable might be not interoperable with C
+
 Wcharacter-truncation
 Fortran Warning
 Warn about truncated character expressions
diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c
index b6929fc..1010a93 100644
--- a/gcc/fortran/options.c
+++ b/gcc/fortran/options.c
@@ -97,6 +97,7 @@  gfc_init_options (unsigned int decoded_options_count,
   gfc_option.warn_ampersand = 0;
   gfc_option.warn_character_truncation = 0;
   gfc_option.warn_array_temp = 0;
+  gfc_option.warn_c_binding_type = 0;
   gfc_option.gfc_warn_conversion = 0;
   gfc_option.warn_conversion_extra = 0;
   gfc_option.warn_function_elimination = 0;
@@ -456,6 +457,7 @@  set_Wall (int setting)
 {
   gfc_option.warn_aliasing = setting;
   gfc_option.warn_ampersand = setting;
+  gfc_option.warn_c_binding_type = setting;
   gfc_option.gfc_warn_conversion = setting;
   gfc_option.warn_line_truncation = setting;
   gfc_option.warn_surprising = setting;
@@ -620,6 +622,10 @@  gfc_handle_option (size_t scode, const char *arg, int value,
       gfc_option.warn_array_temp = value;
       break;
 
+    case OPT_Wc_binding_type:
+      gfc_option.warn_c_binding_type = value;
+      break;
+
     case OPT_Wcharacter_truncation:
       gfc_option.warn_character_truncation = value;
       break;
diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c
index 0cd7cc8..46e5f56 100644
--- a/gcc/fortran/symbol.c
+++ b/gcc/fortran/symbol.c
@@ -274,7 +274,7 @@  gfc_set_default_type (gfc_symbol *sym, int error_flag, gfc_namespace *ns)
   if (ts->type == BT_CHARACTER && ts->u.cl)
     sym->ts.u.cl = gfc_new_charlen (sym->ns, ts->u.cl);
 
-  if (sym->attr.is_bind_c == 1)
+  if (sym->attr.is_bind_c == 1 && gfc_option.warn_c_binding_type)
     {
       /* BIND(C) variables should not be implicitly declared.  */
       gfc_warning_now ("Implicitly declared BIND(C) variable '%s' at %L may "
@@ -287,7 +287,8 @@  gfc_set_default_type (gfc_symbol *sym, int error_flag, gfc_namespace *ns)
       if (sym->ns->proc_name != NULL
 	  && (sym->ns->proc_name->attr.subroutine != 0
 	      || sym->ns->proc_name->attr.function != 0)
-	  && sym->ns->proc_name->attr.is_bind_c != 0)
+	  && sym->ns->proc_name->attr.is_bind_c != 0
+	  && gfc_option.warn_c_binding_type)
         {
           /* Dummy args to a BIND(C) routine may not be interoperable if
              they are implicitly typed.  */
@@ -3694,7 +3695,8 @@  verify_bind_c_derived_type (gfc_symbol *derived_sym)
 		 recompiles with different flags (e.g., -m32 and -m64 on
 		 x86_64 and using integer(4) to claim interop with a
 		 C_LONG).  */
-	      if (derived_sym->attr.is_bind_c == 1)
+	      if (derived_sym->attr.is_bind_c == 1
+		  && gfc_option.warn_c_binding_type)
 		/* If the derived type is bind(c), all fields must be
 		   interop.  */
 		gfc_warning ("Component '%s' in derived type '%s' at %L "
@@ -3702,7 +3704,7 @@  verify_bind_c_derived_type (gfc_symbol *derived_sym)
                              "derived type '%s' is BIND(C)",
                              curr_comp->name, derived_sym->name,
                              &(curr_comp->loc), derived_sym->name);
-	      else
+	      else if (gfc_option.warn_c_binding_type)
 		/* If derived type is param to bind(c) routine, or to one
 		   of the iso_c_binding procs, it must be interoperable, so
 		   all fields must interop too.	 */
diff --git a/gcc/testsuite/gfortran.dg/bind_c_dts_4.f03 b/gcc/testsuite/gfortran.dg/bind_c_dts_4.f03
index b2eb569..c6fc402 100644
--- a/gcc/testsuite/gfortran.dg/bind_c_dts_4.f03
+++ b/gcc/testsuite/gfortran.dg/bind_c_dts_4.f03
@@ -1,4 +1,5 @@ 
 ! { dg-do compile }
+! { dg-options "-Wc-binding-type" }
 module test
 use iso_c_binding, only: c_int
     type, bind(c) ::  foo
diff --git a/gcc/testsuite/gfortran.dg/bind_c_implicit_vars.f03 b/gcc/testsuite/gfortran.dg/bind_c_implicit_vars.f03
index d6b4b6d..bac7d4d 100644
--- a/gcc/testsuite/gfortran.dg/bind_c_implicit_vars.f03
+++ b/gcc/testsuite/gfortran.dg/bind_c_implicit_vars.f03
@@ -1,4 +1,5 @@ 
 ! { dg-do compile }
+! { dg-options "-Wc-binding-type" }
 module bind_c_implicit_vars
 
 bind(c) :: j ! { dg-warning "may not be C interoperable" }
diff --git a/gcc/testsuite/gfortran.dg/bind_c_usage_8.f03 b/gcc/testsuite/gfortran.dg/bind_c_usage_8.f03
index a94545c..e31af86 100644
--- a/gcc/testsuite/gfortran.dg/bind_c_usage_8.f03
+++ b/gcc/testsuite/gfortran.dg/bind_c_usage_8.f03
@@ -1,4 +1,5 @@ 
 ! { dg-do compile }
+! { dg-options "-Wc-binding-type" }
 ! This should compile, though there is a warning about the type of len
 ! (return variable of strlen()) for being implicit.
 ! PR fortran/32797
diff --git a/gcc/testsuite/gfortran.dg/c_kind_tests_2.f03 b/gcc/testsuite/gfortran.dg/c_kind_tests_2.f03
index a8cdbdf..5bc99f5 100644
--- a/gcc/testsuite/gfortran.dg/c_kind_tests_2.f03
+++ b/gcc/testsuite/gfortran.dg/c_kind_tests_2.f03
@@ -1,4 +1,5 @@ 
 ! { dg-do compile }
+! { dg-options "-Wc-binding-type" }
 module c_kind_tests_2
   use, intrinsic :: iso_c_binding
 
diff --git a/gcc/testsuite/gfortran.dg/class_30.f90 b/gcc/testsuite/gfortran.dg/class_30.f90
index f2cedcb..343c0d6 100644
--- a/gcc/testsuite/gfortran.dg/class_30.f90
+++ b/gcc/testsuite/gfortran.dg/class_30.f90
@@ -15,7 +15,6 @@  end type t2
 
 type, bind(C):: t3
   class(t), pointer :: y
-  ! { dg-warning "may not be C interoperable" "" { target *-*-* } 17 }
   ! { dg-error "Polymorphic component y at .1. in SEQUENCE or BIND" "" { target *-*-* } 17 }
 end type t3
 end
--- /dev/null	2012-03-03 08:42:31.311826379 +0100
+++ gcc/gcc/testsuite/gfortran.dg/bind_c_usage_25.f90	2012-03-03 14:20:38.000000000 +0100
@@ -0,0 +1,63 @@ 
+! { dg-do compile }
+! { dg-options "-Wno-c-binding-type" }
+!
+! That's a copy of "bind_c_usage_8.f03", "bind_c_dts_4.f03",
+! "bind_c_implicit_vars.f03" and "c_kind_tests_2.f03"
+! to check that with -Wno-c-binding-type no warning is printed.
+!
+
+MODULE ISO_C_UTILITIES
+   USE ISO_C_BINDING
+   implicit none
+   CHARACTER(C_CHAR), DIMENSION(1), SAVE, TARGET, PRIVATE :: dummy_string="?"
+CONTAINS
+   FUNCTION C_F_STRING(CPTR) RESULT(FPTR)
+     use, intrinsic :: iso_c_binding
+      TYPE(C_PTR), INTENT(IN) :: CPTR ! The C address
+      CHARACTER(KIND=C_CHAR), DIMENSION(:), POINTER :: FPTR
+      INTERFACE
+         FUNCTION strlen(string) RESULT(len) BIND(C,NAME="strlen")
+            USE ISO_C_BINDING
+            TYPE(C_PTR), VALUE :: string ! A C pointer
+         END FUNCTION
+      END INTERFACE
+      CALL C_F_POINTER(FPTR=FPTR, CPTR=CPTR, SHAPE=[strlen(CPTR)])
+   END FUNCTION
+END MODULE ISO_C_UTILITIES
+
+module test
+use iso_c_binding, only: c_int
+    type, bind(c) ::  foo
+      integer :: p
+    end type
+    type(foo), bind(c) :: cp
+end module test
+
+module bind_c_implicit_vars
+
+bind(c) :: j
+
+contains
+  subroutine sub0(i) bind(c)
+    i = 0
+  end subroutine sub0
+end module bind_c_implicit_vars
+
+module c_kind_tests_2
+  use, intrinsic :: iso_c_binding
+
+  integer, parameter :: myF = c_float
+  real(myF), bind(c) :: myCFloat
+  integer(myF), bind(c) :: myCInt       ! { dg-warning "is for type REAL" }
+  integer(c_double), bind(c) :: myCInt2 ! { dg-warning "is for type REAL" }
+
+  integer, parameter :: myI = c_int
+  real(myI) :: myReal             ! { dg-warning "is for type INTEGER" }
+  real(myI), bind(c) :: myCFloat2 ! { dg-warning "is for type INTEGER" }
+  real(4), bind(c) :: myFloat
+end module c_kind_tests_2
+
+! { dg-final { cleanup-modules "c_kind_tests_2" } }
+! { dg-final { cleanup-modules "bind_c_implicit_vars" } }
+! { dg-final { cleanup-modules "test" } }
+! { dg-final { cleanup-modules "iso_c_utilities" } }