Hi Harald,
I forgot to do the git add. Here it is.
Paul
On Wed, 11 Feb 2026 at 20:29, Harald Anlauf <[email protected]> wrote:
>
> Hi Paul,
>
> I do not see the promised updated patch here.
>
> Is it only me, or did you forget to attach it?
>
> Best,
> Harald
>
> Am 11.02.26 um 10:00 AM schrieb Paul Richard Thomas:
> > Hello Sandra and Harald,
> >
> > Many thanks for taking a look at the patch for PR99250. I admit that I
> > was in something of a rush to get it out of the door so that I could
> > return to the last few PDT problems.
> >
> > The use of the KIND argument now works correctly and the testcase has
> > been completely revamped to reflect this. The testcase runs correctly
> > using the shared memory gfortran, for which Jerry has just posted a
> > series of patches. Note that GFORTRAN_NUM_IMAGES=multiple_of_3 is
> > required.
> >
> > When converted to .html, intrinsic.texi looks OK and is now ordered
> > correctly.
> >
> > Regtests OK on FC43/x86_64 mainline. OK to push to mainline?
> >
> > Regards
> >
> > Paul
> >
> > On Mon, 9 Feb 2026 at 23:35, Sandra Loosemore <[email protected]>
> > wrote:
> >>
> >> On 2/9/26 09:54, Paul Richard Thomas wrote:
> >>> Hi All,
> >>>
> >>> This is a boilerplate implementation of the COSHAPE intrinsic. The
> >>> testcase is placed in the main gfortran.dg directory so that it can
> >>> make us of the option -fcoarry=lib to test the number of references to
> >>> _gfortran_caf_num_images (One to set no_images and to for the upper
> >>> bound of the last codimension).
> >>>
> >>> Regtests on FC43/x86_64. OK for mainline?
> >>>
> >>> Paul
> >>>
> >>> PS Could somebody please check the intrinsic.texi entries?
> >>
> >> Ack....
> >>
> >>> diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi
> >>> index cf81791b8b3..accd7825e38 100644
> >>> --- a/gcc/fortran/intrinsic.texi
> >>> +++ b/gcc/fortran/intrinsic.texi
> >>> @@ -127,6 +127,7 @@ Some basic guidelines for editing this document:
> >>> * @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 array
> >>> * @code{COSPI}: COSPI, Circular cosine function
> >>> * @code{COTAN}: COTAN, Cotangent function
> >>> * @code{COTAND}: COTAND, Cotangent function, degrees
> >>> @@ -4635,6 +4636,34 @@ Inverse function: @*
> >>>
> >>>
> >>>
> >>> +@node COSHAPE
> >>> +@section @code{COSHAPE} --- 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{Standard}:
> >>> +Fortran 2018
> >>> +
> >>
> >> The subheadings have been reordered in the Fortran intrinsics
> >> documentation. "Standard" now comes after "See also", or at the very
> >> end of the node if there's no "See also".
> >>
> >>> +@item @emph{Class}:
> >>> +Inquiry function
> >>> +
> >>> +@item @emph{Arguments}:
> >>> +@multitable @columnfractions .15 .70
> >>> +@item @var{COARRAY} @tab Shall be an coarray, of any type.
> >>
> >> s/an coarray/a coarray/
> >>
> >>> +@item @var{KIND} @tab (Optional) A scalar @code{INTEGER} constant
> >>> +expression indicating the kind parameter of the result.
> >>
> >> I think there should be
> >>
> >> @item @emph{Return value}:
> >> ...blah blah...
> >>
> >> after this. You could probably adapt the language from the SHAPE
> >> intrinsic.
> >>
> >> And, probably also add
> >>
> >> @item @emph{See also}:
> >>
> >> pointing at SHAPE.
> >>
> >>> +@end multitable
> >>> +@end table
> >>> +
> >>> +
> >>> +
> >>> @node COSPI
> >>> @section @code{COSPI} --- Circular cosine function
> >>> @fnindex COSPI
> >>
> >> -Sandra
> >>
> >
>
diff --git a/gcc/fortran/check.cc b/gcc/fortran/check.cc
index fae628bae40..528a9831005 100644
--- a/gcc/fortran/check.cc
+++ b/gcc/fortran/check.cc
@@ -2763,6 +2763,26 @@ gfc_check_complex (gfc_expr *x, gfc_expr *y)
}
+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)
{
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 848ad9ca1fa..9f7f5bd150c 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -489,6 +489,7 @@ enum gfc_isym_id
GFC_ISYM_COS,
GFC_ISYM_COSD,
GFC_ISYM_COSH,
+ GFC_ISYM_COSHAPE,
GFC_ISYM_COTAN,
GFC_ISYM_COTAND,
GFC_ISYM_COUNT,
diff --git a/gcc/fortran/intrinsic.cc b/gcc/fortran/intrinsic.cc
index a422fc176b4..8638dd30c74 100644
--- a/gcc/fortran/intrinsic.cc
+++ b/gcc/fortran/intrinsic.cc
@@ -1840,6 +1840,13 @@ add_functions (void)
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_F2008,
+ gfc_check_coshape, gfc_simplify_coshape, gfc_resolve_coshape,
+ ca, BT_REAL, dr, OPTIONAL, 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,
diff --git a/gcc/fortran/intrinsic.h b/gcc/fortran/intrinsic.h
index 048196d65c3..86a66dc4a0b 100644
--- a/gcc/fortran/intrinsic.h
+++ b/gcc/fortran/intrinsic.h
@@ -53,6 +53,7 @@ bool gfc_check_chdir (gfc_expr *);
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 *);
@@ -289,6 +290,7 @@ gfc_expr *gfc_simplify_cmplx (gfc_expr *, gfc_expr *, gfc_expr *);
gfc_expr *gfc_simplify_compiler_options (void);
gfc_expr *gfc_simplify_compiler_version (void);
gfc_expr *gfc_simplify_complex (gfc_expr *, gfc_expr *);
+gfc_expr *gfc_simplify_coshape (gfc_expr *, gfc_expr *);
gfc_expr *gfc_simplify_conjg (gfc_expr *);
gfc_expr *gfc_simplify_cos (gfc_expr *);
gfc_expr *gfc_simplify_cosd (gfc_expr *);
@@ -498,6 +500,7 @@ void gfc_resolve_complex (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 *);
diff --git a/gcc/fortran/iresolve.cc b/gcc/fortran/iresolve.cc
index a821332ecb2..49f7f3c17e3 100644
--- a/gcc/fortran/iresolve.cc
+++ b/gcc/fortran/iresolve.cc
@@ -732,6 +732,25 @@ gfc_resolve_cosh (gfc_expr *f, gfc_expr *x)
}
+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)
{
diff --git a/gcc/fortran/simplify.cc b/gcc/fortran/simplify.cc
index b25cd2c2388..b398b1e343f 100644
--- a/gcc/fortran/simplify.cc
+++ b/gcc/fortran/simplify.cc
@@ -2400,6 +2400,130 @@ gfc_simplify_tanpi (gfc_expr *x)
return range_check (result, "TANPI");
}
+static gfc_expr *
+simplify_bound_dim (gfc_expr *, gfc_expr *, int, int,
+ gfc_array_spec *, gfc_ref *, bool);
+
+gfc_expr *
+gfc_simplify_coshape (gfc_expr *array, gfc_expr *kind)
+{
+ gfc_expr *bounds[GFC_MAX_DIMENSIONS], *shapes[GFC_MAX_DIMENSIONS];
+ gfc_expr *e;
+ gfc_ref *ref;
+ gfc_array_spec *as;
+ int d;
+ int k;
+
+ if (array->expr_type != EXPR_VARIABLE)
+ return NULL;
+
+ /* Follow any component references. */
+ as = (array->ts.type == BT_CLASS && CLASS_DATA (array))
+ ? CLASS_DATA (array)->as
+ : array->symtree->n.sym->as;
+ for (ref = array->ref; ref; ref = ref->next)
+ {
+ switch (ref->type)
+ {
+ case REF_ARRAY:
+ switch (ref->u.ar.type)
+ {
+ case AR_ELEMENT:
+ if (ref->u.ar.as->corank > 0)
+ {
+ gcc_assert (as == ref->u.ar.as);
+ goto done;
+ }
+ as = NULL;
+ continue;
+
+ case AR_FULL:
+ /* We're done because 'as' has already been set in the
+ previous iteration. */
+ goto done;
+
+ case AR_UNKNOWN:
+ return NULL;
+
+ case AR_SECTION:
+ as = ref->u.ar.as;
+ goto done;
+ }
+
+ gcc_unreachable ();
+
+ case REF_COMPONENT:
+ as = ref->u.c.component->as;
+ continue;
+
+ case REF_SUBSTRING:
+ case REF_INQUIRY:
+ continue;
+ }
+ }
+
+ if (!as)
+ gcc_unreachable ();
+
+ done:
+
+ if (as->cotype == AS_DEFERRED || as->cotype == AS_ASSUMED_SHAPE)
+ return NULL;
+
+ /* Simplify the cobounds for each dimension. */
+ for (d = 0; d < as->corank; d++)
+ {
+ shapes[d] = simplify_bound_dim (array, kind, d + 1 + as->rank,
+ 1, as, ref, true);
+ if (shapes[d] == NULL || shapes[d] == &gfc_bad_expr)
+ {
+ int j;
+
+ for (j = 0; j < d; j++)
+ gfc_free_expr (shapes[j]);
+ return shapes[d];
+ }
+
+ bounds[d] = simplify_bound_dim (array, kind, d + 1 + as->rank,
+ 0, as, ref, true);
+ if (bounds[d] == NULL || bounds[d] == &gfc_bad_expr)
+ {
+ int j;
+
+ for (j = 0; j < d; j++)
+ gfc_free_expr (bounds[j]);
+ return bounds[d];
+ }
+
+ mpz_sub (shapes[d]->value.integer, shapes[d]->value.integer, bounds[d]->value.integer);
+ mpz_add_ui (shapes[d]->value.integer, shapes[d]->value.integer, 1);
+ }
+
+ /* Allocate the result expression. */
+ e = gfc_get_expr ();
+ e->where = array->where;
+ e->expr_type = EXPR_ARRAY;
+ e->ts.type = BT_INTEGER;
+ k = get_kind (BT_INTEGER, kind, "COSHAPE", gfc_default_integer_kind);
+ if (k == -1)
+ {
+ gfc_free_expr (e);
+ return &gfc_bad_expr;
+ }
+ e->ts.kind = k;
+
+ e->rank = 1;
+ e->shape = gfc_get_shape (1);
+ mpz_init_set_ui (e->shape[0], as->corank);
+
+ /* Create the constructor for this array. */
+ for (d = 0; d < as->corank; d++)
+ gfc_constructor_append_expr (&e->value.constructor,
+ shapes[d], &e->where);
+ return e;
+}
+
+
gfc_expr *
gfc_simplify_count (gfc_expr *mask, gfc_expr *dim, gfc_expr *kind)
{
diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index cd137212260..dd8c1545e0a 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -5252,6 +5252,7 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
{
case GFC_ISYM_LBOUND:
case GFC_ISYM_UBOUND:
+ case GFC_ISYM_COSHAPE:
case GFC_ISYM_LCOBOUND:
case GFC_ISYM_UCOBOUND:
case GFC_ISYM_MAXLOC:
@@ -5343,6 +5344,7 @@ done:
/* Fall through. */
case GFC_ISYM_SHAPE:
+ case GFC_ISYM_COSHAPE:
{
gfc_expr *arg;
diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc
index db4b1165781..0f8e31068ad 100644
--- a/gcc/fortran/trans-intrinsic.cc
+++ b/gcc/fortran/trans-intrinsic.cc
@@ -2622,12 +2622,13 @@ conv_intrinsic_cobound (gfc_se * se, gfc_expr * expr)
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;
@@ -2708,8 +2709,13 @@ conv_intrinsic_cobound (gfc_se * se, gfc_expr * expr)
resbound = gfc_conv_descriptor_lbound_get (desc, bound);
+ 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
@@ -2763,6 +2769,17 @@ conv_intrinsic_cobound (gfc_se * se, gfc_expr * expr)
}
else
se->expr = resbound;
+
+ 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;
@@ -11308,6 +11325,10 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
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;
@@ -12010,6 +12031,7 @@ gfc_add_intrinsic_ss_code (gfc_loopinfo * loop ATTRIBUTE_UNUSED, gfc_ss * ss)
{
case GFC_ISYM_UBOUND:
case GFC_ISYM_LBOUND:
+ case GFC_ISYM_COSHAPE:
case GFC_ISYM_UCOBOUND:
case GFC_ISYM_LCOBOUND:
case GFC_ISYM_MAXLOC:
@@ -12213,6 +12235,7 @@ gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr,
/* Special cases. */
switch (isym->id)
{
+ case GFC_ISYM_COSHAPE:
case GFC_ISYM_LBOUND:
case GFC_ISYM_LCOBOUND:
case GFC_ISYM_UBOUND: