}
+bool
+gfc_check_coshape (gfc_expr *coarray, gfc_expr *kind)
+{
+ if (flag_coarray == GFC_FCOARRAY_NONE)
+ {
+ gfc_fatal_error ("Coarrays disabled at %L, use %<-fcoarray=%> to enable",
+ gfc_current_intrinsic_where);
+ return false;
+ }
+
+ if (!coarray_check (coarray, 0))
+ return false;
+
+ if (!kind_check (kind, 2, BT_INTEGER))
+ return false;
+
+ return true;
+}
+
+
bool
gfc_check_count (gfc_expr *mask, gfc_expr *dim, gfc_expr *kind)
{
GFC_ISYM_COS,
GFC_ISYM_COSD,
GFC_ISYM_COSH,
+ GFC_ISYM_COSHAPE,
GFC_ISYM_COTAN,
GFC_ISYM_COTAND,
GFC_ISYM_COUNT,
make_generic ("cosh", GFC_ISYM_COSH, GFC_STD_F77);
+ add_sym_2 ("coshape", GFC_ISYM_COSHAPE, CLASS_INQUIRY, ACTUAL_NO,
+ BT_INTEGER, di, GFC_STD_F2018,
+ gfc_check_coshape, NULL , gfc_resolve_coshape,
+ ca, BT_REAL, dr, REQUIRED,
+ kind, BT_INTEGER, di, OPTIONAL);
+
+ make_generic ("coshape", GFC_ISYM_COSHAPE, GFC_STD_F2018);
+
add_sym_3 ("count", GFC_ISYM_COUNT, CLASS_TRANSFORMATIONAL, ACTUAL_NO,
BT_INTEGER, di, GFC_STD_F95,
gfc_check_count, gfc_simplify_count, gfc_resolve_count,
bool gfc_check_chmod (gfc_expr *, gfc_expr *);
bool gfc_check_cmplx (gfc_expr *, gfc_expr *, gfc_expr *);
bool gfc_check_complex (gfc_expr *, gfc_expr *);
+bool gfc_check_coshape (gfc_expr *, gfc_expr *);
bool gfc_check_co_broadcast (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *);
bool gfc_check_co_minmax (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *);
bool gfc_check_co_sum (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *);
void gfc_resolve_conjg (gfc_expr *, gfc_expr *);
void gfc_resolve_cos (gfc_expr *, gfc_expr *);
void gfc_resolve_cosh (gfc_expr *, gfc_expr *);
+void gfc_resolve_coshape (gfc_expr *, gfc_expr *, gfc_expr *);
void gfc_resolve_count (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *);
void gfc_resolve_cshift (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *);
void gfc_resolve_ctime (gfc_expr *, gfc_expr *);
* @code{COS}: COS, Cosine function
* @code{COSD}: COSD, Cosine function, degrees
* @code{COSH}: COSH, Hyperbolic cosine function
+* @code{COSHAPE}: COSHAPE, Determine the coshape of a coarray
* @code{COSPI}: COSPI, Circular cosine function
* @code{COTAN}: COTAN, Cotangent function
* @code{COTAND}: COTAND, Cotangent function, degrees
+@node COSHAPE
+@section @code{COSHAPE} --- Determine the coshape of a coarray
+@fnindex COSHAPE
+@cindex coarray, coshape
+
+@table @asis
+@item @emph{Synopsis}:
+@code{RESULT = COSHAPE(COARRAY [, KIND])}
+
+@item @emph{Description}:
+Returns the shape of the cobounds of a coarray.
+
+@item @emph{Class}:
+Inquiry function
+
+@item @emph{Arguments}:
+@multitable @columnfractions .15 .70
+@item @var{COARRAY} @tab Shall be an coarray, of any type.
+@item @var{KIND} @tab (Optional) A scalar @code{INTEGER} constant
+expression indicating the kind parameter of the result.
+@end multitable
+
+
+@item @emph{Example}:
+
+@smallexample
+program test_cosh
+ real(8) :: x[*]
+ integer, allocatable :: csh (:)
+ csh = coshape(x, kind = kind(csh))
+end program test_cosh
+@end smallexample
+
+@item @emph{Standard}:
+Fortran 2018
+
+@item @emph{See also}:
+@ref{SHAPE}
+@end table
+
+
+
@node COSPI
@section @code{COSPI} --- Circular cosine function
@fnindex COSPI
Fortran 90 and later, with @var{KIND} argument Fortran 2003 and later
@item @emph{See also}:
+@ref{COSHAPE}, @*
@ref{RESHAPE}, @*
@ref{SIZE}
@end table
}
+void
+gfc_resolve_coshape (gfc_expr *f, gfc_expr *array, gfc_expr *kind)
+{
+ f->ts.type = BT_INTEGER;
+ if (kind)
+ f->ts.kind = mpz_get_si (kind->value.integer);
+ else
+ f->ts.kind = gfc_default_integer_kind;
+
+ f->value.function.name
+ = gfc_get_string ("__coshape_%c%d", gfc_type_letter (array->ts.type),
+ gfc_type_abi_kind (&array->ts));
+ f->rank = 1;
+ f->corank = 0;
+ f->shape = gfc_get_shape (1);
+ mpz_init_set_si (f->shape[0], array->corank);
+}
+
+
void
gfc_resolve_count (gfc_expr *f, gfc_expr *mask, gfc_expr *dim, gfc_expr *kind)
{
{
case GFC_ISYM_LBOUND:
case GFC_ISYM_UBOUND:
+ case GFC_ISYM_COSHAPE:
case GFC_ISYM_LCOBOUND:
case GFC_ISYM_UCOBOUND:
case GFC_ISYM_MAXLOC:
/* Otherwise fall through GFC_SS_FUNCTION. */
gcc_fallthrough ();
}
+ case GFC_ISYM_COSHAPE:
case GFC_ISYM_LCOBOUND:
case GFC_ISYM_UCOBOUND:
case GFC_ISYM_THIS_IMAGE:
gfc_actual_arglist *arg;
gfc_actual_arglist *arg2;
gfc_se argse;
- tree bound, resbound, resbound2, desc, cond, tmp;
+ tree bound, lbound, resbound, resbound2, desc, cond, tmp;
tree type;
int corank;
gcc_assert (expr->value.function.isym->id == GFC_ISYM_LCOBOUND
|| expr->value.function.isym->id == GFC_ISYM_UCOBOUND
+ || expr->value.function.isym->id == GFC_ISYM_COSHAPE
|| expr->value.function.isym->id == GFC_ISYM_THIS_IMAGE);
arg = expr->value.function.actual;
if (se->ss)
{
/* Create an implicit second parameter from the loop variable. */
- gcc_assert (!arg2->expr);
+ gcc_assert (!arg2->expr
+ || expr->value.function.isym->id == GFC_ISYM_COSHAPE);
gcc_assert (corank > 0);
gcc_assert (se->loop->dimen == 1);
gcc_assert (se->ss->info->expr == expr);
bound, gfc_rank_cst[arg->expr->rank]);
gfc_advance_se_ss_chain (se);
}
+ else if (expr->value.function.isym->id == GFC_ISYM_COSHAPE)
+ bound = gfc_index_zero_node;
else
{
- /* use the passed argument. */
gcc_assert (arg2->expr);
gfc_init_se (&argse, NULL);
gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
resbound = gfc_conv_descriptor_lbound_get (desc, bound);
+ /* COSHAPE needs the lower cobound and so it is stashed here before resbound
+ is overwritten. */
+ lbound = NULL_TREE;
+ if (expr->value.function.isym->id == GFC_ISYM_COSHAPE)
+ lbound = resbound;
+
/* Handle UCOBOUND with special handling of the last codimension. */
- if (expr->value.function.isym->id == GFC_ISYM_UCOBOUND)
+ if (expr->value.function.isym->id == GFC_ISYM_UCOBOUND
+ || expr->value.function.isym->id == GFC_ISYM_COSHAPE)
{
/* Last codimension: For -fcoarray=single just return
the lcobound - otherwise add
}
else
se->expr = resbound;
+
+ /* Get the coshape for this dimension. */
+ if (expr->value.function.isym->id == GFC_ISYM_COSHAPE)
+ {
+ gcc_assert (lbound != NULL_TREE);
+ se->expr = fold_build2_loc (input_location, MINUS_EXPR,
+ gfc_array_index_type,
+ se->expr, lbound);
+ se->expr = fold_build2_loc (input_location, PLUS_EXPR,
+ gfc_array_index_type,
+ se->expr, gfc_index_one_node);
+ }
}
else
se->expr = resbound;
gfc_conv_intrinsic_conjg (se, expr);
break;
+ case GFC_ISYM_COSHAPE:
+ conv_intrinsic_cobound (se, expr);
+ break;
+
case GFC_ISYM_COUNT:
gfc_conv_intrinsic_count (se, expr);
break;
{
case GFC_ISYM_UBOUND:
case GFC_ISYM_LBOUND:
+ case GFC_ISYM_COSHAPE:
case GFC_ISYM_UCOBOUND:
case GFC_ISYM_LCOBOUND:
case GFC_ISYM_MAXLOC:
/* The two argument version returns a scalar. */
if (expr->value.function.isym->id != GFC_ISYM_SHAPE
+ && expr->value.function.isym->id != GFC_ISYM_COSHAPE
&& expr->value.function.actual->next->expr)
return ss;
/* Special cases. */
switch (isym->id)
{
+ case GFC_ISYM_COSHAPE:
case GFC_ISYM_LBOUND:
case GFC_ISYM_LCOBOUND:
case GFC_ISYM_UBOUND:
--- /dev/null
+! { dg-do compile }
+! { dg-options "-fcoarray=lib -fdump-tree-original" }
+!
+! Test the coshape intrinsic (PR99250)
+!
+program coshape_1
+ integer, Parameter :: i4 = kind (1_4), i8 = kind (1_8)
+ real, codimension[-1:*] :: cr
+ real, dimension(4,4), codimension[0:2,*] :: cr2
+ integer(i4) :: no_images, val4(2)
+ integer(i8), allocatable :: val8(:)
+
+ no_images = num_images()
+
+ if (this_image() == 1) then
+
+! First without the KIND argument...
+ val4(1:1) = coshape(cr)
+ if (val4(1) /= no_images) stop 1
+ if (val4(1) /= 1 + ucobound (cr, 1, i4) - lcobound (cr, 1, i4)) stop 2
+ if (mod (no_images,3) == 0) then
+ val4 = coshape(cr2)
+ if (val4(1) /= 3 .or. product (val4(1:2)) /= no_images) stop 3
+ if (val4(2) /= 1 + ucobound (cr2, 2, i4) - lcobound (cr2, 2, i4)) stop 4
+ else
+ print *, "No. images must be a multiple of 3 for the coshape test #"
+ endif
+
+! ...then with it
+ if (kind (coshape(cr, kind = i4)) /= i4) stop 5
+ if (kind (coshape(cr, kind = i8)) /= i8) stop 6
+
+ val8 = coshape(cr, kind = i8)
+ if (val8(1) /= 1 + ucobound (cr, 1, i8) - lcobound (cr, 1, i8)) stop 7
+ if (val8(1) /= no_images) stop 8
+ if (mod (no_images,3) == 0) then
+ val8 = coshape(cr2, kind = i8)
+ if (val8(1) /= 3 .or. product (val8(1:2)) /= no_images) stop 9
+ if (val8(2) /= 1 + ucobound (cr2, 2, i8) - lcobound (cr2, 2, i8)) stop 10
+ else
+ print *, "No. images must be a multiple of 3 for the coshape test #"
+ endif
+ if (any (shape(cr2) /= [4,4])) stop 11
+ endif
+
+end program coshape_1
+! { dg-final { scan-tree-dump-times "_gfortran_caf_num_images" 9 "original" } }