Hi all,

attached patch reworks the NUM_IMAGES() implementation to adhere to the Fortran
2018 standard.

Regtests ok on x86_64-pc-linux-gnu / F41. Ok for mainline?

Regards,
        Andre
--
Andre Vehreschild * Email: vehre ad gmx dot de
From 1d0262dc068f4c6018d669a88387dbb7baaff39a Mon Sep 17 00:00:00 2001
From: Andre Vehreschild <ve...@gcc.gnu.org>
Date: Thu, 3 Apr 2025 10:11:50 +0200
Subject: [PATCH 5/6] Fortran: Add teams support in image_index and num_images
 for F2018

This more or less completes the set of functions that are affected by
teams.

gcc/fortran/ChangeLog:

	* check.cc (gfc_check_image_index): Check for team or
	team_number correctnes.
	(gfc_check_num_images): Same.
	* gfortran.texi: Update documentation on num_images' API
	function.
	* intrinsic.cc (add_functions): Update signature of image_index
	and num_images.  Both can take either a team handle or number.
	* intrinsic.h (gfc_check_num_images): Update signature to take
	either team or team_number.
	(gfc_check_image_index): Can take coarray, subscripts and team
	or team number now.
	(gfc_simplify_image_index): Same.
	(gfc_simplify_num_images): Same.
	(gfc_resolve_image_index): Same.
	* intrinsic.texi: Update documentation of num_images() Fortran
	function.
	* iresolve.cc (gfc_resolve_image_index): Update signature.
	* simplify.cc (gfc_simplify_num_images): Update signature and
	remove undocumented failed argument.
	(gfc_simplify_image_index): Add team or team number argument.
	* trans-intrinsic.cc (conv_stat_and_team): Because being
	optional teams need to be a pointer to the opaque pointer.
	(conv_caf_sendget): Correct call; was two arguments short.
	(trans_image_index): Support team or team_number.
	(trans_num_images): Same.
	(conv_intrinsic_cobound): Adapt to changed signature of
	num_images in call.
	* trans-stmt.cc (gfc_trans_sync): Same.

libgfortran/ChangeLog:

	* caf/libcaf.h (_gfortran_caf_num_images): Correct prototype.
	* caf/single.c (_gfortran_caf_num_images): Default
	implementation.

gcc/testsuite/ChangeLog:

	* gfortran.dg/coarray_49.f90: Adapt to changed error message.
	* gfortran.dg/coarray_collectives_12.f90: Adapt to changed
	function signature of num_images.
	* gfortran.dg/coarray_collectives_16.f90: Same.
	* gfortran.dg/coarray_lib_this_image_1.f90: Same.
	* gfortran.dg/coarray_lib_this_image_2.f90: Same.
	* gfortran.dg/coarray_this_image_1.f90: Adapt tests for
	num_images.
	* gfortran.dg/coarray_this_image_2.f90: Same.
	* gfortran.dg/coarray_this_image_3.f90: Same.
	* gfortran.dg/num_images_1.f90: Check that deprecated syntax is
	no longer supported.
---
 gcc/fortran/check.cc                          | 63 ++++++++----------
 gcc/fortran/gfortran.texi                     | 26 ++++----
 gcc/fortran/intrinsic.cc                      | 55 ++++++++--------
 gcc/fortran/intrinsic.h                       | 10 +--
 gcc/fortran/intrinsic.texi                    | 45 ++++++-------
 gcc/fortran/iresolve.cc                       |  3 +-
 gcc/fortran/simplify.cc                       | 12 +---
 gcc/fortran/trans-intrinsic.cc                | 66 +++++++++++--------
 gcc/fortran/trans-stmt.cc                     |  3 +-
 gcc/testsuite/gfortran.dg/coarray_49.f90      |  2 +-
 .../gfortran.dg/coarray_collectives_12.f90    |  2 +-
 .../gfortran.dg/coarray_collectives_16.f90    |  2 +-
 .../gfortran.dg/coarray_lib_this_image_1.f90  |  2 +-
 .../gfortran.dg/coarray_lib_this_image_2.f90  |  2 +-
 .../gfortran.dg/coarray_this_image_1.f90      | 14 ++--
 .../gfortran.dg/coarray_this_image_2.f90      | 16 ++---
 .../gfortran.dg/coarray_this_image_3.f90      | 15 ++---
 gcc/testsuite/gfortran.dg/num_images_1.f90    |  2 +-
 libgfortran/caf/libcaf.h                      |  2 +-
 libgfortran/caf/single.c                      |  4 +-
 20 files changed, 171 insertions(+), 175 deletions(-)

diff --git a/gcc/fortran/check.cc b/gcc/fortran/check.cc
index c27f653d3b0..356e0d7f678 100644
--- a/gcc/fortran/check.cc
+++ b/gcc/fortran/check.cc
@@ -6565,7 +6565,8 @@ gfc_check_stat_sub (gfc_expr *name, gfc_expr *array, gfc_expr *status)


 bool
-gfc_check_image_index (gfc_expr *coarray, gfc_expr *sub)
+gfc_check_image_index (gfc_expr *coarray, gfc_expr *sub,
+		       gfc_expr *team_or_team_number)
 {
   mpz_t nelems;

@@ -6585,12 +6586,8 @@ gfc_check_image_index (gfc_expr *coarray, gfc_expr *sub)
       return false;
     }

-  if (sub->ts.type != BT_INTEGER)
-    {
-      gfc_error ("Type of %s argument of IMAGE_INDEX at %L shall be INTEGER",
-		 gfc_current_intrinsic_arg[1]->name, &sub->where);
-      return false;
-    }
+  if (!type_check (sub, 1, BT_INTEGER))
+    return false;

   if (gfc_array_size (sub, &nelems))
     {
@@ -6605,12 +6602,23 @@ gfc_check_image_index (gfc_expr *coarray, gfc_expr *sub)
       mpz_clear (nelems);
     }

+  if (team_or_team_number)
+    {
+      if (!type_check2 (team_or_team_number, 2, BT_DERIVED, BT_INTEGER)
+	  || !scalar_check (team_or_team_number, 2))
+	return false;
+
+      /* Check team is of team_type.  */
+      if (team_or_team_number->ts.type == BT_DERIVED
+	  && !team_type_check (team_or_team_number, 2))
+	return false;
+    }
+
   return true;
 }

-
 bool
-gfc_check_num_images (gfc_expr *distance, gfc_expr *failed)
+gfc_check_num_images (gfc_expr *team_or_team_number)
 {
   if (flag_coarray == GFC_FCOARRAY_NONE)
     {
@@ -6618,34 +6626,21 @@ gfc_check_num_images (gfc_expr *distance, gfc_expr *failed)
       return false;
     }

-  if (distance)
-    {
-      if (!type_check (distance, 0, BT_INTEGER))
-	return false;
-
-      if (!nonnegative_check ("DISTANCE", distance))
-	return false;
-
-      if (!scalar_check (distance, 0))
-	return false;
-
-      if (!gfc_notify_std (GFC_STD_F2018, "DISTANCE= argument to "
-			   "NUM_IMAGES at %L", &distance->where))
-	return false;
-    }
+  if (!team_or_team_number)
+    return true;

-   if (failed)
-    {
-      if (!type_check (failed, 1, BT_LOGICAL))
-	return false;
+  if (!gfc_notify_std (GFC_STD_F2008,
+		       "%<team%> or %<team_number%> argument to %qs at %L",
+		       gfc_current_intrinsic, &team_or_team_number->where))
+    return false;

-      if (!scalar_check (failed, 1))
-	return false;
+  if (!type_check2 (team_or_team_number, 0, BT_DERIVED, BT_INTEGER)
+      || !scalar_check (team_or_team_number, 0))
+    return false;

-      if (!gfc_notify_std (GFC_STD_F2018, "FAILED= argument to "
-			   "NUM_IMAGES at %L", &failed->where))
-	return false;
-    }
+  if (team_or_team_number->ts.type == BT_DERIVED
+      && !team_type_check (team_or_team_number, 0))
+    return false;

   return true;
 }
diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi
index 6c0aa0ce4e3..da0d705c8e6 100644
--- a/gcc/fortran/gfortran.texi
+++ b/gcc/fortran/gfortran.texi
@@ -4326,25 +4326,29 @@ be null here.

 @table @asis
 @item @emph{Synopsis}:
-@code{int _gfortran_caf_num_images(int distance, int failed)}
+@code{int _gfortran_caf_num_images(caf_team_t team, int32_t *team_number)}

 @item @emph{Description}:
-This function returns the number of images in the current team, if
-@var{distance} is 0 or the number of images in the parent team at the specified
-distance. If @var{failed} is -1, the function returns the number of all images at
-the specified distance; if it is 0, the function returns the number of
-nonfailed images, and if it is 1, it returns the number of failed images.
+This function returns the number of images in the team given by @var{team} or
+@var{team_number}, if either one is present.  If both are null, then the number
+of images in the current team is returned.

 @item @emph{Arguments}:
 @multitable @columnfractions .15 .70
-@item @var{distance} @tab the distance from this image to the ancestor.
-Shall be positive.
-@item @var{failed} @tab shall be -1, 0, or 1
+@item @var{team} @tab intent(in), optional; The team the number of images is
+requested for.  If null, the number of images in the current team is returned.
+@item @var{team_number} @tab intent(in), optional; The team id for which the
+number of teams is requested; if unset, then number of images in the current
+team is returned.
 @end multitable

 @item @emph{Notes}:
-This function follows TS18508. If the num_image intrinsic has no arguments,
-then the compiler passes @code{distance=0} and @code{failed=-1} to the function.
+When both argument are given, then it is caf-library dependent which argument
+is examined first.  Current implementations prioritize the @var{team} argument,
+because it is easier to retrive the number of images from it.
+
+Fortran 2008 or later, with no arguments; Fortran 2018 or later with two
+arguments.
 @end table


diff --git a/gcc/fortran/intrinsic.cc b/gcc/fortran/intrinsic.cc
index ce586a20ad5..2eba2094606 100644
--- a/gcc/fortran/intrinsic.cc
+++ b/gcc/fortran/intrinsic.cc
@@ -1395,26 +1395,24 @@ add_functions (void)
 {
   /* Argument names.  These are used as argument keywords and so need to
     match the documentation.  Please keep this list in sorted order.  */
-  const char
-    *a = "a", *a1 = "a1", *a2 = "a2", *ar = "array", *b = "b",
-    *bck = "back", *bd = "boundary", *c = "c", *c_ptr_1 = "c_ptr_1",
-    *c_ptr_2 = "c_ptr_2", *ca = "coarray", *com = "command",
-    *dist = "distance", *dm = "dim", *f = "field", *failed="failed",
-    *fs = "fsource", *han = "handler", *i = "i",
-    *idy = "identity", *image = "image", *j = "j", *kind = "kind",
-    *l = "l", *ln = "len", *level = "level", *m = "matrix", *ma = "matrix_a",
-    *mb = "matrix_b", *md = "mode", *mo = "mold", *msk = "mask",
-    *n = "n", *ncopies= "ncopies", *nm = "name", *num = "number",
-    *op = "operation", *ord = "order", *odd = "ordered", *p = "p",
-	*p1 = "path1", *p2 = "path2", *pad = "pad", *pid = "pid", *pos = "pos",
-	*pt = "pointer", *r = "r", *rd = "round",
-    *s = "s", *set = "set", *sh = "shift", *shp = "shape",
-    *sig = "sig", *src = "source", *ssg = "substring",
-    *sta = "string_a", *stb = "string_b", *stg = "string",
-    *sub = "sub", *sz = "size", *tg = "target", *team = "team", *tm = "time",
-    *ts = "tsource", *ut = "unit", *v = "vector", *va = "vector_a",
-    *vb = "vector_b", *vl = "values", *val = "value", *x = "x", *y = "y",
-    *z = "z";
+  const char *a
+    = "a",
+    *a1 = "a1", *a2 = "a2", *ar = "array", *b = "b", *bck = "back",
+    *bd = "boundary", *c = "c", *c_ptr_1 = "c_ptr_1", *c_ptr_2 = "c_ptr_2",
+    *ca = "coarray", *com = "command", *dm = "dim", *f = "field",
+    *fs = "fsource", *han = "handler", *i = "i", *idy = "identity",
+    *image = "image", *j = "j", *kind = "kind", *l = "l", *ln = "len",
+    *level = "level", *m = "matrix", *ma = "matrix_a", *mb = "matrix_b",
+    *md = "mode", *mo = "mold", *msk = "mask", *n = "n", *ncopies = "ncopies",
+    *nm = "name", *num = "number", *op = "operation", *ord = "order",
+    *odd = "ordered", *p = "p", *p1 = "path1", *p2 = "path2", *pad = "pad",
+    *pid = "pid", *pos = "pos", *pt = "pointer", *r = "r", *rd = "round",
+    *s = "s", *set = "set", *sh = "shift", *shp = "shape", *sig = "sig",
+    *src = "source", *ssg = "substring", *sta = "string_a", *stb = "string_b",
+    *stg = "string", *sub = "sub", *sz = "size", *tg = "target", *team = "team",
+    *team_or_team_number = "team/team_number", *tm = "time", *ts = "tsource",
+    *ut = "unit", *v = "vector", *va = "vector_a", *vb = "vector_b",
+    *vl = "values", *val = "value", *x = "x", *y = "y", *z = "z";

   int di, dr, dd, dl, dc, dz, ii;

@@ -2265,9 +2263,11 @@ add_functions (void)

   make_generic ("ierrno", GFC_ISYM_IERRNO, GFC_STD_GNU);

-  add_sym_2 ("image_index", GFC_ISYM_IMAGE_INDEX, CLASS_INQUIRY, ACTUAL_NO, BT_INTEGER, di, GFC_STD_F2008,
-	     gfc_check_image_index, gfc_simplify_image_index, gfc_resolve_image_index,
-	     ca, BT_REAL, dr, REQUIRED, sub, BT_INTEGER, ii, REQUIRED);
+  add_sym_3 ("image_index", GFC_ISYM_IMAGE_INDEX, CLASS_TRANSFORMATIONAL,
+	     ACTUAL_NO, BT_INTEGER, di, GFC_STD_F2008, gfc_check_image_index,
+	     gfc_simplify_image_index, gfc_resolve_image_index, ca, BT_REAL, dr,
+	     REQUIRED, sub, BT_INTEGER, ii, REQUIRED, team_or_team_number,
+	     BT_VOID, di, OPTIONAL);

   add_sym_2 ("image_status", GFC_ISYM_IMAGE_STATUS, CLASS_ELEMENTAL, ACTUAL_NO,
 	     BT_INTEGER, di, GFC_STD_F2018, gfc_check_image_status,
@@ -2848,11 +2848,10 @@ add_functions (void)

   make_generic ("null", GFC_ISYM_NULL, GFC_STD_F95);

-  add_sym_2 ("num_images", GFC_ISYM_NUM_IMAGES, CLASS_TRANSFORMATIONAL,
-	     ACTUAL_NO, BT_INTEGER, di, GFC_STD_F2008,
-	     gfc_check_num_images, gfc_simplify_num_images, NULL,
-	     dist, BT_INTEGER, di, OPTIONAL,
-	     failed, BT_LOGICAL, dl, OPTIONAL);
+  add_sym_1 ("num_images", GFC_ISYM_NUM_IMAGES, CLASS_TRANSFORMATIONAL,
+	     ACTUAL_NO, BT_INTEGER, di, GFC_STD_F2008, gfc_check_num_images,
+	     gfc_simplify_num_images, NULL, team_or_team_number, BT_VOID, di,
+	     OPTIONAL);

   add_sym_3 ("out_of_range", GFC_ISYM_OUT_OF_RANGE, CLASS_ELEMENTAL, ACTUAL_NO,
 	     BT_LOGICAL, dl, GFC_STD_F2018,
diff --git a/gcc/fortran/intrinsic.h b/gcc/fortran/intrinsic.h
index 3a702b32e10..767792ceb23 100644
--- a/gcc/fortran/intrinsic.h
+++ b/gcc/fortran/intrinsic.h
@@ -132,7 +132,7 @@ bool gfc_check_nearest (gfc_expr *, gfc_expr *);
 bool gfc_check_new_line (gfc_expr *);
 bool gfc_check_norm2 (gfc_expr *, gfc_expr *);
 bool gfc_check_null (gfc_expr *);
-bool gfc_check_num_images (gfc_expr *, gfc_expr *);
+bool gfc_check_num_images (gfc_expr *);
 bool gfc_check_out_of_range (gfc_expr *, gfc_expr *, gfc_expr *);
 bool gfc_check_pack (gfc_expr *, gfc_expr *, gfc_expr *);
 bool gfc_check_parity (gfc_expr *, gfc_expr *);
@@ -222,7 +222,7 @@ bool gfc_check_fseek_sub (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *);
 bool gfc_check_ftell_sub (gfc_expr *, gfc_expr *);
 bool gfc_check_getcwd_sub (gfc_expr *, gfc_expr *);
 bool gfc_check_hostnm_sub (gfc_expr *, gfc_expr *);
-bool gfc_check_image_index (gfc_expr *, gfc_expr *);
+bool gfc_check_image_index (gfc_expr *, gfc_expr *, gfc_expr *);
 bool gfc_check_itime_idate (gfc_expr *);
 bool gfc_check_kill_sub (gfc_expr *, gfc_expr *, gfc_expr *);
 bool gfc_check_ltime_gmtime (gfc_expr *, gfc_expr *);
@@ -328,7 +328,7 @@ gfc_expr *gfc_simplify_ibits (gfc_expr *, gfc_expr *, gfc_expr *);
 gfc_expr *gfc_simplify_ibset (gfc_expr *, gfc_expr *);
 gfc_expr *gfc_simplify_ichar (gfc_expr *, gfc_expr *);
 gfc_expr *gfc_simplify_ieor (gfc_expr *, gfc_expr *);
-gfc_expr *gfc_simplify_image_index (gfc_expr *, gfc_expr *);
+gfc_expr *gfc_simplify_image_index (gfc_expr *, gfc_expr *, gfc_expr *);
 gfc_expr *gfc_simplify_image_status (gfc_expr *, gfc_expr *);
 gfc_expr *gfc_simplify_index (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *);
 gfc_expr *gfc_simplify_int (gfc_expr *, gfc_expr *);
@@ -383,7 +383,7 @@ gfc_expr *gfc_simplify_new_line (gfc_expr *);
 gfc_expr *gfc_simplify_nint (gfc_expr *, gfc_expr *);
 gfc_expr *gfc_simplify_norm2 (gfc_expr *, gfc_expr *);
 gfc_expr *gfc_simplify_null (gfc_expr *);
-gfc_expr *gfc_simplify_num_images (gfc_expr *, gfc_expr *);
+gfc_expr *gfc_simplify_num_images (gfc_expr *);
 gfc_expr *gfc_simplify_idnint (gfc_expr *);
 gfc_expr *gfc_simplify_not (gfc_expr *);
 gfc_expr *gfc_simplify_or (gfc_expr *, gfc_expr *);
@@ -531,7 +531,7 @@ void gfc_resolve_iand (gfc_expr *, gfc_expr *, gfc_expr *);
 void gfc_resolve_ibclr (gfc_expr *, gfc_expr *, gfc_expr *);
 void gfc_resolve_ibits (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *);
 void gfc_resolve_ibset (gfc_expr *, gfc_expr *, gfc_expr *);
-void gfc_resolve_image_index (gfc_expr *, gfc_expr *, gfc_expr *);
+void gfc_resolve_image_index (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *);
 void gfc_resolve_image_status (gfc_expr *, gfc_expr *, gfc_expr *);
 void gfc_resolve_index_func (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *,
 			     gfc_expr *);
diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi
index f020b01c08b..90fa5d9449f 100644
--- a/gcc/fortran/intrinsic.texi
+++ b/gcc/fortran/intrinsic.texi
@@ -11427,47 +11427,48 @@ Fortran 95 and later

 @table @asis
 @item @emph{Synopsis}:
-@code{RESULT = NUM_IMAGES(DISTANCE, FAILED)}
+@multitable @columnfractions .80
+@item @code{RESULT = NUM_IMAGES([TEAM])}
+@item @code{RESULT = NUM_IMAGES(TEAM_NUMBER)}
+@end multitable

 @item @emph{Description}:
-Returns the number of images.
+Returns the number of images in the current team or the given team.

 @item @emph{Class}:
 Transformational function

 @item @emph{Arguments}:
 @multitable @columnfractions .15 .70
-@item @var{DISTANCE} @tab (optional, intent(in)) Nonnegative scalar integer
-@item @var{FAILED}   @tab (optional, intent(in)) Scalar logical expression
+@item @var{TEAM} @tab (optional, intent(in)) If present, return the number of
+images in the given team; if absent, return the number of images in the
+current team.
+@item @var{TEAM_NUMBER} @tab (intent(in)) The number as given in the
+@code{FORM TEAM} statement.
 @end multitable

 @item @emph{Return value}:
-Scalar default-kind integer.  If @var{DISTANCE} is not present or has value 0,
-the number of images in the current team is returned. For values smaller or
-equal distance to the initial team, it returns the number of images index
-on the ancestor team that has a distance of @var{DISTANCE} from the invoking
-team. If @var{DISTANCE} is larger than the distance to the initial team, the
-number of images of the initial team is returned. If @var{FAILED} is not present
-the total number of images is returned; if it has the value @code{.TRUE.},
-the number of failed images is returned, otherwise, the number of images that
-do have not the failed status.
+Scalar default-kind integer.  Can be called without any arguments or a team
+type argument or a team_number argument.

 @item @emph{Example}:
 @smallexample
+use, intrinsic :: iso_fortran_env
 INTEGER :: value[*]
 INTEGER :: i
-value = THIS_IMAGE()
-SYNC ALL
-IF (THIS_IMAGE() == 1) THEN
-  DO i = 1, NUM_IMAGES()
-    WRITE(*,'(2(a,i0))') 'value[', i, '] is ', value[i]
-  END DO
-END IF
+type(team_type) :: t
+
+! When running with 4 images
+print *, num_images() ! 4
+
+form team (mod(this_image(), 2), t)
+print *, num_images(t) ! 2
+print *, num_images(-1) ! 4
 @end smallexample

 @item @emph{Standard}:
-Fortran 2008 and later. With @var{DISTANCE} or @var{FAILED} argument,
-Technical Specification (TS) 18508 or later
+Fortran 2008 and later. With @var{TEAM} or @var{TEAM_NUMBER} argument,
+Fortran 2018 and later.

 @item @emph{See also}:
 @ref{THIS_IMAGE}, @*
diff --git a/gcc/fortran/iresolve.cc b/gcc/fortran/iresolve.cc
index c286c2abe14..6930e2c3622 100644
--- a/gcc/fortran/iresolve.cc
+++ b/gcc/fortran/iresolve.cc
@@ -3229,7 +3229,8 @@ gfc_resolve_get_team (gfc_expr *f, gfc_expr *level ATTRIBUTE_UNUSED)

 void
 gfc_resolve_image_index (gfc_expr *f, gfc_expr *array ATTRIBUTE_UNUSED,
-			 gfc_expr *sub ATTRIBUTE_UNUSED)
+			 gfc_expr *sub ATTRIBUTE_UNUSED,
+			 gfc_expr *team_or_team_number ATTRIBUTE_UNUSED)
 {
   static char image_index[] = "__image_index";
   f->ts.type = BT_INTEGER;
diff --git a/gcc/fortran/simplify.cc b/gcc/fortran/simplify.cc
index b94eb435798..208251b5ec5 100644
--- a/gcc/fortran/simplify.cc
+++ b/gcc/fortran/simplify.cc
@@ -6729,7 +6729,7 @@ gfc_simplify_null (gfc_expr *mold)


 gfc_expr *
-gfc_simplify_num_images (gfc_expr *distance ATTRIBUTE_UNUSED, gfc_expr *failed)
+gfc_simplify_num_images (gfc_expr *team_or_team_number ATTRIBUTE_UNUSED)
 {
   gfc_expr *result;

@@ -6742,16 +6742,9 @@ gfc_simplify_num_images (gfc_expr *distance ATTRIBUTE_UNUSED, gfc_expr *failed)
   if (flag_coarray != GFC_FCOARRAY_SINGLE)
     return NULL;

-  if (failed && failed->expr_type != EXPR_CONSTANT)
-    return NULL;
-
   /* FIXME: gfc_current_locus is wrong.  */
   result = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind,
 				  &gfc_current_locus);
-
-  if (failed && failed->value.logical != 0)
-    mpz_set_si (result->value.integer, 0);
-  else
     mpz_set_si (result->value.integer, 1);

   return result;
@@ -8927,7 +8920,8 @@ gfc_simplify_trim (gfc_expr *e)


 gfc_expr *
-gfc_simplify_image_index (gfc_expr *coarray, gfc_expr *sub)
+gfc_simplify_image_index (gfc_expr *coarray, gfc_expr *sub,
+			  gfc_expr *team_or_team_number ATTRIBUTE_UNUSED)
 {
   gfc_expr *result;
   gfc_ref *ref;
diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc
index 01c19956476..f388ba5bc81 100644
--- a/gcc/fortran/trans-intrinsic.cc
+++ b/gcc/fortran/trans-intrinsic.cc
@@ -1184,7 +1184,9 @@ conv_stat_and_team (stmtblock_t *block, gfc_expr *expr, tree *stat, tree *team,
       gfc_se team_se;
       gfc_init_se (&team_se, NULL);
       gfc_conv_expr_reference (&team_se, team_e);
-      *team = team_se.expr;
+      *team
+	= gfc_build_addr_expr (NULL_TREE, gfc_trans_force_lval (&team_se.pre,
+								team_se.expr));
       gfc_add_block_to_block (block, &team_se.pre);
       gfc_add_block_to_block (block, &team_se.post);
     }
@@ -1197,7 +1199,10 @@ conv_stat_and_team (stmtblock_t *block, gfc_expr *expr, tree *stat, tree *team,
       gfc_se team_se;
       gfc_init_se (&team_se, NULL);
       gfc_conv_expr_reference (&team_se, team_e);
-      *team_no = team_se.expr;
+      *team_no = gfc_build_addr_expr (
+	NULL_TREE,
+	gfc_trans_force_lval (&team_se.pre,
+			      fold_convert (integer_type_node, team_se.expr)));
       gfc_add_block_to_block (block, &team_se.pre);
       gfc_add_block_to_block (block, &team_se.post);
     }
@@ -1790,13 +1795,13 @@ conv_caf_sendget (gfc_code *code)
   ++caf_call_cnt;

   tmp = build_call_expr_loc (
-    input_location, gfor_fndecl_caf_transfer_between_remotes, 20, lhs_token,
+    input_location, gfor_fndecl_caf_transfer_between_remotes, 22, lhs_token,
     opt_lhs_desc, opt_lhs_charlen, lhs_image_index, receiver_fn_index_tree,
     lhs_add_data_tree, lhs_add_data_size, rhs_token, opt_rhs_desc,
     opt_rhs_charlen, rhs_image_index, sender_fn_index_tree, rhs_add_data_tree,
     rhs_add_data_size, rhs_size,
     transfer_rank == 0 ? boolean_true_node : boolean_false_node, lhs_stat,
-    lhs_team, lhs_team_no, rhs_stat, rhs_team, rhs_team_no);
+    rhs_stat, lhs_team, lhs_team_no, rhs_team, rhs_team_no);

   gfc_add_expr_to_block (&block, tmp);
   gfc_add_block_to_block (&block, &lhs_se.post);
@@ -2112,8 +2117,8 @@ conv_intrinsic_team_number (gfc_se *se, gfc_expr *expr)
 static void
 trans_image_index (gfc_se * se, gfc_expr *expr)
 {
-  tree num_images, cond, coindex, type, lbound, ubound, desc, subdesc,
-       tmp, invalid_bound;
+  tree num_images, cond, coindex, type, lbound, ubound, desc, subdesc, tmp,
+    invalid_bound, team = null_pointer_node, team_number = null_pointer_node;
   gfc_se argse, subse;
   int rank, corank, codim;

@@ -2137,6 +2142,22 @@ trans_image_index (gfc_se * se, gfc_expr *expr)
   subdesc = build_fold_indirect_ref_loc (input_location,
 			gfc_conv_descriptor_data_get (subse.expr));

+  if (expr->value.function.actual->next->next->expr)
+    {
+      gfc_init_se (&argse, NULL);
+      gfc_conv_expr_descriptor (&argse,
+				expr->value.function.actual->next->next->expr);
+      if (expr->value.function.actual->next->next->expr->ts.type == BT_DERIVED)
+	team = argse.expr;
+      else
+	team_number = gfc_build_addr_expr (
+	  NULL_TREE,
+	  gfc_trans_force_lval (&argse.pre,
+				fold_convert (integer_type_node, argse.expr)));
+      gfc_add_block_to_block (&se->pre, &argse.pre);
+      gfc_add_block_to_block (&se->post, &argse.post);
+    }
+
   /* Fortran 2008 does not require that the values remain in the cobounds,
      thus we need explicitly check this - and return 0 if they are exceeded.  */

@@ -2212,8 +2233,7 @@ trans_image_index (gfc_se * se, gfc_expr *expr)
   else
     {
       tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
-				 integer_zero_node,
-				 build_int_cst (integer_type_node, -1));
+				 team, team_number);
       num_images = fold_convert (type, tmp);
     }

@@ -2232,32 +2252,26 @@ trans_image_index (gfc_se * se, gfc_expr *expr)
 static void
 trans_num_images (gfc_se * se, gfc_expr *expr)
 {
-  tree tmp, distance, failed;
+  tree tmp, team = null_pointer_node, team_number = null_pointer_node;
   gfc_se argse;

   if (expr->value.function.actual->expr)
     {
       gfc_init_se (&argse, NULL);
       gfc_conv_expr_val (&argse, expr->value.function.actual->expr);
+      if (expr->value.function.actual->expr->ts.type == BT_DERIVED)
+	team = argse.expr;
+      else
+	team_number = gfc_build_addr_expr (
+	  NULL_TREE,
+	  gfc_trans_force_lval (&se->pre,
+				fold_convert (integer_type_node, argse.expr)));
       gfc_add_block_to_block (&se->pre, &argse.pre);
       gfc_add_block_to_block (&se->post, &argse.post);
-      distance = fold_convert (integer_type_node, argse.expr);
     }
-  else
-    distance = integer_zero_node;

-  if (expr->value.function.actual->next->expr)
-    {
-      gfc_init_se (&argse, NULL);
-      gfc_conv_expr_val (&argse, expr->value.function.actual->next->expr);
-      gfc_add_block_to_block (&se->pre, &argse.pre);
-      gfc_add_block_to_block (&se->post, &argse.post);
-      failed = fold_convert (integer_type_node, argse.expr);
-    }
-  else
-    failed = build_int_cst (integer_type_node, -1);
   tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
-			     distance, failed);
+			     team, team_number);
   se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
 }

@@ -2687,8 +2701,7 @@ conv_intrinsic_cobound (gfc_se * se, gfc_expr * expr)

 	  cosize = gfc_conv_descriptor_cosize (desc, arg->expr->rank, corank);
 	  tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
-				     2, integer_zero_node,
-				     build_int_cst (integer_type_node, -1));
+				     2, null_pointer_node, null_pointer_node);
 	  tmp = fold_build2_loc (input_location, MINUS_EXPR,
 				 gfc_array_index_type,
 				 fold_convert (gfc_array_index_type, tmp),
@@ -2703,8 +2716,7 @@ conv_intrinsic_cobound (gfc_se * se, gfc_expr * expr)
 	{
 	  /* ubound = lbound + num_images() - 1.  */
 	  tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
-				     2, integer_zero_node,
-				     build_int_cst (integer_type_node, -1));
+				     2, null_pointer_node, null_pointer_node);
 	  tmp = fold_build2_loc (input_location, MINUS_EXPR,
 				 gfc_array_index_type,
 				 fold_convert (gfc_array_index_type, tmp),
diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc
index 1b7dccd3e35..1d6da3663d5 100644
--- a/gcc/fortran/trans-stmt.cc
+++ b/gcc/fortran/trans-stmt.cc
@@ -1337,8 +1337,7 @@ gfc_trans_sync (gfc_code *code, gfc_exec_op type)
 	{
 	  tree cond2;
 	  tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
-				     2, integer_zero_node,
-				     build_int_cst (integer_type_node, -1));
+				     2, null_pointer_node, null_pointer_node);
 	  cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
 				  images2, tmp);
 	  cond2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
diff --git a/gcc/testsuite/gfortran.dg/coarray_49.f90 b/gcc/testsuite/gfortran.dg/coarray_49.f90
index 370e3fd5847..fd8549b32a8 100644
--- a/gcc/testsuite/gfortran.dg/coarray_49.f90
+++ b/gcc/testsuite/gfortran.dg/coarray_49.f90
@@ -5,5 +5,5 @@

 program p
   integer :: x[*]
-  print *, image_index (x, [1.0]) ! { dg-error "shall be INTEGER" }
+  print *, image_index (x, [1.0]) ! { dg-error "must be INTEGER" }
 end
diff --git a/gcc/testsuite/gfortran.dg/coarray_collectives_12.f90 b/gcc/testsuite/gfortran.dg/coarray_collectives_12.f90
index 299ea62b093..2d8a39a9084 100644
--- a/gcc/testsuite/gfortran.dg/coarray_collectives_12.f90
+++ b/gcc/testsuite/gfortran.dg/coarray_collectives_12.f90
@@ -20,6 +20,6 @@ program test
   call co_broadcast(val3, source_image=res,stat=stat3, errmsg=errmesg3)
 end program test

-! { dg-final { scan-tree-dump-times "_gfortran_caf_co_broadcast \\(&desc.., _gfortran_caf_num_images \\(0, -1\\), &stat1, errmesg1, 6\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "_gfortran_caf_co_broadcast \\(&desc.., _gfortran_caf_num_images \\(0B, 0B\\), &stat1, errmesg1, 6\\);" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "_gfortran_caf_co_broadcast \\(&val2, 4, &stat2, errmesg2, 7\\);" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "_gfortran_caf_co_broadcast \\(&desc.., res, &stat3, errmesg3, 8\\);" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/coarray_collectives_16.f90 b/gcc/testsuite/gfortran.dg/coarray_collectives_16.f90
index 8419cf9159d..05a135012d8 100644
--- a/gcc/testsuite/gfortran.dg/coarray_collectives_16.f90
+++ b/gcc/testsuite/gfortran.dg/coarray_collectives_16.f90
@@ -33,6 +33,6 @@ contains
   end function hc
 end program test

-! { dg-final { scan-tree-dump-times "_gfortran_caf_co_reduce \\(&desc.., fr, 4, _gfortran_caf_num_images \\(0, -1\\), &stat1, errmesg1, 0, 6\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "_gfortran_caf_co_reduce \\(&desc.., fr, 4, _gfortran_caf_num_images \\(0B, 0B\\), &stat1, errmesg1, 0, 6\\);" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "_gfortran_caf_co_reduce \\(&val2, gz, 0, 4, &stat2, errmesg2, 0, 7\\);" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "_gfortran_caf_co_reduce \\(&desc.., hc, 1, res, &stat3, errmesg3, 99, 8\\);" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/coarray_lib_this_image_1.f90 b/gcc/testsuite/gfortran.dg/coarray_lib_this_image_1.f90
index a38c2307516..7939a797501 100644
--- a/gcc/testsuite/gfortran.dg/coarray_lib_this_image_1.f90
+++ b/gcc/testsuite/gfortran.dg/coarray_lib_this_image_1.f90
@@ -19,7 +19,7 @@ end
 ! { dg-final { scan-tree-dump-times "bar \\(real\\(kind=4\\)\\\[2\\\] \\* restrict x, void \\* restrict caf_token.., integer\\(kind=\[48\]\\) caf_offset..\\)" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "mylcobound = 5;" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "parm...dim\\\[1\\\].lbound = 5;" 1 "original" } }
-! { dg-final { scan-tree-dump-times "myucobound =\[^\n\r\]* parm...dim\\\[1\\\].lbound \\+ \[^\n\r]*_gfortran_caf_num_images \\(0, -1\\).? \\+ -?\[0-9\]+\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "myucobound =\[^\n\r\]* parm...dim\\\[1\\\].lbound \\+ \[^\n\r]*_gfortran_caf_num_images \\(0B, 0B\\).? \\+ -?\[0-9\]+\\);" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "mylbound = 1;" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "mythis_image = _gfortran_caf_this_image \\(0B\\);" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "bar \\(x, caf_token.., 0\\);" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/coarray_lib_this_image_2.f90 b/gcc/testsuite/gfortran.dg/coarray_lib_this_image_2.f90
index 3b504f5d568..31a7677ed0e 100644
--- a/gcc/testsuite/gfortran.dg/coarray_lib_this_image_2.f90
+++ b/gcc/testsuite/gfortran.dg/coarray_lib_this_image_2.f90
@@ -19,7 +19,7 @@ end
 ! { dg-final { scan-tree-dump-times "bar \\(struct array02_real\\(kind=4\\) & restrict x, void \\* restrict caf_token.., integer\\(kind=\[48\]\\) caf_offset..\\)" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "mylcobound = 5;" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "parm...dim\\\[1\\\].lbound = 5;" 1 "original" } }
-! { dg-final { scan-tree-dump-times "myucobound =\[^\n\r\]* parm...dim\\\[1\\\].lbound \\+ \[^\n\r\]*_gfortran_caf_num_images \\(0, -1\\).? \\+ -?\[0-9\]+\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "myucobound =\[^\n\r\]* parm...dim\\\[1\\\].lbound \\+ \[^\n\r\]*_gfortran_caf_num_images \\(0B, 0B\\).? \\+ -?\[0-9\]+\\);" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "mylbound = 1;" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "mythis_image = _gfortran_caf_this_image \\(0B\\);" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "bar \\(&parm.\[0-9\]+, caf_token.\[0-9\]+, \\(integer\\(kind=\[48\]\\)\\) parm.\[0-9\]+.data - \\(integer\\(kind=\[48\]\\)\\) x\\);" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/coarray_this_image_1.f90 b/gcc/testsuite/gfortran.dg/coarray_this_image_1.f90
index 779b0567357..5a609d8690f 100644
--- a/gcc/testsuite/gfortran.dg/coarray_this_image_1.f90
+++ b/gcc/testsuite/gfortran.dg/coarray_this_image_1.f90
@@ -41,16 +41,12 @@ endif
 associate(me => this_image())
 end associate
 k1 = num_images()
-k2 = num_images(6)
-k3 = num_images(distance=7)
-k4 = num_images(distance=8, failed=.true.)
-k5 = num_images(failed=.false.)
+k2 = num_images(team)
+k3 = num_images(-1)
 end

 ! { dg-final { scan-tree-dump-times "j\[1-4\] = 1;" 4 "original" } }
 ! { dg-final { scan-tree-dump-times "A\\.\[0-9\]+\\\[2\\\] = \\\{1, 1\\\};" 4 "original" } }
-! { dg-final { scan-tree-dump-times "k1 = 1;" 1 "original" } }
-! { dg-final { scan-tree-dump-times "k2 = 1;" 1 "original" } }
-! { dg-final { scan-tree-dump-times "k3 = 1;" 1 "original" } }
-! { dg-final { scan-tree-dump-times "k4 = 0;" 1 "original" } }
-! { dg-final { scan-tree-dump-times "k5 = 1;" 1 "original" } }
+! { dg-final { scan-tree-dump "k1 = 1;" "original" } }
+! { dg-final { scan-tree-dump "k2 = 1;" "original" } }
+! { dg-final { scan-tree-dump "k3 = 1;" "original" } }
diff --git a/gcc/testsuite/gfortran.dg/coarray_this_image_2.f90 b/gcc/testsuite/gfortran.dg/coarray_this_image_2.f90
index d977e21778c..9713e3dcb8a 100644
--- a/gcc/testsuite/gfortran.dg/coarray_this_image_2.f90
+++ b/gcc/testsuite/gfortran.dg/coarray_this_image_2.f90
@@ -42,18 +42,16 @@ if (j4 /= 1) then
 endif
 end associate
 k1 = num_images()
-k2 = num_images(6)
-k3 = num_images(distance=7)
-k4 = num_images(distance=8, failed=.true.)
-k5 = num_images(failed=.false.)
+k2 = num_images(team)
+k3 = num_images(-1)
+k4 = num_images(1)
 end

 ! { dg-final { scan-tree-dump "j1 = _gfortran_caf_this_image \\(0B\\);" "original" } }
 ! { dg-final { scan-tree-dump "j3 = _gfortran_caf_this_image \\(team\\);" "original" } }
 ! { dg-final { scan-tree-dump-times "D\\.\[0-9\]+ = _gfortran_caf_this_image \\(team\\) \\+ -1;" 2 "original" } }
 ! { dg-final { scan-tree-dump-times "D\\.\[0-9\]+ = _gfortran_caf_this_image \\(0B\\) \\+ -1;" 2 "original" } }
-! { dg-final { scan-tree-dump-times "k1 = _gfortran_caf_num_images \\(0, -1\\);" 1 "original" } }
-! { dg-final { scan-tree-dump-times "k2 = _gfortran_caf_num_images \\(6, -1\\);" 1 "original" } }
-! { dg-final { scan-tree-dump-times "k3 = _gfortran_caf_num_images \\(7, -1\\);" 1 "original" } }
-! { dg-final { scan-tree-dump-times "k4 = _gfortran_caf_num_images \\(8, 1\\);" 1 "original" } }
-! { dg-final { scan-tree-dump-times "k5 = _gfortran_caf_num_images \\(0, 0\\);" 1 "original" } }
+! { dg-final { scan-tree-dump "k1 = _gfortran_caf_num_images \\(0B, 0B\\);" "original" } }
+! { dg-final { scan-tree-dump "k2 = _gfortran_caf_num_images \\(team, 0B\\);"  "original" } }
+! { dg-final { scan-tree-dump "k3 = _gfortran_caf_num_images \\(0B, &D\\.\[0-9\]+\\);" "original" } }
+! { dg-final { scan-tree-dump "k4 = _gfortran_caf_num_images \\(0B, &D\\.\[0-9\]+\\);" "original" } }
diff --git a/gcc/testsuite/gfortran.dg/coarray_this_image_3.f90 b/gcc/testsuite/gfortran.dg/coarray_this_image_3.f90
index d3464813f2b..b8433b20538 100644
--- a/gcc/testsuite/gfortran.dg/coarray_this_image_3.f90
+++ b/gcc/testsuite/gfortran.dg/coarray_this_image_3.f90
@@ -22,13 +22,10 @@ j4 = this_image(caf, 1, team) ! ok
 j5 = this_image(caf, 1, team, 'baz') !{ dg-error "Too many arguments in call" }
 j6 = this_image(dim=1, team=team, coarray=caf)

-!k1 = num_images()
-
-!k2 = num_images(6)
-
-!k3 = num_images(distance=7)
-
-!k4 = num_images(distance=8, failed=.true.)
-
-!k5 = num_images(failed=.false.)
+k1 = num_images() ! ok
+k2 = num_images(team) ! ok
+k3 = num_images(team, 2) !{ dg-error "Too many arguments in call to" }
+k4 = num_images(1) ! ok
+k5 = num_images('abc') !{ dg-error "'team/team_number' argument of 'num_images' intrinsic" }
+k6 = num_images(1, team) !{ dg-error "Too many arguments in call to" }
 end
diff --git a/gcc/testsuite/gfortran.dg/num_images_1.f90 b/gcc/testsuite/gfortran.dg/num_images_1.f90
index dac34bafb4f..e03857c04c3 100644
--- a/gcc/testsuite/gfortran.dg/num_images_1.f90
+++ b/gcc/testsuite/gfortran.dg/num_images_1.f90
@@ -5,5 +5,5 @@
 program foo
    implicit none
    integer k5
-   k5 = num_images(failed=.false.) ! { dg-error "argument to NUM_IMAGES" }
+   k5 = num_images(failed=.false.) ! { dg-error "Cannot find keyword named 'failed' in call to 'num_images'" }
 end program foo
diff --git a/libgfortran/caf/libcaf.h b/libgfortran/caf/libcaf.h
index 97924b36556..2db8e390382 100644
--- a/libgfortran/caf/libcaf.h
+++ b/libgfortran/caf/libcaf.h
@@ -92,7 +92,7 @@ void _gfortran_caf_init (int *, char ***);
 void _gfortran_caf_finalize (void);

 int _gfortran_caf_this_image (caf_team_t);
-int _gfortran_caf_num_images (int, int);
+int _gfortran_caf_num_images (caf_team_t, int32_t *);

 void _gfortran_caf_register (size_t, caf_register_t, caf_token_t *,
 			     gfc_descriptor_t *, int *, char *, size_t);
diff --git a/libgfortran/caf/single.c b/libgfortran/caf/single.c
index 2c277f0ead4..a80fd966f44 100644
--- a/libgfortran/caf/single.c
+++ b/libgfortran/caf/single.c
@@ -202,8 +202,8 @@ _gfortran_caf_this_image (caf_team_t team)
 }

 int
-_gfortran_caf_num_images (int distance __attribute__ ((unused)),
-			  int failed __attribute__ ((unused)))
+_gfortran_caf_num_images (caf_team_t team __attribute__ ((unused)),
+			  int32_t *team_number __attribute__ ((unused)))
 {
   return 1;
 }
--
2.49.0

Reply via email to