https://gcc.gnu.org/g:621fe931be1e0220854e4d3c49cf2ce05cf735f7

commit r16-76-g621fe931be1e0220854e4d3c49cf2ce05cf735f7
Author: Andre Vehreschild <ve...@gcc.gnu.org>
Date:   Mon Apr 7 15:12:09 2025 +0200

    Fortran: Update get_team, team_number and image_status to F2018 [PR88154, 
PR88960, PR97210, PR103001]
    
    Add functions get_team() and team_number() to comply with F2018
    standard.
    
    Update image_status() to comply with F2018 standard.
    
            PR fortran/88154
            PR fortran/88960
            PR fortran/97210
            PR fortran/103001
    
    gcc/fortran/ChangeLog:
    
            * check.cc (team_type_check): Check a type for being team_type
            from the iso_fortran_env module.
            (gfc_check_image_status): Use team_type check.
            (gfc_check_get_team): Check for level argument.
            (gfc_check_team_number): Use team_type check.
            * expr.cc (gfc_check_assign): Add treatment for returning
            team_type in caf-single mode.
            * gfortran.texi: Add/Update documentation for get_team and
            team_number API functions.
            * intrinsic.cc (add_functions): Update get_team signature.
            * intrinsic.h (gfc_resolve_get_team): Add prototype.
            * intrinsic.texi: Add/Update documentation for get_team and
            team_number Fortran functions.
            * iresolve.cc (gfc_resolve_get_team): Resolve return type to be
            of type team_type.
            * iso-fortran-env.def: Update STAT_LOCK constants.  They have
            nothing to do with files.  Add level constants for get_team.
            * libgfortran.h: Add level and unlock_stat constants.
            * simplify.cc (gfc_simplify_get_team): Simply to correct return
            type team_type.
            * trans-decl.cc (gfc_build_builtin_function_decls): Update
            get_team and image_status API prototypes to correct signatures.
            * trans-intrinsic.cc (conv_intrinsic_image_status): Translate
            second parameter correctly.
            (conv_intrinsic_team_number): Translate optional single team
            argument correctly.
            (gfc_conv_intrinsic_function): Add translation of get_team.
    
    libgfortran/ChangeLog:
    
            * caf/libcaf.h: Add constants for get_team's level argument and
            update stat values for failed images.
            (_gfortran_caf_team_number): Add prototype.
            (_gfortran_caf_get_team): Same.
            * caf/single.c (_gfortran_caf_team_number): Get the given team's
            team number.
            (_gfortran_caf_get_team): Get the current team or the team given
            by level when the argument is present.
    
    gcc/testsuite/ChangeLog:
    
            * gfortran.dg/coarray/image_status_1.f08: Correct check for
            team_type.
            * gfortran.dg/pr102458.f90: Adapt to multiple errors.
            * gfortran.dg/coarray/get_team_1.f90: New test.
            * gfortran.dg/team_get_1.f90: New test.
            * gfortran.dg/team_number_1.f90: Correct Fortran syntax.

Diff:
---
 gcc/fortran/check.cc                               |  65 +++++++-----
 gcc/fortran/expr.cc                                |   8 +-
 gcc/fortran/gfortran.texi                          |  50 +++++++++
 gcc/fortran/intrinsic.cc                           |   8 +-
 gcc/fortran/intrinsic.h                            |   2 +-
 gcc/fortran/intrinsic.texi                         | 112 +++++++++++++++++++++
 gcc/fortran/iresolve.cc                            |  22 +++-
 gcc/fortran/iso-fortran-env.def                    |  22 ++--
 gcc/fortran/libgfortran.h                          |  10 +-
 gcc/fortran/simplify.cc                            |   6 +-
 gcc/fortran/trans-decl.cc                          |  14 ++-
 gcc/fortran/trans-intrinsic.cc                     |  21 ++--
 gcc/testsuite/gfortran.dg/coarray/get_team_1.f90   |  29 ++++++
 .../gfortran.dg/coarray/image_status_1.f08         |   2 +-
 gcc/testsuite/gfortran.dg/pr102458.f90             |   2 +-
 gcc/testsuite/gfortran.dg/team_get_1.f90           |  27 +++++
 gcc/testsuite/gfortran.dg/team_number_1.f90        |   6 +-
 libgfortran/caf/libcaf.h                           |  13 ++-
 libgfortran/caf/single.c                           |  26 +++++
 19 files changed, 367 insertions(+), 78 deletions(-)

diff --git a/gcc/fortran/check.cc b/gcc/fortran/check.cc
index 00342787a518..a1c3de3e80dd 100644
--- a/gcc/fortran/check.cc
+++ b/gcc/fortran/check.cc
@@ -1809,6 +1809,23 @@ gfc_check_atomic_ref (gfc_expr *value, gfc_expr *atom, 
gfc_expr *stat)
   return gfc_check_atomic (atom, 1, value, 0, stat, 2);
 }
 
