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
2012-03-03 Tobias Burnus <bur...@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 <bur...@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" } }