}
-bool
-gfc_check_c_associated (gfc_expr *c_ptr_1, gfc_expr *c_ptr_2)
+/* Helper functions check_c_ptr_1 and check_c_ptr_2
+ used in gfc_check_c_associated. */
+
+static inline
+bool check_c_ptr_1 (gfc_expr *c_ptr_1)
{
- if (c_ptr_1)
- {
- if (c_ptr_1->expr_type == EXPR_FUNCTION && c_ptr_1->ts.type == BT_VOID)
- return true;
+ if ((c_ptr_1->ts.type == BT_VOID)
+ && (c_ptr_1->expr_type == EXPR_FUNCTION))
+ return true;
- if (c_ptr_1->ts.type != BT_DERIVED
- || c_ptr_1->ts.u.derived->from_intmod != INTMOD_ISO_C_BINDING
- || (c_ptr_1->ts.u.derived->intmod_sym_id != ISOCBINDING_PTR
- && c_ptr_1->ts.u.derived->intmod_sym_id != ISOCBINDING_FUNPTR))
- {
- gfc_error ("Argument C_PTR_1 at %L to C_ASSOCIATED shall have the "
- "type TYPE(C_PTR) or TYPE(C_FUNPTR)", &c_ptr_1->where);
- return false;
- }
- }
+ if (c_ptr_1->ts.type != BT_DERIVED
+ || c_ptr_1->ts.u.derived->from_intmod != INTMOD_ISO_C_BINDING
+ || (c_ptr_1->ts.u.derived->intmod_sym_id != ISOCBINDING_PTR
+ && c_ptr_1->ts.u.derived->intmod_sym_id != ISOCBINDING_FUNPTR))
+ goto check_1_error;
- if (!scalar_check (c_ptr_1, 0))
+ if ((c_ptr_1->ts.type == BT_DERIVED)
+ && (c_ptr_1->expr_type == EXPR_STRUCTURE)
+ && (c_ptr_1->ts.u.derived->intmod_sym_id
+ == ISOCBINDING_NULL_FUNPTR))
+ goto check_1_error;
+
+ if (scalar_check (c_ptr_1, 0))
+ return true;
+ else
+ /* Return since the check_1_error message may not apply here. */
return false;
- if (c_ptr_2)
- {
- if (c_ptr_2->expr_type == EXPR_FUNCTION && c_ptr_2->ts.type == BT_VOID)
- return true;
+check_1_error:
- if (c_ptr_2->ts.type != BT_DERIVED
- || c_ptr_2->ts.u.derived->from_intmod != INTMOD_ISO_C_BINDING
- || (c_ptr_1->ts.u.derived->intmod_sym_id
- != c_ptr_2->ts.u.derived->intmod_sym_id))
+ gfc_error ("Argument C_PTR_1 at %L to C_ASSOCIATED shall have the "
+ "type TYPE(C_PTR) or TYPE(C_FUNPTR)", &c_ptr_1->where);
+ return false;
+}
+
+static inline
+bool check_c_ptr_2 (gfc_expr *c_ptr_1, gfc_expr *c_ptr_2)
+{
+ switch (c_ptr_2->ts.type)
+ {
+ case BT_VOID:
+ if (c_ptr_2->expr_type == EXPR_FUNCTION)
{
- gfc_error ("Argument C_PTR_2 at %L to C_ASSOCIATED shall have the "
- "same type as C_PTR_1: %s instead of %s", &c_ptr_1->where,
- gfc_typename (&c_ptr_1->ts), gfc_typename (&c_ptr_2->ts));
- return false;
+ if ((c_ptr_1->ts.type == BT_DERIVED)
+ && c_ptr_1->expr_type == EXPR_STRUCTURE
+ && (c_ptr_1->ts.u.derived->intmod_sym_id
+ == ISOCBINDING_FUNPTR))
+ goto check_2_error;
}
- }
+ break;
+
+ case BT_DERIVED:
+ if ((c_ptr_2->expr_type == EXPR_STRUCTURE)
+ && (c_ptr_2->ts.u.derived->intmod_sym_id == ISOCBINDING_PTR)
+ && (c_ptr_1->ts.type == BT_VOID)
+ && (c_ptr_1->expr_type == EXPR_FUNCTION))
+ return scalar_check (c_ptr_2, 1);
- if (c_ptr_2 && !scalar_check (c_ptr_2, 1))
+ if ((c_ptr_2->expr_type == EXPR_STRUCTURE)
+ && (c_ptr_1->ts.type == BT_VOID)
+ && (c_ptr_1->expr_type == EXPR_FUNCTION))
+ goto check_2_error;
+
+ if (c_ptr_2->ts.u.derived->from_intmod != INTMOD_ISO_C_BINDING)
+ goto check_2_error;
+
+ if (c_ptr_1->ts.type == BT_DERIVED
+ && (c_ptr_1->ts.u.derived->intmod_sym_id
+ != c_ptr_2->ts.u.derived->intmod_sym_id))
+ goto check_2_error;
+ break;
+
+ default:
+ goto check_2_error;
+ }
+
+ if (scalar_check (c_ptr_2, 1))
+ return true;
+ else
+ /* Return since the check_2_error message may not apply here. */
return false;
- return true;
+check_2_error:
+
+ gfc_error ("Argument C_PTR_2 at %L to C_ASSOCIATED shall have the "
+ "same type as C_PTR_1: %s instead of %s", &c_ptr_2->where,
+ gfc_typename (&c_ptr_1->ts), gfc_typename (&c_ptr_2->ts));
+
+ return false;
+ }
+
+
+bool
+gfc_check_c_associated (gfc_expr *c_ptr_1, gfc_expr *c_ptr_2)
+{
+ if (c_ptr_2)
+ {
+ if (check_c_ptr_2 (c_ptr_1, c_ptr_2))
+ return check_c_ptr_1 (c_ptr_1);
+ else
+ return false;
+ }
+ else
+ return check_c_ptr_1 (c_ptr_1);
}
--- /dev/null
+! Compiled with pr120049_b.f90
+! { dg-options -O0 }
+! { dg-do compile }
+! { dg-compile-aux-modules "pr120049_b.f90" }
+!
+! Test the fix for PR120049
+program tests_gtk_sup
+ use gtk_sup
+ implicit none
+
+ type mytype
+ integer :: myint
+ end type mytype
+ type(mytype) :: ijkl = mytype(42)
+ logical :: truth
+ real :: var1
+ type(c_ptr), target :: val
+ type(c_funptr), target :: fptr
+ character(15) :: stringy
+ complex :: certainly
+ truth = .true.
+ var1 = 86.
+ stringy = "what the hay!"
+ certainly = (3.14,-4.13)
+ if (c_associated(val, c_loc(val))) then
+ stop 1
+ endif
+ if (c_associated(c_loc(val), val)) then
+ stop 2
+ endif
+ print *, c_associated(fptr, C_NULL_FUNPTR)
+ print *, c_associated(c_loc(val), C_NULL_PTR)
+ print *, c_associated(C_NULL_PTR, c_loc(val))
+ print *, c_associated(c_loc(val), 42) ! { dg-error "C_ASSOCIATED shall have the" }
+ print *, c_associated(c_loc(val), .42) ! { dg-error "C_ASSOCIATED shall have the" }
+ print *, c_associated(c_loc(val), truth) ! { dg-error "C_ASSOCIATED shall have the" }
+ print *, c_associated(c_loc(val), .false.) ! { dg-error "C_ASSOCIATED shall have the" }
+ print *, c_associated(c_loc(val), var1) ! { dg-error "C_ASSOCIATED shall have the" }
+ print *, c_associated(c_loc(val), stringy) ! { dg-error "C_ASSOCIATED shall have the" }
+ print *, c_associated(c_loc(val), certainly) ! { dg-error "C_ASSOCIATED shall have the" }
+ print *, c_associated(42) ! { dg-error "C_ASSOCIATED shall have the" }
+ print *, c_associated(.42) ! { dg-error "C_ASSOCIATED shall have the" }
+ print *, c_associated(truth) ! { dg-error "C_ASSOCIATED shall have the" }
+ print *, c_associated(.false.) ! { dg-error "C_ASSOCIATED shall have the" }
+ print *, c_associated(var1) ! { dg-error "C_ASSOCIATED shall have the" }
+ print *, c_associated(stringy) ! { dg-error "C_ASSOCIATED shall have the" }
+ print *, c_associated(certainly) ! { dg-error "C_ASSOCIATED shall have the" }
+ print *, c_associated(.42) ! { dg-error "C_ASSOCIATED shall have the" }
+ print *, c_associated(val, testit(val)) ! { dg-error "C_ASSOCIATED shall have the" }
+ print *, c_associated(testit(val), val) ! { dg-error "C_ASSOCIATED shall have the" }
+ print *, c_associated(testit(val)) ! { dg-error "C_ASSOCIATED shall have the" }
+ print *, c_associated(c_loc(val), C_NULL_FUNPTR) ! { dg-error "C_ASSOCIATED shall have the" }
+ print *, c_associated(C_NULL_FUNPTR, c_loc(val)) ! { dg-error "C_ASSOCIATED shall have the" }
+contains
+
+ function testit (avalue) result(res)
+ type(c_ptr) :: avalue
+ type(mytype) :: res
+ res%myint = 42
+ end function
+
+end program tests_gtk_sup