Fortran: Fix Bind(C) Array-Descriptor Conversion
gfortran uses internally a different array descriptor ("gfc") as Fortran 2018 alias TS291113 defines for C interoperability via ISO_Fortran_binding.h ("CFI"). Hence, when calling a C function from Fortran, it has to be converted in the callee - and if a BIND(C) procedure is written in Fortran, the CFI argument has to be converted to gfc in order work with the rest of the FE code and the library calls. Before this patch, part was handled in the FE generated code and other parts in libgfortran. With this patch, all code is generated and CFI is defined as proper type - visible in the debugger and to the middle end - avoiding both alias issues and missed optimization issues. This patch also fixes issues like: intent(out) deallocation in the bind(C) callee, using the CFI descriptor also for allocatable and pointer scalars and for len=* character strings. For 'select rank', it also optimizes the code + avoid accessing uninitialized memory if the dummy argument is allocatable/a pointer. It additionally rejects passing a descriptorless type(*) to an assumed-rank dummy argument. [F2018:C711] PR fortran/102086 PR fortran/92189 PR fortran/92621 PR fortran/101308 PR fortran/101309 PR fortran/101635 PR fortran/92482 gcc/fortran/ChangeLog: * decl.c (gfc_verify_c_interop_param): Remove 'sorry' for scalar allocatable/pointer and len=*. * expr.c (is_CFI_desc): Return true for for those. * gfortran.h (CFI_type_kind_shift, CFI_type_mask, CFI_type_from_type_kind, CFI_VERSION, CFI_MAX_RANK, CFI_attribute_pointer, CFI_attribute_allocatable, CFI_attribute_other, CFI_type_Integer, CFI_type_Logical, CFI_type_Real, CFI_type_Complex, CFI_type_Character, CFI_type_ucs4_char, CFI_type_struct, CFI_type_cptr, CFI_type_cfunptr, CFI_type_other): New #define. * trans-array.c (CFI_FIELD_BASE_ADDR, CFI_FIELD_ELEM_LEN, CFI_FIELD_VERSION, CFI_FIELD_RANK, CFI_FIELD_ATTRIBUTE, CFI_FIELD_TYPE, CFI_FIELD_DIM, CFI_DIM_FIELD_LOWER_BOUND, CFI_DIM_FIELD_EXTENT, CFI_DIM_FIELD_SM, gfc_get_cfi_descriptor_field, gfc_get_cfi_desc_base_addr, gfc_get_cfi_desc_elem_len, gfc_get_cfi_desc_version, gfc_get_cfi_desc_rank, gfc_get_cfi_desc_type, gfc_get_cfi_desc_attribute, gfc_get_cfi_dim_item, gfc_get_cfi_dim_lbound, gfc_get_cfi_dim_extent, gfc_get_cfi_dim_sm): New define/functions to access the CFI array descriptor. (gfc_conv_descriptor_type): New function for the GFC descriptor. (gfc_get_array_span): Handle expr of CFI descriptors and assumed-type descriptors. (gfc_trans_array_bounds): Remove 'static'. (gfc_conv_expr_descriptor): For assumed type, use the dtype of the actual argument. (structure_alloc_comps): Remove ' ' inside tabs. * trans-array.h (gfc_trans_array_bounds, gfc_conv_descriptor_type, gfc_get_cfi_desc_base_addr, gfc_get_cfi_desc_elem_len, gfc_get_cfi_desc_version, gfc_get_cfi_desc_rank, gfc_get_cfi_desc_type, gfc_get_cfi_desc_attribute, gfc_get_cfi_dim_lbound, gfc_get_cfi_dim_extent, gfc_get_cfi_dim_sm): New prototypes. * trans-decl.c (gfor_fndecl_cfi_to_gfc, gfor_fndecl_gfc_to_cfi): Remove global vars. (gfc_build_builtin_function_decls): Remove their initialization. (gfc_get_symbol_decl, create_function_arglist, gfc_trans_deferred_vars): Update for CFI. (convert_CFI_desc): Remove and replace by ... (gfc_conv_cfi_to_gfc): ... this function (gfc_generate_function_code): Call it; create local GFC var for CFI. * trans-expr.c (gfc_maybe_dereference_var): Handle CFI. (gfc_conv_subref_array_arg): Handle the if-noncontigous-only copy in when the result should be a descriptor. (gfc_conv_gfc_desc_to_cfi_desc): Completely rewritten. (gfc_conv_procedure_call): CFI fixes. * trans-openmp.c (gfc_omp_is_optional_argument, gfc_omp_check_optional_argument): Handle optional CFI. * trans-stmt.c (gfc_trans_select_rank_cases): Cleanup, avoid invalid code for allocatable/pointer dummies, which cannot be assumed size. * trans-types.c (gfc_cfi_descriptor_base): New global var. (gfc_get_dtype_rank_type): Skip rank init for rank < 0. (gfc_sym_type): Handle CFI dummies. (gfc_get_function_type): Update call. (gfc_get_cfi_dim_type, gfc_get_cfi_type): New. * trans-types.h (gfc_sym_type): Update prototype. (gfc_get_cfi_type): New prototype. * trans.c (gfc_trans_runtime_check): Make conditions more consistent to avoid '<logical> AND_THEN <long int>' in conditions. * trans.h (gfor_fndecl_cfi_to_gfc, gfor_fndecl_gfc_to_cfi): Remove global-var declaration. libgfortran/ChangeLog: * ISO_Fortran_binding.h (CFI_type_cfunptr): Make unique type again. * runtime/ISO_Fortran_binding.c (cfi_desc_to_gfc_desc, gfc_desc_to_cfi_desc): Add comment that those are no longer called by new code. libgomp/ChangeLog: * testsuite/libgomp.fortran/optional-bind-c.f90: New test. gcc/testsuite/ChangeLog: * gfortran.dg/ISO_Fortran_binding_4.f90: Extend testcase. * gfortran.dg/PR100914.f90: Remove xfail. * gfortran.dg/PR100915.c: Expect CFI_type_cfunptr. * gfortran.dg/PR100915.f90: Handle CFI_type_cfunptr != CFI_type_cptr. * gfortran.dg/PR93963.f90: Extend select-rank tests. * gfortran.dg/bind-c-intent-out.f90: Change to dg-do run, update scan-dump. * gfortran.dg/bind_c_array_params_2.f90: Update/extend scan-dump. * gfortran.dg/bind_c_char_10.f90: Update scan-dump. * gfortran.dg/bind_c_char_8.f90: Remove dg-error "sorry". * gfortran.dg/c-interop/allocatable-dummy.f90: Remove xfail. * gfortran.dg/c-interop/c1255-1.f90: Likewise. * gfortran.dg/c-interop/c407c-1.f90: Update dg-error. * gfortran.dg/c-interop/cf-descriptor-5.f90: Remove xfail. * gfortran.dg/c-interop/cf-out-descriptor-3.f90: Likewise. * gfortran.dg/c-interop/cf-out-descriptor-4.f90: Likewise. * gfortran.dg/c-interop/cf-out-descriptor-5.f90: Likewise. * gfortran.dg/c-interop/contiguous-2.f90: Likewise. * gfortran.dg/c-interop/contiguous-3.f90: Likewise. * gfortran.dg/c-interop/deferred-character-1.f90: Likewise. * gfortran.dg/c-interop/deferred-character-2.f90: Likewise. * gfortran.dg/c-interop/fc-descriptor-3.f90: Likewise. * gfortran.dg/c-interop/fc-descriptor-5.f90: Likewise. * gfortran.dg/c-interop/fc-descriptor-6.f90: Likewise. * gfortran.dg/c-interop/fc-out-descriptor-3.f90: Likewise. * gfortran.dg/c-interop/fc-out-descriptor-4.f90: Likewise. * gfortran.dg/c-interop/fc-out-descriptor-5.f90: Likewise. * gfortran.dg/c-interop/fc-out-descriptor-6.f90: Likewise. * gfortran.dg/c-interop/ff-descriptor-5.f90: Likewise. * gfortran.dg/c-interop/ff-descriptor-6.f90: Likewise. * gfortran.dg/c-interop/fc-descriptor-7.f90: Remove xfail + extend. * gfortran.dg/c-interop/fc-descriptor-7-c.c: Update for changes. * gfortran.dg/c-interop/shape.f90: Add implicit none. * gfortran.dg/c-interop/typecodes-array-char-c.c: Add kind=4 char. * gfortran.dg/c-interop/typecodes-array-char.f90: Likewise. * gfortran.dg/c-interop/typecodes-array-float128.f90: Remove xfail. * gfortran.dg/c-interop/typecodes-scalar-basic.f90: Likewise. * gfortran.dg/c-interop/typecodes-scalar-float128.f90: Likewise. * gfortran.dg/c-interop/typecodes-scalar-int128.f90: Likewise. * gfortran.dg/c-interop/typecodes-scalar-longdouble.f90: Likewise. * gfortran.dg/iso_c_binding_char_1.f90: Remove dg-error "sorry". * gfortran.dg/pr93792.f90: Turn XFAIL into PASS. * gfortran.dg/ISO_Fortran_binding_19.f90: New test. * gfortran.dg/assumed_type_12.f90: New test. * gfortran.dg/assumed_type_13.c: New test. * gfortran.dg/assumed_type_13.f90: New test. * gfortran.dg/bind-c-char-descr.f90: New test. * gfortran.dg/bind-c-contiguous-1.c: New test. * gfortran.dg/bind-c-contiguous-1.f90: New test. * gfortran.dg/bind-c-contiguous-2.f90: New test. * gfortran.dg/bind-c-contiguous-3.c: New test. * gfortran.dg/bind-c-contiguous-3.f90: New test. * gfortran.dg/bind-c-contiguous-4.c: New test. * gfortran.dg/bind-c-contiguous-4.f90: New test. * gfortran.dg/bind-c-contiguous-5.c: New test. * gfortran.dg/bind-c-contiguous-5.f90: New test.
This commit is contained in:
parent
a5b1b2a186
commit
64f9623765
71 changed files with 9151 additions and 483 deletions
|
@ -1605,15 +1605,6 @@ gfc_verify_c_interop_param (gfc_symbol *sym)
|
|||
sym->name, &sym->declared_at,
|
||||
sym->ns->proc_name->name))
|
||||
retval = false;
|
||||
else if (!sym->attr.dimension)
|
||||
{
|
||||
/* FIXME: Use CFI array descriptor for scalars. */
|
||||
gfc_error ("Sorry, deferred-length scalar character dummy "
|
||||
"argument %qs at %L of procedure %qs with "
|
||||
"BIND(C) not yet supported", sym->name,
|
||||
&sym->declared_at, sym->ns->proc_name->name);
|
||||
retval = false;
|
||||
}
|
||||
}
|
||||
else if (sym->attr.value
|
||||
&& (!cl || !cl->length
|
||||
|
@ -1636,20 +1627,6 @@ gfc_verify_c_interop_param (gfc_symbol *sym)
|
|||
"attribute", sym->name, &sym->declared_at,
|
||||
sym->ns->proc_name->name))
|
||||
retval = false;
|
||||
else if (!sym->attr.dimension
|
||||
|| sym->as->type == AS_ASSUMED_SIZE
|
||||
|| sym->as->type == AS_EXPLICIT)
|
||||
{
|
||||
/* FIXME: Valid - should use the CFI array descriptor, but
|
||||
not yet handled for scalars and assumed-/explicit-size
|
||||
arrays. */
|
||||
gfc_error ("Sorry, character dummy argument %qs at %L "
|
||||
"with assumed length is not yet supported for "
|
||||
"procedure %qs with BIND(C) attribute",
|
||||
sym->name, &sym->declared_at,
|
||||
sym->ns->proc_name->name);
|
||||
retval = false;
|
||||
}
|
||||
}
|
||||
else if (cl->length->expr_type != EXPR_CONSTANT
|
||||
|| mpz_cmp_si (cl->length->value.integer, 1) != 0)
|
||||
|
|
|
@ -1110,11 +1110,13 @@ is_CFI_desc (gfc_symbol *sym, gfc_expr *e)
|
|||
|
||||
if (sym && sym->attr.dummy
|
||||
&& sym->ns->proc_name->attr.is_bind_c
|
||||
&& sym->attr.dimension
|
||||
&& (sym->attr.pointer
|
||||
|| sym->attr.allocatable
|
||||
|| sym->as->type == AS_ASSUMED_SHAPE
|
||||
|| sym->as->type == AS_ASSUMED_RANK))
|
||||
|| (sym->attr.dimension
|
||||
&& (sym->as->type == AS_ASSUMED_SHAPE
|
||||
|| sym->as->type == AS_ASSUMED_RANK))
|
||||
|| (sym->ts.type == BT_CHARACTER
|
||||
&& (!sym->ts.u.cl || !sym->ts.u.cl->length))))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
|
|
@ -105,6 +105,40 @@ typedef struct
|
|||
}
|
||||
mstring;
|
||||
|
||||
/* ISO_Fortran_binding.h
|
||||
CAUTION: This has to be kept in sync with libgfortran. */
|
||||
|
||||
#define CFI_type_kind_shift 8
|
||||
#define CFI_type_mask 0xFF
|
||||
#define CFI_type_from_type_kind(t, k) (t + (k << CFI_type_kind_shift))
|
||||
|
||||
/* Constants, defined as macros. */
|
||||
#define CFI_VERSION 1
|
||||
#define CFI_MAX_RANK 15
|
||||
|
||||
/* Attributes. */
|
||||
#define CFI_attribute_pointer 0
|
||||
#define CFI_attribute_allocatable 1
|
||||
#define CFI_attribute_other 2
|
||||
|
||||
#define CFI_type_mask 0xFF
|
||||
#define CFI_type_kind_shift 8
|
||||
|
||||
/* Intrinsic types. Their kind number defines their storage size. */
|
||||
#define CFI_type_Integer 1
|
||||
#define CFI_type_Logical 2
|
||||
#define CFI_type_Real 3
|
||||
#define CFI_type_Complex 4
|
||||
#define CFI_type_Character 5
|
||||
|
||||
/* Combined type (for more, see ISO_Fortran_binding.h). */
|
||||
#define CFI_type_ucs4_char (CFI_type_Character + (4 << CFI_type_kind_shift))
|
||||
|
||||
/* Types with no kind. */
|
||||
#define CFI_type_struct 6
|
||||
#define CFI_type_cptr 7
|
||||
#define CFI_type_cfunptr 8
|
||||
#define CFI_type_other -1
|
||||
|
||||
|
||||
/*************************** Enums *****************************/
|
||||
|
|
|
@ -103,6 +103,111 @@ gfc_array_dataptr_type (tree desc)
|
|||
return (GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc)));
|
||||
}
|
||||
|
||||
/* Build expressions to access members of the CFI descriptor. */
|
||||
#define CFI_FIELD_BASE_ADDR 0
|
||||
#define CFI_FIELD_ELEM_LEN 1
|
||||
#define CFI_FIELD_VERSION 2
|
||||
#define CFI_FIELD_RANK 3
|
||||
#define CFI_FIELD_ATTRIBUTE 4
|
||||
#define CFI_FIELD_TYPE 5
|
||||
#define CFI_FIELD_DIM 6
|
||||
|
||||
#define CFI_DIM_FIELD_LOWER_BOUND 0
|
||||
#define CFI_DIM_FIELD_EXTENT 1
|
||||
#define CFI_DIM_FIELD_SM 2
|
||||
|
||||
static tree
|
||||
gfc_get_cfi_descriptor_field (tree desc, unsigned field_idx)
|
||||
{
|
||||
tree type = TREE_TYPE (desc);
|
||||
gcc_assert (TREE_CODE (type) == RECORD_TYPE
|
||||
&& TYPE_FIELDS (type)
|
||||
&& (strcmp ("base_addr",
|
||||
IDENTIFIER_POINTER (DECL_NAME (TYPE_FIELDS (type))))
|
||||
== 0));
|
||||
tree field = gfc_advance_chain (TYPE_FIELDS (type), field_idx);
|
||||
gcc_assert (field != NULL_TREE);
|
||||
|
||||
return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
|
||||
desc, field, NULL_TREE);
|
||||
}
|
||||
|
||||
tree
|
||||
gfc_get_cfi_desc_base_addr (tree desc)
|
||||
{
|
||||
return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_BASE_ADDR);
|
||||
}
|
||||
|
||||
tree
|
||||
gfc_get_cfi_desc_elem_len (tree desc)
|
||||
{
|
||||
return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_ELEM_LEN);
|
||||
}
|
||||
|
||||
tree
|
||||
gfc_get_cfi_desc_version (tree desc)
|
||||
{
|
||||
return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_VERSION);
|
||||
}
|
||||
|
||||
tree
|
||||
gfc_get_cfi_desc_rank (tree desc)
|
||||
{
|
||||
return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_RANK);
|
||||
}
|
||||
|
||||
tree
|
||||
gfc_get_cfi_desc_type (tree desc)
|
||||
{
|
||||
return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_TYPE);
|
||||
}
|
||||
|
||||
tree
|
||||
gfc_get_cfi_desc_attribute (tree desc)
|
||||
{
|
||||
return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_ATTRIBUTE);
|
||||
}
|
||||
|
||||
static tree
|
||||
gfc_get_cfi_dim_item (tree desc, tree idx, unsigned field_idx)
|
||||
{
|
||||
tree tmp = gfc_get_cfi_descriptor_field (desc, CFI_FIELD_DIM);
|
||||
tmp = gfc_build_array_ref (tmp, idx, NULL);
|
||||
tree field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), field_idx);
|
||||
gcc_assert (field != NULL_TREE);
|
||||
return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
|
||||
tmp, field, NULL_TREE);
|
||||
}
|
||||
|
||||
tree
|
||||
gfc_get_cfi_dim_lbound (tree desc, tree idx)
|
||||
{
|
||||
return gfc_get_cfi_dim_item (desc, idx, CFI_DIM_FIELD_LOWER_BOUND);
|
||||
}
|
||||
|
||||
tree
|
||||
gfc_get_cfi_dim_extent (tree desc, tree idx)
|
||||
{
|
||||
return gfc_get_cfi_dim_item (desc, idx, CFI_DIM_FIELD_EXTENT);
|
||||
}
|
||||
|
||||
tree
|
||||
gfc_get_cfi_dim_sm (tree desc, tree idx)
|
||||
{
|
||||
return gfc_get_cfi_dim_item (desc, idx, CFI_DIM_FIELD_SM);
|
||||
}
|
||||
|
||||
#undef CFI_FIELD_BASE_ADDR
|
||||
#undef CFI_FIELD_ELEM_LEN
|
||||
#undef CFI_FIELD_VERSION
|
||||
#undef CFI_FIELD_RANK
|
||||
#undef CFI_FIELD_ATTRIBUTE
|
||||
#undef CFI_FIELD_TYPE
|
||||
#undef CFI_FIELD_DIM
|
||||
|
||||
#undef CFI_DIM_FIELD_LOWER_BOUND
|
||||
#undef CFI_DIM_FIELD_EXTENT
|
||||
#undef CFI_DIM_FIELD_SM
|
||||
|
||||
/* Build expressions to access the members of an array descriptor.
|
||||
It's surprisingly easy to mess up here, so never access
|
||||
|
@ -288,6 +393,20 @@ gfc_conv_descriptor_attribute (tree desc)
|
|||
dtype, tmp, NULL_TREE);
|
||||
}
|
||||
|
||||
tree
|
||||
gfc_conv_descriptor_type (tree desc)
|
||||
{
|
||||
tree tmp;
|
||||
tree dtype;
|
||||
|
||||
dtype = gfc_conv_descriptor_dtype (desc);
|
||||
tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)), GFC_DTYPE_TYPE);
|
||||
gcc_assert (tmp!= NULL_TREE
|
||||
&& TREE_TYPE (tmp) == signed_char_type_node);
|
||||
return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
|
||||
dtype, tmp, NULL_TREE);
|
||||
}
|
||||
|
||||
tree
|
||||
gfc_get_descriptor_dimension (tree desc)
|
||||
{
|
||||
|
@ -825,7 +944,11 @@ gfc_get_array_span (tree desc, gfc_expr *expr)
|
|||
{
|
||||
tree tmp;
|
||||
|
||||
if (is_pointer_array (desc) || get_CFI_desc (NULL, expr, &desc, NULL))
|
||||
if (is_pointer_array (desc)
|
||||
|| (get_CFI_desc (NULL, expr, &desc, NULL)
|
||||
&& (POINTER_TYPE_P (TREE_TYPE (desc))
|
||||
? GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (desc)))
|
||||
: GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))))
|
||||
{
|
||||
if (POINTER_TYPE_P (TREE_TYPE (desc)))
|
||||
desc = build_fold_indirect_ref_loc (input_location, desc);
|
||||
|
@ -833,6 +956,14 @@ gfc_get_array_span (tree desc, gfc_expr *expr)
|
|||
/* This will have the span field set. */
|
||||
tmp = gfc_conv_descriptor_span_get (desc);
|
||||
}
|
||||
else if (expr->ts.type == BT_ASSUMED)
|
||||
{
|
||||
if (DECL_LANG_SPECIFIC (desc) && GFC_DECL_SAVED_DESCRIPTOR (desc))
|
||||
desc = GFC_DECL_SAVED_DESCRIPTOR (desc);
|
||||
if (POINTER_TYPE_P (TREE_TYPE (desc)))
|
||||
desc = build_fold_indirect_ref_loc (input_location, desc);
|
||||
tmp = gfc_conv_descriptor_span_get (desc);
|
||||
}
|
||||
else if (TREE_CODE (desc) == COMPONENT_REF
|
||||
&& GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
|
||||
&& GFC_CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (desc, 0))))
|
||||
|
@ -6286,7 +6417,7 @@ gfc_trans_array_cobounds (tree type, stmtblock_t * pblock,
|
|||
/* Generate code to evaluate non-constant array bounds. Sets *poffset and
|
||||
returns the size (in elements) of the array. */
|
||||
|
||||
static tree
|
||||
tree
|
||||
gfc_trans_array_bounds (tree type, gfc_symbol * sym, tree * poffset,
|
||||
stmtblock_t * pblock)
|
||||
{
|
||||
|
@ -7755,6 +7886,15 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
|
|||
tmp = gfc_conv_descriptor_dtype (parm);
|
||||
if (se->unlimited_polymorphic)
|
||||
dtype = gfc_get_dtype (TREE_TYPE (desc), &loop.dimen);
|
||||
else if (expr->ts.type == BT_ASSUMED)
|
||||
{
|
||||
tree tmp2 = desc;
|
||||
if (DECL_LANG_SPECIFIC (tmp2) && GFC_DECL_SAVED_DESCRIPTOR (tmp2))
|
||||
tmp2 = GFC_DECL_SAVED_DESCRIPTOR (tmp2);
|
||||
if (POINTER_TYPE_P (TREE_TYPE (tmp2)))
|
||||
tmp2 = build_fold_indirect_ref_loc (input_location, tmp2);
|
||||
dtype = gfc_conv_descriptor_dtype (tmp2);
|
||||
}
|
||||
else
|
||||
dtype = gfc_get_dtype (parmtype);
|
||||
gfc_add_modify (&loop.pre, tmp, dtype);
|
||||
|
@ -9006,7 +9146,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
|
|||
DECL_ARTIFICIAL (cdesc) = 1;
|
||||
|
||||
gfc_add_modify (&tmpblock, gfc_conv_descriptor_dtype (cdesc),
|
||||
gfc_get_dtype_rank_type (1, tmp));
|
||||
gfc_get_dtype_rank_type (1, tmp));
|
||||
gfc_conv_descriptor_lbound_set (&tmpblock, cdesc,
|
||||
gfc_index_zero_node,
|
||||
gfc_index_one_node);
|
||||
|
|
|
@ -160,7 +160,8 @@ tree gfc_conv_array_stride (tree, int);
|
|||
tree gfc_conv_array_lbound (tree, int);
|
||||
tree gfc_conv_array_ubound (tree, int);
|
||||
|
||||
/* Set cobounds of an array. */
|
||||
/* Set (co)bounds of an array. */
|
||||
tree gfc_trans_array_bounds (tree, gfc_symbol *, tree *, stmtblock_t *);
|
||||
void gfc_trans_array_cobounds (tree, stmtblock_t *, const gfc_symbol *);
|
||||
|
||||
/* Build expressions for accessing components of an array descriptor. */
|
||||
|
@ -175,6 +176,7 @@ tree gfc_conv_descriptor_dtype (tree);
|
|||
tree gfc_conv_descriptor_rank (tree);
|
||||
tree gfc_conv_descriptor_elem_len (tree);
|
||||
tree gfc_conv_descriptor_attribute (tree);
|
||||
tree gfc_conv_descriptor_type (tree);
|
||||
tree gfc_get_descriptor_dimension (tree);
|
||||
tree gfc_conv_descriptor_stride_get (tree, tree);
|
||||
tree gfc_conv_descriptor_lbound_get (tree, tree);
|
||||
|
@ -188,6 +190,18 @@ void gfc_conv_descriptor_stride_set (stmtblock_t *, tree, tree, tree);
|
|||
void gfc_conv_descriptor_lbound_set (stmtblock_t *, tree, tree, tree);
|
||||
void gfc_conv_descriptor_ubound_set (stmtblock_t *, tree, tree, tree);
|
||||
|
||||
/* CFI descriptor. */
|
||||
tree gfc_get_cfi_desc_base_addr (tree);
|
||||
tree gfc_get_cfi_desc_elem_len (tree);
|
||||
tree gfc_get_cfi_desc_version (tree);
|
||||
tree gfc_get_cfi_desc_rank (tree);
|
||||
tree gfc_get_cfi_desc_type (tree);
|
||||
tree gfc_get_cfi_desc_attribute (tree);
|
||||
tree gfc_get_cfi_dim_lbound (tree, tree);
|
||||
tree gfc_get_cfi_dim_extent (tree, tree);
|
||||
tree gfc_get_cfi_dim_sm (tree, tree);
|
||||
|
||||
|
||||
/* Shift lower bound of descriptor, updating ubound and offset. */
|
||||
void gfc_conv_shift_descriptor_lbound (stmtblock_t*, tree, int, tree);
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2866,6 +2866,9 @@ tree
|
|||
gfc_maybe_dereference_var (gfc_symbol *sym, tree var, bool descriptor_only_p,
|
||||
bool is_classarray)
|
||||
{
|
||||
if (is_CFI_desc (sym, NULL))
|
||||
return build_fold_indirect_ref_loc (input_location, var);
|
||||
|
||||
/* Characters are entirely different from other types, they are treated
|
||||
separately. */
|
||||
if (sym->ts.type == BT_CHARACTER)
|
||||
|
@ -4922,7 +4925,7 @@ gfc_conv_subref_array_arg (gfc_se *se, gfc_expr * expr, int g77,
|
|||
|
||||
if (fsym && proc_name)
|
||||
msg = xasprintf ("An array temporary was created for argument "
|
||||
"'%s' of procedure '%s'", fsym->name, proc_name);
|
||||
"'%s' of procedure '%s'", fsym->name, proc_name);
|
||||
else
|
||||
msg = xasprintf ("An array temporary was created");
|
||||
|
||||
|
@ -5220,6 +5223,8 @@ class_array_fcn:
|
|||
tree post_cond;
|
||||
|
||||
type = TREE_TYPE (parmse->expr);
|
||||
if (POINTER_TYPE_P (type) && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (type)))
|
||||
type = TREE_TYPE (type);
|
||||
pointer = gfc_create_var (type, "arg_ptr");
|
||||
|
||||
if (check_contiguous)
|
||||
|
@ -5263,17 +5268,25 @@ class_array_fcn:
|
|||
gfc_add_block_to_block (&se->pre, &(&array_se)->pre);
|
||||
gfc_add_block_to_block (&se->pre, &(&array_se)->post);
|
||||
|
||||
/* if_stmt = { pointer = &a[0]; } . */
|
||||
/* if_stmt = { descriptor ? pointer = a : pointer = &a[0]; } . */
|
||||
gfc_init_block (&if_block);
|
||||
tmp = gfc_conv_array_data (array_se.expr);
|
||||
tmp = fold_convert (type, tmp);
|
||||
gfc_add_modify (&if_block, pointer, tmp);
|
||||
if (GFC_DESCRIPTOR_TYPE_P (type))
|
||||
gfc_add_modify (&if_block, pointer, array_se.expr);
|
||||
else
|
||||
{
|
||||
tmp = gfc_conv_array_data (array_se.expr);
|
||||
tmp = fold_convert (type, tmp);
|
||||
gfc_add_modify (&if_block, pointer, tmp);
|
||||
}
|
||||
if_stmt = gfc_finish_block (&if_block);
|
||||
|
||||
/* else_stmt = { parmse->pre(); pointer = parmse->expr; } . */
|
||||
gfc_init_block (&else_block);
|
||||
gfc_add_block_to_block (&else_block, &parmse->pre);
|
||||
gfc_add_modify (&else_block, pointer, parmse->expr);
|
||||
tmp = (GFC_DESCRIPTOR_TYPE_P (type)
|
||||
? build_fold_indirect_ref_loc (input_location, parmse->expr)
|
||||
: parmse->expr);
|
||||
gfc_add_modify (&else_block, pointer, tmp);
|
||||
else_stmt = gfc_finish_block (&else_block);
|
||||
|
||||
/* And put the above into an if statement. */
|
||||
|
@ -5300,7 +5313,11 @@ class_array_fcn:
|
|||
|
||||
/* else_stmt = { pointer = NULL; } . */
|
||||
gfc_init_block (&else_block);
|
||||
gfc_add_modify (&else_block, pointer, build_int_cst (type, 0));
|
||||
if (GFC_DESCRIPTOR_TYPE_P (type))
|
||||
gfc_conv_descriptor_data_set (&else_block, pointer,
|
||||
null_pointer_node);
|
||||
else
|
||||
gfc_add_modify (&else_block, pointer, build_int_cst (type, 0));
|
||||
else_stmt = gfc_finish_block (&else_block);
|
||||
|
||||
tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
|
||||
|
@ -5344,6 +5361,24 @@ class_array_fcn:
|
|||
tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, post_cond,
|
||||
post_stmts, build_empty_stmt (input_location));
|
||||
gfc_add_expr_to_block (&se->post, tmp);
|
||||
if (GFC_DESCRIPTOR_TYPE_P (type))
|
||||
{
|
||||
type = TREE_TYPE (parmse->expr);
|
||||
if (POINTER_TYPE_P (type))
|
||||
{
|
||||
pointer = gfc_build_addr_expr (type, pointer);
|
||||
if (pass_optional)
|
||||
{
|
||||
tmp = gfc_likely (present_var, PRED_FORTRAN_ABSENT_DUMMY);
|
||||
pointer = fold_build3_loc (input_location, COND_EXPR, type,
|
||||
tmp, pointer,
|
||||
fold_convert (type,
|
||||
null_pointer_node));
|
||||
}
|
||||
}
|
||||
else
|
||||
gcc_assert (!pass_optional);
|
||||
}
|
||||
se->expr = pointer;
|
||||
}
|
||||
|
||||
|
@ -5484,168 +5519,457 @@ set_dtype_for_unallocated (gfc_se *parmse, gfc_expr *e)
|
|||
static void
|
||||
gfc_conv_gfc_desc_to_cfi_desc (gfc_se *parmse, gfc_expr *e, gfc_symbol *fsym)
|
||||
{
|
||||
tree tmp;
|
||||
tree cfi_desc_ptr;
|
||||
tree gfc_desc_ptr;
|
||||
tree type;
|
||||
tree cond;
|
||||
tree desc_attr;
|
||||
int attribute;
|
||||
int cfi_attribute;
|
||||
symbol_attribute attr = gfc_expr_attr (e);
|
||||
stmtblock_t block, block2;
|
||||
tree cfi, gfc, tmp, tmp2;
|
||||
tree present = NULL;
|
||||
tree gfc_strlen = NULL;
|
||||
tree rank;
|
||||
gfc_se se;
|
||||
|
||||
/* If this is a full array or a scalar, the allocatable and pointer
|
||||
attributes can be passed. Otherwise it is 'CFI_attribute_other'*/
|
||||
attribute = 2;
|
||||
if (!e->rank || gfc_get_full_arrayspec_from_expr (e))
|
||||
if (fsym->attr.optional
|
||||
&& e->expr_type == EXPR_VARIABLE
|
||||
&& e->symtree->n.sym->attr.optional)
|
||||
present = gfc_conv_expr_present (e->symtree->n.sym);
|
||||
|
||||
gfc_init_block (&block);
|
||||
|
||||
/* Convert original argument to a tree. */
|
||||
gfc_init_se (&se, NULL);
|
||||
if (e->rank == 0)
|
||||
{
|
||||
if (attr.pointer)
|
||||
attribute = 0;
|
||||
else if (attr.allocatable)
|
||||
attribute = 1;
|
||||
se.want_pointer = 1;
|
||||
gfc_conv_expr (&se, e);
|
||||
gfc = se.expr;
|
||||
/* gfc_conv_constant ignores se.want_poiner, e.g. for string_cst. */
|
||||
if (!POINTER_TYPE_P (TREE_TYPE (gfc)))
|
||||
gfc = gfc_build_addr_expr (NULL, gfc);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the actual argument can be noncontiguous, copy-in/out is required,
|
||||
if the dummy has either the CONTIGUOUS attribute or is an assumed-
|
||||
length assumed-length/assumed-size CHARACTER array. */
|
||||
se.force_no_tmp = 1;
|
||||
if ((fsym->attr.contiguous
|
||||
|| (fsym->ts.type == BT_CHARACTER && !fsym->ts.u.cl->length
|
||||
&& (fsym->as->type == AS_ASSUMED_SIZE
|
||||
|| fsym->as->type == AS_EXPLICIT)))
|
||||
&& !gfc_is_simply_contiguous (e, false, true))
|
||||
{
|
||||
bool optional = fsym->attr.optional;
|
||||
fsym->attr.optional = 0;
|
||||
gfc_conv_subref_array_arg (&se, e, false, fsym->attr.intent,
|
||||
fsym->attr.pointer, fsym,
|
||||
fsym->ns->proc_name->name, NULL,
|
||||
/* check_contiguous= */ true);
|
||||
fsym->attr.optional = optional;
|
||||
}
|
||||
else
|
||||
gfc_conv_expr_descriptor (&se, e);
|
||||
gfc = se.expr;
|
||||
/* For dt(:)%var the elem_len*stride != sm, hence, GFC uses
|
||||
elem_len = sizeof(dt) and base_addr = dt(lb) instead.
|
||||
gfc_get_dataptr_offset fixes the base_addr; for elem_len, see below.
|
||||
While sm is fine as it uses span*stride and not elem_len. */
|
||||
if (POINTER_TYPE_P (TREE_TYPE (gfc)))
|
||||
gfc = build_fold_indirect_ref_loc (input_location, gfc);
|
||||
else if (is_subref_array (e) && e->ts.type != BT_CHARACTER)
|
||||
gfc_get_dataptr_offset (&se.pre, gfc, gfc, NULL, true, e);
|
||||
}
|
||||
if (e->ts.type == BT_CHARACTER)
|
||||
{
|
||||
if (se.string_length)
|
||||
gfc_strlen = se.string_length;
|
||||
else if (e->ts.u.cl->backend_decl)
|
||||
gfc_strlen = e->ts.u.cl->backend_decl;
|
||||
else
|
||||
gcc_unreachable ();
|
||||
}
|
||||
gfc_add_block_to_block (&block, &se.pre);
|
||||
|
||||
/* Create array decriptor and set version, rank, attribute, type. */
|
||||
cfi = gfc_create_var (gfc_get_cfi_type (e->rank < 0
|
||||
? GFC_MAX_DIMENSIONS : e->rank,
|
||||
false), "cfi");
|
||||
/* Convert to CFI_cdesc_t, which has dim[] to avoid TBAA issues,*/
|
||||
if (fsym->attr.dimension && fsym->as->type == AS_ASSUMED_RANK)
|
||||
{
|
||||
tmp = gfc_get_cfi_type (-1, !fsym->attr.pointer && !fsym->attr.target);
|
||||
tmp = build_pointer_type (tmp);
|
||||
parmse->expr = cfi = gfc_build_addr_expr (tmp, cfi);
|
||||
cfi = build_fold_indirect_ref_loc (input_location, cfi);
|
||||
}
|
||||
else
|
||||
parmse->expr = gfc_build_addr_expr (NULL, cfi);
|
||||
|
||||
tmp = gfc_get_cfi_desc_version (cfi);
|
||||
gfc_add_modify (&block, tmp,
|
||||
build_int_cst (TREE_TYPE (tmp), CFI_VERSION));
|
||||
if (e->rank < 0)
|
||||
rank = fold_convert (signed_char_type_node, gfc_conv_descriptor_rank (gfc));
|
||||
else
|
||||
rank = build_int_cst (signed_char_type_node, e->rank);
|
||||
tmp = gfc_get_cfi_desc_rank (cfi);
|
||||
gfc_add_modify (&block, tmp, rank);
|
||||
int itype = CFI_type_other;
|
||||
if (e->ts.f90_type == BT_VOID)
|
||||
itype = (e->ts.u.derived->intmod_sym_id == ISOCBINDING_FUNPTR
|
||||
? CFI_type_cfunptr : CFI_type_cptr);
|
||||
else
|
||||
switch (e->ts.type)
|
||||
{
|
||||
case BT_INTEGER:
|
||||
case BT_LOGICAL:
|
||||
case BT_REAL:
|
||||
case BT_COMPLEX:
|
||||
itype = CFI_type_from_type_kind (e->ts.type, e->ts.kind);
|
||||
break;
|
||||
case BT_CHARACTER:
|
||||
itype = CFI_type_from_type_kind (CFI_type_Character, e->ts.kind);
|
||||
break;
|
||||
case BT_DERIVED:
|
||||
itype = CFI_type_struct;
|
||||
break;
|
||||
case BT_VOID:
|
||||
itype = (e->ts.u.derived->intmod_sym_id == ISOCBINDING_FUNPTR
|
||||
? CFI_type_cfunptr : CFI_type_cptr);
|
||||
break;
|
||||
case BT_ASSUMED:
|
||||
itype = CFI_type_other; // FIXME: Or CFI_type_cptr ?
|
||||
break;
|
||||
case BT_CLASS:
|
||||
case BT_PROCEDURE:
|
||||
case BT_HOLLERITH:
|
||||
case BT_UNION:
|
||||
case BT_BOZ:
|
||||
case BT_UNKNOWN:
|
||||
// FIXME: Really unreachable? Or reachable for type(*) ? If so, CFI_type_other?
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
tmp = gfc_get_cfi_desc_type (cfi);
|
||||
gfc_add_modify (&block, tmp,
|
||||
build_int_cst (TREE_TYPE (tmp), itype));
|
||||
|
||||
int attr = CFI_attribute_other;
|
||||
if (fsym->attr.pointer)
|
||||
attr = CFI_attribute_pointer;
|
||||
else if (fsym->attr.allocatable)
|
||||
attr = CFI_attribute_allocatable;
|
||||
tmp = gfc_get_cfi_desc_attribute (cfi);
|
||||
gfc_add_modify (&block, tmp,
|
||||
build_int_cst (TREE_TYPE (tmp), attr));
|
||||
|
||||
if (e->rank == 0)
|
||||
{
|
||||
tmp = gfc_get_cfi_desc_base_addr (cfi);
|
||||
gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), gfc));
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp = gfc_get_cfi_desc_base_addr (cfi);
|
||||
tmp2 = gfc_conv_descriptor_data_get (gfc);
|
||||
gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), tmp2));
|
||||
}
|
||||
|
||||
if (fsym->attr.pointer)
|
||||
cfi_attribute = 0;
|
||||
else if (fsym->attr.allocatable)
|
||||
cfi_attribute = 1;
|
||||
else
|
||||
cfi_attribute = 2;
|
||||
/* Set elem_len if known - must be before the next if block.
|
||||
Note that allocatable implies 'len=:'. */
|
||||
if (e->ts.type != BT_ASSUMED && e->ts.type != BT_CHARACTER )
|
||||
{
|
||||
/* Length is known at compile time; use use 'block' for it. */
|
||||
tmp = size_in_bytes (gfc_typenode_for_spec (&e->ts));
|
||||
tmp2 = gfc_get_cfi_desc_elem_len (cfi);
|
||||
gfc_add_modify (&block, tmp2, fold_convert (TREE_TYPE (tmp2), tmp));
|
||||
}
|
||||
|
||||
/* When allocatable + intent out, free the cfi descriptor. */
|
||||
if (fsym->attr.allocatable && fsym->attr.intent == INTENT_OUT)
|
||||
{
|
||||
tmp = gfc_get_cfi_desc_base_addr (cfi);
|
||||
tree call = builtin_decl_explicit (BUILT_IN_FREE);
|
||||
call = build_call_expr_loc (input_location, call, 1, tmp);
|
||||
gfc_add_expr_to_block (&block, fold_convert (void_type_node, call));
|
||||
gfc_add_modify (&block, tmp,
|
||||
fold_convert (TREE_TYPE (tmp), null_pointer_node));
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* If not unallocated/unassociated. */
|
||||
gfc_init_block (&block2);
|
||||
|
||||
/* Set elem_len, which may be only known at run time. */
|
||||
if (e->ts.type == BT_CHARACTER)
|
||||
{
|
||||
gcc_assert (gfc_strlen);
|
||||
tmp = gfc_strlen;
|
||||
if (e->ts.kind != 1)
|
||||
tmp = fold_build2_loc (input_location, MULT_EXPR,
|
||||
gfc_charlen_type_node, tmp,
|
||||
build_int_cst (gfc_charlen_type_node,
|
||||
e->ts.kind));
|
||||
tmp2 = gfc_get_cfi_desc_elem_len (cfi);
|
||||
gfc_add_modify (&block2, tmp2, fold_convert (TREE_TYPE (tmp2), tmp));
|
||||
}
|
||||
else if (e->ts.type == BT_ASSUMED)
|
||||
{
|
||||
tmp = gfc_conv_descriptor_elem_len (gfc);
|
||||
tmp2 = gfc_get_cfi_desc_elem_len (cfi);
|
||||
gfc_add_modify (&block2, tmp2, fold_convert (TREE_TYPE (tmp2), tmp));
|
||||
}
|
||||
|
||||
if (e->ts.type == BT_ASSUMED)
|
||||
{
|
||||
/* Note: type(*) implies assumed-shape/assumed-rank if fsym requires
|
||||
an CFI descriptor. Use the type in the descritor as it provide
|
||||
mode information. (Quality of implementation feature.) */
|
||||
tree cond;
|
||||
tree ctype = gfc_get_cfi_desc_type (cfi);
|
||||
tree type = fold_convert (TREE_TYPE (ctype),
|
||||
gfc_conv_descriptor_type (gfc));
|
||||
tree kind = fold_convert (TREE_TYPE (ctype),
|
||||
gfc_conv_descriptor_elem_len (gfc));
|
||||
kind = fold_build2_loc (input_location, LSHIFT_EXPR, TREE_TYPE (type),
|
||||
kind, build_int_cst (TREE_TYPE (type),
|
||||
CFI_type_kind_shift));
|
||||
|
||||
/* if (BT_VOID) CFI_type_cptr else CFI_type_other */
|
||||
/* Note: BT_VOID is could also be CFI_type_funcptr, but assume c_ptr. */
|
||||
cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, type,
|
||||
build_int_cst (TREE_TYPE (type), BT_VOID));
|
||||
tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node, ctype,
|
||||
build_int_cst (TREE_TYPE (type), CFI_type_cptr));
|
||||
tmp2 = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
|
||||
ctype,
|
||||
build_int_cst (TREE_TYPE (type), CFI_type_other));
|
||||
tmp2 = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
|
||||
tmp, tmp2);
|
||||
/* if (BT_DERIVED) CFI_type_struct else < tmp2 > */
|
||||
cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, type,
|
||||
build_int_cst (TREE_TYPE (type), BT_DERIVED));
|
||||
tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node, ctype,
|
||||
build_int_cst (TREE_TYPE (type), CFI_type_struct));
|
||||
tmp2 = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
|
||||
tmp, tmp2);
|
||||
/* if (BT_CHARACTER) CFI_type_Character + kind=1 else < tmp2 > */
|
||||
/* Note: could also be kind=4, with cfi->elem_len = gfc->elem_len*4. */
|
||||
cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, type,
|
||||
build_int_cst (TREE_TYPE (type), BT_CHARACTER));
|
||||
tmp = build_int_cst (TREE_TYPE (type),
|
||||
CFI_type_from_type_kind (CFI_type_Character, 1));
|
||||
tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
|
||||
ctype, tmp);
|
||||
tmp2 = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
|
||||
tmp, tmp2);
|
||||
/* if (BT_COMPLEX) CFI_type_Complex + kind/2 else < tmp2 > */
|
||||
cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, type,
|
||||
build_int_cst (TREE_TYPE (type), BT_COMPLEX));
|
||||
tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, TREE_TYPE (type),
|
||||
kind, build_int_cst (TREE_TYPE (type), 2));
|
||||
tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (type), tmp,
|
||||
build_int_cst (TREE_TYPE (type),
|
||||
CFI_type_Complex));
|
||||
tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
|
||||
ctype, tmp);
|
||||
tmp2 = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
|
||||
tmp, tmp2);
|
||||
/* if (BT_INTEGER || BT_LOGICAL || BT_REAL) type + kind else <tmp2> */
|
||||
cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, type,
|
||||
build_int_cst (TREE_TYPE (type), BT_INTEGER));
|
||||
tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, type,
|
||||
build_int_cst (TREE_TYPE (type), BT_LOGICAL));
|
||||
cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, boolean_type_node,
|
||||
cond, tmp);
|
||||
tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, type,
|
||||
build_int_cst (TREE_TYPE (type), BT_REAL));
|
||||
cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, boolean_type_node,
|
||||
cond, tmp);
|
||||
tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (type),
|
||||
type, kind);
|
||||
tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
|
||||
ctype, tmp);
|
||||
tmp2 = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
|
||||
tmp, tmp2);
|
||||
gfc_add_expr_to_block (&block2, tmp2);
|
||||
}
|
||||
|
||||
if (e->rank != 0)
|
||||
{
|
||||
parmse->force_no_tmp = 1;
|
||||
if (fsym->attr.contiguous
|
||||
&& !gfc_is_simply_contiguous (e, false, true))
|
||||
gfc_conv_subref_array_arg (parmse, e, false, fsym->attr.intent,
|
||||
fsym->attr.pointer);
|
||||
/* Loop: for (i = 0; i < rank; ++i). */
|
||||
tree idx = gfc_create_var (TREE_TYPE (rank), "idx");
|
||||
/* Loop body. */
|
||||
stmtblock_t loop_body;
|
||||
gfc_init_block (&loop_body);
|
||||
/* cfi->dim[i].lower_bound = (allocatable/pointer)
|
||||
? gfc->dim[i].lbound : 0 */
|
||||
if (fsym->attr.pointer || fsym->attr.allocatable)
|
||||
tmp = gfc_conv_descriptor_lbound_get (gfc, idx);
|
||||
else
|
||||
gfc_conv_expr_descriptor (parmse, e);
|
||||
tmp = gfc_index_zero_node;
|
||||
gfc_add_modify (&loop_body, gfc_get_cfi_dim_lbound (cfi, idx), tmp);
|
||||
/* cfi->dim[i].extent = gfc->dim[i].ubound - gfc->dim[i].lbound + 1. */
|
||||
tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
|
||||
gfc_conv_descriptor_ubound_get (gfc, idx),
|
||||
gfc_conv_descriptor_lbound_get (gfc, idx));
|
||||
tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
|
||||
tmp, gfc_index_one_node);
|
||||
gfc_add_modify (&loop_body, gfc_get_cfi_dim_extent (cfi, idx), tmp);
|
||||
/* d->dim[n].sm = gfc->dim[i].stride * gfc->span); */
|
||||
tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
|
||||
gfc_conv_descriptor_stride_get (gfc, idx),
|
||||
gfc_conv_descriptor_span_get (gfc));
|
||||
gfc_add_modify (&loop_body, gfc_get_cfi_dim_sm (cfi, idx), tmp);
|
||||
|
||||
if (POINTER_TYPE_P (TREE_TYPE (parmse->expr)))
|
||||
parmse->expr = build_fold_indirect_ref_loc (input_location,
|
||||
parmse->expr);
|
||||
bool is_artificial = (INDIRECT_REF_P (parmse->expr)
|
||||
? DECL_ARTIFICIAL (TREE_OPERAND (parmse->expr, 0))
|
||||
: DECL_ARTIFICIAL (parmse->expr));
|
||||
/* Generate loop. */
|
||||
gfc_simple_for_loop (&block2, idx, build_int_cst (TREE_TYPE (idx), 0),
|
||||
rank, LT_EXPR, build_int_cst (TREE_TYPE (idx), 1),
|
||||
gfc_finish_block (&loop_body));
|
||||
|
||||
/* Unallocated allocatable arrays and unassociated pointer arrays
|
||||
need their dtype setting if they are argument associated with
|
||||
assumed rank dummies. */
|
||||
if (fsym && fsym->as
|
||||
&& (gfc_expr_attr (e).pointer
|
||||
|| gfc_expr_attr (e).allocatable))
|
||||
set_dtype_for_unallocated (parmse, e);
|
||||
|
||||
/* All the temporary descriptors are marked as DECL_ARTIFICIAL. If
|
||||
the expression type is different from the descriptor type, then
|
||||
the offset must be found (eg. to a component ref or substring)
|
||||
and the dtype updated. Assumed type entities are only allowed
|
||||
to be dummies in Fortran. They therefore lack the decl specific
|
||||
appendiges and so must be treated differently from other fortran
|
||||
entities passed to CFI descriptors in the interface decl. */
|
||||
type = e->ts.type != BT_ASSUMED ? gfc_typenode_for_spec (&e->ts) :
|
||||
NULL_TREE;
|
||||
|
||||
if (type && is_artificial
|
||||
&& type != gfc_get_element_type (TREE_TYPE (parmse->expr)))
|
||||
if (e->expr_type == EXPR_VARIABLE
|
||||
&& e->ref
|
||||
&& e->ref->u.ar.type == AR_FULL
|
||||
&& e->symtree->n.sym->attr.dummy
|
||||
&& e->symtree->n.sym->as
|
||||
&& e->symtree->n.sym->as->type == AS_ASSUMED_SIZE)
|
||||
{
|
||||
/* Obtain the offset to the data. */
|
||||
gfc_get_dataptr_offset (&parmse->pre, parmse->expr, parmse->expr,
|
||||
gfc_index_zero_node, true, e);
|
||||
tmp = gfc_get_cfi_dim_extent (cfi, gfc_rank_cst[e->rank-1]),
|
||||
gfc_add_modify (&block2, tmp, build_int_cst (TREE_TYPE (tmp), -1));
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the dtype. */
|
||||
gfc_add_modify (&parmse->pre,
|
||||
gfc_conv_descriptor_dtype (parmse->expr),
|
||||
gfc_get_dtype_rank_type (e->rank, type));
|
||||
}
|
||||
else if (type == NULL_TREE
|
||||
|| (!is_subref_array (e) && !is_artificial))
|
||||
{
|
||||
/* Make sure that the span is set for expressions where it
|
||||
might not have been done already. */
|
||||
tmp = gfc_conv_descriptor_elem_len (parmse->expr);
|
||||
tmp = fold_convert (gfc_array_index_type, tmp);
|
||||
gfc_conv_descriptor_span_set (&parmse->pre, parmse->expr, tmp);
|
||||
}
|
||||
if (fsym->attr.allocatable || fsym->attr.pointer)
|
||||
{
|
||||
tmp = gfc_get_cfi_desc_base_addr (cfi),
|
||||
tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
|
||||
tmp, null_pointer_node);
|
||||
tmp = build3_v (COND_EXPR, tmp, gfc_finish_block (&block2),
|
||||
build_empty_stmt (input_location));
|
||||
gfc_add_expr_to_block (&block, tmp);
|
||||
}
|
||||
else
|
||||
gfc_add_block_to_block (&block, &block2);
|
||||
|
||||
|
||||
done:
|
||||
if (present)
|
||||
{
|
||||
parmse->expr = build3_loc (input_location, COND_EXPR,
|
||||
TREE_TYPE (parmse->expr),
|
||||
present, parmse->expr, null_pointer_node);
|
||||
tmp = build3_v (COND_EXPR, present, gfc_finish_block (&block),
|
||||
build_empty_stmt (input_location));
|
||||
gfc_add_expr_to_block (&parmse->pre, tmp);
|
||||
}
|
||||
else
|
||||
gfc_add_block_to_block (&parmse->pre, &block);
|
||||
|
||||
gfc_init_block (&block);
|
||||
|
||||
if ((!fsym->attr.allocatable && !fsym->attr.pointer)
|
||||
|| fsym->attr.intent == INTENT_IN)
|
||||
goto post_call;
|
||||
|
||||
gfc_init_block (&block2);
|
||||
if (e->rank == 0)
|
||||
{
|
||||
tmp = gfc_get_cfi_desc_base_addr (cfi);
|
||||
gfc_add_modify (&block, gfc, fold_convert (TREE_TYPE (gfc), tmp));
|
||||
}
|
||||
else
|
||||
{
|
||||
gfc_conv_expr (parmse, e);
|
||||
tmp = gfc_get_cfi_desc_base_addr (cfi);
|
||||
gfc_conv_descriptor_data_set (&block, gfc, tmp);
|
||||
|
||||
if (POINTER_TYPE_P (TREE_TYPE (parmse->expr)))
|
||||
parmse->expr = build_fold_indirect_ref_loc (input_location,
|
||||
parmse->expr);
|
||||
if (fsym->attr.allocatable)
|
||||
{
|
||||
/* gfc->span = cfi->elem_len. */
|
||||
tmp = fold_convert (gfc_array_index_type,
|
||||
gfc_get_cfi_dim_sm (cfi, gfc_rank_cst[0]));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* gfc->span = ((cfi->dim[0].sm % cfi->elem_len)
|
||||
? cfi->dim[0].sm : cfi->elem_len). */
|
||||
tmp = gfc_get_cfi_dim_sm (cfi, gfc_rank_cst[0]);
|
||||
tmp2 = fold_convert (gfc_array_index_type,
|
||||
gfc_get_cfi_desc_elem_len (cfi));
|
||||
tmp = fold_build2_loc (input_location, TRUNC_MOD_EXPR,
|
||||
gfc_array_index_type, tmp, tmp2);
|
||||
tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
|
||||
tmp, gfc_index_zero_node);
|
||||
tmp = build3_loc (input_location, COND_EXPR, gfc_array_index_type, tmp,
|
||||
gfc_get_cfi_dim_sm (cfi, gfc_rank_cst[0]), tmp2);
|
||||
}
|
||||
gfc_conv_descriptor_span_set (&block2, gfc, tmp);
|
||||
|
||||
parmse->expr = gfc_conv_scalar_to_descriptor (parmse,
|
||||
parmse->expr, attr);
|
||||
/* Calculate offset + set lbound, ubound and stride. */
|
||||
gfc_conv_descriptor_offset_set (&block2, gfc, gfc_index_zero_node);
|
||||
/* Loop: for (i = 0; i < rank; ++i). */
|
||||
tree idx = gfc_create_var (TREE_TYPE (rank), "idx");
|
||||
/* Loop body. */
|
||||
stmtblock_t loop_body;
|
||||
gfc_init_block (&loop_body);
|
||||
/* gfc->dim[i].lbound = ... */
|
||||
tmp = gfc_get_cfi_dim_lbound (cfi, idx);
|
||||
gfc_conv_descriptor_lbound_set (&loop_body, gfc, idx, tmp);
|
||||
|
||||
/* gfc->dim[i].ubound = gfc->dim[i].lbound + cfi->dim[i].extent - 1. */
|
||||
tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
|
||||
gfc_conv_descriptor_lbound_get (gfc, idx),
|
||||
gfc_index_one_node);
|
||||
tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
|
||||
gfc_get_cfi_dim_extent (cfi, idx), tmp);
|
||||
gfc_conv_descriptor_ubound_set (&loop_body, gfc, idx, tmp);
|
||||
|
||||
/* gfc->dim[i].stride = cfi->dim[i].sm / cfi>elem_len */
|
||||
tmp = gfc_get_cfi_dim_sm (cfi, idx);
|
||||
tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
|
||||
gfc_array_index_type, tmp,
|
||||
fold_convert (gfc_array_index_type,
|
||||
gfc_get_cfi_desc_elem_len (cfi)));
|
||||
gfc_conv_descriptor_stride_set (&loop_body, gfc, idx, tmp);
|
||||
|
||||
/* gfc->offset -= gfc->dim[i].stride * gfc->dim[i].lbound. */
|
||||
tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
|
||||
gfc_conv_descriptor_stride_get (gfc, idx),
|
||||
gfc_conv_descriptor_lbound_get (gfc, idx));
|
||||
tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
|
||||
gfc_conv_descriptor_offset_get (gfc), tmp);
|
||||
gfc_conv_descriptor_offset_set (&loop_body, gfc, tmp);
|
||||
/* Generate loop. */
|
||||
gfc_simple_for_loop (&block2, idx, build_int_cst (TREE_TYPE (idx), 0),
|
||||
rank, LT_EXPR, build_int_cst (TREE_TYPE (idx), 1),
|
||||
gfc_finish_block (&loop_body));
|
||||
}
|
||||
|
||||
/* Set the CFI attribute field through a temporary value for the
|
||||
gfc attribute. */
|
||||
desc_attr = gfc_conv_descriptor_attribute (parmse->expr);
|
||||
tmp = fold_build2_loc (input_location, MODIFY_EXPR,
|
||||
void_type_node, desc_attr,
|
||||
build_int_cst (TREE_TYPE (desc_attr), cfi_attribute));
|
||||
gfc_add_expr_to_block (&parmse->pre, tmp);
|
||||
|
||||
/* Now pass the gfc_descriptor by reference. */
|
||||
parmse->expr = gfc_build_addr_expr (NULL_TREE, parmse->expr);
|
||||
|
||||
/* Variables to point to the gfc and CFI descriptors; cfi = NULL implies
|
||||
that the CFI descriptor is allocated by the gfor_fndecl_gfc_to_cfi call. */
|
||||
gfc_desc_ptr = parmse->expr;
|
||||
cfi_desc_ptr = gfc_create_var (pvoid_type_node, "cfi");
|
||||
gfc_add_modify (&parmse->pre, cfi_desc_ptr, null_pointer_node);
|
||||
|
||||
/* Allocate the CFI descriptor itself and fill the fields. */
|
||||
tmp = gfc_build_addr_expr (NULL_TREE, cfi_desc_ptr);
|
||||
tmp = build_call_expr_loc (input_location,
|
||||
gfor_fndecl_gfc_to_cfi, 2, tmp, gfc_desc_ptr);
|
||||
gfc_add_expr_to_block (&parmse->pre, tmp);
|
||||
|
||||
/* Now set the gfc descriptor attribute. */
|
||||
tmp = fold_build2_loc (input_location, MODIFY_EXPR,
|
||||
void_type_node, desc_attr,
|
||||
build_int_cst (TREE_TYPE (desc_attr), attribute));
|
||||
gfc_add_expr_to_block (&parmse->pre, tmp);
|
||||
|
||||
/* The CFI descriptor is passed to the bind_C procedure. */
|
||||
parmse->expr = cfi_desc_ptr;
|
||||
|
||||
/* Free the CFI descriptor. */
|
||||
tmp = gfc_call_free (cfi_desc_ptr);
|
||||
gfc_prepend_expr_to_block (&parmse->post, tmp);
|
||||
|
||||
/* Transfer values back to gfc descriptor. */
|
||||
if (cfi_attribute != 2 /* CFI_attribute_other. */
|
||||
&& !fsym->attr.value
|
||||
&& fsym->attr.intent != INTENT_IN)
|
||||
if (e->ts.type == BT_CHARACTER && !e->ts.u.cl->length)
|
||||
{
|
||||
tmp = gfc_build_addr_expr (NULL_TREE, parmse->expr);
|
||||
tmp = build_call_expr_loc (input_location,
|
||||
gfor_fndecl_cfi_to_gfc, 2, gfc_desc_ptr, tmp);
|
||||
gfc_prepend_expr_to_block (&parmse->post, tmp);
|
||||
tmp = fold_convert (gfc_charlen_type_node,
|
||||
gfc_get_cfi_desc_elem_len (cfi));
|
||||
if (e->ts.kind != 1)
|
||||
tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
|
||||
gfc_charlen_type_node, tmp,
|
||||
build_int_cst (gfc_charlen_type_node,
|
||||
e->ts.kind));
|
||||
gfc_add_modify (&block2, gfc_strlen, tmp);
|
||||
}
|
||||
|
||||
/* Deal with an optional dummy being passed to an optional formal arg
|
||||
by finishing the pre and post blocks and making their execution
|
||||
conditional on the dummy being present. */
|
||||
if (fsym->attr.optional && e->expr_type == EXPR_VARIABLE
|
||||
&& e->symtree->n.sym->attr.optional)
|
||||
tmp = gfc_get_cfi_desc_base_addr (cfi),
|
||||
tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
|
||||
tmp, null_pointer_node);
|
||||
tmp = build3_v (COND_EXPR, tmp, gfc_finish_block (&block2),
|
||||
build_empty_stmt (input_location));
|
||||
gfc_add_expr_to_block (&block, tmp);
|
||||
|
||||
post_call:
|
||||
gfc_add_block_to_block (&block, &se.post);
|
||||
if (present && block.head)
|
||||
{
|
||||
cond = gfc_conv_expr_present (e->symtree->n.sym);
|
||||
tmp = fold_build2 (MODIFY_EXPR, void_type_node,
|
||||
cfi_desc_ptr,
|
||||
build_int_cst (pvoid_type_node, 0));
|
||||
tmp = build3_v (COND_EXPR, cond,
|
||||
gfc_finish_block (&parmse->pre), tmp);
|
||||
gfc_add_expr_to_block (&parmse->pre, tmp);
|
||||
tmp = build3_v (COND_EXPR, cond,
|
||||
gfc_finish_block (&parmse->post),
|
||||
tmp = build3_v (COND_EXPR, present, gfc_finish_block (&block),
|
||||
build_empty_stmt (input_location));
|
||||
gfc_add_expr_to_block (&parmse->post, tmp);
|
||||
}
|
||||
else if (block.head)
|
||||
gfc_add_block_to_block (&parmse->post, &block);
|
||||
}
|
||||
|
||||
|
||||
|
@ -5764,17 +6088,12 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
|
|||
arg = arg->next, formal = formal ? formal->next : NULL, ++argc)
|
||||
{
|
||||
bool finalized = false;
|
||||
bool assumed_length_string = false;
|
||||
tree derived_array = NULL_TREE;
|
||||
|
||||
e = arg->expr;
|
||||
fsym = formal ? formal->sym : NULL;
|
||||
parm_kind = MISSING;
|
||||
|
||||
if (fsym && fsym->ts.type == BT_CHARACTER
|
||||
&& (!fsym->ts.u.cl || !fsym->ts.u.cl->length))
|
||||
assumed_length_string = true;
|
||||
|
||||
/* If the procedure requires an explicit interface, the actual
|
||||
argument is passed according to the corresponding formal
|
||||
argument. If the corresponding formal argument is a POINTER,
|
||||
|
@ -6005,9 +6324,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
|
|||
parmse.expr = convert (type, tmp);
|
||||
}
|
||||
|
||||
else if (sym->attr.is_bind_c && e
|
||||
&& (is_CFI_desc (fsym, NULL)
|
||||
|| assumed_length_string))
|
||||
else if (sym->attr.is_bind_c && e && is_CFI_desc (fsym, NULL))
|
||||
/* Implement F2018, 18.3.6, list item (5), bullet point 2. */
|
||||
gfc_conv_gfc_desc_to_cfi_desc (&parmse, e, fsym);
|
||||
|
||||
|
@ -6217,7 +6534,8 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
|
|||
if (fsym && fsym->attr.intent == INTENT_OUT
|
||||
&& (fsym->attr.allocatable
|
||||
|| (fsym->ts.type == BT_CLASS
|
||||
&& CLASS_DATA (fsym)->attr.allocatable)))
|
||||
&& CLASS_DATA (fsym)->attr.allocatable))
|
||||
&& !is_CFI_desc (fsym, NULL))
|
||||
{
|
||||
stmtblock_t block;
|
||||
tree ptr;
|
||||
|
@ -6474,8 +6792,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
|
|||
ref->u.ar.type = AR_SECTION;
|
||||
}
|
||||
|
||||
if (sym->attr.is_bind_c && e
|
||||
&& (is_CFI_desc (fsym, NULL) || assumed_length_string))
|
||||
if (sym->attr.is_bind_c && e && is_CFI_desc (fsym, NULL))
|
||||
/* Implement F2018, 18.3.6, list item (5), bullet point 2. */
|
||||
gfc_conv_gfc_desc_to_cfi_desc (&parmse, e, fsym);
|
||||
|
||||
|
@ -6535,9 +6852,11 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
|
|||
sym->name, NULL);
|
||||
|
||||
/* If an ALLOCATABLE dummy argument has INTENT(OUT) and is
|
||||
allocated on entry, it must be deallocated. */
|
||||
allocated on entry, it must be deallocated.
|
||||
CFI descriptors are handled elsewhere. */
|
||||
if (fsym && fsym->attr.allocatable
|
||||
&& fsym->attr.intent == INTENT_OUT)
|
||||
&& fsym->attr.intent == INTENT_OUT
|
||||
&& !is_CFI_desc (fsym, NULL))
|
||||
{
|
||||
if (fsym->ts.type == BT_DERIVED
|
||||
&& fsym->ts.u.derived->attr.alloc_comp)
|
||||
|
|
|
@ -72,7 +72,8 @@ gfc_omp_is_allocatable_or_ptr (const_tree decl)
|
|||
static bool
|
||||
gfc_omp_is_optional_argument (const_tree decl)
|
||||
{
|
||||
return (TREE_CODE (decl) == PARM_DECL
|
||||
/* Note: VAR_DECL can occur with BIND(C) and array descriptors. */
|
||||
return ((TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == VAR_DECL)
|
||||
&& DECL_LANG_SPECIFIC (decl)
|
||||
&& TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
|
||||
&& !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))
|
||||
|
@ -105,8 +106,9 @@ gfc_omp_check_optional_argument (tree decl, bool for_present_check)
|
|||
|| GFC_ARRAY_TYPE_P (TREE_TYPE (decl))))
|
||||
decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
|
||||
|
||||
/* Note: With BIND(C), array descriptors are converted to a VAR_DECL. */
|
||||
if (decl == NULL_TREE
|
||||
|| TREE_CODE (decl) != PARM_DECL
|
||||
|| (TREE_CODE (decl) != PARM_DECL && TREE_CODE (decl) != VAR_DECL)
|
||||
|| !DECL_LANG_SPECIFIC (decl)
|
||||
|| !GFC_DECL_OPTIONAL_ARGUMENT (decl))
|
||||
return NULL_TREE;
|
||||
|
|
|
@ -3670,10 +3670,7 @@ gfc_trans_select_rank_cases (gfc_code * code)
|
|||
tree tmp;
|
||||
tree cond;
|
||||
tree low;
|
||||
tree sexpr;
|
||||
tree rank;
|
||||
tree rank_minus_one;
|
||||
tree minus_one;
|
||||
gfc_se se;
|
||||
gfc_se cse;
|
||||
stmtblock_t block;
|
||||
|
@ -3687,24 +3684,25 @@ gfc_trans_select_rank_cases (gfc_code * code)
|
|||
gfc_conv_expr_descriptor (&se, code->expr1);
|
||||
rank = gfc_conv_descriptor_rank (se.expr);
|
||||
rank = gfc_evaluate_now (rank, &block);
|
||||
minus_one = build_int_cst (TREE_TYPE (rank), -1);
|
||||
tmp = fold_build2_loc (input_location, MINUS_EXPR,
|
||||
gfc_array_index_type,
|
||||
fold_convert (gfc_array_index_type, rank),
|
||||
build_int_cst (gfc_array_index_type, 1));
|
||||
rank_minus_one = gfc_evaluate_now (tmp, &block);
|
||||
tmp = gfc_conv_descriptor_ubound_get (se.expr, rank_minus_one);
|
||||
cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
|
||||
tmp, build_int_cst (TREE_TYPE (tmp), -1));
|
||||
tmp = fold_build3_loc (input_location, COND_EXPR,
|
||||
TREE_TYPE (rank), cond,
|
||||
rank, minus_one);
|
||||
cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
|
||||
rank, build_int_cst (TREE_TYPE (rank), 0));
|
||||
sexpr = fold_build3_loc (input_location, COND_EXPR,
|
||||
TREE_TYPE (rank), cond,
|
||||
rank, tmp);
|
||||
sexpr = gfc_evaluate_now (sexpr, &block);
|
||||
symbol_attribute attr = gfc_expr_attr (code->expr1);
|
||||
if (!attr.pointer || !attr.allocatable)
|
||||
{
|
||||
/* Special case for assumed-rank ('rank(*)', internally -1):
|
||||
rank = (rank == 0 || ubound[rank-1] != -1) ? rank : -1. */
|
||||
cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
|
||||
rank, build_int_cst (TREE_TYPE (rank), 0));
|
||||
tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
|
||||
fold_convert (gfc_array_index_type, rank),
|
||||
gfc_index_one_node);
|
||||
tmp = gfc_conv_descriptor_ubound_get (se.expr, tmp);
|
||||
tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
|
||||
tmp, build_int_cst (TREE_TYPE (tmp), -1));
|
||||
cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
|
||||
logical_type_node, cond, tmp);
|
||||
tmp = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (rank),
|
||||
cond, rank, build_int_cst (TREE_TYPE (rank), -1));
|
||||
rank = gfc_evaluate_now (tmp, &block);
|
||||
}
|
||||
TREE_USED (code->exit_label) = 0;
|
||||
|
||||
repeat:
|
||||
|
@ -3748,8 +3746,8 @@ repeat:
|
|||
if (low != NULL_TREE)
|
||||
{
|
||||
cond = fold_build2_loc (input_location, EQ_EXPR,
|
||||
TREE_TYPE (sexpr), sexpr,
|
||||
fold_convert (TREE_TYPE (sexpr), low));
|
||||
TREE_TYPE (rank), rank,
|
||||
fold_convert (TREE_TYPE (rank), low));
|
||||
tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
|
||||
cond, tmp,
|
||||
build_empty_stmt (input_location));
|
||||
|
|
|
@ -77,6 +77,7 @@ static GTY(()) tree gfc_desc_dim_type;
|
|||
static GTY(()) tree gfc_max_array_element_size;
|
||||
static GTY(()) tree gfc_array_descriptor_base[2 * (GFC_MAX_DIMENSIONS+1)];
|
||||
static GTY(()) tree gfc_array_descriptor_base_caf[2 * (GFC_MAX_DIMENSIONS+1)];
|
||||
static GTY(()) tree gfc_cfi_descriptor_base[2 * (CFI_MAX_RANK + 2)];
|
||||
|
||||
/* Arrays for all integral and real kinds. We'll fill this in at runtime
|
||||
after the target has a chance to process command-line options. */
|
||||
|
@ -1575,8 +1576,9 @@ gfc_get_dtype_rank_type (int rank, tree etype)
|
|||
|
||||
field = gfc_advance_chain (TYPE_FIELDS (dtype_type_node),
|
||||
GFC_DTYPE_RANK);
|
||||
CONSTRUCTOR_APPEND_ELT (v, field,
|
||||
build_int_cst (TREE_TYPE (field), rank));
|
||||
if (rank >= 0)
|
||||
CONSTRUCTOR_APPEND_ELT (v, field,
|
||||
build_int_cst (TREE_TYPE (field), rank));
|
||||
|
||||
field = gfc_advance_chain (TYPE_FIELDS (dtype_type_node),
|
||||
GFC_DTYPE_TYPE);
|
||||
|
@ -2244,7 +2246,7 @@ gfc_nonrestricted_type (tree t)
|
|||
especially for character and array types. */
|
||||
|
||||
tree
|
||||
gfc_sym_type (gfc_symbol * sym)
|
||||
gfc_sym_type (gfc_symbol * sym, bool is_bind_c)
|
||||
{
|
||||
tree type;
|
||||
int byref;
|
||||
|
@ -2299,7 +2301,11 @@ gfc_sym_type (gfc_symbol * sym)
|
|||
if (!restricted)
|
||||
type = gfc_nonrestricted_type (type);
|
||||
|
||||
if (sym->attr.dimension || sym->attr.codimension)
|
||||
/* Dummy argument to a bind(C) procedure. */
|
||||
if (is_bind_c && is_CFI_desc (sym, NULL))
|
||||
type = gfc_get_cfi_type (sym->attr.dimension ? sym->as->rank : 0,
|
||||
/* restricted = */ false);
|
||||
else if (sym->attr.dimension || sym->attr.codimension)
|
||||
{
|
||||
if (gfc_is_nodesc_array (sym))
|
||||
{
|
||||
|
@ -3132,7 +3138,7 @@ gfc_get_function_type (gfc_symbol * sym, gfc_actual_arglist *actual_args,
|
|||
type = build_pointer_type (type);
|
||||
}
|
||||
else
|
||||
type = gfc_sym_type (arg);
|
||||
type = gfc_sym_type (arg, sym->attr.is_bind_c);
|
||||
|
||||
/* Parameter Passing Convention
|
||||
|
||||
|
@ -3723,4 +3729,95 @@ gfc_get_caf_reference_type ()
|
|||
return reference_type;
|
||||
}
|
||||
|
||||
static tree
|
||||
gfc_get_cfi_dim_type ()
|
||||
{
|
||||
static tree CFI_dim_t = NULL;
|
||||
|
||||
if (CFI_dim_t)
|
||||
return CFI_dim_t;
|
||||
|
||||
CFI_dim_t = make_node (RECORD_TYPE);
|
||||
TYPE_NAME (CFI_dim_t) = get_identifier ("CFI_dim_t");
|
||||
TYPE_NAMELESS (CFI_dim_t) = 1;
|
||||
tree field;
|
||||
tree *chain = NULL;
|
||||
field = gfc_add_field_to_struct_1 (CFI_dim_t, get_identifier ("lower_bound"),
|
||||
gfc_array_index_type, &chain);
|
||||
suppress_warning (field);
|
||||
field = gfc_add_field_to_struct_1 (CFI_dim_t, get_identifier ("extent"),
|
||||
gfc_array_index_type, &chain);
|
||||
suppress_warning (field);
|
||||
field = gfc_add_field_to_struct_1 (CFI_dim_t, get_identifier ("sm"),
|
||||
gfc_array_index_type, &chain);
|
||||
suppress_warning (field);
|
||||
gfc_finish_type (CFI_dim_t);
|
||||
TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (CFI_dim_t)) = 1;
|
||||
return CFI_dim_t;
|
||||
}
|
||||
|
||||
|
||||
/* Return the CFI type; use dimen == -1 for dim[] (only for pointers);
|
||||
otherwise dim[dimen] is used. */
|
||||
|
||||
tree
|
||||
gfc_get_cfi_type (int dimen, bool restricted)
|
||||
{
|
||||
gcc_assert (dimen >= -1 && dimen <= CFI_MAX_RANK);
|
||||
|
||||
int idx = 2*(dimen + 1) + restricted;
|
||||
|
||||
if (gfc_cfi_descriptor_base[idx])
|
||||
return gfc_cfi_descriptor_base[idx];
|
||||
|
||||
/* Build the type node. */
|
||||
tree CFI_cdesc_t = make_node (RECORD_TYPE);
|
||||
char name[GFC_MAX_SYMBOL_LEN + 1];
|
||||
if (dimen != -1)
|
||||
sprintf (name, "CFI_cdesc_t" GFC_RANK_PRINTF_FORMAT, dimen);
|
||||
TYPE_NAME (CFI_cdesc_t) = get_identifier (dimen < 0 ? "CFI_cdesc_t" : name);
|
||||
TYPE_NAMELESS (CFI_cdesc_t) = 1;
|
||||
|
||||
tree field;
|
||||
tree *chain = NULL;
|
||||
field = gfc_add_field_to_struct_1 (CFI_cdesc_t, get_identifier ("base_addr"),
|
||||
(restricted ? prvoid_type_node
|
||||
: ptr_type_node), &chain);
|
||||
suppress_warning (field);
|
||||
field = gfc_add_field_to_struct_1 (CFI_cdesc_t, get_identifier ("elem_len"),
|
||||
size_type_node, &chain);
|
||||
suppress_warning (field);
|
||||
field = gfc_add_field_to_struct_1 (CFI_cdesc_t, get_identifier ("version"),
|
||||
integer_type_node, &chain);
|
||||
suppress_warning (field);
|
||||
field = gfc_add_field_to_struct_1 (CFI_cdesc_t, get_identifier ("rank"),
|
||||
signed_char_type_node, &chain);
|
||||
suppress_warning (field);
|
||||
field = gfc_add_field_to_struct_1 (CFI_cdesc_t, get_identifier ("attribute"),
|
||||
signed_char_type_node, &chain);
|
||||
suppress_warning (field);
|
||||
field = gfc_add_field_to_struct_1 (CFI_cdesc_t, get_identifier ("type"),
|
||||
get_typenode_from_name (INT16_TYPE),
|
||||
&chain);
|
||||
suppress_warning (field);
|
||||
|
||||
if (dimen != 0)
|
||||
{
|
||||
tree range = NULL_TREE;
|
||||
if (dimen > 0)
|
||||
range = gfc_rank_cst[dimen - 1];
|
||||
range = build_range_type (gfc_array_index_type, gfc_index_zero_node,
|
||||
range);
|
||||
tree CFI_dim_t = build_array_type (gfc_get_cfi_dim_type (), range);
|
||||
field = gfc_add_field_to_struct_1 (CFI_cdesc_t, get_identifier ("dim"),
|
||||
CFI_dim_t, &chain);
|
||||
suppress_warning (field);
|
||||
}
|
||||
|
||||
TYPE_TYPELESS_STORAGE (CFI_cdesc_t) = 1;
|
||||
gfc_finish_type (CFI_cdesc_t);
|
||||
gfc_cfi_descriptor_base[idx] = CFI_cdesc_t;
|
||||
return CFI_cdesc_t;
|
||||
}
|
||||
|
||||
#include "gt-fortran-trans-types.h"
|
||||
|
|
|
@ -84,7 +84,8 @@ tree gfc_get_character_type (int, gfc_charlen *);
|
|||
tree gfc_get_character_type_len (int, tree);
|
||||
tree gfc_get_character_type_len_for_eltype (tree, tree);
|
||||
|
||||
tree gfc_sym_type (gfc_symbol *);
|
||||
tree gfc_sym_type (gfc_symbol *, bool is_bind_c_arg = false);
|
||||
tree gfc_get_cfi_type (int dimen, bool restricted);
|
||||
tree gfc_typenode_for_spec (gfc_typespec *, int c = 0);
|
||||
int gfc_copy_dt_decls_ifequal (gfc_symbol *, gfc_symbol *, bool);
|
||||
|
||||
|
|
|
@ -608,9 +608,9 @@ gfc_trans_runtime_check (bool error, bool once, tree cond, stmtblock_t * pblock,
|
|||
|
||||
if (once)
|
||||
{
|
||||
tmpvar = gfc_create_var (logical_type_node, "print_warning");
|
||||
tmpvar = gfc_create_var (boolean_type_node, "print_warning");
|
||||
TREE_STATIC (tmpvar) = 1;
|
||||
DECL_INITIAL (tmpvar) = logical_true_node;
|
||||
DECL_INITIAL (tmpvar) = boolean_true_node;
|
||||
gfc_add_expr_to_block (pblock, tmpvar);
|
||||
}
|
||||
|
||||
|
@ -631,7 +631,7 @@ gfc_trans_runtime_check (bool error, bool once, tree cond, stmtblock_t * pblock,
|
|||
va_end (ap);
|
||||
|
||||
if (once)
|
||||
gfc_add_modify (&block, tmpvar, logical_false_node);
|
||||
gfc_add_modify (&block, tmpvar, boolean_false_node);
|
||||
|
||||
body = gfc_finish_block (&block);
|
||||
|
||||
|
@ -643,9 +643,8 @@ gfc_trans_runtime_check (bool error, bool once, tree cond, stmtblock_t * pblock,
|
|||
{
|
||||
if (once)
|
||||
cond = fold_build2_loc (gfc_get_location (where), TRUTH_AND_EXPR,
|
||||
long_integer_type_node, tmpvar, cond);
|
||||
else
|
||||
cond = fold_convert (long_integer_type_node, cond);
|
||||
boolean_type_node, tmpvar,
|
||||
fold_convert (boolean_type_node, cond));
|
||||
|
||||
tmp = fold_build3_loc (gfc_get_location (where), COND_EXPR, void_type_node,
|
||||
cond, body,
|
||||
|
|
|
@ -857,8 +857,6 @@ extern GTY(()) tree gfor_fndecl_ctime;
|
|||
extern GTY(()) tree gfor_fndecl_fdate;
|
||||
extern GTY(()) tree gfor_fndecl_in_pack;
|
||||
extern GTY(()) tree gfor_fndecl_in_unpack;
|
||||
extern GTY(()) tree gfor_fndecl_cfi_to_gfc;
|
||||
extern GTY(()) tree gfor_fndecl_gfc_to_cfi;
|
||||
extern GTY(()) tree gfor_fndecl_associated;
|
||||
extern GTY(()) tree gfor_fndecl_system_clock4;
|
||||
extern GTY(()) tree gfor_fndecl_system_clock8;
|
||||
|
|
28
gcc/testsuite/gfortran.dg/ISO_Fortran_binding_19.f90
Normal file
28
gcc/testsuite/gfortran.dg/ISO_Fortran_binding_19.f90
Normal file
|
@ -0,0 +1,28 @@
|
|||
! { dg-do run }
|
||||
! This testcase failed before with optimization as
|
||||
! allocatef's CFI descriptor argument 'x' failed with -fstrict-alias due to
|
||||
! internally alising with the GFC descriptor
|
||||
!
|
||||
|
||||
program testit
|
||||
use iso_c_binding
|
||||
implicit none (external, type)
|
||||
type, bind (c) :: m
|
||||
integer(C_INT) :: i, j
|
||||
end type
|
||||
type(m), allocatable :: a(:)
|
||||
|
||||
call testf (a)
|
||||
|
||||
contains
|
||||
subroutine allocatef (x) bind (c)
|
||||
type(m), allocatable :: x(:)
|
||||
allocate (x(5:15))
|
||||
end subroutine
|
||||
|
||||
subroutine testf (y)
|
||||
type(m), allocatable, target :: y(:)
|
||||
call allocatef (y)
|
||||
if (.not. allocated (y)) stop 1
|
||||
end subroutine
|
||||
end program
|
|
@ -19,23 +19,37 @@ contains
|
|||
|
||||
subroutine substr(str) BIND(C)
|
||||
character(*) :: str(:)
|
||||
if (str(2) .ne. "ghi") stop 2
|
||||
if (str(1) .ne. "bcd") stop 2
|
||||
if (str(2) .ne. "ghi") stop 3
|
||||
str = ['uvw','xyz']
|
||||
end subroutine
|
||||
|
||||
subroutine substr4(str4) BIND(C)
|
||||
character(*, kind=4) :: str4(:)
|
||||
print *, str4(1)
|
||||
print *, str4(2)
|
||||
if (str4(1) .ne. 4_"bcd") stop 4
|
||||
if (str4(2) .ne. 4_"ghi") stop 5
|
||||
str4 = [4_'uvw', 4_'xyz']
|
||||
end subroutine
|
||||
|
||||
end module
|
||||
|
||||
program p
|
||||
use mod_ctg
|
||||
implicit none
|
||||
real :: x(6)
|
||||
character(5) :: str(2) = ['abcde','fghij']
|
||||
character(5) :: str(2) = ['abcde', 'fghij']
|
||||
character(5, kind=4) :: str4(2) = [4_'abcde', 4_'fghij']
|
||||
integer :: i
|
||||
|
||||
x = [ (real(i), i=1, size(x)) ]
|
||||
call ctg(x(2::2))
|
||||
if (any (abs (x - [1.,20.,3.,40.,5.,60.]) > 1.e-6)) stop 3
|
||||
|
||||
call substr(str(:)(2:4))
|
||||
if (any (str .ne. ['auvwe','fxyzj'])) stop 4
|
||||
!call substr(str(:)(2:4))
|
||||
!if (any (str .ne. ['auvwe','fxyzj'])) stop 4
|
||||
|
||||
call substr4(str4(:)(2:4))
|
||||
if (any (str4 .ne. [4_'auvwe', 4_'fxyzj'])) stop 4
|
||||
end program
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
! Fails on x86 targets where sizeof(long double) == 16.
|
||||
! { dg-do run { xfail { { x86_64*-*-* i?86*-*-* } && longdouble128 } } }
|
||||
! { dg-do run }
|
||||
! { dg-additional-sources PR100914.c }
|
||||
! { dg-require-effective-target fortran_real_c_float128 }
|
||||
! { dg-additional-options "-Wno-pedantic" }
|
||||
|
|
|
@ -67,7 +67,7 @@ check_fn (const CFI_cdesc_t *restrict auxp, const CFI_type_t type, const signed
|
|||
/* */
|
||||
assert (auxp->type==type);
|
||||
ityp = _CFI_decode_type(auxp->type);
|
||||
assert (ityp == CFI_type_cptr);
|
||||
assert (ityp == CFI_type_cfunptr);
|
||||
iknd = _CFI_decode_kind(auxp->type);
|
||||
assert (_CFI_decode_type(type)==ityp);
|
||||
assert (kind==iknd);
|
||||
|
|
|
@ -14,7 +14,7 @@ module isof_m
|
|||
private
|
||||
|
||||
public :: &
|
||||
CFI_type_cptr
|
||||
CFI_type_cptr, CFI_type_cfunptr
|
||||
|
||||
public :: &
|
||||
check_fn_as, &
|
||||
|
@ -33,6 +33,7 @@ module isof_m
|
|||
|
||||
! Intrinsic types. Their kind number defines their storage size. */
|
||||
integer(kind=c_signed_char), parameter :: CFI_type_cptr = 7
|
||||
integer(kind=c_signed_char), parameter :: CFI_type_cfunptr = 8
|
||||
|
||||
interface
|
||||
subroutine check_fn_as(a, t, k, e, n) &
|
||||
|
@ -99,7 +100,7 @@ module iso_check_m
|
|||
c_funptr, c_funloc, c_associated
|
||||
|
||||
use :: isof_m, only: &
|
||||
CFI_type_cptr
|
||||
CFI_type_cptr, CFI_type_cfunptr
|
||||
|
||||
use :: isof_m, only: &
|
||||
check_fn_as, &
|
||||
|
@ -155,7 +156,7 @@ contains
|
|||
!
|
||||
k = 0
|
||||
e = storage_size(a)/b
|
||||
t = cfi_encode_type(CFI_type_cptr, k)
|
||||
t = cfi_encode_type(CFI_type_cfunptr, k)
|
||||
! Assumes 64-bit target.
|
||||
! if(e/=8) stop 5
|
||||
do i = 1, n
|
||||
|
@ -176,7 +177,7 @@ contains
|
|||
!
|
||||
k = 0
|
||||
e = storage_size(a)/b
|
||||
t = cfi_encode_type(CFI_type_cptr, k)
|
||||
t = cfi_encode_type(CFI_type_cfunptr, k)
|
||||
! Assumes 64-bit target.
|
||||
! if(e/=8) stop 8
|
||||
do i = 1, n
|
||||
|
@ -198,7 +199,7 @@ contains
|
|||
!
|
||||
k = 0
|
||||
e = storage_size(a)/b
|
||||
t = cfi_encode_type(CFI_type_cptr, k)
|
||||
t = cfi_encode_type(CFI_type_cfunptr, k)
|
||||
! Assumes 64-bit target.
|
||||
! if(e/=8) stop 11
|
||||
select rank(a)
|
||||
|
@ -229,7 +230,7 @@ contains
|
|||
!
|
||||
k = 0
|
||||
e = storage_size(a)/b
|
||||
t = cfi_encode_type(CFI_type_cptr, k)
|
||||
t = cfi_encode_type(CFI_type_cfunptr, k)
|
||||
! Assumes 64-bit target.
|
||||
! if(e/=8) stop 16
|
||||
select rank(a)
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
! Test the fix for PR93963
|
||||
!
|
||||
|
||||
module m
|
||||
contains
|
||||
function rank_p(this) result(rnk) bind(c)
|
||||
use, intrinsic :: iso_c_binding, only: c_int
|
||||
|
||||
|
@ -97,27 +99,60 @@ function rank_a(this) result(rnk) bind(c)
|
|||
return
|
||||
end function rank_a
|
||||
|
||||
program selr_p
|
||||
|
||||
function rank_o(this) result(rnk) bind(c)
|
||||
use, intrinsic :: iso_c_binding, only: c_int
|
||||
|
||||
implicit none
|
||||
|
||||
integer(kind=c_int), intent(in) :: this(..)
|
||||
integer(kind=c_int) :: rnk
|
||||
|
||||
interface
|
||||
function rank_p(this) result(rnk) bind(c)
|
||||
use, intrinsic :: iso_c_binding, only: c_int
|
||||
integer(kind=c_int), pointer, intent(in) :: this(..)
|
||||
integer(kind=c_int) :: rnk
|
||||
end function rank_p
|
||||
end interface
|
||||
select rank(this)
|
||||
rank(0)
|
||||
rnk = 0
|
||||
rank(1)
|
||||
rnk = 1
|
||||
rank(2)
|
||||
rnk = 2
|
||||
rank(3)
|
||||
rnk = 3
|
||||
rank(4)
|
||||
rnk = 4
|
||||
rank(5)
|
||||
rnk = 5
|
||||
rank(6)
|
||||
rnk = 6
|
||||
rank(7)
|
||||
rnk = 7
|
||||
rank(8)
|
||||
rnk = 8
|
||||
rank(9)
|
||||
rnk = 9
|
||||
rank(10)
|
||||
rnk = 10
|
||||
rank(11)
|
||||
rnk = 11
|
||||
rank(12)
|
||||
rnk = 12
|
||||
rank(13)
|
||||
rnk = 13
|
||||
rank(14)
|
||||
rnk = 14
|
||||
rank(15)
|
||||
rnk = 15
|
||||
rank default
|
||||
rnk = -1000
|
||||
end select
|
||||
return
|
||||
end function rank_o
|
||||
|
||||
interface
|
||||
function rank_a(this) result(rnk) bind(c)
|
||||
use, intrinsic :: iso_c_binding, only: c_int
|
||||
integer(kind=c_int), allocatable, intent(in) :: this(..)
|
||||
integer(kind=c_int) :: rnk
|
||||
end function rank_a
|
||||
end interface
|
||||
end module m
|
||||
|
||||
program selr_p
|
||||
use m
|
||||
use, intrinsic :: iso_c_binding, only: c_int
|
||||
|
||||
implicit none
|
||||
|
||||
integer(kind=c_int), parameter :: siz = 7
|
||||
integer(kind=c_int), parameter :: rnk = 1
|
||||
|
@ -139,12 +174,19 @@ program selr_p
|
|||
irnk = rank_p(intp)
|
||||
if (irnk /= rnk) stop 5
|
||||
if (irnk /= rank(intp)) stop 6
|
||||
irnk = rank_o(intp)
|
||||
if (irnk /= rnk) stop 7
|
||||
if (irnk /= rank(intp)) stop 8
|
||||
deallocate(intp)
|
||||
nullify(intp)
|
||||
!
|
||||
allocate(inta(siz))
|
||||
if (irnk /= rnk) stop 7
|
||||
if (irnk /= rank(inta)) stop 8
|
||||
irnk = rank_a(inta)
|
||||
if (irnk /= rnk) stop 9
|
||||
if (irnk /= rank(inta)) stop 10
|
||||
irnk = rank_o(inta)
|
||||
if (irnk /= rnk) stop 11
|
||||
if (irnk /= rank(inta)) stop 12
|
||||
deallocate(inta)
|
||||
|
||||
end program selr_p
|
||||
|
|
34
gcc/testsuite/gfortran.dg/assumed_type_12.f90
Normal file
34
gcc/testsuite/gfortran.dg/assumed_type_12.f90
Normal file
|
@ -0,0 +1,34 @@
|
|||
! PR fortran/102086
|
||||
|
||||
implicit none (type, external)
|
||||
contains
|
||||
subroutine as(a)
|
||||
type(*) :: a(:,:)
|
||||
end
|
||||
subroutine ar(b)
|
||||
type(*) :: b(..)
|
||||
end
|
||||
subroutine bar(x,y)
|
||||
type(*) :: x
|
||||
type(*) :: y(3,*)
|
||||
call as(x) ! { dg-error "Rank mismatch in argument 'a' at .1. \\(rank-2 and scalar\\)" }
|
||||
call ar(x) ! { dg-error "Assumed-type actual argument at .1. corresponding to assumed-rank dummy argument 'b' must be assumed-shape or assumed-rank" }
|
||||
call ar(y) ! { dg-error "Assumed-type actual argument at .1. corresponding to assumed-rank dummy argument 'b' must be assumed-shape or assumed-rank" }
|
||||
call as(y(1,3)) ! { dg-error "Assumed-type variable y at .1. shall not have a subobject reference" }
|
||||
call ar(y(1,3)) ! { dg-error "Assumed-type variable y at .1. shall not have a subobject reference" }
|
||||
call as(y(1:1,3:3)) ! { dg-error "Assumed-type variable y at .1. shall not have a subobject reference" }
|
||||
call ar(y(1:1,3:3)) ! { dg-error "Assumed-type variable y at .1. shall not have a subobject reference" }
|
||||
end
|
||||
|
||||
subroutine okayish(x,y,z)
|
||||
type(*) :: x(:)
|
||||
type(*) :: y(:,:)
|
||||
type(*) :: z(..)
|
||||
call as(x) ! { dg-error "Rank mismatch in argument 'a' at .1. \\(rank-2 and rank-1\\)" }
|
||||
call as(y)
|
||||
call as(z) ! { dg-error "The assumed-rank array at .1. requires that the dummy argument 'a' has assumed-rank" }
|
||||
call ar(x)
|
||||
call ar(y)
|
||||
call ar(z)
|
||||
end
|
||||
end
|
26
gcc/testsuite/gfortran.dg/assumed_type_13.c
Normal file
26
gcc/testsuite/gfortran.dg/assumed_type_13.c
Normal file
|
@ -0,0 +1,26 @@
|
|||
#include <ISO_Fortran_binding.h>
|
||||
|
||||
void
|
||||
test_c (CFI_cdesc_t *x, size_t n, int num)
|
||||
{
|
||||
if (!x->base_addr)
|
||||
__builtin_abort ();
|
||||
if (x->version != CFI_VERSION)
|
||||
__builtin_abort ();
|
||||
if (x->rank != 1)
|
||||
__builtin_abort ();
|
||||
if (x->attribute != CFI_attribute_other)
|
||||
__builtin_abort ();
|
||||
if (x->dim[0].lower_bound != 0)
|
||||
__builtin_abort ();
|
||||
if (x->dim[0].extent != 3)
|
||||
__builtin_abort ();
|
||||
|
||||
if (x->elem_len != n || x->dim[0].sm != n)
|
||||
__builtin_abort ();
|
||||
|
||||
if (num == 1 && x->type != CFI_type_int16_t)
|
||||
__builtin_abort ();
|
||||
if (num == 2 && x->type != CFI_type_double_Complex)
|
||||
__builtin_abort ();
|
||||
}
|
66
gcc/testsuite/gfortran.dg/assumed_type_13.f90
Normal file
66
gcc/testsuite/gfortran.dg/assumed_type_13.f90
Normal file
|
@ -0,0 +1,66 @@
|
|||
! { dg-do run }
|
||||
! { dg-additional-sources assumed_type_13.c }
|
||||
|
||||
use iso_c_binding, only: c_size_t, c_int
|
||||
implicit none (type, external)
|
||||
|
||||
interface
|
||||
subroutine test_c (x, n, num) bind (C)
|
||||
import :: c_size_t, c_int
|
||||
integer(c_size_t), value :: n
|
||||
integer(c_int), value :: num
|
||||
type(*) :: x(:)
|
||||
end subroutine test_c
|
||||
end interface
|
||||
|
||||
complex(8) :: b(3)
|
||||
|
||||
call test_c ([1_2, 2_2, 3_2], sizeof(1_2), num=1)
|
||||
call test_c (b, sizeof(b(1)), num=2)
|
||||
call outer_bc ([1_2, 2_2, 3_2], sizeof(1_2), num=1)
|
||||
call outer_bc (b, sizeof(b(1)), num=2)
|
||||
call outer_f ([1_2, 2_2, 3_2], sizeof(1_2), num=1)
|
||||
call outer_f (b, sizeof(b(1)), num=2)
|
||||
|
||||
contains
|
||||
|
||||
subroutine outer_bc (x, n, num) bind(C)
|
||||
integer(c_size_t), value :: n
|
||||
integer(c_int), value :: num
|
||||
type(*) :: x(:)
|
||||
! print *,sizeof(x)/size(x), n
|
||||
if (sizeof(x)/size(x) /= n) error stop 1
|
||||
call inner_bc (x, n, num)
|
||||
call inner_f (x, n, num)
|
||||
call test_c (x, n, num)
|
||||
end
|
||||
|
||||
subroutine outer_f (x, n, num)
|
||||
integer(c_size_t), value :: n
|
||||
integer(c_int), value :: num
|
||||
type(*) :: x(:)
|
||||
! print *,sizeof(x)/size(x), n
|
||||
if (sizeof(x)/size(x) /= n) error stop 1
|
||||
call inner_f (x, n, num)
|
||||
call inner_bc (x, n, num)
|
||||
call test_c (x, n, num)
|
||||
end
|
||||
|
||||
subroutine inner_bc(x, n, num) bind(C)
|
||||
integer(c_size_t), value :: n
|
||||
integer(c_int), value :: num
|
||||
type(*) :: x(:)
|
||||
! print *,sizeof(x)/size(x), n
|
||||
if (sizeof(x)/size(x) /= n) error stop 2
|
||||
call test_c (x, n, num)
|
||||
end
|
||||
|
||||
subroutine inner_f(x, n, num)
|
||||
integer(c_size_t), value :: n
|
||||
integer(c_int), value :: num
|
||||
type(*) :: x(:)
|
||||
! print *,sizeof(x)/size(x), n
|
||||
if (sizeof(x)/size(x) /= n) error stop 3
|
||||
call test_c (x, n, num)
|
||||
end
|
||||
end
|
104
gcc/testsuite/gfortran.dg/bind-c-char-descr.f90
Normal file
104
gcc/testsuite/gfortran.dg/bind-c-char-descr.f90
Normal file
|
@ -0,0 +1,104 @@
|
|||
! PR fortran/92482
|
||||
!
|
||||
! Contributed by José Rui Faustino de Sousa
|
||||
!
|
||||
! Note the xfail issue below for 'strg_print_2("abc")
|
||||
|
||||
program strp_p
|
||||
|
||||
use, intrinsic :: iso_c_binding, only: &
|
||||
c_char
|
||||
|
||||
implicit none
|
||||
|
||||
integer, parameter :: l = 3
|
||||
|
||||
character(len=l, kind=c_char), target :: str
|
||||
character(len=:, kind=c_char), pointer :: strp_1
|
||||
character(len=l, kind=c_char), pointer :: strp_2
|
||||
|
||||
str = "abc"
|
||||
nullify(strp_1, strp_2)
|
||||
strp_1 => str
|
||||
strp_2 => str
|
||||
if (len(str) /= 3 .or. str /= "abc") stop 1
|
||||
if (len(strp_1) /= 3 .or. strp_1 /= "abc") stop 2
|
||||
if (len(strp_2) /= 3 .or. strp_2 /= "abc") stop 3
|
||||
call strg_print_0("abc") ! Error (10.0.0) or segmentation fault (9.1.0)
|
||||
call strg_print_0(str) ! Error (10.0.0) or segmentation fault (9.1.0)
|
||||
call strg_print_0(strp_1) ! Error (10.0.0) or segmentation fault (9.1.0)
|
||||
call strg_print_0(strp_2) ! Error (10.0.0) or segmentation fault (9.1.0)
|
||||
call strg_print_1(strp_1) ! Not yet supported
|
||||
|
||||
call strg_print_2("abc", xfail=.true.)
|
||||
call strg_print_2(str)
|
||||
call strg_print_2(strp_1)
|
||||
call strg_print_2(strp_2)
|
||||
|
||||
call strg_print_2_c("abc")
|
||||
call strg_print_2_c(str)
|
||||
call strg_print_2_c(strp_1)
|
||||
call strg_print_2_c(strp_2)
|
||||
|
||||
contains
|
||||
|
||||
subroutine strg_print_0(this) bind(c) ! Error (10.0.0 20191106) or warning (9.1.0) issued with bind(c)
|
||||
character(len=*, kind=c_char), target, intent(in) :: this
|
||||
|
||||
if (len (this) /= 3) stop 10
|
||||
if (this /= "abc") stop 11
|
||||
end subroutine strg_print_0
|
||||
|
||||
subroutine strg_print_1(this) bind(c) ! Not yet supported with bind(c)
|
||||
character(len=:, kind=c_char), pointer, intent(in) :: this
|
||||
character(len=:), pointer :: strn
|
||||
|
||||
if (.not. associated (this)) stop 20
|
||||
if (len (this) /= 3) stop 21
|
||||
if (this /= "abc") stop 22
|
||||
strn => this
|
||||
if (.not. associated (strn)) stop 23
|
||||
if(associated(strn))then
|
||||
if (len (this) /= 3) stop 24
|
||||
if (this /= "abc") stop 25
|
||||
end if
|
||||
end subroutine strg_print_1
|
||||
|
||||
subroutine strg_print_2(this, xfail)
|
||||
use, intrinsic :: iso_c_binding, only: &
|
||||
c_loc, c_f_pointer
|
||||
|
||||
type(*), target, intent(in) :: this(..)
|
||||
logical, optional, value :: xfail
|
||||
character(len=l), pointer :: strn
|
||||
|
||||
call c_f_pointer(c_loc(this), strn)
|
||||
if (.not. associated (strn)) stop 30
|
||||
if(associated(strn))then
|
||||
if (len (strn) /= 3) stop 31
|
||||
if (strn /= "abc") then
|
||||
if (present (xfail)) then
|
||||
print *, 'INVALID STRING - EXPECTED "abc" / PR47225'
|
||||
else
|
||||
stop 32
|
||||
end if
|
||||
end if
|
||||
end if
|
||||
end subroutine strg_print_2
|
||||
|
||||
subroutine strg_print_2_c(this) bind(c)
|
||||
use, intrinsic :: iso_c_binding, only: &
|
||||
c_loc, c_f_pointer
|
||||
|
||||
type(*), target, intent(in) :: this(..)
|
||||
character(len=l), pointer :: strn
|
||||
|
||||
call c_f_pointer(c_loc(this), strn)
|
||||
if (.not. associated (strn)) stop 40
|
||||
if(associated(strn))then
|
||||
if (len (strn) /= 3) stop 41
|
||||
if (strn /= "abc") stop 42
|
||||
end if
|
||||
end subroutine strg_print_2_c
|
||||
|
||||
end program strp_p
|
345
gcc/testsuite/gfortran.dg/bind-c-contiguous-1.c
Normal file
345
gcc/testsuite/gfortran.dg/bind-c-contiguous-1.c
Normal file
|
@ -0,0 +1,345 @@
|
|||
#include <ISO_Fortran_binding.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
struct loc_t {
|
||||
intptr_t x, y, z;
|
||||
};
|
||||
|
||||
typedef struct loc_t (*ftn_fn) (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_assumed_size_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_assumed_size_in_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_expl_size_f (CFI_cdesc_t *,CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_expl_size_in_f (CFI_cdesc_t *,CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_assumed_rank_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_assumed_rank_in_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_assumed_rank_cont_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_assumed_rank_cont_in_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_assumed_shape_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_assumed_shape_in_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_assumed_shape_cont_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_assumed_shape_cont_in_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
|
||||
static void
|
||||
basic_check(CFI_cdesc_t *x, bool is_cont)
|
||||
{
|
||||
if (!x->base_addr)
|
||||
__builtin_abort ();
|
||||
if (x->elem_len != 3*sizeof(char))
|
||||
__builtin_abort ();
|
||||
if (x->version != CFI_VERSION)
|
||||
__builtin_abort ();
|
||||
if (x->rank != 1)
|
||||
__builtin_abort ();
|
||||
if (x->attribute != CFI_attribute_other)
|
||||
__builtin_abort ();
|
||||
if (x->type != CFI_type_char)
|
||||
__builtin_abort ();
|
||||
if (x->dim[0].lower_bound != 0)
|
||||
__builtin_abort ();
|
||||
if (x->dim[0].extent != 3)
|
||||
__builtin_abort ();
|
||||
if (CFI_is_contiguous (x) != (x->elem_len == x->dim[0].sm))
|
||||
__builtin_abort ();
|
||||
if (is_cont != CFI_is_contiguous (x))
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
static void
|
||||
print_str (void *p, size_t len)
|
||||
{
|
||||
__builtin_printf ("DEBUG: >");
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
__builtin_printf ("%c", ((const char*) p)[i]);
|
||||
__builtin_printf ("<\n");
|
||||
}
|
||||
|
||||
static void
|
||||
check_str (CFI_cdesc_t *x, const char *str, const CFI_index_t subscripts[])
|
||||
{
|
||||
/* Avoid checking for '\0'. */
|
||||
if (strncmp ((const char*) CFI_address (x, subscripts), str, strlen(str)) != 0)
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
static void
|
||||
set_str (CFI_cdesc_t *x, const char *str, const CFI_index_t subscripts[])
|
||||
{
|
||||
char *p = CFI_address (x, subscripts);
|
||||
size_t len = strlen (str);
|
||||
if (x->elem_len != len)
|
||||
__builtin_abort ();
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
p[i] = str[i];
|
||||
}
|
||||
|
||||
static struct loc_t
|
||||
do_call (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num, bool intent_in, ftn_fn fn, bool is_cont, bool fort_cont)
|
||||
{
|
||||
const CFI_index_t zero[1] = { 0 };
|
||||
const CFI_index_t one[1] = { 1 };
|
||||
const CFI_index_t two[1] = { 2 };
|
||||
struct loc_t addr1, addr2;
|
||||
if (k != 3)
|
||||
__builtin_abort ();
|
||||
basic_check (x, is_cont || num == 2);
|
||||
basic_check (y, is_cont || num == 2);
|
||||
basic_check (z, is_cont || num == 2);
|
||||
if (!is_cont && num == 1)
|
||||
{
|
||||
check_str (x, "abc", zero);
|
||||
check_str (x, "ghi", one);
|
||||
check_str (x, "nop", two);
|
||||
check_str (y, "abc", zero);
|
||||
check_str (y, "ghi", one);
|
||||
check_str (y, "nop", two);
|
||||
check_str (z, "abc", zero);
|
||||
check_str (z, "ghi", one);
|
||||
check_str (z, "nop", two);
|
||||
}
|
||||
else if (num == 1)
|
||||
{
|
||||
if (strncmp ((const char*) x->base_addr, "abcghinop", 9) != 0)
|
||||
__builtin_abort ();
|
||||
if (strncmp ((const char*) y->base_addr, "abcghinop", 9) != 0)
|
||||
__builtin_abort ();
|
||||
if (strncmp ((const char*) z->base_addr, "abcghinop", 9) != 0)
|
||||
__builtin_abort ();
|
||||
}
|
||||
else if (num == 2)
|
||||
{
|
||||
if (strncmp ((const char*) x->base_addr, "defghijlm", 9) != 0)
|
||||
__builtin_abort ();
|
||||
if (strncmp ((const char*) y->base_addr, "defghijlm", 9) != 0)
|
||||
__builtin_abort ();
|
||||
if (strncmp ((const char*) z->base_addr, "defghijlm", 9) != 0)
|
||||
__builtin_abort ();
|
||||
}
|
||||
else
|
||||
__builtin_abort ();
|
||||
addr1.x = (intptr_t) x->base_addr;
|
||||
addr1.y = (intptr_t) y->base_addr;
|
||||
addr1.z = (intptr_t) z->base_addr;
|
||||
addr2 = fn (x, y, z, 3, num);
|
||||
if (!CFI_is_contiguous (x) && fort_cont)
|
||||
{
|
||||
/* Check for callee copy in/copy out. */
|
||||
if (addr1.x == addr2.x || addr1.x != (intptr_t) x->base_addr)
|
||||
__builtin_abort ();
|
||||
if (addr1.y == addr2.y || addr1.y != (intptr_t) y->base_addr)
|
||||
__builtin_abort ();
|
||||
if (addr1.z == addr2.z || addr1.z != (intptr_t) z->base_addr)
|
||||
__builtin_abort ();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (addr1.x != addr2.x || addr1.x != (intptr_t) x->base_addr)
|
||||
__builtin_abort ();
|
||||
if (addr1.y != addr2.y || addr1.y != (intptr_t) y->base_addr)
|
||||
__builtin_abort ();
|
||||
if (addr1.z != addr2.z || addr1.z != (intptr_t) z->base_addr)
|
||||
__builtin_abort ();
|
||||
}
|
||||
// intent_in
|
||||
if (intent_in && !is_cont && num == 1)
|
||||
{
|
||||
check_str (x, "abc", zero);
|
||||
check_str (x, "ghi", one);
|
||||
check_str (x, "nop", two);
|
||||
check_str (y, "abc", zero);
|
||||
check_str (y, "ghi", one);
|
||||
check_str (y, "nop", two);
|
||||
check_str (z, "abc", zero);
|
||||
check_str (z, "ghi", one);
|
||||
check_str (z, "nop", two);
|
||||
}
|
||||
else if (intent_in && num == 1)
|
||||
{
|
||||
if (strncmp ((const char*) x->base_addr, "abcghinop", 9) != 0)
|
||||
__builtin_abort ();
|
||||
if (strncmp ((const char*) y->base_addr, "abcghinop", 9) != 0)
|
||||
__builtin_abort ();
|
||||
if (strncmp ((const char*) z->base_addr, "abcghinop", 9) != 0)
|
||||
__builtin_abort ();
|
||||
}
|
||||
else if (intent_in && num == 2)
|
||||
{
|
||||
if (strncmp ((const char*) x->base_addr, "defghijlm", 9) != 0)
|
||||
__builtin_abort ();
|
||||
if (strncmp ((const char*) y->base_addr, "defghijlm", 9) != 0)
|
||||
__builtin_abort ();
|
||||
if (strncmp ((const char*) z->base_addr, "defghijlm", 9) != 0)
|
||||
__builtin_abort ();
|
||||
}
|
||||
else if (intent_in)
|
||||
__builtin_abort ();
|
||||
if (intent_in)
|
||||
{
|
||||
if (is_cont && num == 1)
|
||||
{
|
||||
/* Copy in - set the value to check that no copy out is done. */
|
||||
memcpy ((char*) x->base_addr, "123456789", 9);
|
||||
memcpy ((char*) y->base_addr, "123456789", 9);
|
||||
memcpy ((char*) z->base_addr, "123456789", 9);
|
||||
}
|
||||
return addr1;
|
||||
}
|
||||
// !intent_in
|
||||
if (!is_cont && num == 1)
|
||||
{
|
||||
check_str (x, "ABC", zero);
|
||||
check_str (x, "DEF", one);
|
||||
check_str (x, "GHI", two);
|
||||
check_str (y, "ABC", zero);
|
||||
check_str (y, "DEF", one);
|
||||
check_str (y, "GHI", two);
|
||||
check_str (z, "ABC", zero);
|
||||
check_str (z, "DEF", one);
|
||||
check_str (z, "GHI", two);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strncmp ((const char*) x->base_addr, "ABCDEFGHI", 9) != 0)
|
||||
__builtin_abort ();
|
||||
if (strncmp ((const char*) y->base_addr, "ABCDEFGHI", 9) != 0)
|
||||
__builtin_abort ();
|
||||
if (strncmp ((const char*) z->base_addr, "ABCDEFGHI", 9) != 0)
|
||||
__builtin_abort ();
|
||||
}
|
||||
return addr1;
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_assumed_size_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, false, char_assumed_size_f, true, false);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_assumed_size_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, true, char_assumed_size_in_f, true, false);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_expl_size_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, false, char_expl_size_f, true, false);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_expl_size_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, true, char_expl_size_in_f, true, false);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_assumed_rank_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, false, char_assumed_rank_f, false, false);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_assumed_rank_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, true, char_assumed_rank_in_f, false, false);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_assumed_rank_cont_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, false, char_assumed_rank_cont_f, true, false);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_assumed_rank_cont_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, true, char_assumed_rank_cont_in_f, true, false);
|
||||
}
|
||||
|
||||
static void
|
||||
reset_var (CFI_cdesc_t *x, int num)
|
||||
{
|
||||
const CFI_index_t zero[1] = { 0 };
|
||||
const CFI_index_t one[1] = { 1 };
|
||||
const CFI_index_t two[1] = { 2 };
|
||||
|
||||
if (num == 1)
|
||||
{
|
||||
set_str (x, "abc", zero);
|
||||
set_str (x, "ghi", one);
|
||||
set_str (x, "nop", two);
|
||||
}
|
||||
else if (num == 2)
|
||||
{
|
||||
set_str (x, "def", zero);
|
||||
set_str (x, "ghi", one);
|
||||
set_str (x, "jlm", two);
|
||||
}
|
||||
else
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
static void
|
||||
reset_vars (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z, int num)
|
||||
{
|
||||
reset_var (x, num);
|
||||
reset_var (y, num);
|
||||
reset_var (z, num);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_assumed_shape_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
/* Make use of having a noncontiguous argument to check that the callee
|
||||
handles noncontiguous variables. */
|
||||
do_call (x, y, z, k, num, false, char_assumed_size_f, false, true);
|
||||
reset_vars (x, y, z, num);
|
||||
do_call (x, y, z, k, num, true, char_assumed_size_in_f, false, true);
|
||||
reset_vars (x, y, z, num);
|
||||
do_call (x, y, z, k, num, false, char_expl_size_f, false, true);
|
||||
reset_vars (x, y, z, num);
|
||||
do_call (x, y, z, k, num, true, char_expl_size_in_f, false, true);
|
||||
reset_vars (x, y, z, num);
|
||||
do_call (x, y, z, k, num, false, char_assumed_rank_cont_f, false, true);
|
||||
reset_vars (x, y, z, num);
|
||||
do_call (x, y, z, k, num, true, char_assumed_rank_cont_in_f, false, true);
|
||||
reset_vars (x, y, z, num);
|
||||
do_call (x, y, z, k, num, false, char_assumed_shape_cont_f, false, true);
|
||||
reset_vars (x, y, z, num);
|
||||
do_call (x, y, z, k, num, true, char_assumed_shape_cont_in_f, false, true);
|
||||
/* Actual func call. */
|
||||
reset_vars (x, y, z, num);
|
||||
return do_call (x, y, z, k, num, false, char_assumed_shape_f, false, false);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_assumed_shape_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, true, char_assumed_shape_in_f, false, false);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_assumed_shape_cont_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, false, char_assumed_shape_cont_f, true, false);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_assumed_shape_cont_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, true, char_assumed_shape_cont_in_f, true, false);
|
||||
}
|
1574
gcc/testsuite/gfortran.dg/bind-c-contiguous-1.f90
Normal file
1574
gcc/testsuite/gfortran.dg/bind-c-contiguous-1.f90
Normal file
File diff suppressed because it is too large
Load diff
82
gcc/testsuite/gfortran.dg/bind-c-contiguous-2.f90
Normal file
82
gcc/testsuite/gfortran.dg/bind-c-contiguous-2.f90
Normal file
|
@ -0,0 +1,82 @@
|
|||
! { dg-additional-options "-fdump-tree-original" }
|
||||
|
||||
integer function f(xx) bind(c) result(ii)
|
||||
implicit none
|
||||
integer, contiguous :: xx(..)
|
||||
ii = rank(xx)
|
||||
end
|
||||
|
||||
integer function h(yy) bind(c) result(jj)
|
||||
implicit none
|
||||
character(len=*), contiguous :: yy(:)
|
||||
jj = rank(yy)
|
||||
end
|
||||
|
||||
integer function g(zz) bind(c) result(kk)
|
||||
implicit none
|
||||
character(len=*) :: zz(*)
|
||||
kk = rank(zz)
|
||||
end
|
||||
|
||||
|
||||
|
||||
integer function f2(aa) bind(c) result(ii)
|
||||
implicit none
|
||||
integer, contiguous :: aa(..)
|
||||
intent(in) :: aa
|
||||
ii = rank(aa)
|
||||
end
|
||||
|
||||
integer function h2(bb) bind(c) result(jj)
|
||||
implicit none
|
||||
character(len=*), contiguous :: bb(:)
|
||||
intent(in) :: bb
|
||||
jj = rank(bb)
|
||||
end
|
||||
|
||||
integer function g2(cc) bind(c) result(kk)
|
||||
implicit none
|
||||
character(len=*) :: cc(*)
|
||||
intent(in) :: cc
|
||||
kk = rank(cc)
|
||||
end
|
||||
|
||||
!
|
||||
! Copy-in/out variable:
|
||||
!
|
||||
! { dg-final { scan-tree-dump-times "xx->data =\[^;\]+ __builtin_malloc \\(_xx->elem_len \\* size.\[0-9\]+\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "yy->data =\[^;\]+ __builtin_malloc \\(_yy->elem_len \\* size.\[0-9\]+\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "zz =\[^;\]+ __builtin_malloc \\(_zz->elem_len \\* size.\[0-9\]+\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "aa->data =\[^;\]+ __builtin_malloc \\(_aa->elem_len \\* size.\[0-9\]+\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "bb->data =\[^;\]+ __builtin_malloc \\(_bb->elem_len \\* size.\[0-9\]+\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "cc =\[^;\]+ __builtin_malloc \\(_cc->elem_len \\* size.\[0-9\]+\\);" 1 "original" } }
|
||||
|
||||
! { dg-final { scan-tree-dump-times "__builtin_free \\(\[^;\]+ xx->data\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "__builtin_free \\(\[^;\]+ yy->data\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "__builtin_free \\(zz\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "__builtin_free \\(\[^;\]+ aa->data\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "__builtin_free \\(\[^;\]+ bb->data\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "__builtin_free \\(cc\\);" 1 "original" } }
|
||||
|
||||
! Copy in + out
|
||||
|
||||
! { dg-final { scan-tree-dump-times "__builtin_memcpy \\(\\(void \\*\\) xx->data \\+ xx->dtype.elem_len \\* arrayidx.\[0-9\]+, _xx->base_addr \\+ shift.\[0-9\]+, xx->dtype.elem_len\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "xx->data = \\(void \\* restrict\\) _xx->base_addr;" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "__builtin_memcpy \\(\\(void \\*\\) xx->data \\+ xx->dtype.elem_len \\* arrayidx.\[0-9\]+, _xx->base_addr \\+ shift.\[0-9\]+, xx->dtype.elem_len\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "__builtin_memcpy \\(\\(void \\*\\) yy->data \\+ yy->dtype.elem_len \\* arrayidx.\[0-9\]+, _yy->base_addr \\+ shift.\[0-9\]+, yy->dtype.elem_len\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "yy->data = \\(void \\* restrict\\) _yy->base_addr;" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "__builtin_memcpy \\(_yy->base_addr \\+ shift.\[0-9\]+, \\(void \\*\\) yy->data \\+ yy->dtype.elem_len \\* arrayidx.\[0-9\]+, yy->dtype.elem_len\\);" 1 "original" } }
|
||||
|
||||
! { dg-final { scan-tree-dump-times "zz = \\(character\\(kind=1\\)\\\[0:\\\]\\\[1:zz.\[0-9\]+\\\] \\* restrict\\) _zz->base_addr;" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "__builtin_memcpy \\(\\(void \\*\\) zz \\+ _zz->elem_len \\* arrayidx.\[0-9\]+, _zz->base_addr \\+ shift.\[0-9\]+, _zz->elem_len\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "__builtin_memcpy \\(_zz->base_addr \\+ shift.\[0-9\]+, \\(void \\*\\) zz \\+ _zz->elem_len \\* arrayidx.\[0-9\]+, _zz->elem_len\\);" 1 "original" } }
|
||||
|
||||
! Copy in only
|
||||
|
||||
! { dg-final { scan-tree-dump-times "__builtin_memcpy \\(\\(void \\*\\) aa->data \\+ aa->dtype.elem_len \\* arrayidx.\[0-9\]+, _aa->base_addr \\+ shift.\[0-9\]+, aa->dtype.elem_len\\);" 1 "original" } }
|
||||
|
||||
! { dg-final { scan-tree-dump-times "aa->data = \\(void \\* restrict\\) _aa->base_addr;" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "__builtin_memcpy \\(\\(void \\*\\) bb->data \\+ bb->dtype.elem_len \\* arrayidx.\[0-9\]+, _bb->base_addr \\+ shift.\[0-9\]+, bb->dtype.elem_len\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "bb->data = \\(void \\* restrict\\) _bb->base_addr;" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "cc = \\(character\\(kind=1\\)\\\[0:\\\]\\\[1:cc.\[0-9\]+\\\] \\* restrict\\) _cc->base_addr;" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "__builtin_memcpy \\(\\(void \\*\\) cc \\+ _cc->elem_len \\* arrayidx.\[0-9\]+, _cc->base_addr \\+ shift.\[0-9\]+, _cc->elem_len\\);" 1 "original" } }
|
180
gcc/testsuite/gfortran.dg/bind-c-contiguous-3.c
Normal file
180
gcc/testsuite/gfortran.dg/bind-c-contiguous-3.c
Normal file
|
@ -0,0 +1,180 @@
|
|||
#include <ISO_Fortran_binding.h>
|
||||
|
||||
intptr_t assumed_rank_alloc_f (CFI_cdesc_t *);
|
||||
intptr_t assumed_rank_pointer_f (CFI_cdesc_t *);
|
||||
intptr_t assumed_rank_f (CFI_cdesc_t *);
|
||||
intptr_t assumed_rank_cont_f (CFI_cdesc_t *);
|
||||
intptr_t assumed_shape_f (CFI_cdesc_t *);
|
||||
intptr_t assumed_shape_cont_f (CFI_cdesc_t *);
|
||||
intptr_t deferred_shape_alloc_f (CFI_cdesc_t *);
|
||||
intptr_t deferred_shape_pointer_f (CFI_cdesc_t *);
|
||||
|
||||
|
||||
static void
|
||||
basic_check(CFI_cdesc_t *x)
|
||||
{
|
||||
if (!x->base_addr)
|
||||
__builtin_abort ();
|
||||
if (x->elem_len != sizeof(int32_t))
|
||||
__builtin_abort ();
|
||||
if (x->version != CFI_VERSION)
|
||||
__builtin_abort ();
|
||||
if (x->rank != 4)
|
||||
__builtin_abort ();
|
||||
if (x->type != CFI_type_int32_t)
|
||||
__builtin_abort ();
|
||||
if (x->attribute == CFI_attribute_other)
|
||||
{
|
||||
if (x->dim[0].lower_bound != 0)
|
||||
__builtin_abort ();
|
||||
if (x->dim[1].lower_bound != 0)
|
||||
__builtin_abort ();
|
||||
if (x->dim[2].lower_bound != 0)
|
||||
__builtin_abort ();
|
||||
if (x->dim[3].lower_bound != 0)
|
||||
__builtin_abort ();
|
||||
}
|
||||
}
|
||||
|
||||
intptr_t
|
||||
assumed_rank_alloc_c (CFI_cdesc_t *x)
|
||||
{
|
||||
basic_check (x);
|
||||
if (!CFI_is_contiguous (x))
|
||||
__builtin_abort ();
|
||||
if (x->attribute != CFI_attribute_allocatable)
|
||||
__builtin_abort ();
|
||||
intptr_t addr = (intptr_t) x->base_addr;
|
||||
intptr_t addr2 = assumed_rank_alloc_f (x);
|
||||
if (addr != addr2 || addr != (intptr_t) x->base_addr)
|
||||
__builtin_abort ();
|
||||
return addr;
|
||||
}
|
||||
|
||||
intptr_t
|
||||
assumed_rank_pointer_c (CFI_cdesc_t *x)
|
||||
{
|
||||
basic_check (x);
|
||||
if (x->attribute != CFI_attribute_pointer)
|
||||
__builtin_abort ();
|
||||
intptr_t addr = (intptr_t) x->base_addr;
|
||||
intptr_t addr2 = assumed_rank_pointer_f (x);
|
||||
if (addr != addr2 || addr != (intptr_t) x->base_addr)
|
||||
__builtin_abort ();
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
||||
intptr_t
|
||||
assumed_rank_c (CFI_cdesc_t *x)
|
||||
{
|
||||
basic_check (x);
|
||||
if (x->attribute != CFI_attribute_other)
|
||||
__builtin_abort ();
|
||||
intptr_t addr = (intptr_t) x->base_addr;
|
||||
intptr_t addr2 = assumed_rank_f (x);
|
||||
if (addr != addr2 || addr != (intptr_t) x->base_addr)
|
||||
__builtin_abort ();
|
||||
return addr;
|
||||
}
|
||||
|
||||
intptr_t
|
||||
assumed_rank_cont_c (CFI_cdesc_t *x)
|
||||
{
|
||||
basic_check (x);
|
||||
if (!CFI_is_contiguous (x))
|
||||
__builtin_abort ();
|
||||
if (x->attribute != CFI_attribute_other)
|
||||
__builtin_abort ();
|
||||
intptr_t addr = (intptr_t) x->base_addr;
|
||||
intptr_t addr2 = assumed_rank_cont_f (x);
|
||||
if (addr != addr2 || addr != (intptr_t) x->base_addr)
|
||||
__builtin_abort ();
|
||||
return addr;
|
||||
}
|
||||
|
||||
intptr_t
|
||||
assumed_shape_c (CFI_cdesc_t *x, int num)
|
||||
{
|
||||
basic_check (x);
|
||||
if (x->attribute != CFI_attribute_other)
|
||||
__builtin_abort ();
|
||||
intptr_t addr = (intptr_t) x->base_addr;
|
||||
intptr_t addr2;
|
||||
if (num == 1 || num == 2 || num == 3)
|
||||
{
|
||||
if (!CFI_is_contiguous (x))
|
||||
__builtin_abort ();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (CFI_is_contiguous (x))
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
if (num == 1 || num == 4)
|
||||
addr2 = assumed_shape_f (x);
|
||||
else if (num == 2 || num == 5)
|
||||
addr2 = assumed_shape_cont_f (x);
|
||||
else if (num == 3 || num == 6)
|
||||
addr2 = assumed_rank_cont_f (x);
|
||||
else
|
||||
__builtin_abort ();
|
||||
|
||||
if (num == 1 || num == 2 || num == 3)
|
||||
{
|
||||
if (addr != addr2)
|
||||
__builtin_abort ();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (CFI_is_contiguous (x))
|
||||
__builtin_abort ();
|
||||
}
|
||||
if (addr != (intptr_t) x->base_addr)
|
||||
__builtin_abort ();
|
||||
return addr2;
|
||||
}
|
||||
|
||||
intptr_t
|
||||
assumed_shape_cont_c (CFI_cdesc_t *x)
|
||||
{
|
||||
basic_check (x);
|
||||
if (!CFI_is_contiguous (x))
|
||||
__builtin_abort ();
|
||||
if (x->attribute != CFI_attribute_other)
|
||||
__builtin_abort ();
|
||||
intptr_t addr = (intptr_t) x->base_addr;
|
||||
intptr_t addr2 = assumed_shape_cont_f (x);
|
||||
if (addr != addr2 || addr != (intptr_t) x->base_addr)
|
||||
__builtin_abort ();
|
||||
return addr;
|
||||
}
|
||||
|
||||
intptr_t
|
||||
deferred_shape_alloc_c (CFI_cdesc_t *x)
|
||||
{
|
||||
basic_check (x);
|
||||
if (!CFI_is_contiguous (x))
|
||||
__builtin_abort ();
|
||||
if (x->attribute != CFI_attribute_allocatable)
|
||||
__builtin_abort ();
|
||||
intptr_t addr = (intptr_t) x->base_addr;
|
||||
intptr_t addr2 = deferred_shape_alloc_f (x);
|
||||
if (addr != addr2 || addr != (intptr_t) x->base_addr)
|
||||
__builtin_abort ();
|
||||
return addr;
|
||||
}
|
||||
|
||||
intptr_t
|
||||
deferred_shape_pointer_c (CFI_cdesc_t *x)
|
||||
{
|
||||
basic_check (x);
|
||||
if (x->attribute != CFI_attribute_pointer)
|
||||
__builtin_abort ();
|
||||
intptr_t addr = (intptr_t) x->base_addr;
|
||||
intptr_t addr2 = deferred_shape_pointer_f (x);
|
||||
if (addr != addr2 || addr != (intptr_t) x->base_addr)
|
||||
__builtin_abort ();
|
||||
return addr;
|
||||
}
|
656
gcc/testsuite/gfortran.dg/bind-c-contiguous-3.f90
Normal file
656
gcc/testsuite/gfortran.dg/bind-c-contiguous-3.f90
Normal file
|
@ -0,0 +1,656 @@
|
|||
! { dg-do run }
|
||||
! { dg-additional-sources bind-c-contiguous-3.c }
|
||||
|
||||
! Test that multi-dim contiguous is properly handled.
|
||||
|
||||
module m
|
||||
use iso_c_binding, only: c_intptr_t, c_int
|
||||
implicit none (type, external)
|
||||
|
||||
interface
|
||||
integer(c_intptr_t) function assumed_rank_alloc_c (xx) bind(c)
|
||||
import :: c_intptr_t
|
||||
integer, allocatable :: xx(..)
|
||||
end function
|
||||
integer(c_intptr_t) function assumed_rank_pointer_c (xx) bind(c)
|
||||
import :: c_intptr_t
|
||||
integer, pointer :: xx(..)
|
||||
end function
|
||||
integer(c_intptr_t) function assumed_rank_c (xx) bind(c)
|
||||
import :: c_intptr_t
|
||||
integer :: xx(..)
|
||||
end function
|
||||
integer(c_intptr_t) function assumed_rank_cont_c (xx) bind(c)
|
||||
import :: c_intptr_t
|
||||
integer, contiguous :: xx(..)
|
||||
end function
|
||||
integer(c_intptr_t) function assumed_shape_c (xx, num) bind(c)
|
||||
import :: c_intptr_t, c_int
|
||||
integer :: xx(:,:,:,:)
|
||||
integer(c_int), value :: num
|
||||
end function
|
||||
integer(c_intptr_t) function assumed_shape_cont_c (xx) bind(c)
|
||||
import :: c_intptr_t
|
||||
integer, contiguous :: xx(:,:,:,:)
|
||||
end function
|
||||
integer(c_intptr_t) function deferred_shape_alloc_c (xx) bind(c)
|
||||
import :: c_intptr_t
|
||||
integer, allocatable :: xx(:,:,:,:)
|
||||
end function
|
||||
integer(c_intptr_t) function deferred_shape_pointer_c (xx) bind(c)
|
||||
import :: c_intptr_t
|
||||
integer, pointer :: xx(:,:,:,:)
|
||||
end function
|
||||
|
||||
end interface
|
||||
|
||||
contains
|
||||
|
||||
integer function get_n (idx, lbound, extent) result(res)
|
||||
integer, contiguous :: idx(:), lbound(:), extent(:)
|
||||
integer :: i
|
||||
if (size(idx) /= size(lbound) .or. size(idx) /= size(extent)) &
|
||||
error stop 20
|
||||
res = idx(1) - lbound(1) + 1
|
||||
do i = 2, size(idx)
|
||||
res = res + product(extent(:i-1)) * (idx(i)-lbound(i))
|
||||
end do
|
||||
end
|
||||
|
||||
integer(c_intptr_t) function assumed_rank_alloc_f (xx) bind(c) result(res)
|
||||
integer, allocatable :: xx(..)
|
||||
integer :: i, j, k, l, lb(4)
|
||||
select rank (xx)
|
||||
rank (4)
|
||||
do l = lbound(xx, dim=4), ubound(xx, dim=4)
|
||||
do k = lbound(xx, dim=3), ubound(xx, dim=3)
|
||||
do j = lbound(xx, dim=2), ubound(xx, dim=2)
|
||||
do i = lbound(xx, dim=1), ubound(xx, dim=1)
|
||||
xx(i,j,k,l) = -get_n([i,j,k,l], lbound(xx), shape(xx))
|
||||
end do
|
||||
end do
|
||||
end do
|
||||
end do
|
||||
lb = lbound(xx)
|
||||
res = %loc(xx(lb(1),lb(2),lb(3),lb(4))) ! { dg-warning "Legacy Extension" }
|
||||
rank default
|
||||
error stop 99
|
||||
end select
|
||||
end
|
||||
|
||||
integer(c_intptr_t) function assumed_rank_pointer_f (xx) bind(c) result(res)
|
||||
integer, pointer :: xx(..)
|
||||
integer :: i, j, k, l, lb(4)
|
||||
select rank (xx)
|
||||
rank (4)
|
||||
do l = lbound(xx, dim=4), ubound(xx, dim=4)
|
||||
do k = lbound(xx, dim=3), ubound(xx, dim=3)
|
||||
do j = lbound(xx, dim=2), ubound(xx, dim=2)
|
||||
do i = lbound(xx, dim=1), ubound(xx, dim=1)
|
||||
xx(i,j,k,l) = -get_n([i,j,k,l], lbound(xx), shape(xx))
|
||||
end do
|
||||
end do
|
||||
end do
|
||||
end do
|
||||
lb = lbound(xx)
|
||||
res = %loc(xx(lb(1),lb(2),lb(3),lb(4))) ! { dg-warning "Legacy Extension" }
|
||||
rank default
|
||||
error stop 99
|
||||
end select
|
||||
end
|
||||
|
||||
|
||||
integer(c_intptr_t) function assumed_rank_f (xx) bind(c) result(res)
|
||||
integer :: xx(..)
|
||||
integer :: i, j, k, l
|
||||
select rank (xx)
|
||||
rank (4)
|
||||
do l = 1, size(xx, dim=4)
|
||||
do k = 1, size(xx, dim=3)
|
||||
do j = 1, size(xx, dim=2)
|
||||
do i = 1, size(xx, dim=1)
|
||||
xx(i,j,k,l) = -get_n([i,j,k,l], lbound(xx), shape(xx))
|
||||
end do
|
||||
end do
|
||||
end do
|
||||
end do
|
||||
res = %loc(xx(1,1,1,1)) ! { dg-warning "Legacy Extension" }
|
||||
rank default
|
||||
error stop 99
|
||||
end select
|
||||
end
|
||||
|
||||
integer(c_intptr_t) function assumed_rank_cont_f (xx) bind(c) result(res)
|
||||
integer, contiguous :: xx(..)
|
||||
integer :: i, j, k, l
|
||||
select rank (xx)
|
||||
rank (4)
|
||||
do l = 1, size(xx, dim=4)
|
||||
do k = 1, size(xx, dim=3)
|
||||
do j = 1, size(xx, dim=2)
|
||||
do i = 1, size(xx, dim=1)
|
||||
xx(i,j,k,l) = -get_n([i,j,k,l], lbound(xx), shape(xx))
|
||||
end do
|
||||
end do
|
||||
end do
|
||||
end do
|
||||
res = %loc(xx(1,1,1,1)) ! { dg-warning "Legacy Extension" }
|
||||
rank default
|
||||
error stop 99
|
||||
end select
|
||||
end
|
||||
|
||||
integer(c_intptr_t) function assumed_shape_f (xx) bind(c) result(res)
|
||||
integer :: xx(:,:,:,:)
|
||||
integer :: i, j, k, l
|
||||
do l = 1, ubound(xx, dim=4)
|
||||
do k = 1, ubound(xx, dim=3)
|
||||
do j = 1, ubound(xx, dim=2)
|
||||
do i = 1, ubound(xx, dim=1)
|
||||
xx(i,j,k,l) = -get_n([i,j,k,l], lbound(xx), shape(xx))
|
||||
end do
|
||||
end do
|
||||
end do
|
||||
end do
|
||||
res = %loc(xx(1,1,1,1)) ! { dg-warning "Legacy Extension" }
|
||||
end
|
||||
|
||||
integer(c_intptr_t) function assumed_shape2_f (xx, n) bind(c) result(res)
|
||||
integer, value :: n
|
||||
integer :: xx(-n:, -n:, -n:, -n:)
|
||||
integer :: i, j, k, l
|
||||
do l = -n, ubound(xx, dim=4)
|
||||
do k = -n, ubound(xx, dim=3)
|
||||
do j = -n, ubound(xx, dim=2)
|
||||
do i = -n, ubound(xx, dim=1)
|
||||
xx(i,j,k,l) = -get_n([i,j,k,l], lbound(xx), shape(xx))
|
||||
end do
|
||||
end do
|
||||
end do
|
||||
end do
|
||||
res = %loc(xx(-n,-n,-n,-n)) ! { dg-warning "Legacy Extension" }
|
||||
end
|
||||
|
||||
integer(c_intptr_t) function assumed_shape_cont_f (xx) bind(c) result(res)
|
||||
integer, contiguous :: xx(:,:,:,:)
|
||||
integer :: i, j, k, l
|
||||
do l = 1, ubound(xx, dim=4)
|
||||
do k = 1, ubound(xx, dim=3)
|
||||
do j = 1, ubound(xx, dim=2)
|
||||
do i = 1, ubound(xx, dim=1)
|
||||
xx(i,j,k,l) = -get_n([i,j,k,l], lbound(xx), shape(xx))
|
||||
end do
|
||||
end do
|
||||
end do
|
||||
end do
|
||||
res = %loc(xx(1,1,1,1)) ! { dg-warning "Legacy Extension" }
|
||||
end
|
||||
|
||||
integer(c_intptr_t) function assumed_shape2_cont_f (xx, n) bind(c) result(res)
|
||||
integer, value :: n
|
||||
integer, contiguous :: xx(-n:, -n:, -n:, -n:)
|
||||
integer :: i, j, k, l
|
||||
do l = -n, ubound(xx, dim=4)
|
||||
do k = -n, ubound(xx, dim=3)
|
||||
do j = -n, ubound(xx, dim=2)
|
||||
do i = -n, ubound(xx, dim=1)
|
||||
xx(i,j,k,l) = -get_n([i,j,k,l], lbound(xx), shape(xx))
|
||||
end do
|
||||
end do
|
||||
end do
|
||||
end do
|
||||
res = %loc(xx(-n,-n,-n,-n)) ! { dg-warning "Legacy Extension" }
|
||||
end
|
||||
|
||||
integer(c_intptr_t) function deferred_shape_alloc_f (xx) bind(c) result(res)
|
||||
integer, allocatable :: xx(:,:,:,:)
|
||||
integer :: i, j, k, l, lb(4)
|
||||
do l = lbound(xx, dim=4), ubound(xx, dim=4)
|
||||
do k = lbound(xx, dim=3), ubound(xx, dim=3)
|
||||
do j = lbound(xx, dim=2), ubound(xx, dim=2)
|
||||
do i = lbound(xx, dim=1), ubound(xx, dim=1)
|
||||
xx(i,j,k,l) = -get_n([i,j,k,l], lbound(xx), shape(xx))
|
||||
end do
|
||||
end do
|
||||
end do
|
||||
end do
|
||||
lb = lbound(xx)
|
||||
res = %loc(xx(lb(1),lb(2),lb(3),lb(4))) ! { dg-warning "Legacy Extension" }
|
||||
end
|
||||
|
||||
integer(c_intptr_t) function deferred_shape_pointer_f (xx) bind(c) result(res)
|
||||
integer, pointer :: xx(:,:,:,:)
|
||||
integer :: i, j, k, l, lb(4)
|
||||
do l = lbound(xx, dim=4), ubound(xx, dim=4)
|
||||
do k = lbound(xx, dim=3), ubound(xx, dim=3)
|
||||
do j = lbound(xx, dim=2), ubound(xx, dim=2)
|
||||
do i = lbound(xx, dim=1), ubound(xx, dim=1)
|
||||
xx(i,j,k,l) = -get_n([i,j,k,l], lbound(xx), shape(xx))
|
||||
end do
|
||||
end do
|
||||
end do
|
||||
end do
|
||||
lb = lbound(xx)
|
||||
res = %loc(xx(lb(1),lb(2),lb(3),lb(4))) ! { dg-warning "Legacy Extension" }
|
||||
end
|
||||
end module
|
||||
|
||||
|
||||
use m
|
||||
implicit none (type, external)
|
||||
integer, dimension(10,10,10,10) :: var_init, var
|
||||
target :: var
|
||||
integer, allocatable, dimension(:,:,:,:) :: a1, a2
|
||||
integer, pointer, dimension(:,:,:,:) :: p1, p2
|
||||
integer(c_intptr_t) :: loc4
|
||||
integer :: i, k, j, l, cnt
|
||||
|
||||
do l = 1, ubound(var_init, dim=4)
|
||||
do k = 1, ubound(var_init, dim=3)
|
||||
do j = 1, ubound(var_init, dim=2)
|
||||
do i = 1, ubound(var_init, dim=1)
|
||||
var_init(i,j,k,l) = get_n([i,j,k,l], lbound(var_init), shape(var_init))
|
||||
end do
|
||||
end do
|
||||
end do
|
||||
end do
|
||||
|
||||
! Fortran calls
|
||||
|
||||
! ----- allocatable + pointer dummies -------
|
||||
|
||||
allocate(a1, mold=var_init)
|
||||
allocate(p1, mold=var_init)
|
||||
allocate(a2(-5:4,-10:-1,1:10,11:20))
|
||||
allocate(p2(-5:4,-10:-1,1:10,11:20))
|
||||
|
||||
a1(:,:,:,:) = var_init
|
||||
loc4 = assumed_rank_alloc_f (a1)
|
||||
cnt = size(a1) - check_unmod (a1)
|
||||
call check (a1, loc4, .true., cnt)
|
||||
call check2 (a1)
|
||||
|
||||
a2(:,:,:,:) = var_init
|
||||
loc4 = assumed_rank_alloc_f (a2)
|
||||
cnt = size(a2) - check_unmod (a2)
|
||||
call check (a2, loc4, .true., cnt)
|
||||
call check2 (a2)
|
||||
|
||||
a1(:,:,:,:) = var_init
|
||||
loc4 = deferred_shape_alloc_f (a1)
|
||||
cnt = size(a1) - check_unmod (a1)
|
||||
call check (a1, loc4, .true., cnt)
|
||||
call check2 (a1)
|
||||
|
||||
a2(:,:,:,:) = var_init
|
||||
loc4 = deferred_shape_alloc_f (a2)
|
||||
cnt = size(a2) - check_unmod (a2)
|
||||
call check (a2, loc4, .true., cnt)
|
||||
call check2 (a2)
|
||||
|
||||
deallocate(a1, a2)
|
||||
|
||||
p1(:,:,:,:) = var_init
|
||||
loc4 = assumed_rank_pointer_f (p1)
|
||||
cnt = size(p1) - check_unmod (p1)
|
||||
call check (p1, loc4, .true., cnt)
|
||||
call check2 (p1)
|
||||
|
||||
p2(:,:,:,:) = var_init
|
||||
loc4 = assumed_rank_pointer_f (p2)
|
||||
cnt = size(p2) - check_unmod (p2)
|
||||
call check (p2, loc4, .true., cnt)
|
||||
call check2 (p2)
|
||||
|
||||
p1(:,:,:,:) = var_init
|
||||
loc4 = deferred_shape_pointer_f (p1)
|
||||
cnt = size(p1) - check_unmod (p1)
|
||||
call check (p1, loc4, .true., cnt)
|
||||
call check2 (p1)
|
||||
|
||||
p2(:,:,:,:) = var_init
|
||||
loc4 = deferred_shape_pointer_f (p2)
|
||||
cnt = size(p2) - check_unmod (p2)
|
||||
call check (p2, loc4, .true., cnt)
|
||||
call check2 (p2)
|
||||
|
||||
deallocate(p1, p2)
|
||||
|
||||
! --- p => var(4:7,::3,::2,:)
|
||||
var = var_init
|
||||
p1 => var(4:7,::3,::2,:)
|
||||
loc4 = assumed_rank_pointer_f (p1)
|
||||
cnt = size(p1) - check_unmod (p1)
|
||||
call check (p1, loc4, .false., cnt)
|
||||
call check2 (p1)
|
||||
|
||||
var = var_init
|
||||
p2(-5:,-10:,1:,11:) => var(4:7,::3,::2,:)
|
||||
loc4 = assumed_rank_pointer_f (p2)
|
||||
cnt = size(p2) - check_unmod (p2)
|
||||
call check (p2, loc4, .false., cnt)
|
||||
call check2 (p2)
|
||||
|
||||
var = var_init
|
||||
p1 => var(4:7,::3,::2,:)
|
||||
loc4 = deferred_shape_pointer_f (p1)
|
||||
cnt = size(p1) - check_unmod (p1)
|
||||
call check (p1, loc4, .false., cnt)
|
||||
call check2 (p1)
|
||||
|
||||
var = var_init
|
||||
p2(-5:,-10:,1:,11:) => var(4:7,::3,::2,:)
|
||||
loc4 = deferred_shape_pointer_f (p2)
|
||||
cnt = size(p2) - check_unmod (p2)
|
||||
call check (p2, loc4, .false., cnt)
|
||||
call check2 (p2)
|
||||
|
||||
|
||||
|
||||
! ----- nonallocatable + nonpointer dummies -------
|
||||
|
||||
var = var_init
|
||||
loc4 = assumed_rank_f (var)
|
||||
cnt = size(var) - check_unmod (var)
|
||||
call check (var, loc4, .false., cnt)
|
||||
call check2 (var)
|
||||
|
||||
var = var_init
|
||||
loc4 = assumed_shape_f (var)
|
||||
cnt = size(var) - check_unmod (var)
|
||||
call check (var, loc4, .false., cnt)
|
||||
call check2 (var)
|
||||
|
||||
var = var_init
|
||||
loc4 = assumed_shape2_f (var, 99)
|
||||
cnt = size(var) - check_unmod (var)
|
||||
call check (var, loc4, .false., cnt)
|
||||
call check2 (var)
|
||||
|
||||
var = var_init
|
||||
loc4 = assumed_rank_cont_f (var)
|
||||
cnt = size(var) - check_unmod (var)
|
||||
call check (var, loc4, .true., cnt)
|
||||
call check2 (var)
|
||||
|
||||
var = var_init
|
||||
loc4 = assumed_shape_cont_f (var)
|
||||
cnt = size(var) - check_unmod (var)
|
||||
call check (var, loc4, .true., cnt)
|
||||
call check2 (var)
|
||||
|
||||
var = var_init
|
||||
loc4 = assumed_shape2_cont_f (var, 99)
|
||||
cnt = size(var) - check_unmod (var)
|
||||
call check (var, loc4, .true., cnt)
|
||||
call check2 (var)
|
||||
|
||||
! --- var(4:7,::3,::2,:)
|
||||
|
||||
var = var_init
|
||||
loc4 = assumed_rank_f (var(4:7,::3,::2,:))
|
||||
cnt = size(var) - check_unmod (var)
|
||||
call check (var(4:7,::3,::2,:), loc4, .false., cnt)
|
||||
call check2 (var(4:7,::3,::2,:))
|
||||
|
||||
var = var_init
|
||||
loc4 = assumed_shape_f (var(4:7,::3,::2,:))
|
||||
cnt = size(var) - check_unmod (var)
|
||||
call check (var(4:7,::3,::2,:), loc4, .false., cnt)
|
||||
call check2 (var(4:7,::3,::2,:))
|
||||
|
||||
var = var_init
|
||||
loc4 = assumed_shape2_f (var(4:7,::3,::2,:), 99)
|
||||
cnt = size(var) - check_unmod (var)
|
||||
call check (var(4:7,::3,::2,:), loc4, .false., cnt)
|
||||
call check2 (var(4:7,::3,::2,:))
|
||||
|
||||
var = var_init
|
||||
loc4 = assumed_rank_cont_f (var(4:7,::3,::2,:))
|
||||
cnt = size(var) - check_unmod (var)
|
||||
call check (var(4:7,::3,::2,:), loc4, .true., cnt)
|
||||
call check2 (var(4:7,::3,::2,:))
|
||||
|
||||
var = var_init
|
||||
loc4 = assumed_shape_cont_f (var(4:7,::3,::2,:))
|
||||
cnt = size(var) - check_unmod (var)
|
||||
call check (var(4:7,::3,::2,:), loc4, .true., cnt)
|
||||
call check2 (var(4:7,::3,::2,:))
|
||||
|
||||
var = var_init
|
||||
loc4 = assumed_shape2_cont_f (var(4:7,::3,::2,:), 99)
|
||||
cnt = size(var) - check_unmod (var)
|
||||
call check (var(4:7,::3,::2,:), loc4, .true., cnt)
|
||||
call check2 (var(4:7,::3,::2,:))
|
||||
|
||||
|
||||
! C calls
|
||||
|
||||
! ----- allocatable + pointer dummies -------
|
||||
|
||||
allocate(a1, mold=var_init)
|
||||
allocate(p1, mold=var_init)
|
||||
allocate(a2(-5:4,-10:-1,1:10,11:20))
|
||||
allocate(p2(-5:4,-10:-1,1:10,11:20))
|
||||
|
||||
a1(:,:,:,:) = var_init
|
||||
loc4 = assumed_rank_alloc_c (a1)
|
||||
cnt = size(a1) - check_unmod (a1)
|
||||
call check (a1, loc4, .true., cnt)
|
||||
call check2 (a1)
|
||||
|
||||
a2(:,:,:,:) = var_init
|
||||
loc4 = assumed_rank_alloc_c (a2)
|
||||
cnt = size(a2) - check_unmod (a2)
|
||||
call check (a2, loc4, .true., cnt)
|
||||
call check2 (a2)
|
||||
|
||||
a1(:,:,:,:) = var_init
|
||||
loc4 = deferred_shape_alloc_c (a1)
|
||||
cnt = size(a1) - check_unmod (a1)
|
||||
call check (a1, loc4, .true., cnt)
|
||||
call check2 (a1)
|
||||
|
||||
a2(:,:,:,:) = var_init
|
||||
loc4 = deferred_shape_alloc_c (a2)
|
||||
cnt = size(a2) - check_unmod (a2)
|
||||
call check (a2, loc4, .true., cnt)
|
||||
call check2 (a2)
|
||||
|
||||
deallocate(a1, a2)
|
||||
|
||||
p1(:,:,:,:) = var_init
|
||||
loc4 = assumed_rank_pointer_c (p1)
|
||||
cnt = size(p1) - check_unmod (p1)
|
||||
call check (p1, loc4, .true., cnt)
|
||||
call check2 (p1)
|
||||
|
||||
p2(:,:,:,:) = var_init
|
||||
loc4 = assumed_rank_pointer_c (p2)
|
||||
cnt = size(p2) - check_unmod (p2)
|
||||
call check (p2, loc4, .true., cnt)
|
||||
call check2 (p2)
|
||||
|
||||
p1(:,:,:,:) = var_init
|
||||
loc4 = deferred_shape_pointer_c (p1)
|
||||
cnt = size(p1) - check_unmod (p1)
|
||||
call check (p1, loc4, .true., cnt)
|
||||
call check2 (p1)
|
||||
|
||||
p2(:,:,:,:) = var_init
|
||||
loc4 = deferred_shape_pointer_c (p2)
|
||||
cnt = size(p2) - check_unmod (p2)
|
||||
call check (p2, loc4, .true., cnt)
|
||||
call check2 (p2)
|
||||
|
||||
deallocate(p1, p2)
|
||||
|
||||
! --- p => var(4:7,::3,::2,:)
|
||||
var = var_init
|
||||
p1 => var(4:7,::3,::2,:)
|
||||
loc4 = assumed_rank_pointer_c (p1)
|
||||
cnt = size(p1) - check_unmod (p1)
|
||||
call check (p1, loc4, .false., cnt)
|
||||
call check2 (p1)
|
||||
|
||||
var = var_init
|
||||
p2(-5:,-10:,1:,11:) => var(4:7,::3,::2,:)
|
||||
loc4 = assumed_rank_pointer_c (p2)
|
||||
cnt = size(p2) - check_unmod (p2)
|
||||
call check (p2, loc4, .false., cnt)
|
||||
call check2 (p2)
|
||||
|
||||
var = var_init
|
||||
p1 => var(4:7,::3,::2,:)
|
||||
loc4 = deferred_shape_pointer_c (p1)
|
||||
cnt = size(p1) - check_unmod (p1)
|
||||
call check (p1, loc4, .false., cnt)
|
||||
call check2 (p1)
|
||||
|
||||
var = var_init
|
||||
p2(-5:,-10:,1:,11:) => var(4:7,::3,::2,:)
|
||||
loc4 = deferred_shape_pointer_c (p2)
|
||||
cnt = size(p2) - check_unmod (p2)
|
||||
call check (p2, loc4, .false., cnt)
|
||||
call check2 (p2)
|
||||
|
||||
|
||||
! ----- nonallocatable + nonpointer dummies -------
|
||||
|
||||
var = var_init
|
||||
loc4 = assumed_rank_c (var)
|
||||
cnt = size(var) - check_unmod (var)
|
||||
call check (var, loc4, .false., cnt)
|
||||
call check2 (var)
|
||||
|
||||
var = var_init
|
||||
! calls assumed_shape_f
|
||||
loc4 = assumed_shape_c (var, num=1)
|
||||
cnt = size(var) - check_unmod (var)
|
||||
call check (var, loc4, .false., cnt)
|
||||
call check2 (var)
|
||||
|
||||
var = var_init
|
||||
! calls assumed_shape_cont_f
|
||||
loc4 = assumed_shape_c (var, num=2)
|
||||
cnt = size(var) - check_unmod (var)
|
||||
call check (var, loc4, .true., cnt)
|
||||
call check2 (var)
|
||||
|
||||
var = var_init
|
||||
! calls assumed_rank_cont_f
|
||||
loc4 = assumed_shape_c (var, num=3)
|
||||
cnt = size(var) - check_unmod (var)
|
||||
call check (var, loc4, .true., cnt)
|
||||
call check2 (var)
|
||||
|
||||
var = var_init
|
||||
loc4 = assumed_rank_cont_c (var)
|
||||
cnt = size(var) - check_unmod (var)
|
||||
call check (var, loc4, .true., cnt)
|
||||
call check2 (var)
|
||||
|
||||
var = var_init
|
||||
loc4 = assumed_shape_cont_c (var)
|
||||
cnt = size(var) - check_unmod (var)
|
||||
call check (var, loc4, .true., cnt)
|
||||
call check2 (var)
|
||||
|
||||
! --- var(4:7,::3,::2,:)
|
||||
|
||||
var = var_init
|
||||
loc4 = assumed_rank_c (var(4:7,::3,::2,:))
|
||||
cnt = size(var) - check_unmod (var)
|
||||
call check (var(4:7,::3,::2,:), loc4, .false., cnt)
|
||||
call check2 (var(4:7,::3,::2,:))
|
||||
|
||||
var = var_init
|
||||
! calls assumed_shape_f
|
||||
loc4 = assumed_shape_c (var(4:7,::3,::2,:), num=4)
|
||||
cnt = size(var) - check_unmod (var)
|
||||
call check (var(4:7,::3,::2,:), loc4, .false., cnt)
|
||||
call check2 (var(4:7,::3,::2,:))
|
||||
|
||||
var = var_init
|
||||
! calls assumed_shape_cont_f
|
||||
loc4 = assumed_shape_c (var(4:7,::3,::2,:), num=5)
|
||||
cnt = size(var) - check_unmod (var)
|
||||
call check (var(4:7,::3,::2,:), loc4, .true., cnt)
|
||||
call check2 (var(4:7,::3,::2,:))
|
||||
|
||||
var = var_init
|
||||
! calls assumed_rank_cont_f
|
||||
loc4 = assumed_shape_c (var(4:7,::3,::2,:), num=6)
|
||||
cnt = size(var) - check_unmod (var)
|
||||
call check (var(4:7,::3,::2,:), loc4, .true., cnt)
|
||||
call check2 (var(4:7,::3,::2,:))
|
||||
|
||||
var = var_init
|
||||
loc4 = assumed_rank_cont_c (var(4:7,::3,::2,:))
|
||||
cnt = size(var) - check_unmod (var)
|
||||
call check (var(4:7,::3,::2,:), loc4, .true., cnt)
|
||||
call check2 (var(4:7,::3,::2,:))
|
||||
|
||||
var = var_init
|
||||
loc4 = assumed_shape_cont_c (var(4:7,::3,::2,:))
|
||||
cnt = size(var) - check_unmod (var)
|
||||
call check (var(4:7,::3,::2,:), loc4, .true., cnt)
|
||||
call check2 (var(4:7,::3,::2,:))
|
||||
|
||||
|
||||
contains
|
||||
|
||||
! Ensure that the rest is still okay
|
||||
! Returns the number of elements >= 0
|
||||
integer function check_unmod (x) result(cnt)
|
||||
integer, contiguous, intent(in) :: x(:,:,:,:)
|
||||
integer :: i, k, j, l
|
||||
cnt = 0
|
||||
do l = 1, ubound(x, dim=4)
|
||||
do k = 1, ubound(x, dim=3)
|
||||
do j = 1, ubound(x, dim=2)
|
||||
do i = 1, ubound(x, dim=1)
|
||||
if (x(i,j,k,l) >= 0) then
|
||||
cnt = cnt + 1
|
||||
if (x(i,j,k,l) /= get_n([i,j,k,l], lbound(x), shape(x))) &
|
||||
error stop 5
|
||||
endif
|
||||
end do
|
||||
end do
|
||||
end do
|
||||
end do
|
||||
end
|
||||
|
||||
subroutine check(x, loc1, cont, cnt)
|
||||
integer, intent(in) :: x(:,:,:,:)
|
||||
integer(c_intptr_t), intent(in), optional :: loc1
|
||||
logical, intent(in), optional :: cont ! dummy has CONTIGUOUS attr
|
||||
integer, intent(in), optional :: cnt
|
||||
integer(c_intptr_t) :: loc2
|
||||
integer :: i, k, j, l
|
||||
if (present (loc1)) then
|
||||
loc2 = %loc(x(1,1,1,1)) ! { dg-warning "Legacy Extension" }
|
||||
if (is_contiguous (x) .or. .not.cont) then
|
||||
if (loc1 /= loc2) error stop 1
|
||||
else
|
||||
if (loc1 == loc2) error stop 2
|
||||
end if
|
||||
if (cnt /= size(x)) error stop 3
|
||||
end if
|
||||
do l = 1, ubound(x, dim=4)
|
||||
do k = 1, ubound(x, dim=3)
|
||||
do j = 1, ubound(x, dim=2)
|
||||
do i = 1, ubound(x, dim=1)
|
||||
if (x(i,j,k,l) /= -get_n([i,j,k,l], lbound(x), shape(x))) &
|
||||
error stop 4
|
||||
end do
|
||||
end do
|
||||
end do
|
||||
end do
|
||||
end
|
||||
|
||||
subroutine check2(x)
|
||||
integer, contiguous, intent(in) :: x(:,:,:,:)
|
||||
call check(x)
|
||||
end subroutine
|
||||
end
|
370
gcc/testsuite/gfortran.dg/bind-c-contiguous-4.c
Normal file
370
gcc/testsuite/gfortran.dg/bind-c-contiguous-4.c
Normal file
|
@ -0,0 +1,370 @@
|
|||
#include <ISO_Fortran_binding.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
struct loc_t {
|
||||
intptr_t x, y, z;
|
||||
};
|
||||
|
||||
typedef struct loc_t (*ftn_fn) (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_assumed_size_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_assumed_size_in_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_expl_size_f (CFI_cdesc_t *,CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_expl_size_in_f (CFI_cdesc_t *,CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_assumed_rank_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_assumed_rank_in_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_assumed_rank_cont_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_assumed_rank_cont_in_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_assumed_shape_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_assumed_shape_in_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_assumed_shape_cont_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_assumed_shape_cont_in_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
|
||||
static void
|
||||
basic_check(CFI_cdesc_t *x, bool is_cont)
|
||||
{
|
||||
if (!x->base_addr)
|
||||
__builtin_abort ();
|
||||
if (x->elem_len != 3*sizeof(char))
|
||||
__builtin_abort ();
|
||||
if (x->version != CFI_VERSION)
|
||||
__builtin_abort ();
|
||||
if (x->rank != 1)
|
||||
__builtin_abort ();
|
||||
if (x->attribute != CFI_attribute_other)
|
||||
__builtin_abort ();
|
||||
if (x->type != CFI_type_char)
|
||||
__builtin_abort ();
|
||||
if (x->dim[0].lower_bound != 0)
|
||||
__builtin_abort ();
|
||||
if (x->dim[0].extent != 3)
|
||||
__builtin_abort ();
|
||||
if (CFI_is_contiguous (x) != (x->elem_len == x->dim[0].sm))
|
||||
__builtin_abort ();
|
||||
if (is_cont != CFI_is_contiguous (x))
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
static void
|
||||
print_str (void *p, size_t len)
|
||||
{
|
||||
__builtin_printf ("DEBUG: >");
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
__builtin_printf ("%c", ((const char*) p)[i]);
|
||||
__builtin_printf ("<\n");
|
||||
}
|
||||
|
||||
static void
|
||||
check_str (CFI_cdesc_t *x, const char *str, const CFI_index_t subscripts[])
|
||||
{
|
||||
/* Avoid checking for '\0'. */
|
||||
if (strncmp ((const char*) CFI_address (x, subscripts), str, strlen(str)) != 0)
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
static void
|
||||
set_str (CFI_cdesc_t *x, const char *str, const CFI_index_t subscripts[])
|
||||
{
|
||||
char *p = CFI_address (x, subscripts);
|
||||
size_t len = strlen (str);
|
||||
if (x->elem_len != len)
|
||||
__builtin_abort ();
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
p[i] = str[i];
|
||||
}
|
||||
|
||||
static struct loc_t
|
||||
do_call (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num, bool intent_in, ftn_fn fn, bool is_cont, bool fort_cont)
|
||||
{
|
||||
const CFI_index_t zero[1] = { 0 };
|
||||
const CFI_index_t one[1] = { 1 };
|
||||
const CFI_index_t two[1] = { 2 };
|
||||
struct loc_t addr1, addr2;
|
||||
if (k != 3)
|
||||
__builtin_abort ();
|
||||
|
||||
if (num == 3)
|
||||
{
|
||||
if (x != NULL)
|
||||
__builtin_abort ();
|
||||
if (y != NULL)
|
||||
__builtin_abort ();
|
||||
if (z != NULL)
|
||||
__builtin_abort ();
|
||||
addr2 = fn (x, y, z, 3, num);
|
||||
if (addr2.x != -1 || addr2.y != -1 || addr2.z != -1)
|
||||
__builtin_abort ();
|
||||
return addr2;
|
||||
}
|
||||
if (x == NULL)
|
||||
__builtin_abort ();
|
||||
if (y == NULL)
|
||||
__builtin_abort ();
|
||||
if (z == NULL)
|
||||
__builtin_abort ();
|
||||
basic_check (x, is_cont || num == 2);
|
||||
basic_check (y, is_cont || num == 2);
|
||||
basic_check (z, is_cont || num == 2);
|
||||
if (!is_cont && num == 1)
|
||||
{
|
||||
check_str (x, "abc", zero);
|
||||
check_str (x, "ghi", one);
|
||||
check_str (x, "nop", two);
|
||||
check_str (y, "abc", zero);
|
||||
check_str (y, "ghi", one);
|
||||
check_str (y, "nop", two);
|
||||
check_str (z, "abc", zero);
|
||||
check_str (z, "ghi", one);
|
||||
check_str (z, "nop", two);
|
||||
}
|
||||
else if (num == 1)
|
||||
{
|
||||
if (strncmp ((const char*) x->base_addr, "abcghinop", 9) != 0)
|
||||
__builtin_abort ();
|
||||
if (strncmp ((const char*) y->base_addr, "abcghinop", 9) != 0)
|
||||
__builtin_abort ();
|
||||
if (strncmp ((const char*) z->base_addr, "abcghinop", 9) != 0)
|
||||
__builtin_abort ();
|
||||
}
|
||||
else if (num == 2)
|
||||
{
|
||||
if (strncmp ((const char*) x->base_addr, "defghijlm", 9) != 0)
|
||||
__builtin_abort ();
|
||||
if (strncmp ((const char*) y->base_addr, "defghijlm", 9) != 0)
|
||||
__builtin_abort ();
|
||||
if (strncmp ((const char*) z->base_addr, "defghijlm", 9) != 0)
|
||||
__builtin_abort ();
|
||||
}
|
||||
else
|
||||
__builtin_abort ();
|
||||
addr1.x = (intptr_t) x->base_addr;
|
||||
addr1.y = (intptr_t) y->base_addr;
|
||||
addr1.z = (intptr_t) z->base_addr;
|
||||
addr2 = fn (x, y, z, 3, num);
|
||||
if (!CFI_is_contiguous (x) && fort_cont)
|
||||
{
|
||||
/* Check for callee copy in/copy out. */
|
||||
if (addr1.x == addr2.x || addr1.x != (intptr_t) x->base_addr)
|
||||
__builtin_abort ();
|
||||
if (addr1.y == addr2.y || addr1.y != (intptr_t) y->base_addr)
|
||||
__builtin_abort ();
|
||||
if (addr1.z == addr2.z || addr1.z != (intptr_t) z->base_addr)
|
||||
__builtin_abort ();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (addr1.x != addr2.x || addr1.x != (intptr_t) x->base_addr)
|
||||
__builtin_abort ();
|
||||
if (addr1.y != addr2.y || addr1.y != (intptr_t) y->base_addr)
|
||||
__builtin_abort ();
|
||||
if (addr1.z != addr2.z || addr1.z != (intptr_t) z->base_addr)
|
||||
__builtin_abort ();
|
||||
}
|
||||
// intent_in
|
||||
if (intent_in && !is_cont && num == 1)
|
||||
{
|
||||
check_str (x, "abc", zero);
|
||||
check_str (x, "ghi", one);
|
||||
check_str (x, "nop", two);
|
||||
check_str (y, "abc", zero);
|
||||
check_str (y, "ghi", one);
|
||||
check_str (y, "nop", two);
|
||||
check_str (z, "abc", zero);
|
||||
check_str (z, "ghi", one);
|
||||
check_str (z, "nop", two);
|
||||
}
|
||||
else if (intent_in && num == 1)
|
||||
{
|
||||
if (strncmp ((const char*) x->base_addr, "abcghinop", 9) != 0)
|
||||
__builtin_abort ();
|
||||
if (strncmp ((const char*) y->base_addr, "abcghinop", 9) != 0)
|
||||
__builtin_abort ();
|
||||
if (strncmp ((const char*) z->base_addr, "abcghinop", 9) != 0)
|
||||
__builtin_abort ();
|
||||
}
|
||||
else if (intent_in && num == 2)
|
||||
{
|
||||
if (strncmp ((const char*) x->base_addr, "defghijlm", 9) != 0)
|
||||
__builtin_abort ();
|
||||
if (strncmp ((const char*) y->base_addr, "defghijlm", 9) != 0)
|
||||
__builtin_abort ();
|
||||
if (strncmp ((const char*) z->base_addr, "defghijlm", 9) != 0)
|
||||
__builtin_abort ();
|
||||
}
|
||||
else if (intent_in)
|
||||
__builtin_abort ();
|
||||
if (intent_in)
|
||||
{
|
||||
if (is_cont && num == 1)
|
||||
{
|
||||
/* Copy in - set the value to check that no copy out is done. */
|
||||
memcpy ((char*) x->base_addr, "123456789", 9);
|
||||
memcpy ((char*) y->base_addr, "123456789", 9);
|
||||
memcpy ((char*) z->base_addr, "123456789", 9);
|
||||
}
|
||||
return addr1;
|
||||
}
|
||||
// !intent_in
|
||||
if (!is_cont && num == 1)
|
||||
{
|
||||
check_str (x, "ABC", zero);
|
||||
check_str (x, "DEF", one);
|
||||
check_str (x, "GHI", two);
|
||||
check_str (y, "ABC", zero);
|
||||
check_str (y, "DEF", one);
|
||||
check_str (y, "GHI", two);
|
||||
check_str (z, "ABC", zero);
|
||||
check_str (z, "DEF", one);
|
||||
check_str (z, "GHI", two);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strncmp ((const char*) x->base_addr, "ABCDEFGHI", 9) != 0)
|
||||
__builtin_abort ();
|
||||
if (strncmp ((const char*) y->base_addr, "ABCDEFGHI", 9) != 0)
|
||||
__builtin_abort ();
|
||||
if (strncmp ((const char*) z->base_addr, "ABCDEFGHI", 9) != 0)
|
||||
__builtin_abort ();
|
||||
}
|
||||
return addr1;
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_assumed_size_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, false, char_assumed_size_f, true, false);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_assumed_size_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, true, char_assumed_size_in_f, true, false);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_expl_size_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, false, char_expl_size_f, true, false);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_expl_size_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, true, char_expl_size_in_f, true, false);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_assumed_rank_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, false, char_assumed_rank_f, false, false);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_assumed_rank_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, true, char_assumed_rank_in_f, false, false);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_assumed_rank_cont_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, false, char_assumed_rank_cont_f, true, false);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_assumed_rank_cont_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, true, char_assumed_rank_cont_in_f, true, false);
|
||||
}
|
||||
|
||||
static void
|
||||
reset_var (CFI_cdesc_t *x, int num)
|
||||
{
|
||||
const CFI_index_t zero[1] = { 0 };
|
||||
const CFI_index_t one[1] = { 1 };
|
||||
const CFI_index_t two[1] = { 2 };
|
||||
|
||||
if (num == 1)
|
||||
{
|
||||
set_str (x, "abc", zero);
|
||||
set_str (x, "ghi", one);
|
||||
set_str (x, "nop", two);
|
||||
}
|
||||
else if (num == 2)
|
||||
{
|
||||
set_str (x, "def", zero);
|
||||
set_str (x, "ghi", one);
|
||||
set_str (x, "jlm", two);
|
||||
}
|
||||
else if (num == 3)
|
||||
{
|
||||
if (x != NULL)
|
||||
__builtin_abort ();
|
||||
}
|
||||
else
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
static void
|
||||
reset_vars (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z, int num)
|
||||
{
|
||||
reset_var (x, num);
|
||||
reset_var (y, num);
|
||||
reset_var (z, num);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_assumed_shape_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
/* Make use of having a noncontiguous argument to check that the callee
|
||||
handles noncontiguous variables. */
|
||||
do_call (x, y, z, k, num, false, char_assumed_size_f, false, true);
|
||||
reset_vars (x, y, z, num);
|
||||
do_call (x, y, z, k, num, true, char_assumed_size_in_f, false, true);
|
||||
reset_vars (x, y, z, num);
|
||||
do_call (x, y, z, k, num, false, char_expl_size_f, false, true);
|
||||
reset_vars (x, y, z, num);
|
||||
do_call (x, y, z, k, num, true, char_expl_size_in_f, false, true);
|
||||
reset_vars (x, y, z, num);
|
||||
do_call (x, y, z, k, num, false, char_assumed_rank_cont_f, false, true);
|
||||
reset_vars (x, y, z, num);
|
||||
do_call (x, y, z, k, num, true, char_assumed_rank_cont_in_f, false, true);
|
||||
reset_vars (x, y, z, num);
|
||||
do_call (x, y, z, k, num, false, char_assumed_shape_cont_f, false, true);
|
||||
reset_vars (x, y, z, num);
|
||||
do_call (x, y, z, k, num, true, char_assumed_shape_cont_in_f, false, true);
|
||||
/* Actual func call. */
|
||||
reset_vars (x, y, z, num);
|
||||
return do_call (x, y, z, k, num, false, char_assumed_shape_f, false, false);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_assumed_shape_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, true, char_assumed_shape_in_f, false, false);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_assumed_shape_cont_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, false, char_assumed_shape_cont_f, true, false);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_assumed_shape_cont_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, true, char_assumed_shape_cont_in_f, true, false);
|
||||
}
|
1720
gcc/testsuite/gfortran.dg/bind-c-contiguous-4.f90
Normal file
1720
gcc/testsuite/gfortran.dg/bind-c-contiguous-4.f90
Normal file
File diff suppressed because it is too large
Load diff
345
gcc/testsuite/gfortran.dg/bind-c-contiguous-5.c
Normal file
345
gcc/testsuite/gfortran.dg/bind-c-contiguous-5.c
Normal file
|
@ -0,0 +1,345 @@
|
|||
#include <ISO_Fortran_binding.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
struct loc_t {
|
||||
intptr_t x, y, z;
|
||||
};
|
||||
|
||||
typedef struct loc_t (*ftn_fn) (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_assumed_size_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_assumed_size_in_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_expl_size_f (CFI_cdesc_t *,CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_expl_size_in_f (CFI_cdesc_t *,CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_assumed_rank_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_assumed_rank_in_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_assumed_rank_cont_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_assumed_rank_cont_in_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_assumed_shape_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_assumed_shape_in_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_assumed_shape_cont_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
struct loc_t char_assumed_shape_cont_in_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
|
||||
|
||||
static void
|
||||
basic_check(CFI_cdesc_t *x, bool is_cont)
|
||||
{
|
||||
if (!x->base_addr)
|
||||
__builtin_abort ();
|
||||
if (x->elem_len != 3*(4*sizeof(char))) /* ucs4_char */
|
||||
__builtin_abort ();
|
||||
if (x->version != CFI_VERSION)
|
||||
__builtin_abort ();
|
||||
if (x->rank != 1)
|
||||
__builtin_abort ();
|
||||
if (x->attribute != CFI_attribute_other)
|
||||
__builtin_abort ();
|
||||
if (x->type != CFI_type_ucs4_char)
|
||||
__builtin_abort ();
|
||||
if (x->dim[0].lower_bound != 0)
|
||||
__builtin_abort ();
|
||||
if (x->dim[0].extent != 3)
|
||||
__builtin_abort ();
|
||||
if (CFI_is_contiguous (x) != (x->elem_len == x->dim[0].sm))
|
||||
__builtin_abort ();
|
||||
if (is_cont != CFI_is_contiguous (x))
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
static void
|
||||
print_str (void *p, size_t len)
|
||||
{
|
||||
__builtin_printf ("DEBUG: >");
|
||||
/* Use ' ' for '\0' */
|
||||
for (size_t i = 0; i < len*4; ++i)
|
||||
__builtin_printf ("%c", ((const char*) p)[i] ? ((const char*) p)[i] : ' ');
|
||||
__builtin_printf ("<\n");
|
||||
}
|
||||
|
||||
static void
|
||||
check_str (CFI_cdesc_t *x, const char *str, size_t n, const CFI_index_t subscripts[])
|
||||
{
|
||||
/* Avoid checking for '\0'. */
|
||||
if (memcmp ((const char*) CFI_address (x, subscripts), str, n) != 0)
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
static void
|
||||
set_str (CFI_cdesc_t *x, const char *str, size_t n, const CFI_index_t subscripts[])
|
||||
{
|
||||
char *p = CFI_address (x, subscripts);
|
||||
if (x->elem_len != n)
|
||||
__builtin_abort ();
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
p[i] = str[i];
|
||||
}
|
||||
|
||||
static struct loc_t
|
||||
do_call (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num, bool intent_in, ftn_fn fn, bool is_cont, bool fort_cont)
|
||||
{
|
||||
const CFI_index_t zero[1] = { 0 };
|
||||
const CFI_index_t one[1] = { 1 };
|
||||
const CFI_index_t two[1] = { 2 };
|
||||
struct loc_t addr1, addr2;
|
||||
if (k != 3)
|
||||
__builtin_abort ();
|
||||
basic_check (x, is_cont || num == 2);
|
||||
basic_check (y, is_cont || num == 2);
|
||||
basic_check (z, is_cont || num == 2);
|
||||
if (!is_cont && num == 1)
|
||||
{
|
||||
check_str (x, "a\0\0\0b\0\0\0c\0\0\0", 3*4, zero);
|
||||
check_str (x, "g\0\0\0h\0\0\0i\0\0\0", 3*4, one);
|
||||
check_str (x, "n\0\0\0o\0\0\0p\0\0\0", 3*4, two);
|
||||
check_str (y, "a\0\0\0b\0\0\0c\0\0\0", 3*4, zero);
|
||||
check_str (y, "g\0\0\0h\0\0\0i\0\0\0", 3*4, one);
|
||||
check_str (y, "n\0\0\0o\0\0\0p\0\0\0", 3*4, two);
|
||||
check_str (z, "a\0\0\0b\0\0\0c\0\0\0", 3*4, zero);
|
||||
check_str (z, "g\0\0\0h\0\0\0i\0\0\0", 3*4, one);
|
||||
check_str (z, "n\0\0\0o\0\0\0p\0\0\0", 3*4, two);
|
||||
}
|
||||
else if (num == 1)
|
||||
{
|
||||
if (memcmp ((const char*) x->base_addr, "a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p\0\0\0", 9*4) != 0)
|
||||
__builtin_abort ();
|
||||
if (memcmp ((const char*) y->base_addr, "a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p\0\0\0", 9*4) != 0)
|
||||
__builtin_abort ();
|
||||
if (memcmp ((const char*) z->base_addr, "a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p\0\0\0", 9*4) != 0)
|
||||
__builtin_abort ();
|
||||
}
|
||||
else if (num == 2)
|
||||
{
|
||||
if (memcmp ((const char*) x->base_addr, "d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m\0\0\0", 9*4) != 0)
|
||||
__builtin_abort ();
|
||||
if (memcmp ((const char*) y->base_addr, "d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m\0\0\0", 9*4) != 0)
|
||||
__builtin_abort ();
|
||||
if (memcmp ((const char*) z->base_addr, "d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m\0\0\0", 9*4) != 0)
|
||||
__builtin_abort ();
|
||||
}
|
||||
else
|
||||
__builtin_abort ();
|
||||
addr1.x = (intptr_t) x->base_addr;
|
||||
addr1.y = (intptr_t) y->base_addr;
|
||||
addr1.z = (intptr_t) z->base_addr;
|
||||
addr2 = fn (x, y, z, 3, num);
|
||||
if (!CFI_is_contiguous (x) && fort_cont)
|
||||
{
|
||||
/* Check for callee copy in/copy out. */
|
||||
if (addr1.x == addr2.x || addr1.x != (intptr_t) x->base_addr)
|
||||
__builtin_abort ();
|
||||
if (addr1.y == addr2.y || addr1.y != (intptr_t) y->base_addr)
|
||||
__builtin_abort ();
|
||||
if (addr1.z == addr2.z || addr1.z != (intptr_t) z->base_addr)
|
||||
__builtin_abort ();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (addr1.x != addr2.x || addr1.x != (intptr_t) x->base_addr)
|
||||
__builtin_abort ();
|
||||
if (addr1.y != addr2.y || addr1.y != (intptr_t) y->base_addr)
|
||||
__builtin_abort ();
|
||||
if (addr1.z != addr2.z || addr1.z != (intptr_t) z->base_addr)
|
||||
__builtin_abort ();
|
||||
}
|
||||
// intent_in
|
||||
if (intent_in && !is_cont && num == 1)
|
||||
{
|
||||
check_str (x, "a\0\0\0b\0\0\0c\0\0\0", 3*4, zero);
|
||||
check_str (x, "g\0\0\0h\0\0\0i\0\0\0", 3*4, one);
|
||||
check_str (x, "n\0\0\0o\0\0\0p\0\0\0", 3*4, two);
|
||||
check_str (y, "a\0\0\0b\0\0\0c\0\0\0", 3*4, zero);
|
||||
check_str (y, "g\0\0\0h\0\0\0i\0\0\0", 3*4, one);
|
||||
check_str (y, "n\0\0\0o\0\0\0p\0\0\0", 3*4, two);
|
||||
check_str (z, "a\0\0\0b\0\0\0c\0\0\0", 3*4, zero);
|
||||
check_str (z, "g\0\0\0h\0\0\0i\0\0\0", 3*4, one);
|
||||
check_str (z, "n\0\0\0o\0\0\0p\0\0\0", 3*4, two);
|
||||
}
|
||||
else if (intent_in && num == 1)
|
||||
{
|
||||
if (memcmp ((const char*) x->base_addr, "a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p\0\0\0", 9*4) != 0)
|
||||
__builtin_abort ();
|
||||
if (memcmp ((const char*) y->base_addr, "a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p\0\0\0", 9*4) != 0)
|
||||
__builtin_abort ();
|
||||
if (memcmp ((const char*) z->base_addr, "a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p\0\0\0", 9*4) != 0)
|
||||
__builtin_abort ();
|
||||
}
|
||||
else if (intent_in && num == 2)
|
||||
{
|
||||
if (memcmp ((const char*) x->base_addr, "d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m\0\0\0", 9) != 0)
|
||||
__builtin_abort ();
|
||||
if (memcmp ((const char*) y->base_addr, "d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m\0\0\0", 9) != 0)
|
||||
__builtin_abort ();
|
||||
if (memcmp ((const char*) z->base_addr, "d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m\0\0\0", 9) != 0)
|
||||
__builtin_abort ();
|
||||
}
|
||||
else if (intent_in)
|
||||
__builtin_abort ();
|
||||
if (intent_in)
|
||||
{
|
||||
if (is_cont && num == 1)
|
||||
{
|
||||
/* Copy in - set the value to check that no copy out is done. */
|
||||
memcpy ((char*) x->base_addr, "1\0\0\0""2\0\0\0""3\0\0\0""4\0\0\0""5\0\0\0""6\0\0\0""7\0\0\0""8\0\0\0""9\0\0\0", 9*4);
|
||||
memcpy ((char*) y->base_addr, "1\0\0\0""2\0\0\0""3\0\0\0""4\0\0\0""5\0\0\0""6\0\0\0""7\0\0\0""8\0\0\0""9\0\0\0", 9*4);
|
||||
memcpy ((char*) z->base_addr, "1\0\0\0""2\0\0\0""3\0\0\0""4\0\0\0""5\0\0\0""6\0\0\0""7\0\0\0""8\0\0\0""9\0\0\0", 9*4);
|
||||
}
|
||||
return addr1;
|
||||
}
|
||||
// !intent_in
|
||||
if (!is_cont && num == 1)
|
||||
{
|
||||
check_str (x, "A\0\0\0B\0\0\0C\0\0\0", 3*4, zero);
|
||||
check_str (x, "D\0\0\0E\0\0\0F\0\0\0", 3*4, one);
|
||||
check_str (x, "G\0\0\0H\0\0\0I\0\0\0", 3*4, two);
|
||||
check_str (y, "A\0\0\0B\0\0\0C\0\0\0", 3*4, zero);
|
||||
check_str (y, "D\0\0\0E\0\0\0F\0\0\0", 3*4, one);
|
||||
check_str (y, "G\0\0\0H\0\0\0I\0\0\0", 3*4, two);
|
||||
check_str (z, "A\0\0\0B\0\0\0C\0\0\0", 3*4, zero);
|
||||
check_str (z, "D\0\0\0E\0\0\0F\0\0\0", 3*4, one);
|
||||
check_str (z, "G\0\0\0H\0\0\0I\0\0\0", 3*4, two);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (memcmp ((const char*) x->base_addr, "A\0\0\0B\0\0\0C\0\0\0D\0\0\0E\0\0\0F\0\0\0G\0\0\0H\0\0\0I\0\0\0", 9*4) != 0)
|
||||
__builtin_abort ();
|
||||
if (memcmp ((const char*) y->base_addr, "A\0\0\0B\0\0\0C\0\0\0D\0\0\0E\0\0\0F\0\0\0G\0\0\0H\0\0\0I\0\0\0", 9*4) != 0)
|
||||
__builtin_abort ();
|
||||
if (memcmp ((const char*) z->base_addr, "A\0\0\0B\0\0\0C\0\0\0D\0\0\0E\0\0\0F\0\0\0G\0\0\0H\0\0\0I\0\0\0", 9*4) != 0)
|
||||
__builtin_abort ();
|
||||
}
|
||||
return addr1;
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_assumed_size_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, false, char_assumed_size_f, true, false);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_assumed_size_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, true, char_assumed_size_in_f, true, false);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_expl_size_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, false, char_expl_size_f, true, false);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_expl_size_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, true, char_expl_size_in_f, true, false);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_assumed_rank_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, false, char_assumed_rank_f, false, false);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_assumed_rank_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, true, char_assumed_rank_in_f, false, false);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_assumed_rank_cont_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, false, char_assumed_rank_cont_f, true, false);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_assumed_rank_cont_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, true, char_assumed_rank_cont_in_f, true, false);
|
||||
}
|
||||
|
||||
static void
|
||||
reset_var (CFI_cdesc_t *x, int num)
|
||||
{
|
||||
const CFI_index_t zero[1] = { 0 };
|
||||
const CFI_index_t one[1] = { 1 };
|
||||
const CFI_index_t two[1] = { 2 };
|
||||
|
||||
if (num == 1)
|
||||
{
|
||||
set_str (x, "a\0\0\0b\0\0\0c\0\0\0", 3*4, zero);
|
||||
set_str (x, "g\0\0\0h\0\0\0i\0\0\0", 3*4, one);
|
||||
set_str (x, "n\0\0\0o\0\0\0p\0\0\0", 3*4, two);
|
||||
}
|
||||
else if (num == 2)
|
||||
{
|
||||
set_str (x, "d\0\0\0e\0\0\0f\0\0\0", 3*4, zero);
|
||||
set_str (x, "g\0\0\0h\0\0\0i\0\0\0", 3*4, one);
|
||||
set_str (x, "j\0\0\0l\0\0\0m\0\0\0", 3*4, two);
|
||||
}
|
||||
else
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
static void
|
||||
reset_vars (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z, int num)
|
||||
{
|
||||
reset_var (x, num);
|
||||
reset_var (y, num);
|
||||
reset_var (z, num);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_assumed_shape_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
/* Make use of having a noncontiguous argument to check that the callee
|
||||
handles noncontiguous variables. */
|
||||
do_call (x, y, z, k, num, false, char_assumed_size_f, false, true);
|
||||
reset_vars (x, y, z, num);
|
||||
do_call (x, y, z, k, num, true, char_assumed_size_in_f, false, true);
|
||||
reset_vars (x, y, z, num);
|
||||
do_call (x, y, z, k, num, false, char_expl_size_f, false, true);
|
||||
reset_vars (x, y, z, num);
|
||||
do_call (x, y, z, k, num, true, char_expl_size_in_f, false, true);
|
||||
reset_vars (x, y, z, num);
|
||||
do_call (x, y, z, k, num, false, char_assumed_rank_cont_f, false, true);
|
||||
reset_vars (x, y, z, num);
|
||||
do_call (x, y, z, k, num, true, char_assumed_rank_cont_in_f, false, true);
|
||||
reset_vars (x, y, z, num);
|
||||
do_call (x, y, z, k, num, false, char_assumed_shape_cont_f, false, true);
|
||||
reset_vars (x, y, z, num);
|
||||
do_call (x, y, z, k, num, true, char_assumed_shape_cont_in_f, false, true);
|
||||
/* Actual func call. */
|
||||
reset_vars (x, y, z, num);
|
||||
return do_call (x, y, z, k, num, false, char_assumed_shape_f, false, false);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_assumed_shape_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, true, char_assumed_shape_in_f, false, false);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_assumed_shape_cont_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, false, char_assumed_shape_cont_f, true, false);
|
||||
}
|
||||
|
||||
struct loc_t
|
||||
char_assumed_shape_cont_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
|
||||
int k, int num)
|
||||
{
|
||||
return do_call (x, y, z, k, num, true, char_assumed_shape_cont_in_f, true, false);
|
||||
}
|
1574
gcc/testsuite/gfortran.dg/bind-c-contiguous-5.f90
Normal file
1574
gcc/testsuite/gfortran.dg/bind-c-contiguous-5.f90
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,4 @@
|
|||
! { dg-do compile }
|
||||
! { dg-do run }
|
||||
! { dg-options "-fdump-tree-original" }
|
||||
!
|
||||
! PR fortran/91863
|
||||
|
@ -28,15 +28,20 @@ program p
|
|||
if (.not.allocated(a)) stop 1
|
||||
if (any(shape(a) /= [3])) stop 2
|
||||
if (lbound(a,1) /= 3 .or. ubound(a,1) /= 5) stop 3
|
||||
print *, a(0), a(1), a(2), a(3), a(4)
|
||||
print *, a
|
||||
if (any(a /= [1, 2, 3])) stop 4
|
||||
end program p
|
||||
|
||||
! "cfi" only appears in context of "a" -> bind-C descriptor
|
||||
! the intent(out) implies freeing in the callee (!), hence the "free"
|
||||
! the intent(out) implies freeing in the callee (!) (when implemented in Fortran), hence the "free"
|
||||
! and also in the caller (when implemented in Fortran)
|
||||
! It is the only 'free' as 'a' is part of the main program and, hence, implicitly has the SAVE attribute.
|
||||
! The 'cfi = 0' appears before the call due to the deallocate and when preparing the C descriptor
|
||||
! As cfi (i.e. the descriptor itself) is allocated in libgomp, it has to be freed after the call.
|
||||
|
||||
! { dg-final { scan-tree-dump-times "__builtin_free" 2 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "__builtin_free \\(cfi\\.\[0-9\]+\\);" 2 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "cfi\\.\[0-9\]+ = 0B;" 2 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "__builtin_free \\(_x->base_addr\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_x->base_addr = 0B;" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "__builtin_free \\(cfi\\.\[0-9\]+\\.base_addr\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "cfi\\.\[0-9\]+\\.base_addr = 0B;" 1 "original" } }
|
||||
|
|
|
@ -22,4 +22,32 @@ end
|
|||
! { dg-final { scan-assembler-times "brasl\t%r\[0-9\]*,myBindC" 1 { target { s390*-*-* } } } }
|
||||
! { dg-final { scan-assembler-times "bl \.myBindC" 1 { target { powerpc-ibm-aix* } } } }
|
||||
! { dg-final { scan-assembler-times "add_u32\t\[sv\]\[0-9\]*, \[sv\]\[0-9\]*, myBindC@rel32@lo" 1 { target { amdgcn*-*-* } } } }
|
||||
! { dg-final { scan-tree-dump-times "gfc_desc_to_cfi_desc \\\(&cfi\\." 1 "original" } }
|
||||
|
||||
|
||||
! { dg-final { scan-tree-dump "parm...span = 4;" "original" } }
|
||||
! { dg-final { scan-tree-dump "parm...dtype = {.elem_len=4, .rank=2, .type=1};" "original" } }
|
||||
! { dg-final { scan-tree-dump "parm...dim\\\[0\\\].lbound = 1;" "original" } }
|
||||
! { dg-final { scan-tree-dump "parm...dim\\\[0\\\].ubound = 4;" "original" } }
|
||||
! { dg-final { scan-tree-dump "parm...dim\\\[0\\\].stride = 1;" "original" } }
|
||||
! { dg-final { scan-tree-dump "parm...dim\\\[1\\\].lbound = 1;" "original" } }
|
||||
! { dg-final { scan-tree-dump "parm...dim\\\[1\\\].ubound = 4;" "original" } }
|
||||
! { dg-final { scan-tree-dump "parm...dim\\\[1\\\].stride = 4;" "original" } }
|
||||
! { dg-final { scan-tree-dump "parm...data = \\(void \\*\\) &aa\\\[0\\\];" "original" } }
|
||||
! { dg-final { scan-tree-dump "parm...offset = -5;" "original" } }
|
||||
! { dg-final { scan-tree-dump "cfi...version = 1;" "original" } }
|
||||
! { dg-final { scan-tree-dump "cfi...rank = 2;" "original" } }
|
||||
! { dg-final { scan-tree-dump "cfi...type = 1025;" "original" } }
|
||||
! { dg-final { scan-tree-dump "cfi...attribute = 2;" "original" } }
|
||||
! { dg-final { scan-tree-dump "cfi...base_addr = parm.0.data;" "original" } }
|
||||
! { dg-final { scan-tree-dump "cfi...elem_len = 4;" "original" } }
|
||||
! { dg-final { scan-tree-dump "idx.2 = 0;" "original" } }
|
||||
|
||||
! { dg-final { scan-tree-dump "if \\(idx.. <= 1\\) goto L..;" "original" } }
|
||||
! { dg-final { scan-tree-dump "cfi...dim\\\[idx..\\\].lower_bound = 0;" "original" } }
|
||||
! { dg-final { scan-tree-dump "cfi...dim\\\[idx..\\\].extent = \\(parm...dim\\\[idx..\\\].ubound - parm...dim\\\[idx..\\\].lbound\\) \\+ 1;" "original" } }
|
||||
! { dg-final { scan-tree-dump "cfi...dim\\\[idx..\\\].sm = parm...dim\\\[idx..\\\].stride \\* parm...span;" "original" } }
|
||||
! { dg-final { scan-tree-dump "idx.. = idx.. \\+ 1;" "original" } }
|
||||
|
||||
! { dg-final { scan-tree-dump "test \\(&cfi..\\);" "original" } }
|
||||
|
||||
|
||||
|
|
|
@ -466,15 +466,16 @@ program main
|
|||
end
|
||||
|
||||
! All arguments shall use array descriptors
|
||||
! { dg-final { scan-tree-dump-times "void as1 \\(struct array01_character\\(kind=1\\) & restrict x1\\)" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "void as2 \\(struct array01_character\\(kind=1\\) & restrict x2\\)" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "void as4 \\(struct array01_character\\(kind=1\\) & restrict xstar\\)" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "void as3 \\(struct array01_character\\(kind=1\\) & restrict xn, integer(kind=4) & restrict n)
|
||||
! { dg-final { scan-tree-dump-times "void ar1 \\(struct array15_character\\(kind=1\\) & restrict x1\\)" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "void ar2 \\(struct array15_character\\(kind=1\\) & restrict x2\\)" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "void ar3 \\(struct array15_character\\(kind=1\\) & restrict xn, integer(kind=4) & restrict n)
|
||||
! { dg-final { scan-tree-dump-times "void ar4 \\(struct array15_character\\(kind=1\\) & restrict xstar\\)" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "void a5a \\(struct array01_character\\(kind=1\\) & restrict xcolon\\)" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "void a5ar \\(struct array15_character\\(kind=1\\) & restrict xcolon\\)" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "void a5p \\(struct array01_character\\(kind=1\\) & xcolon\\)" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "void a5pr \\(struct array15_character\\(kind=1\\) & xcolon\\)" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "void as1 \\(struct CFI_cdesc_t01 & restrict _x1\\)" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "void as2 \\(struct CFI_cdesc_t01 & restrict _x2\\)" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "void as3 \\(struct CFI_cdesc_t01 & restrict _xn, integer\\(kind=4\\) & restrict n\\)" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "void as4 \\(struct CFI_cdesc_t01 & restrict _xstar\\)" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "void ar1 \\(struct CFI_cdesc_t & restrict _x1\\)" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "void ar2 \\(struct CFI_cdesc_t & restrict _x2\\)" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "void ar3 \\(struct CFI_cdesc_t & restrict _xn, integer\\(kind=4\\) & restrict n\\)" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "void ar4 \\(struct CFI_cdesc_t & restrict _xstar\\)" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "void a5ar \\(struct CFI_cdesc_t & restrict _xcolon\\)" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "void a5a \\(struct CFI_cdesc_t01 & restrict _xcolon\\)" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "void a5pr \\(struct CFI_cdesc_t & _xcolon\\)" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "void a5p \\(struct CFI_cdesc_t01 & _xcolon\\)" 1 "original" } }
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ subroutine s3 (xn, n) bind(C) ! { dg-error "Character dummy argument 'xn' at .1.
|
|||
character(len=n) :: xn
|
||||
end
|
||||
|
||||
subroutine s4 (xstar) bind(C) ! { dg-error "Sorry, character dummy argument 'xstar' at .1. with assumed length is not yet supported for procedure 's4' with BIND\\(C\\) attribute" }
|
||||
subroutine s4 (xstar) bind(C)
|
||||
character(len=*) :: xstar
|
||||
end
|
||||
|
||||
|
@ -85,7 +85,7 @@ subroutine az3 (xn, n) bind(C) ! { dg-error "Character dummy argument 'xn' at .1
|
|||
character(len=n) :: xn(*)
|
||||
end
|
||||
|
||||
subroutine az4 (xstar) bind(C) ! { dg-error "Sorry, character dummy argument 'xstar' at .1. with assumed length is not yet supported for procedure 'az4' with BIND\\(C\\) attribute" }
|
||||
subroutine az4 (xstar) bind(C)
|
||||
character(len=*) :: xstar(*)
|
||||
end
|
||||
|
||||
|
@ -104,7 +104,7 @@ subroutine ae3 (xn, n) bind(C) ! { dg-error "Character dummy argument 'xn' at .1
|
|||
character(len=n) :: xn(9)
|
||||
end
|
||||
|
||||
subroutine ae4 (xstar) bind(C) ! { dg-error "Sorry, character dummy argument 'xstar' at .1. with assumed length is not yet supported for procedure 'ae4' with BIND\\(C\\) attribute" }
|
||||
subroutine ae4 (xstar) bind(C)
|
||||
character(len=*) :: xstar(3)
|
||||
end
|
||||
|
||||
|
@ -128,7 +128,7 @@ subroutine s4a (xstar) bind(C) ! { dg-error "Allocatable character dummy argumen
|
|||
character(len=*), allocatable :: xstar
|
||||
end
|
||||
|
||||
subroutine s5a (xcolon) bind(C) ! { dg-error "Sorry, deferred-length scalar character dummy argument 'xcolon' at .1. of procedure 's5a' with BIND\\(C\\) not yet supported" }
|
||||
subroutine s5a (xcolon) bind(C)
|
||||
character(len=:), allocatable :: xcolon
|
||||
end
|
||||
|
||||
|
@ -198,7 +198,7 @@ subroutine s4p (xstar) bind(C) ! { dg-error "Pointer character dummy argument 'x
|
|||
character(len=*), pointer :: xstar
|
||||
end
|
||||
|
||||
subroutine s5p (xcolon) bind(C) ! { dg-error "Sorry, deferred-length scalar character dummy argument 'xcolon' at .1. of procedure 's5p' with BIND\\(C\\) not yet supported" }
|
||||
subroutine s5p (xcolon) bind(C)
|
||||
character(len=:), pointer :: xcolon
|
||||
end
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
! PR 101308
|
||||
! PR 92621(?)
|
||||
! { dg-do run { xfail *-*-* } }
|
||||
! { dg-do run }
|
||||
! { dg-additional-sources "allocatable-dummy-c.c dump-descriptors.c" }
|
||||
! { dg-additional-options "-g" }
|
||||
!
|
||||
|
|
|
@ -56,7 +56,7 @@ module m
|
|||
end subroutine
|
||||
|
||||
! dummy is assumed length character variable
|
||||
subroutine s6 (x) bind (c) ! { dg-bogus "Sorry" "pr92482" { xfail *-*-* } }
|
||||
subroutine s6 (x) bind (c)
|
||||
use ISO_C_BINDING
|
||||
implicit none
|
||||
character(len=*) :: x
|
||||
|
|
|
@ -44,7 +44,7 @@ subroutine s2 (x)
|
|||
implicit none
|
||||
type(*) :: x(*)
|
||||
|
||||
call g (x, 1) ! { dg-error "Assumed.type" }
|
||||
call g (x, 1) ! { dg-error "Assumed-type actual argument at .1. corresponding to assumed-rank dummy argument 'a' must be assumed-shape or assumed-rank" }
|
||||
end subroutine
|
||||
|
||||
! Check that a scalar gives an error.
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
! in C works and that you can use it to call back into a Fortran function
|
||||
! with an assumed-length dummy that is declared with C binding.
|
||||
|
||||
subroutine ftest (a, n) bind (c, name="ftest") ! { dg-bogus "Sorry" "pr92482" { xfail *-*-* } }
|
||||
subroutine ftest (a, n) bind (c, name="ftest")
|
||||
use iso_c_binding
|
||||
character(kind=C_CHAR, len=*) :: a
|
||||
integer(C_INT), value :: n
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
! PR 92621 (?)
|
||||
! { dg-do run { xfail *-*-* } }
|
||||
! { dg-do run }
|
||||
! { dg-additional-sources "cf-out-descriptor-3-c.c dump-descriptors.c" }
|
||||
! { dg-additional-options "-g" }
|
||||
!
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
! PR 92621 (?)
|
||||
! { dg-do run { xfail *-*-* } }
|
||||
! { dg-do run }
|
||||
! { dg-additional-sources "cf-out-descriptor-4-c.c dump-descriptors.c" }
|
||||
! { dg-additional-options "-g" }
|
||||
!
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
! This program checks use of an assumed-length character dummy argument
|
||||
! as an intent(out) parameter in subroutines with C binding.
|
||||
|
||||
subroutine ftest (a, n) bind (c, name="ftest") ! { dg-bogus "Sorry" "pr92482" { xfail *-*-* } }
|
||||
subroutine ftest (a, n) bind (c, name="ftest")
|
||||
use iso_c_binding
|
||||
character(kind=C_CHAR, len=*), intent(out) :: a
|
||||
integer(C_INT), value :: n
|
||||
|
@ -20,13 +20,13 @@ program testit
|
|||
implicit none
|
||||
|
||||
interface
|
||||
subroutine ctest (a, n) bind (c) ! { dg-bogus "Sorry" "pr92482" { xfail *-*-* } }
|
||||
subroutine ctest (a, n) bind (c)
|
||||
use iso_c_binding
|
||||
character(kind=C_CHAR, len=*), intent(out) :: a
|
||||
integer(C_INT), value :: n
|
||||
end subroutine
|
||||
|
||||
subroutine ftest (a, n) bind (c) ! { dg-bogus "Sorry" "pr92482" { xfail *-*-* } }
|
||||
subroutine ftest (a, n) bind (c)
|
||||
use iso_c_binding
|
||||
character(kind=C_CHAR, len=*), intent(out) :: a
|
||||
integer(C_INT), value :: n
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
! PR 101304
|
||||
! { dg-do run { xfail *-*-* } }
|
||||
! { dg-do run }
|
||||
! { dg-additional-sources "contiguous-2-c.c dump-descriptors.c" }
|
||||
! { dg-additional-options "-g" }
|
||||
!
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
! PR 101304
|
||||
! { dg-do run { xfail *-*-* } }
|
||||
! { dg-do run }
|
||||
! { dg-additional-sources "contiguous-3-c.c dump-descriptors.c" }
|
||||
! { dg-additional-options "-g" }
|
||||
!
|
||||
|
|
|
@ -16,12 +16,12 @@ module m
|
|||
interface
|
||||
|
||||
! These are supposed to be OK
|
||||
subroutine good1 (x, n) bind (c) ! { dg-bogus "Sorry" "pr92482" { xfail *-*-* } }
|
||||
subroutine good1 (x, n) bind (c)
|
||||
use iso_c_binding
|
||||
character (kind=C_CHAR, len=:), allocatable :: x
|
||||
integer(C_INT), value :: n
|
||||
end subroutine
|
||||
subroutine good2 (x, n) bind (c) ! { dg-bogus "Sorry" "pr92482" { xfail *-*-* } }
|
||||
subroutine good2 (x, n) bind (c)
|
||||
use iso_c_binding
|
||||
character (kind=C_CHAR, len=:), pointer :: x
|
||||
integer(C_INT), value :: n
|
||||
|
|
|
@ -43,7 +43,7 @@ program testit
|
|||
p = 'bar'
|
||||
end subroutine
|
||||
|
||||
subroutine frobc (a, p) bind (c) ! { dg-bogus "Sorry" "pr92482" { xfail *-*-* } }
|
||||
subroutine frobc (a, p) bind (c)
|
||||
use iso_c_binding
|
||||
character (kind=C_CHAR, len=:), allocatable :: a
|
||||
character (kind=C_CHAR, len=:), pointer :: p
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
! PR 101308
|
||||
! { dg-do run { xfail *-*-* } }
|
||||
! { dg-do run }
|
||||
! { dg-additional-sources "fc-descriptor-3-c.c dump-descriptors.c" }
|
||||
! { dg-additional-options "-g" }
|
||||
!
|
||||
|
|
|
@ -11,7 +11,7 @@ program testit
|
|||
implicit none
|
||||
|
||||
interface
|
||||
subroutine ctest (a) bind (c) ! { dg-bogus "Sorry" "pr92482" { xfail *-*-* } }
|
||||
subroutine ctest (a) bind (c)
|
||||
use iso_c_binding
|
||||
character(len=*,kind=C_CHAR) :: a
|
||||
end subroutine
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
! Reported as pr94070.
|
||||
! { dg-do run { xfail *-*-* } }
|
||||
! { dg-do run }
|
||||
! { dg-additional-sources "fc-descriptor-6-c.c dump-descriptors.c" }
|
||||
! { dg-additional-options "-g" }
|
||||
!
|
||||
|
|
|
@ -3,14 +3,18 @@
|
|||
#include <ISO_Fortran_binding.h>
|
||||
#include "dump-descriptors.h"
|
||||
|
||||
extern void ctest (CFI_cdesc_t *a);
|
||||
extern void ctest (CFI_cdesc_t *, _Bool);
|
||||
|
||||
void
|
||||
ctest (CFI_cdesc_t *a)
|
||||
ctest (CFI_cdesc_t *a, _Bool is_cont)
|
||||
{
|
||||
CFI_index_t subscripts[2];
|
||||
/* Dump the descriptor contents to test that we can access the fields
|
||||
correctly, etc. */
|
||||
|
||||
#if DEBUG
|
||||
dump_CFI_cdesc_t (a);
|
||||
#endif
|
||||
|
||||
/* We expect to get an array of shape (5,10) that may not be
|
||||
contiguous. */
|
||||
|
@ -33,14 +37,17 @@ ctest (CFI_cdesc_t *a)
|
|||
if (a->dim[1].extent != 10)
|
||||
abort ();
|
||||
|
||||
/* There shall be an ordering of the dimensions such that the absolute
|
||||
value of the sm member of the first dimension is not less than the
|
||||
elem_len member of the C descriptor and the absolute value of the sm
|
||||
member of each subsequent dimension is not less than the absolute
|
||||
value of the sm member of the previous dimension multiplied
|
||||
by the extent of the previous dimension. */
|
||||
if (is_cont != CFI_is_contiguous (a))
|
||||
abort ();
|
||||
|
||||
if (abs (a->dim[0].sm) < a->elem_len)
|
||||
abort ();
|
||||
if (abs (a->dim[1].sm) < abs (a->dim[0].sm) * a->dim[0].extent)
|
||||
abort ();
|
||||
|
||||
for (int j = 0; j < 5; ++j)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
subscripts[0] = j; subscripts[1] = i;
|
||||
if (*(int *) CFI_address (a, subscripts) != (i+1) + 100*(j+1))
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
! PR 101309
|
||||
! { dg-do run { xfail *-*-* } }
|
||||
! { dg-do run }
|
||||
! { dg-additional-sources "fc-descriptor-7-c.c dump-descriptors.c" }
|
||||
! { dg-additional-options "-g" }
|
||||
!
|
||||
|
@ -8,30 +8,140 @@
|
|||
|
||||
program testit
|
||||
use iso_c_binding
|
||||
implicit none
|
||||
implicit none (type, external)
|
||||
|
||||
interface
|
||||
subroutine ctest (a) bind (c)
|
||||
subroutine ctest (a, is_cont) bind (c)
|
||||
use iso_c_binding
|
||||
integer(C_INT), intent (in) :: a(:,:)
|
||||
integer(C_INT) :: a(:,:)
|
||||
logical(C_Bool), value :: is_cont
|
||||
end subroutine
|
||||
subroutine ctest_cont (a, is_cont) bind (c, name="ctest")
|
||||
use iso_c_binding
|
||||
integer(C_INT), contiguous :: a(:,:)
|
||||
logical(C_Bool), value :: is_cont
|
||||
end subroutine
|
||||
|
||||
subroutine ctest_ar (a, is_cont) bind (c, name="ctest")
|
||||
use iso_c_binding
|
||||
integer(C_INT) :: a(..)
|
||||
logical(C_Bool), value :: is_cont
|
||||
end subroutine
|
||||
subroutine ctest_ar_cont (a, is_cont) bind (c, name="ctest")
|
||||
use iso_c_binding
|
||||
integer(C_INT), contiguous :: a(..)
|
||||
logical(C_Bool), value :: is_cont
|
||||
end subroutine
|
||||
end interface
|
||||
|
||||
integer :: i , j
|
||||
integer(C_INT), target :: aa(10,5)
|
||||
integer(C_INT), target :: bb(10,10)
|
||||
|
||||
! Original array
|
||||
do j = 1, 5
|
||||
do i = 1, 10
|
||||
aa(i,j) = i + 100*j
|
||||
end do
|
||||
end do
|
||||
|
||||
! Transposed array
|
||||
do j = 2, 10, 2
|
||||
do i = 1, 10
|
||||
bb(j, i) = i + 100*((j-2)/2 + 1)
|
||||
end do
|
||||
end do
|
||||
|
||||
if (any (transpose (aa) /= bb(2:10:2, :))) error stop 1
|
||||
|
||||
! Test both calling the C function directly, and via another function
|
||||
! that takes an assumed-shape argument.
|
||||
call ctest (transpose (aa))
|
||||
call ftest (transpose (aa))
|
||||
call ctest (bb(2:10:2, :))
|
||||
call ftest (bb(2:10:2, :))
|
||||
! that takes an assumed-shape/assumed-rank argument.
|
||||
|
||||
call ftest (transpose (aa), is_cont=.true._c_bool) ! Implementation choice: copy in; hence, contiguous
|
||||
if (any (transpose (aa) /= bb(2:10:2, :))) error stop 1
|
||||
|
||||
call ctest (transpose (aa), is_cont=.false._c_bool) ! Implementation choice: noncontigous / sm inversed
|
||||
if (any (transpose (aa) /= bb(2:10:2, :))) error stop 1
|
||||
call ctest_cont (transpose (aa), is_cont=.true._c_bool)
|
||||
if (any (transpose (aa) /= bb(2:10:2, :))) error stop 1
|
||||
call ctest_ar (transpose (aa), is_cont=.false._c_bool) ! Implementation choice: noncontigous / sm inversed
|
||||
if (any (transpose (aa) /= bb(2:10:2, :))) error stop 1
|
||||
call ctest_ar_cont (transpose (aa), is_cont=.true._c_bool)
|
||||
if (any (transpose (aa) /= bb(2:10:2, :))) error stop 1
|
||||
|
||||
|
||||
call ftest (bb(2:10:2, :), is_cont=.false._c_bool)
|
||||
if (any (transpose (aa) /= bb(2:10:2, :))) error stop 1
|
||||
|
||||
call ctest (bb(2:10:2, :), is_cont=.false._c_bool)
|
||||
if (any (transpose (aa) /= bb(2:10:2, :))) error stop 1
|
||||
call ctest_cont (bb(2:10:2, :), is_cont=.true._c_bool)
|
||||
if (any (transpose (aa) /= bb(2:10:2, :))) error stop 1
|
||||
call ctest_ar (bb(2:10:2, :), is_cont=.false._c_bool)
|
||||
if (any (transpose (aa) /= bb(2:10:2, :))) error stop 1
|
||||
call ctest_ar_cont (bb(2:10:2, :), is_cont=.true._c_bool)
|
||||
if (any (transpose (aa) /= bb(2:10:2, :))) error stop 1
|
||||
|
||||
contains
|
||||
subroutine ftest (a)
|
||||
subroutine ftest (a, is_cont)
|
||||
use iso_c_binding
|
||||
integer(C_INT), intent(in) :: a(:,:)
|
||||
call ctest (a)
|
||||
integer(C_INT) :: a(:,:)
|
||||
logical(c_bool), value, intent(in) :: is_cont
|
||||
if (is_cont .NEQV. is_contiguous (a)) error stop 2
|
||||
if (any (shape (a) /= [5, 10])) error stop 3
|
||||
do j = 1, 5
|
||||
do i = 1, 10
|
||||
if (a(j, i) /= i + 100*j) error stop 4
|
||||
if (a(j, i) /= aa(i,j)) error stop
|
||||
end do
|
||||
end do
|
||||
call ctest (a, is_cont)
|
||||
call ctest_cont (a, is_cont=.true._c_bool)
|
||||
call ctest_ar (a, is_cont)
|
||||
call ctest_ar_cont (a, is_cont=.true._c_bool)
|
||||
end subroutine
|
||||
|
||||
subroutine ftest_ar (a, is_cont)
|
||||
use iso_c_binding
|
||||
integer(C_INT) :: a(..)
|
||||
logical(c_bool), value, intent(in) :: is_cont
|
||||
if (is_cont .NEQV. is_contiguous (a)) error stop 2
|
||||
if (any (shape (a) /= [5, 10])) error stop 3
|
||||
select rank (a)
|
||||
rank(2)
|
||||
do j = 1, 5
|
||||
do i = 1, 10
|
||||
if (a(j, i) /= i + 100*j) error stop 4
|
||||
if (a(j, i) /= aa(i,j)) error stop
|
||||
end do
|
||||
end do
|
||||
call ctest (a, is_cont)
|
||||
call ctest_cont (a, is_cont=.true._c_bool)
|
||||
call ftest_ar_con (a, is_cont=.true._c_bool)
|
||||
end select
|
||||
call ctest_ar (a, is_cont)
|
||||
! call ctest_ar_cont (a, is_cont=.true._c_bool) ! TODO/FIXME: ICE, cf. PR fortran/102729
|
||||
! call ftest_ar_con (a, is_cont=.true._c_bool) ! TODO/FIXME: ICE, cf. PR fortran/102729
|
||||
end subroutine
|
||||
|
||||
subroutine ftest_ar_con (a, is_cont)
|
||||
use iso_c_binding
|
||||
integer(C_INT), contiguous :: a(..)
|
||||
logical(c_bool), value, intent(in) :: is_cont
|
||||
if (is_cont .NEQV. is_contiguous (a)) error stop 2
|
||||
if (any (shape (a) /= [5, 10])) error stop 3
|
||||
select rank (a)
|
||||
rank(2)
|
||||
do j = 1, 5
|
||||
do i = 1, 10
|
||||
if (a(j, i) /= i + 100*j) error stop 4
|
||||
if (a(j, i) /= aa(i,j)) error stop
|
||||
end do
|
||||
end do
|
||||
call ctest (a, is_cont)
|
||||
call ctest_cont (a, is_cont=.true._c_bool)
|
||||
end select
|
||||
call ctest_ar (a, is_cont)
|
||||
call ctest_ar_cont (a, is_cont=.true._c_bool)
|
||||
end subroutine
|
||||
end program
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
! PR 101308
|
||||
! { dg-do run { xfail *-*-* } }
|
||||
! { dg-do run }
|
||||
! { dg-additional-sources "fc-out-descriptor-3-c.c dump-descriptors.c" }
|
||||
! { dg-additional-options "-g" }
|
||||
!
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
! PR 92621 (?)
|
||||
! { dg-do run { xfail *-*-* } }
|
||||
! { dg-do run }
|
||||
! { dg-additional-sources "fc-out-descriptor-4-c.c dump-descriptors.c" }
|
||||
! { dg-additional-options "-g" }
|
||||
!
|
||||
|
|
|
@ -10,7 +10,7 @@ program testit
|
|||
implicit none
|
||||
|
||||
interface
|
||||
subroutine ctest (a) bind (c) ! { dg-bogus "Sorry" "pr92482" { xfail *-*-* } }
|
||||
subroutine ctest (a) bind (c)
|
||||
use iso_c_binding
|
||||
character(len=*,kind=C_CHAR), intent(out) :: a
|
||||
end subroutine
|
||||
|
@ -26,7 +26,7 @@ program testit
|
|||
call ftest (aa)
|
||||
|
||||
contains
|
||||
subroutine ftest (a) bind (c) ! { dg-bogus "Sorry" "pr92482" { xfail *-*-* } }
|
||||
subroutine ftest (a) bind (c)
|
||||
use iso_c_binding
|
||||
character(len=*,kind=C_CHAR), intent(out) :: a
|
||||
call ctest (a)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
! Reported as pr94070.
|
||||
! { dg-do run { xfail *-*-* } }
|
||||
! { dg-do run }
|
||||
! { dg-additional-sources "fc-out-descriptor-6-c.c dump-descriptors.c" }
|
||||
! { dg-additional-options "-g" }
|
||||
!
|
||||
|
|
|
@ -17,7 +17,7 @@ contains
|
|||
|
||||
! C binding version
|
||||
|
||||
subroutine checkc (a) bind (c) ! { dg-bogus "Sorry" "pr92482" { xfail *-*-* } }
|
||||
subroutine checkc (a) bind (c)
|
||||
use iso_c_binding
|
||||
character(len=*,kind=C_CHAR) :: a
|
||||
|
||||
|
@ -37,7 +37,7 @@ contains
|
|||
end subroutine
|
||||
|
||||
! C binding version
|
||||
subroutine testc (a) bind (c) ! { dg-bogus "Sorry" "pr92482" { xfail *-*-* } }
|
||||
subroutine testc (a) bind (c)
|
||||
use iso_c_binding
|
||||
character(len=*,kind=C_CHAR) :: a
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
! Reported as pr94070.
|
||||
! { dg-do run { xfail *-*-* } }
|
||||
! { dg-do run }
|
||||
!
|
||||
! This program checks that passing assumed-size arrays to
|
||||
! and from Fortran functions with C binding works.
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
! subroutine with an assumed-rank dummy.
|
||||
|
||||
program test
|
||||
|
||||
implicit none
|
||||
! Define some arrays for testing.
|
||||
integer, target :: x1(5)
|
||||
integer :: y1(0:9)
|
||||
|
@ -51,7 +51,7 @@ contains
|
|||
r = rank(a)
|
||||
|
||||
block
|
||||
integer :: s(r)
|
||||
integer :: s(r), i
|
||||
s = shape(a)
|
||||
do i = 1, r
|
||||
if (s(i) .ne. size(a,i)) stop 101
|
||||
|
|
|
@ -33,3 +33,9 @@ ctest_1 (CFI_cdesc_t *arg_char, CFI_cdesc_t *arg_ucs4)
|
|||
check (arg_ucs4, 4, CFI_type_ucs4_char);
|
||||
}
|
||||
|
||||
void
|
||||
ctest_5 (CFI_cdesc_t *arg_char, CFI_cdesc_t *arg_ucs4)
|
||||
{
|
||||
check (arg_char, 5*1, CFI_type_char);
|
||||
check (arg_ucs4, 5*4, CFI_type_ucs4_char);
|
||||
}
|
||||
|
|
|
@ -27,11 +27,21 @@ program testit
|
|||
character(kind=ucs4) :: arg_ucs4(:)
|
||||
end subroutine
|
||||
|
||||
subroutine ctest_5 (arg_cchar, arg_ucs4) bind (c)
|
||||
use iso_c_binding
|
||||
integer, parameter :: ucs4 = selected_char_kind ('ISO_10646')
|
||||
character(kind=C_CHAR,len=*) :: arg_cchar(:)
|
||||
character(kind=ucs4,len=*) :: arg_ucs4(:)
|
||||
end subroutine
|
||||
|
||||
end interface
|
||||
|
||||
character(kind=C_CHAR) :: var_cchar(4)
|
||||
character(kind=ucs4) :: var_ucs4(4)
|
||||
character(kind=C_CHAR,len=5) :: var_cchar_5(4)
|
||||
character(kind=ucs4,len=5) :: var_ucs4_5(4)
|
||||
|
||||
call ctest_1 (var_cchar, var_ucs4)
|
||||
call ctest_5 (var_cchar_5, var_ucs4_5)
|
||||
|
||||
end program
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
! PR 100914
|
||||
! PR 100917
|
||||
! Fails on x86 targets where sizeof(long double) == 16 (PR100917).
|
||||
! { dg-do run { xfail { { x86_64*-*-* i?86*-*-* } && longdouble128 } } }
|
||||
! { dg-do run }
|
||||
! { dg-require-effective-target fortran_real_c_float128 }
|
||||
! { dg-additional-sources "typecodes-array-float128-c.c dump-descriptors.c" }
|
||||
! { dg-additional-options "-g" }
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
! PR 101305
|
||||
! PR 100917
|
||||
! xfailed due to PR 101308
|
||||
! { dg-do run { xfail *-*-* } }
|
||||
! { dg-do run }
|
||||
! { dg-additional-sources "typecodes-scalar-basic-c.c dump-descriptors.c" }
|
||||
! { dg-additional-options "-g" }
|
||||
!
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
! xfailed due to PR 101308
|
||||
! PR 101305
|
||||
! PR 100914
|
||||
! { dg-do run { xfail *-*-* } }
|
||||
! { dg-do run }
|
||||
! { dg-require-effective-target fortran_real_c_float128 }
|
||||
! { dg-additional-sources "typecodes-scalar-float128-c.c dump-descriptors.c" }
|
||||
! { dg-additional-options "-g" }
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
! PR 101305
|
||||
! xfailed due to PR 101308
|
||||
! { dg-do run { xfail *-*-* } }
|
||||
! { dg-do run }
|
||||
! { dg-require-effective-target fortran_integer_16 }
|
||||
! { dg-additional-sources "typecodes-scalar-int128-c.c dump-descriptors.c" }
|
||||
! { dg-additional-options "-g" }
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
! xfailed due to PR 101308
|
||||
! PR 101305
|
||||
! PR 100917
|
||||
! { dg-do run { xfail *-*-* } }
|
||||
! { dg-do run }
|
||||
! { dg-additional-sources "typecodes-scalar-longdouble-c.c dump-descriptors.c" }
|
||||
! { dg-additional-options "-g" }
|
||||
!
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
!
|
||||
! Contributed by Thomas Koenig <tkoenig@gcc.gnu.org>
|
||||
!
|
||||
subroutine bar(c,d) BIND(C) ! { dg-error "character dummy argument 'c' at .1. with assumed length is not yet supported for procedure 'bar' with BIND\\(C\\) attribute" }
|
||||
! { dg-error "Character dummy argument 'd' at .1. must be of constant length of one or assumed length, unless it has assumed shape or assumed rank, as procedure 'bar' has the BIND\\(C\\) attribute" "" { target *-*-* } .-1 }
|
||||
subroutine bar(c,d) BIND(C) ! { dg-error "Character dummy argument 'd' at .1. must be of constant length of one or assumed length, unless it has assumed shape or assumed rank, as procedure 'bar' has the BIND\\(C\\) attribute" }
|
||||
character (len=*) c
|
||||
character (len=2) d
|
||||
end
|
||||
|
|
|
@ -14,4 +14,4 @@ end
|
|||
! { dg-error "Parameterized type 't' does not have a component" " " { target *-*-* } 5 }
|
||||
! { dg-error "BOZ literal constant at .1. cannot appear" " " { target *-*-* } 6 }
|
||||
! { dg-error "Cannot open module file" " " { target *-*-* } 10 }
|
||||
! { dg-excess-errors "compilation terminated" }
|
||||
! { dg-prune-output "compilation terminated" }
|
||||
|
|
|
@ -152,14 +152,10 @@ extern int CFI_setpointer (CFI_cdesc_t *, CFI_cdesc_t *, const CFI_index_t []);
|
|||
#define CFI_type_Complex 4
|
||||
#define CFI_type_Character 5
|
||||
|
||||
/* Types with no kind. FIXME: GFC descriptors currently use BT_VOID for
|
||||
both C_PTR and C_FUNPTR, so we have no choice but to make them
|
||||
identical here too. That can potentially break on targets where
|
||||
function and data pointers have different sizes/representations.
|
||||
See PR 100915. */
|
||||
/* Types with no kind. */
|
||||
#define CFI_type_struct 6
|
||||
#define CFI_type_cptr 7
|
||||
#define CFI_type_cfunptr CFI_type_cptr
|
||||
#define CFI_type_cfunptr 8
|
||||
#define CFI_type_other -1
|
||||
|
||||
/* Types with kind parameter.
|
||||
|
|
|
@ -34,6 +34,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
|||
extern void cfi_desc_to_gfc_desc (gfc_array_void *, CFI_cdesc_t **);
|
||||
export_proto(cfi_desc_to_gfc_desc);
|
||||
|
||||
/* NOTE: Since GCC 12, the FE generates code to do the conversion
|
||||
directly without calling this function. */
|
||||
void
|
||||
cfi_desc_to_gfc_desc (gfc_array_void *d, CFI_cdesc_t **s_ptr)
|
||||
{
|
||||
|
@ -122,6 +124,8 @@ cfi_desc_to_gfc_desc (gfc_array_void *d, CFI_cdesc_t **s_ptr)
|
|||
extern void gfc_desc_to_cfi_desc (CFI_cdesc_t **, const gfc_array_void *);
|
||||
export_proto(gfc_desc_to_cfi_desc);
|
||||
|
||||
/* NOTE: Since GCC 12, the FE generates code to do the conversion
|
||||
directly without calling this function. */
|
||||
void
|
||||
gfc_desc_to_cfi_desc (CFI_cdesc_t **d_ptr, const gfc_array_void *s)
|
||||
{
|
||||
|
|
18
libgomp/testsuite/libgomp.fortran/optional-bind-c.f90
Normal file
18
libgomp/testsuite/libgomp.fortran/optional-bind-c.f90
Normal file
|
@ -0,0 +1,18 @@
|
|||
! With bind(C), the C (CFI) array descriptor is converted to
|
||||
! a Fortran array descriptor - thus, internally a PARM_DECL is
|
||||
! converted to a VAR_DECL - check that the optional check still works
|
||||
|
||||
module m
|
||||
contains
|
||||
subroutine foo(x, y) bind(C)
|
||||
integer, optional :: x,y(:)
|
||||
!$omp target map(tofrom:x)
|
||||
if (present (x)) x = 5
|
||||
if (present (y)) y(1) = 5
|
||||
!$omp end target
|
||||
end
|
||||
end
|
||||
|
||||
use m
|
||||
call foo()
|
||||
end
|
Loading…
Add table
Reference in a new issue