+bool
+team_type_check (gfc_expr *e, int n)
+{
+  if (e->ts.type != BT_DERIVED || !e->ts.u.derived
+      || e->ts.u.derived->from_intmod != INTMOD_ISO_FORTRAN_ENV
+      || e->ts.u.derived->intmod_sym_id != ISOFORTRAN_TEAM_TYPE)
+    {
+      gfc_error ("%qs argument of %qs intrinsic at %L shall be of type "
+                "%<team_type%> from the intrinsic module "
+                "%<ISO_FORTRAN_ENV%>",
+                gfc_current_intrinsic_arg[n]->name, gfc_current_intrinsic,
+                &e->where);
+      return false;
+    }
+
+  return true;
+}
 
 bool
 gfc_check_image_status (gfc_expr *image, gfc_expr *team)
@@ -1818,14 +1835,7 @@ gfc_check_image_status (gfc_expr *image, gfc_expr *team)
       || !positive_check (0, image))
     return false;
 
-  if (team)
-    {
-      gfc_error ("%qs argument of %qs intrinsic at %L not yet supported",
-                gfc_current_intrinsic_arg[1]->name, gfc_current_intrinsic,
-                &team->where);
-      return false;
-    }
-  return true;
+  return !team || (scalar_check (team, 0) && team_type_check (team, 0));
 }
 
 
@@ -1905,10 +1915,25 @@ gfc_check_get_team (gfc_expr *level)
 {
   if (level)
     {
-      gfc_error ("%qs argument of %qs intrinsic at %L not yet supported",
-                gfc_current_intrinsic_arg[0]->name, gfc_current_intrinsic,
-                &level->where);
-      return false;
+      int l;
+
+      if (!type_check (level, 0, BT_INTEGER) || !scalar_check (level, 0))
+       return false;
+
+      /* When level is a constant, try to extract it.  If not, the runtime has
+        to check.  */
+      if (gfc_extract_int (level, &l, 0))
+       return true;
+
+      if (l < GFC_CAF_INITIAL_TEAM || l > GFC_CAF_CURRENT_TEAM)
+       {
+         gfc_error ("%qs argument of %qs intrinsic at %L shall specify one of "
+                    "the INITIAL_TEAM, PARENT_TEAM or CURRENT_TEAM constants "
+                    "from the intrinsic module ISO_FORTRAN_ENV",
+                    gfc_current_intrinsic_arg[0]->name, gfc_current_intrinsic,
+                    &level->where);
+         return false;
+       }
     }
   return true;
 }
@@ -6635,21 +6660,7 @@ gfc_check_team_number (gfc_expr *team)
       return false;
     }
 
-  if (team)
-    {
-      if (team->ts.type != BT_DERIVED
-         || team->ts.u.derived->from_intmod != INTMOD_ISO_FORTRAN_ENV
-         || team->ts.u.derived->intmod_sym_id != ISOFORTRAN_TEAM_TYPE)
-        {
-          gfc_error ("TEAM argument at %L to the intrinsic TEAM_NUMBER "
-                     "shall be of type TEAM_TYPE", &team->where);
-          return false;
-        }
-    }
-  else
-    return true;
-
-  return true;
+  return !team || (scalar_check (team, 0) && team_type_check (team, 0));
 }
 
 
diff --git a/gcc/fortran/expr.cc b/gcc/fortran/expr.cc
index 0753667e061d..07e9bac37a1c 100644
--- a/gcc/fortran/expr.cc
+++ b/gcc/fortran/expr.cc
@@ -3836,7 +3836,13 @@ gfc_check_assign (gfc_expr *lvalue, gfc_expr *rvalue, 
int conform,
       if (has_pointer && (ref == NULL || ref->next == NULL)
          && lvalue->symtree->n.sym->attr.data)
         return true;
-      else
+      /* Prevent the following error message for caf-single mode, because there
+        are no teams in single mode and the simplify returns a null then.  */
+      else if (!(flag_coarray == GFC_FCOARRAY_SINGLE
+                && rvalue->ts.type == BT_DERIVED
+                && rvalue->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV
+                && rvalue->ts.u.derived->intmod_sym_id
+                     == ISOFORTRAN_TEAM_TYPE))
        {
          gfc_error ("NULL appears on right-hand side in assignment at %L",
                     &rvalue->where);
diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi
index ff385671d214..a80963159919 100644
--- a/gcc/fortran/gfortran.texi
+++ b/gcc/fortran/gfortran.texi
@@ -4234,6 +4234,8 @@ future implementation of teams.  It is about to change 
without further notice.
 * _gfortran_caf_change_team:: Team activation function
 * _gfortran_caf_end_team:: Team termination function
 * _gfortran_caf_sync_team:: Synchronize all images of a given team
+* _gfortran_caf_get_team:: Get the opaque handle of the specified team
+* _gfortran_caf_team_number:: Get the unique id of the given team
 @end menu
 
 
@@ -5786,6 +5788,54 @@ an error message; may be NULL.
 @end table
 
 
+
+@node _gfortran_caf_get_team
+@subsection @code{_gfortran_caf_get_team} --- Get the opaque handle of the 
specified team
+@cindex Coarray, _gfortran_caf_get_team
+
+@table @asis
+@item @emph{Synopsis}:
+@code{caf_team_t _gfortran_caf_get_team (int32_t *level)}
+
+@item @emph{Description}:
+Get the current team, when @var{level} is null, or the team specified by
+@var{level} set to @code{INITIAL_TEAM}, @code{PARENT_TEAM} or
+@code{CURRENT_TEAM} from the @code{ISO_FORTRAN_ENV} intrinsic module.  When
+being on the @code{INITIAL_TEAM} and requesting its @code{PARENT_TEAM}, then
+the initial team is returned.
+
+@item @emph{Arguments}:
+@multitable @columnfractions .15 .70
+@item @var{level} @tab intent(in)  If set to one of the levels specified in
+the @code{ISO_FORTRAN_ENV} module, the function returns the handle of the given
+team.  Values different from the allowed ones lead to a runtime error.
+@end multitable
+@end table
+
+
+
+@node _gfortran_caf_team_number
+@subsection @code{_gfortran_caf_team_number} --- Get the unique id of the 
given team
+@cindex Coarray, _gfortran_caf_team_number
+
+@table @asis
+@item @emph{Synopsis}:
+@code{int _gfortran_caf_team_number (caf_team_t team)}
+
+@item @emph{Description}:
+The team id given when forming the team @ref{_gfortran_caf_form_team} of the
+team specified by @var{team}, if given, or of the current team, if @var{team}
+is absent.  It is a runtime error to specify a non-existing team.
+The team has to be formed, i.e., it is not necessary that it is changed
+into to get the team number.  The initial team has the team number @code{-1}.
+
+@item @emph{Arguments}:
+@multitable @columnfractions .15 .70
+@item @var{team} @tab intent(in)  The team for which the team id is desired.
+@end multitable
+@end table
+
+
 @c Intrinsic Procedures
 @c ---------------------------------------------------------------------
 
diff --git a/gcc/fortran/intrinsic.cc b/gcc/fortran/intrinsic.cc
index 91f16c7f35f9..7d459d0d84a2 100644
--- a/gcc/fortran/intrinsic.cc
+++ b/gcc/fortran/intrinsic.cc
@@ -2112,10 +2112,10 @@ add_functions (void)
 
   make_generic ("getpid", GFC_ISYM_GETPID, GFC_STD_GNU);
 
-  add_sym_1 ("get_team", GFC_ISYM_GET_TEAM, CLASS_TRANSFORMATIONAL,
-            ACTUAL_NO, BT_INTEGER, di, GFC_STD_F2018,
-            gfc_check_get_team, NULL, gfc_resolve_get_team,
-            level, BT_INTEGER, di, OPTIONAL);
+  add_sym_1 ("get_team", GFC_ISYM_GET_TEAM, CLASS_TRANSFORMATIONAL, ACTUAL_NO,
+            BT_DERIVED, di, GFC_STD_F2018, gfc_check_get_team,
+            gfc_simplify_get_team, gfc_resolve_get_team, level, BT_INTEGER, di,
+            OPTIONAL);
 
   add_sym_0 ("getuid", GFC_ISYM_GETUID, CLASS_IMPURE, ACTUAL_NO, BT_INTEGER,
             di, GFC_STD_GNU, NULL, NULL, gfc_resolve_getuid);
diff --git a/gcc/fortran/intrinsic.h b/gcc/fortran/intrinsic.h
index 70e14c4098b1..c177fcbc3df8 100644
--- a/gcc/fortran/intrinsic.h
+++ b/gcc/fortran/intrinsic.h
@@ -479,6 +479,7 @@ void gfc_resolve_bessel_n2 (gfc_expr *, gfc_expr *, 
gfc_expr *, gfc_expr *a);
 void gfc_resolve_btest (gfc_expr *, gfc_expr *, gfc_expr *);
 void gfc_resolve_c_loc (gfc_expr *, gfc_expr *);
 void gfc_resolve_c_funloc (gfc_expr *, gfc_expr *);
+void gfc_resolve_get_team (gfc_expr *, gfc_expr *);
 void gfc_resolve_ceiling (gfc_expr *, gfc_expr *, gfc_expr *);
 void gfc_resolve_char (gfc_expr *, gfc_expr *, gfc_expr *);
 void gfc_resolve_chdir (gfc_expr *, gfc_expr *);
@@ -523,7 +524,6 @@ void gfc_resolve_gamma (gfc_expr *, gfc_expr *);
 void gfc_resolve_getcwd (gfc_expr *, gfc_expr *);
 void gfc_resolve_getgid (gfc_expr *);
 void gfc_resolve_getpid (gfc_expr *);
-void gfc_resolve_get_team (gfc_expr *, gfc_expr *);
 void gfc_resolve_getuid (gfc_expr *);
 void gfc_resolve_hostnm (gfc_expr *, gfc_expr *);
 void gfc_resolve_hypot (gfc_expr *, gfc_expr *, gfc_expr *);
diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi
index ad89064cb595..cc01a9d8ded5 100644
--- a/gcc/fortran/intrinsic.texi
+++ b/gcc/fortran/intrinsic.texi
@@ -170,6 +170,7 @@ Some basic guidelines for editing this document:
 * @code{GETGID}:        GETGID,    Group ID function
 * @code{GETLOG}:        GETLOG,    Get login name
 * @code{GETPID}:        GETPID,    Process ID function
+* @code{GET_TEAM}:      GET_TEAM,  Get the handle of a team
 * @code{GETUID}:        GETUID,    User ID function
 * @code{GMTIME}:        GMTIME,    Convert time to GMT info
 * @code{HOSTNM}:        HOSTNM,    Get system host name
@@ -311,6 +312,7 @@ Some basic guidelines for editing this document:
 * @code{TAN}:           TAN,       Tangent function
 * @code{TAND}:          TAND,      Tangent function, degrees
 * @code{TANH}:          TANH,      Hyperbolic tangent function
+* @code{TEAM_NUMBER}:   TEAM_NUMBER, Retrieve team id of given team
 * @code{THIS_IMAGE}:    THIS_IMAGE, Cosubscript index of this image
 * @code{TIME}:          TIME,      Time function
 * @code{TIME8}:         TIME8,     Time function (64-bit)
@@ -7336,6 +7338,59 @@ GNU extension
 
 
 
+@node GET_TEAM
+@section @code{GET_TEAM} --- Get the handle of a team
+@fnindex GET_TEAM
+@cindex coarray, @code{GET_TEAM}
+@cindex images, get a handle to a team
+
+@table @asis
+@item @emph{Synopsis}:
+@code{RESULT = GET_TEAM([LEVEL])}
+
+@item @emph{Description}:
+Returns the handle of the current team, if @var{LEVEL} is not given.  Or the
+team specified by @var{LEVEL}, where @var{LEVEL} is one of the constants
+@code{INITIAL_TEAM}, @code{PARENT_TEAM} or @code{CURRENT_TEAM} from the
+intrinsic module @code{ISO_FORTRAN_ENV}.  Calling the function with
+@code{PARENT_TEAM} while being on the initial team, returns a handle to the
+initial team.  This ensures that always a valid team is returned, given that
+team handles can neither be checked for validity nor compared with each other
+or null.
+
+@item @emph{Class}:
+Transformational function
+
+@item @emph{Return value}:
+An opaque handle of @code{TEAM_TYPE} from the intrinsic module
+@code{ISO_FORTRAN_ENV}.
+
+@item @emph{Example}:
+@smallexample
+program info
+  use, intrinsic :: iso_fortran_env
+  type(team_type) :: init, curr, par, nt
+
+  init = get_team()
+  curr = get_team(current_team) ! init equals curr here
+  form team(1, nt)
+  change team(nt)
+    curr = get_team() ! or get_team(current_team)
+    par = get_team(parent_team) ! par equals init here
+  end team
+end program info
+@end smallexample
+
+@item @emph{Standard}:
+Fortran 2018 or later
+
+@item @emph{See also}:
+@ref{THIS_IMAGE}, @*
+@ref{ISO_FORTRAN_ENV}
+@end table
+
+
+
 @node GETUID
 @section @code{GETUID} --- User ID function
 @fnindex GETUID
@@ -14467,6 +14522,54 @@ Fortran 77 and later, for a complex argument Fortran 
2008 or later
 
 
 
+@node TEAM_NUMBER
+@section @code{TEAM_NUMBER} --- Retrieve team id of given team
+@fnindex TEAM_NUMBER
+@cindex coarray, @code{TEAM_NUMBER}
+@cindex teams, index of given team
+
+@table @asis
+@item @emph{Synopsis}:
+@item @code{RESULT = TEAM_NUMBER([TEAM])}
+
+@item @emph{Description}:
+Returns the team id for the given @var{TEAM} as assigned by @code{FORM TEAM}.
+If @var{TEAM} is absent, returns the team number of the current team.
+
+@item @emph{Class}:
+Transformational function
+
+@item @emph{Arguments}:
+@multitable @columnfractions .15 .70
+@item @var{TEAM} @tab (optional, intent(in)) The handle of the team for which
+the number, aka id, is desired.
+@end multitable
+
+@item @emph{Return value}:
+Default integer.  The id as given in a call @code{FORM TEAM}. Applying
+@code{TEAM_NUMBER} to the initial team will result in @code{-1} to be returned.
+Returns the id of the current team, if @var{TEAM} is null.
+
+@item @emph{Example}:
+@smallexample
+use, intrinsic :: iso_fortran_env
+type(team_type) :: t
+
+print *, team_number() ! -1
+form team (99, t)
+print *, team_number(t) ! 99
+@end smallexample
+
+@item @emph{Standard}:
+Fortran 2018 and later.
+
+@item @emph{See also}:
+@ref{GET_TEAM}, @*
+@ref{TEAM_NUMBER}
+@end table
+
+
+
 @node THIS_IMAGE
 @section @code{THIS_IMAGE} --- Function that returns the cosubscript index of 
this image
 @fnindex THIS_IMAGE
@@ -15354,12 +15457,18 @@ parameters of the @code{CHARACTER} type. (Fortran 
2008 or later.)
 @item @code{CHARACTER_STORAGE_SIZE}:
 Size in bits of the character storage unit.
 
+@item @code{CURRENT_TEAM}:
+The argument to @ref{GET_TEAM} to retrieve a handle of the current team.
+
 @item @code{ERROR_UNIT}:
 Identifies the preconnected unit used for error reporting.
 
 @item @code{FILE_STORAGE_SIZE}:
 Size in bits of the file-storage unit.
 
+@item @code{INTIAL_TEAM}:
+Argument to @ref{GET_TEAM} to retrieve a handle of the initial team.
+
 @item @code{INPUT_UNIT}:
 Identifies the preconnected unit identified by the asterisk
 (@code{*}) in @code{READ} statement.
@@ -15397,6 +15506,9 @@ parameters of the @code{LOGICAL} type. (Fortran 2008 or 
later.)
 Identifies the preconnected unit identified by the asterisk
 (@code{*}) in @code{WRITE} statement.
 
+@item @code{PARENT_TEAM}:
+Argument to @ref{GET_TEAM} to retrieve a handle to the parent team.
+
 @item @code{REAL32}, @code{REAL64}, @code{REAL128}:
 Kind type parameters to specify a REAL type with a storage
 size of 32, 64, and 128 bits. It is negative if a target platform
diff --git a/gcc/fortran/iresolve.cc b/gcc/fortran/iresolve.cc
index 858ffb1daebf..567bf528b2a4 100644
--- a/gcc/fortran/iresolve.cc
+++ b/gcc/fortran/iresolve.cc
@@ -3209,11 +3209,21 @@ gfc_resolve_get_team (gfc_expr *f, gfc_expr *level 
ATTRIBUTE_UNUSED)
 {
   static char get_team[] = "_gfortran_caf_get_team";
   f->rank = 0;
-  f->ts.type = BT_INTEGER;
-  f->ts.kind = gfc_default_integer_kind;
+  f->ts.type = BT_DERIVED;
+  gfc_find_symbol ("team_type", gfc_current_ns, 1, &f->ts.u.derived);
+  if (!f->ts.u.derived
+      || f->ts.u.derived->from_intmod != INTMOD_ISO_FORTRAN_ENV)
+    {
+      gfc_error (
+       "GET_TEAM at %L needs USE of the intrinsic module ISO_FORTRAN_ENV "
+       "to define its result type TEAM_TYPE",
+       &f->where);
+      f->ts.type = BT_UNKNOWN;
+    }
   f->value.function.name = get_team;
-}
 
+  /* No requirements to resolve for level argument now.  */
+}
 
 /* Resolve image_index (...).  */
 
@@ -3248,15 +3258,17 @@ gfc_resolve_stopped_images (gfc_expr *f, gfc_expr *team 
ATTRIBUTE_UNUSED,
 /* Resolve team_number (team).  */
 
 void
-gfc_resolve_team_number (gfc_expr *f, gfc_expr *team ATTRIBUTE_UNUSED)
+gfc_resolve_team_number (gfc_expr *f, gfc_expr *team)
 {
   static char team_number[] = "_gfortran_caf_team_number";
   f->rank = 0;
   f->ts.type = BT_INTEGER;
   f->ts.kind = gfc_default_integer_kind;
   f->value.function.name = team_number;
-}
 
+  if (team)
+    gfc_resolve_expr (team);
+}
 
 void
 gfc_resolve_this_image (gfc_expr *f, gfc_expr *array, gfc_expr *dim,
diff --git a/gcc/fortran/iso-fortran-env.def b/gcc/fortran/iso-fortran-env.def
index 970f09fddd3a..250a730e1bf5 100644
--- a/gcc/fortran/iso-fortran-env.def
+++ b/gcc/fortran/iso-fortran-env.def
@@ -83,17 +83,23 @@ NAMED_INTCST (ISOFORTRANENV_REAL64, "real64", \
               gfc_get_real_kind_from_width_isofortranenv (64), GFC_STD_F2008)
 NAMED_INTCST (ISOFORTRANENV_REAL128, "real128", \
               gfc_get_real_kind_from_width_isofortranenv (128), GFC_STD_F2008)
-NAMED_INTCST (ISOFORTRANENV_FILE_STAT_LOCKED, "stat_locked", \
+NAMED_INTCST (ISOFORTRANENV_STAT_LOCKED, "stat_locked", \
               GFC_STAT_LOCKED, GFC_STD_F2008)
-NAMED_INTCST (ISOFORTRANENV_FILE_STAT_LOCKED_OTHER_IMAGE, \
+NAMED_INTCST (ISOFORTRANENV_STAT_LOCKED_OTHER_IMAGE, \
               "stat_locked_other_image", \
              GFC_STAT_LOCKED_OTHER_IMAGE, GFC_STD_F2008)
-NAMED_INTCST (ISOFORTRANENV_FILE_STAT_STOPPED_IMAGE, "stat_stopped_image", \
-              GFC_STAT_STOPPED_IMAGE, GFC_STD_F2008)
-NAMED_INTCST (ISOFORTRANENV_FILE_STAT_FAILED_IMAGE, "stat_failed_image", \
-              GFC_STAT_FAILED_IMAGE, GFC_STD_F2018)
-NAMED_INTCST (ISOFORTRANENV_FILE_STAT_UNLOCKED, "stat_unlocked", \
-              GFC_STAT_UNLOCKED, GFC_STD_F2008)
+NAMED_INTCST (ISOFORTRANENV_STAT_STOPPED_IMAGE, "stat_stopped_image", \
+             GFC_STAT_STOPPED_IMAGE, GFC_STD_F2008)
+NAMED_INTCST (ISOFORTRANENV_STAT_FAILED_IMAGE, "stat_failed_image", \
+             GFC_STAT_FAILED_IMAGE, GFC_STD_F2018)
+NAMED_INTCST (ISOFORTRANENV_STAT_UNLOCKED, "stat_unlocked", \
+             GFC_STAT_UNLOCKED, GFC_STD_F2008)
+NAMED_INTCST (ISOFORTRANENV_INITIAL_TEAM, "initial_team", \
+             GFC_CAF_INITIAL_TEAM, GFC_STD_F2018)
+NAMED_INTCST (ISOFORTRANENV_PARENT_TEAM, "parent_team", \
+             GFC_CAF_PARENT_TEAM, GFC_STD_F2018)
+NAMED_INTCST (ISOFORTRANENV_CURRENT_TEAM, "current_team", \
+             GFC_CAF_CURRENT_TEAM, GFC_STD_F2018)
 
 
 /* The arguments to NAMED_KINDARRAY are:
diff --git a/gcc/fortran/libgfortran.h b/gcc/fortran/libgfortran.h
index 956536538eef..9de5afb6c83e 100644
--- a/gcc/fortran/libgfortran.h
+++ b/gcc/fortran/libgfortran.h
@@ -154,10 +154,18 @@ typedef enum
   GFC_STAT_LOCKED,
   GFC_STAT_LOCKED_OTHER_IMAGE,
   GFC_STAT_STOPPED_IMAGE = 6000, /* See LIBERROR_INQUIRE_INTERNAL_UNIT above. 
*/
-  GFC_STAT_FAILED_IMAGE  = 6001
+  GFC_STAT_FAILED_IMAGE  = 6001,
+  GFC_STAT_UNLOCKED_FAILED_IMAGE = 6002
 }
 libgfortran_stat_codes;
 
+typedef enum
+{
+  GFC_CAF_INITIAL_TEAM = 0,
+  GFC_CAF_PARENT_TEAM,
+  GFC_CAF_CURRENT_TEAM
+} libgfortran_team_levels;
+
 typedef enum
 {
   GFC_CAF_ATOMIC_ADD = 1,
diff --git a/gcc/fortran/simplify.cc b/gcc/fortran/simplify.cc
index 92ab17b2b963..6e773d1a3a14 100644
--- a/gcc/fortran/simplify.cc
+++ b/gcc/fortran/simplify.cc
@@ -3133,8 +3133,10 @@ gfc_simplify_get_team (gfc_expr *level ATTRIBUTE_UNUSED)
   if (flag_coarray == GFC_FCOARRAY_SINGLE)
     {
       gfc_expr *result;
-      result = gfc_get_array_expr (BT_INTEGER, gfc_default_integer_kind, 
&gfc_current_locus);
-      result->rank = 0;
+      result = gfc_get_null_expr (&gfc_current_locus);
+      result->ts.type = BT_DERIVED;
+      gfc_find_symbol ("team_type", gfc_current_ns, 1, &result->ts.u.derived);
+
       return result;
     }
 
diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc
index ae996a05f07e..a2905b666c7a 100644
--- a/gcc/fortran/trans-decl.cc
+++ b/gcc/fortran/trans-decl.cc
@@ -4215,10 +4215,9 @@ gfc_build_builtin_function_decls (void)
        get_identifier (PREFIX ("caf_end_team")), ". w w w ", void_type_node, 3,
        pint_type, pchar_type_node, size_type_node);
 
-      gfor_fndecl_caf_get_team
-       = gfc_build_library_function_decl (
-           get_identifier (PREFIX("caf_get_team")),
-           void_type_node, 1, integer_type_node);
+      gfor_fndecl_caf_get_team = gfc_build_library_function_decl_with_spec (
+       get_identifier (PREFIX ("caf_get_team")), ". r ", pvoid_type_node, 1,
+       pint_type);
 
       gfor_fndecl_caf_sync_team = gfc_build_library_function_decl_with_spec (
        get_identifier (PREFIX ("caf_sync_team")), ". r w w w ", void_type_node,
@@ -4229,10 +4228,9 @@ gfc_build_builtin_function_decls (void)
            get_identifier (PREFIX("caf_team_number")), ". r ",
            integer_type_node, 1, integer_type_node);
 
-      gfor_fndecl_caf_image_status
-       = gfc_build_library_function_decl_with_spec (
-           get_identifier (PREFIX("caf_image_status")), ". . r ",
-           integer_type_node, 2, integer_type_node, ppvoid_type_node);
+      gfor_fndecl_caf_image_status = gfc_build_library_function_decl_with_spec 
(
+       get_identifier (PREFIX ("caf_image_status")), ". r r ",
+       integer_type_node, 2, integer_type_node, ppvoid_type_node);
 
       gfor_fndecl_caf_stopped_images
        = gfc_build_library_function_decl_with_spec (
diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc
index cab3ebc00086..2e314609b16e 100644
--- a/gcc/fortran/trans-intrinsic.cc
+++ b/gcc/fortran/trans-intrinsic.cc
@@ -2072,7 +2072,8 @@ conv_intrinsic_image_status (gfc_se *se, gfc_expr *expr)
     }
   else if (flag_coarray == GFC_FCOARRAY_LIB)
     tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_image_status, 2,
-                              args[0], build_int_cst (integer_type_node, -1));
+                              args[0],
+                              num_args < 2 ? null_pointer_node : args[1]);
   else
     gcc_unreachable ();
 
@@ -2092,18 +2093,7 @@ conv_intrinsic_team_number (gfc_se *se, gfc_expr *expr)
 
   if (flag_coarray ==
       GFC_FCOARRAY_SINGLE && expr->value.function.actual->expr)
-    {
-      tree arg;
-
-      arg = gfc_evaluate_now (args[0], &se->pre);
-      tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
-                            fold_convert (integer_type_node, arg),
-                            integer_one_node);
-      tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
-                            tmp, integer_zero_node,
-                            build_int_cst (integer_type_node,
-                                           GFC_STAT_STOPPED_IMAGE));
-    }
+    tmp = gfc_evaluate_now (args[0], &se->pre);
   else if (flag_coarray == GFC_FCOARRAY_SINGLE)
     {
       // the value -1 represents that no team has been created yet
@@ -2111,10 +2101,10 @@ conv_intrinsic_team_number (gfc_se *se, gfc_expr *expr)
     }
   else if (flag_coarray == GFC_FCOARRAY_LIB && 
expr->value.function.actual->expr)
     tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_team_number, 1,
-                              args[0], build_int_cst (integer_type_node, -1));
+                              args[0]);
   else if (flag_coarray == GFC_FCOARRAY_LIB)
     tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_team_number, 1,
-               integer_zero_node, build_int_cst (integer_type_node, -1));
+                              null_pointer_node);
   else
     gcc_unreachable ();
 
@@ -11475,6 +11465,7 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * 
expr)
     case GFC_ISYM_GETGID:
     case GFC_ISYM_GETPID:
     case GFC_ISYM_GETUID:
+    case GFC_ISYM_GET_TEAM:
     case GFC_ISYM_HOSTNM:
     case GFC_ISYM_IERRNO:
     case GFC_ISYM_IRAND:
diff --git a/gcc/testsuite/gfortran.dg/coarray/get_team_1.f90 
b/gcc/testsuite/gfortran.dg/coarray/get_team_1.f90
new file mode 100644
index 000000000000..f37d1c7f3795
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/coarray/get_team_1.f90
@@ -0,0 +1,29 @@
+!{ dg-do compile }
+
+! PR 97210
+! Tests get_team syntax
+
+  use iso_fortran_env
+  implicit none
+  type(team_type) :: team, ret
+  integer :: level
+
+  ret = get_team()
+  ret = get_team('abc') !{ dg-error "must be INTEGER" }
+  ret = get_team(level, 'abc') !{ dg-error "Too many arguments" }
+  ret = get_team([1,2]) !{ dg-error "must be a scalar" }
+  ret = get_team(team) !{ dg-error "must be INTEGER" }
+  
+  ret = get_team(INITIAL_TEAM)
+  ret = get_team(CURRENT_TEAM)
+  ret = get_team(PARENT_TEAM)
+  ret = get_team(INITIAL_TEAM, CURRENT_TEAM) !{ dg-error "Too many arguments" }
+
+  level = INITIAL_TEAM
+  ret = get_team(level)
+  ret = get_team(99) !{ dg-error "specify one of the INITIAL_TEAM, 
PARENT_TEAM" }
+  level = 99
+  ret = get_team(level)
+  level = get_team() !{ dg-error "Cannot convert TYPE\\(team_type\\)" }
+end
+
diff --git a/gcc/testsuite/gfortran.dg/coarray/image_status_1.f08 
b/gcc/testsuite/gfortran.dg/coarray/image_status_1.f08
index 098a2bb958e1..b7ec5a6a9c97 100644
--- a/gcc/testsuite/gfortran.dg/coarray/image_status_1.f08
+++ b/gcc/testsuite/gfortran.dg/coarray/image_status_1.f08
@@ -18,7 +18,7 @@ program test_image_status_1
   isv = image_status(k2) ! Ok
   isv = image_status(k4) ! Ok
   isv = image_status(k8) ! Ok
-  isv = image_status(1, team=1) ! { dg-error "'team' argument of 
'image_status' intrinsic at \\(1\\) not yet supported" }
+  isv = image_status(1, team=1) ! { dg-error "shall be of type 'team_type'" }
   isv = image_status()          ! { dg-error "Missing actual argument 'image' 
in call to 'image_status' at \\(1\\)" }
   isv = image_status(team=1)    ! { dg-error "Missing actual argument 'image' 
in call to 'image_status' at \\(1\\)" }
 
diff --git a/gcc/testsuite/gfortran.dg/pr102458.f90 
b/gcc/testsuite/gfortran.dg/pr102458.f90
index 555e4978fdb1..7c13084acf48 100644
--- a/gcc/testsuite/gfortran.dg/pr102458.f90
+++ b/gcc/testsuite/gfortran.dg/pr102458.f90
@@ -9,7 +9,7 @@ end
 
 program p
   block
-    integer :: a(get_team()) = 1 ! { dg-error "Automatic array" }
+    integer :: a(get_team()) = 1 ! { dg-error "Automatic array | 
ISO_FORTRAN_ENV | must be of INTEGER" }
     print *, a
   end block
 end
diff --git a/gcc/testsuite/gfortran.dg/team_get_1.f90 
b/gcc/testsuite/gfortran.dg/team_get_1.f90
new file mode 100644
index 000000000000..fe00ce823712
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/team_get_1.f90
@@ -0,0 +1,27 @@
+!{ dg-do compile }
+!{ dg-additional-options "-fcoarray=lib -fdump-tree-original" }
+
+! PR 87939
+! Tests get_team
+
+  use iso_fortran_env
+  implicit none
+  type(team_type) :: team, ret
+  integer :: new_team, level
+
+  new_team = mod(this_image(),2)+1
+
+  form team (new_team,team)
+
+  ret = get_team()
+  ret = get_team(INITIAL_TEAM)
+  ret = get_team(PARENT_TEAM)
+  ret = get_team(CURRENT_TEAM)
+  level = INITIAL_TEAM
+  ret = get_team(level)
+  
+end
+
+! { dg-final { scan-tree-dump "_gfortran_caf_get_team \\(0B\\)" "original" } }
+! { dg-final { scan-tree-dump-times "_gfortran_caf_get_team 
\\(&C\.\[0-9\]+\\)" 3 "original" } }
+! { dg-final { scan-tree-dump "_gfortran_caf_get_team \\(&level\\)" "original" 
} }
diff --git a/gcc/testsuite/gfortran.dg/team_number_1.f90 
b/gcc/testsuite/gfortran.dg/team_number_1.f90
index e44e17b644b2..f0ee7d1768da 100644
--- a/gcc/testsuite/gfortran.dg/team_number_1.f90
+++ b/gcc/testsuite/gfortran.dg/team_number_1.f90
@@ -1,13 +1,13 @@
 ! { dg-do run }
 ! { dg-options "-fcoarray=single" }
 !
-! Tests if team_number intrinsic fucntion works
+! Tests if team_number intrinsic function works
 !
   use iso_fortran_env, only : team_type
   implicit none
-  type(team_type) team
+  type(team_type) :: team
   integer, parameter :: standard_initial_value=-1
-  integer new_team
+  integer :: new_team
 
   if (team_number()/=standard_initial_value) STOP 1
 
diff --git a/libgfortran/caf/libcaf.h b/libgfortran/caf/libcaf.h
index a674a1929e53..e1853b77caf9 100644
--- a/libgfortran/caf/libcaf.h
+++ b/libgfortran/caf/libcaf.h
@@ -39,10 +39,19 @@ typedef enum
   CAF_STAT_LOCKED,
   CAF_STAT_LOCKED_OTHER_IMAGE,
   CAF_STAT_STOPPED_IMAGE = 6000,
-  CAF_STAT_FAILED_IMAGE  = 6001
+  CAF_STAT_FAILED_IMAGE  = 6001,
+  CAF_STAT_UNLOCKED_FAILED_IMAGE = 6002
 }
 caf_stat_codes_t;
 
+/* Definitions of the Fortran 2018 standard; need to kept in sync with
+   ISO_FORTRAN_ENV, cf. gcc/fortran/libgfortran.h.  */
+typedef enum
+{
+  CAF_INITIAL_TEAM = 0,
+  CAF_PARENT_TEAM,
+  CAF_CURRENT_TEAM
+} caf_team_level_t;
 
 /* Describes what type of array we are registerring.  Keep in sync with
    gcc/fortran/trans.h.  */
@@ -178,5 +187,7 @@ void _gfortran_caf_form_team (int, caf_team_t *, int *, int 
*, char *, size_t);
 void _gfortran_caf_change_team (caf_team_t, int *, char *, size_t);
 void _gfortran_caf_end_team (int *, char *, size_t);
 void _gfortran_caf_sync_team (caf_team_t, int *, char *, size_t);
+int _gfortran_caf_team_number (caf_team_t);
+caf_team_t _gfortran_caf_get_team (int32_t *);
 
 #endif  /* LIBCAF_H  */
diff --git a/libgfortran/caf/single.c b/libgfortran/caf/single.c
index a705699bfa93..4b04e24321d2 100644
--- a/libgfortran/caf/single.c
+++ b/libgfortran/caf/single.c
@@ -1084,3 +1084,29 @@ _gfortran_caf_sync_team (caf_team_t team __attribute__ 
((unused)), int *stat,
   if (stat)
     *stat = 0;
 }
+
+int
+_gfortran_caf_team_number (caf_team_t team)
+{
+  return ((caf_single_team_t) team)->team_no;
+}
+
+caf_team_t
+_gfortran_caf_get_team (int32_t *level)
+{
+  if (!level)
+    return caf_team_stack;
+
+  switch ((caf_team_level_t) *level)
+    {
+    case CAF_INITIAL_TEAM:
+      return caf_initial_team;
+    case CAF_PARENT_TEAM:
+      return caf_team_stack->parent ? caf_team_stack->parent : caf_team_stack;
+    case CAF_CURRENT_TEAM:
+      return caf_team_stack;
+    default:
+      caf_runtime_error ("Illegal value for GET_TEAM");
+    }
+  return NULL; /* To prevent any warnings.  */
+}

Reply via email to