Hi All,

The moment I saw the DIN4 proposal for "Generic processing of assumed rank
objects", I thought that this was a highly intuitive and implementable
proposal. I implemented a test version in June and had some correspondence
with Reinhold Bader about it shortly before he passed away.

Malcolm Cohen wrote J3/24-136r1 in response to this and I have posted a
comment in PR116733 addressing the the extent to which the attached patch
addresses his remarks.

Before this patch goes through the approval process, we have to consider
how experimental F202y features can be carried forward. I was badly bitten
by failing to synchronise the array descriptor reform branch to the extent
that I gave up on it and adopted the simplified reform that is now in
place. Given the likely timescale before the full adoption of the F202y
standard, this is a considerable risk for experimental features, given the
variability of active maintainers:

What I propose is the following:
(i) For audit purposes, I have opened PR116732, which should be blocked by
PRs for each experimental F202y feature;
(ii) These PRs should represent a complete audit trail for each feature; and
(iii) All such experimental features should be enabled on mainline by
--std=f202y, which is equivalent to -std=f2023+f202y.

The attached patch enables pointer assignment and associate, both with rank
remapping, plus the reshape intrinsics. which was not part of the DIN4
proposal.

The ChangeLog entries do a pretty complete job of describing the patch.

Regtests correctly. OK for mainline?

Paul
diff --git a/gcc/fortran/array.cc b/gcc/fortran/array.cc
index 1fa61ebfe2a..3f724852db9 100644
--- a/gcc/fortran/array.cc
+++ b/gcc/fortran/array.cc
@@ -866,7 +866,7 @@ gfc_set_array_spec (gfc_symbol *sym, gfc_array_spec *as, locus *error_loc)
 {
   int i;
   symbol_attribute *attr;
-  
+
   if (as == NULL)
     return true;
 
@@ -875,7 +875,7 @@ gfc_set_array_spec (gfc_symbol *sym, gfc_array_spec *as, locus *error_loc)
   attr = &sym->attr;
   if (gfc_submodule_procedure(attr))
     return true;
-  
+
   if (as->rank
       && !gfc_add_dimension (&sym->attr, sym->name, error_loc))
     return false;
@@ -2454,7 +2454,7 @@ gfc_ref_dimen_size (gfc_array_ref *ar, int dimen, mpz_t *result, mpz_t *end)
 	mpz_set_ui (stride, 1);
       else
 	{
-	  stride_expr = gfc_copy_expr(ar->stride[dimen]); 
+	  stride_expr = gfc_copy_expr(ar->stride[dimen]);
 
 	  if (!gfc_simplify_expr (stride_expr, 1)
 	     || stride_expr->expr_type != EXPR_CONSTANT
diff --git a/gcc/fortran/expr.cc b/gcc/fortran/expr.cc
index 81c641e2322..9e5b141518c 100644
--- a/gcc/fortran/expr.cc
+++ b/gcc/fortran/expr.cc
@@ -4357,9 +4357,18 @@ gfc_check_pointer_assign (gfc_expr *lvalue, gfc_expr *rvalue,
 	  return false;
 	}
 
+      /* An assumed rank target is an experimental F202y feature.  */
+      if (rvalue->rank == -1 && !(gfc_option.allow_std & GFC_STD_F202Y))
+	{
+	  gfc_error ("The assumed rank target at %L is an experimental F202y "
+		     "feature. Use option -std=f202y to enable",
+		     &rvalue->where);
+	  return false;
+	}
+
       /* The target must be either rank one or it must be simply contiguous
 	 and F2008 must be allowed.  */
-      if (rvalue->rank != 1)
+      if (rvalue->rank != 1 && rvalue->rank != -1)
 	{
 	  if (!gfc_is_simply_contiguous (rvalue, true, false))
 	    {
@@ -4372,6 +4381,21 @@ gfc_check_pointer_assign (gfc_expr *lvalue, gfc_expr *rvalue,
 	    return false;
 	}
     }
+  else if (rvalue->rank == -1)
+    {
+      gfc_error ("The data-target at %L ia an assumed rank object and so the "
+		 "data-pointer-object %s must have a bounds remapping list "
+		 "(list of lbound:ubound for each dimension)",
+		  &rvalue->where, lvalue->symtree->name);
+      return false;
+    }
+
+  if (rvalue->rank == -1 && !gfc_is_simply_contiguous (rvalue, true, false))
+    {
+      gfc_error ("The assumed rank data-target at %L must be contiguous",
+		 &rvalue->where);
+      return false;
+    }
 
   /* Now punt if we are dealing with a NULLIFY(X) or X = NULL(X).  */
   if (rvalue->expr_type == EXPR_NULL)
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 37c28691f41..57890472d04 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -3020,6 +3020,8 @@ typedef struct gfc_association_list
 
   gfc_expr *target;
 
+  gfc_array_ref *ar;
+
   /* Used for inferring the derived type of an associate name, whose selector
      is a sibling derived type function that has not yet been parsed.  */
   gfc_symbol *derived_types;
diff --git a/gcc/fortran/interface.cc b/gcc/fortran/interface.cc
index b592fe4f6c7..dbcbed8bf30 100644
--- a/gcc/fortran/interface.cc
+++ b/gcc/fortran/interface.cc
@@ -3337,6 +3337,16 @@ gfc_compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
 	  goto match;
 	}
 
+      if (warn_surprising
+	  && a->expr->expr_type == EXPR_VARIABLE
+	  && a->expr->symtree->n.sym->as
+	  && a->expr->symtree->n.sym->as->type == AS_ASSUMED_SIZE
+	  && f->sym->as
+	  && f->sym->as->type == AS_ASSUMED_RANK)
+	gfc_warning (0, "The assumed-size dummy %qs is being passed at %L to "
+		     "an assumed-rank dummy %qs", a->expr->symtree->name,
+		     &a->expr->where, f->sym->name);
+
       if (a->expr->expr_type == EXPR_NULL
 	  && a->expr->ts.type == BT_UNKNOWN
 	  && f->sym->ts.type == BT_CHARACTER
diff --git a/gcc/fortran/intrinsic.cc b/gcc/fortran/intrinsic.cc
index 0a6be215825..d95f35145b5 100644
--- a/gcc/fortran/intrinsic.cc
+++ b/gcc/fortran/intrinsic.cc
@@ -293,11 +293,15 @@ do_ts29113_check (gfc_intrinsic_sym *specific, gfc_actual_arglist *arg)
 		     &a->expr->where, gfc_current_intrinsic);
 	  ok = false;
 	}
-      else if (a->expr->rank == -1 && !specific->inquiry)
+      else if (a->expr->rank == -1
+	       && !(specific->inquiry
+		    || (specific->id == GFC_ISYM_RESHAPE
+			&& (gfc_option.allow_std & GFC_STD_F202Y))))
 	{
 	  gfc_error ("Assumed-rank argument at %L is only permitted as actual "
-		     "argument to intrinsic inquiry functions",
-		     &a->expr->where);
+		     "argument to intrinsic inquiry functions or to reshape. "
+		     "The latter is an experimental F202y feature. Use "
+		     "-std=f202y to enable", &a->expr->where);
 	  ok = false;
 	}
       else if (a->expr->rank == -1 && arg != a)
@@ -307,6 +311,13 @@ do_ts29113_check (gfc_intrinsic_sym *specific, gfc_actual_arglist *arg)
 		     &a->expr->where, gfc_current_intrinsic);
 	  ok = false;
 	}
+      else if (a->expr->rank == -1 && specific->id == GFC_ISYM_RESHAPE
+	       && !gfc_is_simply_contiguous (a->expr, true, false))
+	{
+	  gfc_error ("Assumed rank argument to the reshape intrinsic at %L "
+		     "must be contiguous", &a->expr->where);
+	  ok = false;
+	}
     }
 
   return ok;
diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi
index 1225a0f967d..de638a34df3 100644
--- a/gcc/fortran/invoke.texi
+++ b/gcc/fortran/invoke.texi
@@ -1,5 +1,5 @@
 @c Copyright (C) 2004-2024 Free Software Foundation, Inc.
-@c This is part of the GNU Fortran manual.   
+@c This is part of the GNU Fortran manual.
 @c For copying conditions, see the file gfortran.texi.
 
 @ignore
@@ -139,7 +139,7 @@ by type.  Explanations are in the following sections.
 -H -P
 -U@var{macro} -cpp -dD -dI -dM -dN -dU -fworking-directory
 -imultilib @var{dir}
--iprefix @var{file} -iquote -isysroot @var{dir} -isystem @var{dir} -nocpp 
+-iprefix @var{file} -iquote -isysroot @var{dir} -isystem @var{dir} -nocpp
 -nostdinc
 -undef
 }
@@ -311,7 +311,7 @@ JIAND, etc...). For a complete list of intrinsics see the full documentation.
 Obsolete flag.  The purpose of this option was to
 enable legacy math intrinsics such as COTAN and degree-valued trigonometric
 functions (e.g. TAND, ATAND, etc...) for compatability with older code. This
-option is no longer operable. The trigonometric functions are now either 
+option is no longer operable. The trigonometric functions are now either
 part of Fortran 2023 or GNU extensions.
 
 @opindex @code{fdec-static}
@@ -340,7 +340,7 @@ following the final comma.
 @cindex symbol names
 @cindex character set
 @item -fdollar-ok
-Allow @samp{$} as a valid non-first character in a symbol name. Symbols 
+Allow @samp{$} as a valid non-first character in a symbol name. Symbols
 that start with @samp{$} are rejected since it is unclear which rules to
 apply to implicit typing as different vendors implement different rules.
 Using @samp{$} in @code{IMPLICIT} statements is also rejected.
@@ -605,7 +605,10 @@ beyond the relevant language standard, and warnings are given for the
 Fortran 77 features that are permitted but obsolescent in later
 standards. The deprecated option @samp{-std=f2008ts} acts as an alias for
 @samp{-std=f2018}. It is only present for backwards compatibility with
-earlier gfortran versions and should not be used any more.
+earlier gfortran versions and should not be used any more. @samp{-std=f202y}
+acts as an alias for @samp{-std=f2023} and enables proposed features for
+testing Fortran 202y. As the Fortran 202y standard develops, implementation
+might change or the experimental new features might be removed.
 
 @opindex @code{ftest-forall-temp}
 @item -ftest-forall-temp
@@ -717,7 +720,7 @@ Like @option{-dD}, but emit only the macro names, not their expansions.
 @cindex debugging, preprocessor
 @item -dU
 Like @option{dD} except that only macros that are expanded, or whose
-definedness is tested in preprocessor directives, are output; the 
+definedness is tested in preprocessor directives, are output; the
 output is delayed until the use or test of the macro; and @code{'#undef'}
 directives are also output for macros tested but undefined at the time.
 
@@ -907,7 +910,7 @@ with a @option{-D} option.
 Errors are diagnostic messages that report that the GNU Fortran compiler
 cannot compile the relevant piece of source code.  The compiler will
 continue to process the program in an attempt to report further errors
-to aid in debugging, but will not produce any compiled output.  
+to aid in debugging, but will not produce any compiled output.
 
 Warnings are diagnostic messages that report constructions which
 are not inherently erroneous but which are risky or suggest there is
@@ -1026,7 +1029,7 @@ avoid such temporaries.
 @opindex @code{Wc-binding-type}
 @cindex warning, C binding type
 @item -Wc-binding-type
-Warn if the a variable might not be C interoperable.  In particular, warn if 
+Warn if the a variable might not be C interoperable.  In particular, warn if
 the variable has been declared using an intrinsic type with default kind
 instead of using a kind parameter defined for C interoperability in the
 intrinsic @code{ISO_C_Binding} module.  This option is implied by
@@ -1049,7 +1052,7 @@ error.
 @cindex warnings, conversion
 @cindex conversion
 @item -Wconversion
-Warn about implicit conversions that are likely to change the value of 
+Warn about implicit conversions that are likely to change the value of
 the expression after conversion. Implied by @option{-Wall}.
 
 @opindex @code{Wconversion-extra}
@@ -1190,7 +1193,7 @@ the desired intrinsic/procedure.  This option is implied by @option{-Wall}.
 @cindex warnings, use statements
 @cindex intrinsic
 @item -Wuse-without-only
-Warn if a @code{USE} statement has no @code{ONLY} qualifier and 
+Warn if a @code{USE} statement has no @code{ONLY} qualifier and
 thus implicitly imports all public entities of the used module.
 
 @opindex @code{Wunused-dummy-argument}
@@ -1436,8 +1439,8 @@ they are not in the default location expected by the compiler.
 @cindex options, linking
 @cindex linking, static
 
-These options come into play when the compiler links object files into an 
-executable output file. They are meaningless if the compiler is not doing 
+These options come into play when the compiler links object files into an
+executable output file. They are meaningless if the compiler is not doing
 a link step.
 
 @table @gcctabopt
@@ -1609,7 +1612,7 @@ referenced in it. Does not affect common blocks. (Some Fortran compilers
 provide this option under the name @option{-static} or @option{-save}.)
 The default, which is @option{-fautomatic}, uses the stack for local
 variables smaller than the value given by @option{-fmax-stack-var-size}.
-Use the option @option{-frecursive} to use no static memory. 
+Use the option @option{-frecursive} to use no static memory.
 
 Local variables or arrays having an explicit @code{SAVE} attribute are
 silently ignored unless the @option{-pedantic} option is added.
@@ -1880,7 +1883,7 @@ Deprecated alias for @option{-fcheck=array-temps}.
 
 @opindex @code{fmax-array-constructor}
 @item -fmax-array-constructor=@var{n}
-This option can be used to increase the upper limit permitted in 
+This option can be used to increase the upper limit permitted in
 array constructors.  The code below requires this option to expand
 the array at compile time.
 
diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt
index f5fbe47121c..e3f0f29bbc7 100644
--- a/gcc/fortran/lang.opt
+++ b/gcc/fortran/lang.opt
@@ -7,12 +7,12 @@
 ; the terms of the GNU General Public License as published by the Free
 ; Software Foundation; either version 3, or (at your option) any later
 ; version.
-; 
+;
 ; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
 ; WARRANTY; without even the implied warranty of MERCHANTABILITY or
 ; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 ; for more details.
-; 
+;
 ; You should have received a copy of the GNU General Public License
 ; along with GCC; see the file COPYING3.  If not see
 ; <http://www.gnu.org/licenses/>.
@@ -903,6 +903,10 @@ std=f2023
 Fortran
 Conform to the ISO Fortran 2023 standard.
 
+std=f202y
+Fortran
+Enable experimental Fortran 202y features.
+
 std=f95
 Fortran
 Conform to the ISO Fortran 95 standard.
diff --git a/gcc/fortran/libgfortran.h b/gcc/fortran/libgfortran.h
index 895629d6f80..5cec975dc7d 100644
--- a/gcc/fortran/libgfortran.h
+++ b/gcc/fortran/libgfortran.h
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3.  If not see
    Nevertheless, some features available in F2018 are prohibited in F2023.
    Please remember to keep those definitions in sync with
    gfortran.texi.  */
+#define GFC_STD_F202Y		(1<<14)	/* Enable proposed F202y features.  */
 #define GFC_STD_F2023_DEL	(1<<13)	/* Prohibited in F2023.  */
 #define GFC_STD_F2023		(1<<12)	/* New in F2023.  */
 #define GFC_STD_F2018_DEL	(1<<11)	/* Deleted in F2018.  */
diff --git a/gcc/fortran/match.cc b/gcc/fortran/match.cc
index 0cd78a57a2f..81610b93345 100644
--- a/gcc/fortran/match.cc
+++ b/gcc/fortran/match.cc
@@ -1920,7 +1920,31 @@ gfc_match_associate (void)
       gfc_association_list* a;
 
       /* Match the next association.  */
-      if (gfc_match (" %n =>", newAssoc->name) != MATCH_YES)
+      if (gfc_match (" %n ", newAssoc->name) != MATCH_YES)
+	{
+	  /* "Expected associate name at %C" would be better.
+	      Change associate_3.f03 to match.  */
+	  gfc_error ("Expected associate name at %C");
+	  goto assocListError;
+	}
+
+      /* Required for an assumed rank target.  */
+      if (gfc_peek_char () == '(')
+	{
+	  newAssoc->ar = gfc_get_array_ref ();
+	  if (gfc_match_array_ref (newAssoc->ar, NULL, 0, 0) != MATCH_YES)
+	    {
+	      gfc_error ("Bad bounds remapping list at %C");
+	      goto assocListError;
+	    }
+	}
+
+      if (newAssoc->ar && !(gfc_option.allow_std & GFC_STD_F202Y))
+	gfc_error_now ("The bounds remapping list at %C is an experimental "
+		       "F202y feature. Use std=f202y to enable");
+
+      /* Match the next association.  */
+      if (gfc_match (" =>", newAssoc->name) != MATCH_YES)
 	{
 	  gfc_error ("Expected association at %C");
 	  goto assocListError;
@@ -1964,6 +1988,35 @@ gfc_match_associate (void)
 	  goto assocListError;
 	}
 
+      if (newAssoc->target->expr_type == EXPR_VARIABLE
+	  && newAssoc->target->symtree->n.sym->as
+	  && newAssoc->target->symtree->n.sym->as->type == AS_ASSUMED_RANK)
+	{
+	  bool bounds_remapping_list = true;
+	  if (!newAssoc->ar)
+	    bounds_remapping_list = false;
+	  else
+	    for (int dim = 0; dim < newAssoc->ar->dimen; dim++)
+	      if (!newAssoc->ar->start[dim] || !newAssoc->ar->end[dim]
+		  || newAssoc->ar->stride[dim] != NULL)
+		bounds_remapping_list = false;
+
+	  if (!bounds_remapping_list)
+	    {
+	      gfc_error ("The associate name %s with an assumed rank "
+			 "target at %L must have a bounds remapping list "
+			 "(list of lbound:ubound for each dimension)",
+			 newAssoc->name, &newAssoc->target->where);
+	      goto assocListError;
+	    }
+
+	  if (!newAssoc->target->symtree->n.sym->attr.contiguous)
+	    {
+	      gfc_error ("The assumed rank target at %C must be contiguous");
+	      goto assocListError;
+	    }
+	}
+
       /* The `variable' field is left blank for now; because the target is not
 	 yet resolved, we can't use gfc_has_vector_subscript to determine it
 	 for now.  This is set during resolution.  */
diff --git a/gcc/fortran/options.cc b/gcc/fortran/options.cc
index d8c5c8e62fc..ce33b3806d3 100644
--- a/gcc/fortran/options.cc
+++ b/gcc/fortran/options.cc
@@ -156,7 +156,7 @@ gfc_init_options (unsigned int decoded_options_count,
   gfc_option.flag_preprocessed = 0;
   gfc_option.flag_d_lines = -1;
   set_init_local_zero (0);
-  
+
   gfc_option.fpe = 0;
   /* All except GFC_FPE_INEXACT.  */
   gfc_option.fpe_summary = GFC_FPE_INVALID | GFC_FPE_DENORMAL
@@ -383,7 +383,7 @@ gfc_post_options (const char **pfilename)
 	{
 	  gfc_current_form = FORM_FREE;
 	  main_input_filename = filename;
-	  gfc_warning_now (0, "Reading file %qs as free form", 
+	  gfc_warning_now (0, "Reading file %qs as free form",
 			   (filename[0] == '\0') ? "<stdin>" : filename);
 	}
     }
@@ -472,7 +472,7 @@ gfc_post_options (const char **pfilename)
   /* Implement -fno-automatic as -fmax-stack-var-size=0.  */
   if (!flag_automatic)
     flag_max_stack_var_size = 0;
-  
+
   /* If the user did not specify an inline matmul limit, inline up to the BLAS
      limit or up to 30 if no external BLAS is specified.  */
 
@@ -624,7 +624,7 @@ gfc_handle_runtime_check_option (const char *arg)
 				 GFC_RTCHECK_RECURSION, GFC_RTCHECK_DO,
 				 GFC_RTCHECK_POINTER, GFC_RTCHECK_MEM,
 				 GFC_RTCHECK_BITS, 0 };
- 
+
   while (*arg)
     {
       while (*arg == ',')
@@ -685,7 +685,7 @@ gfc_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
     case OPT_fcheck_array_temporaries:
       SET_BITFLAG (gfc_option.rtcheck, value, GFC_RTCHECK_ARRAY_TEMPS);
       break;
-      
+
     case OPT_fd_lines_as_code:
       gfc_option.flag_d_lines = 1;
       break;
@@ -822,6 +822,15 @@ gfc_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
       warn_tabs = 1;
       break;
 
+    case OPT_std_f202y:
+      gfc_option.allow_std = GFC_STD_OPT_F23 | GFC_STD_F202Y;
+      gfc_option.warn_std = GFC_STD_F95_OBS | GFC_STD_F2008_OBS
+	| GFC_STD_F2018_OBS;
+      gfc_option.max_identifier_length = 63;
+      warn_ampersand = 1;
+      warn_tabs = 1;
+      break;
+
     case OPT_std_gnu:
       set_default_std_flags ();
       break;
@@ -857,10 +866,10 @@ gfc_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
 
     }
 
-  Fortran_handle_option_auto (&global_options, &global_options_set, 
-                              scode, arg, value, 
-                              gfc_option_lang_mask (), kind,
-                              loc, handlers, global_dc);
+  Fortran_handle_option_auto (&global_options, &global_options_set,
+			      scode, arg, value,
+			      gfc_option_lang_mask (), kind,
+			      loc, handlers, global_dc);
   return result;
 }
 
@@ -907,7 +916,7 @@ gfc_get_option_string (void)
 
   result = XCNEWVEC (char, len);
 
-  pos = 0; 
+  pos = 0;
   for (j = 1; j < save_decoded_options_count; j++)
     {
       switch (save_decoded_options[j].opt_index)
diff --git a/gcc/fortran/parse.cc b/gcc/fortran/parse.cc
index c506e18233e..9eaa8f30f92 100644
--- a/gcc/fortran/parse.cc
+++ b/gcc/fortran/parse.cc
@@ -5315,6 +5315,16 @@ parse_associate (void)
 	  else
 	    sym->attr.class_ok = 1;
 	}
+      else if (rank == -1 && a->ar)
+	{
+	  sym->as = gfc_get_array_spec ();
+	  sym->as->rank = a->ar->dimen;
+	  sym->as->corank = a->ar->codimen;
+	  sym->as->type = AS_DEFERRED;
+	  sym->attr.dimension = 1;
+	  sym->attr.codimension = sym->as->corank ? 1 : 0;
+	  sym->attr.pointer = 1;
+	}
       else if ((!sym->as && (rank != 0 || corank != 0))
 	       || (sym->as
 		   && (sym->as->rank != rank || sym->as->corank != corank)))
diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc
index ebe449e7119..512042f56b4 100644
--- a/gcc/fortran/resolve.cc
+++ b/gcc/fortran/resolve.cc
@@ -5807,7 +5807,8 @@ gfc_expression_rank (gfc_expr *e)
 	  break;
 	}
     }
-  if (last_arr_ref && last_arr_ref->u.ar.as)
+  if (last_arr_ref && last_arr_ref->u.ar.as
+      && last_arr_ref->u.ar.as->rank != -1)
     {
       for (i = last_arr_ref->u.ar.as->rank;
 	   i < last_arr_ref->u.ar.as->rank + last_arr_ref->u.ar.as->corank; ++i)
@@ -5956,7 +5957,8 @@ resolve_variable (gfc_expr *e)
     {
       if (!actual_arg
 	  && !(cs_base && cs_base->current
-	       && cs_base->current->op == EXEC_SELECT_RANK))
+	       && (cs_base->current->op == EXEC_SELECT_RANK
+		   || sym->attr.target)))
 	{
 	  gfc_error ("Assumed-rank variable %s at %L may only be used as "
 		     "actual argument", sym->name, &e->where);
diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index 8c35926436d..e7cd44620af 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -4843,9 +4843,12 @@ done:
 		    se.descriptor_only = 1;
 		    gfc_conv_expr (&se, arg);
 		    /* This is a bare variable, so there is no preliminary
-		       or cleanup code.  */
-		    gcc_assert (se.pre.head == NULL_TREE
-				&& se.post.head == NULL_TREE);
+		       or cleanup code unless -std=f202y and bounds checking
+		       is on.  */
+		    if (!((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
+			  && (gfc_option.allow_std & GFC_STD_F202Y)))
+		      gcc_assert (se.pre.head == NULL_TREE
+				  && se.post.head == NULL_TREE);
 		    rank = gfc_conv_descriptor_rank (se.expr);
 		    tmp = fold_build2_loc (input_location, MINUS_EXPR,
 					   gfc_array_index_type,
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 07e28a9f7a8..aa0ee1b0164 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -3242,6 +3242,31 @@ gfc_conv_variable (gfc_se * se, gfc_expr * expr)
 	se->expr = gfc_conv_descriptor_data_get (se->expr);
     }
 
+  /* F202Y: Runtime warning that an assumed rank object is associated
+     with an assumed size object.  */
+  if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
+      && (gfc_option.allow_std & GFC_STD_F202Y)
+      && expr->rank == -1 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se->expr)))
+    {
+      tree dim, lower, upper, cond;
+      char *msg;
+
+      dim = fold_convert (signed_char_type_node,
+			  gfc_conv_descriptor_rank (se->expr));
+      dim = fold_build2_loc (input_location, MINUS_EXPR, signed_char_type_node,
+			     dim, build_int_cst (signed_char_type_node, 1));
+      lower = gfc_conv_descriptor_lbound_get (se->expr, dim);
+      upper = gfc_conv_descriptor_ubound_get (se->expr, dim);
+
+      msg = xasprintf ("Assumed rank object %s is associated with an "
+		       "assumed size object", sym->name);
+      cond = fold_build2_loc (input_location, LT_EXPR,
+			      logical_type_node, upper, lower);
+      gfc_trans_runtime_check (false, true, cond, &se->pre,
+			       &gfc_current_locus, msg);
+      free (msg);
+    }
+
   /* Some expressions leak through that haven't been fixed up.  */
   if (IS_INFERRED_TYPE (expr) && expr->ref)
     gfc_fixup_inferred_type_refs (expr);
@@ -10759,20 +10784,26 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2)
 
 	      /* Copy offset but adjust it such that it would correspond
 		 to a lbound of zero.  */
-	      offs = gfc_conv_descriptor_offset_get (rse.expr);
-	      for (dim = 0; dim < expr2->rank; ++dim)
+	      if (expr2->rank == -1)
+		gfc_conv_descriptor_offset_set (&block, desc,
+						gfc_index_zero_node);
+	      else
 		{
-		  stride = gfc_conv_descriptor_stride_get (rse.expr,
-							   gfc_rank_cst[dim]);
-		  lbound = gfc_conv_descriptor_lbound_get (rse.expr,
-							   gfc_rank_cst[dim]);
-		  tmp = fold_build2_loc (input_location, MULT_EXPR,
-					 gfc_array_index_type, stride, lbound);
-		  offs = fold_build2_loc (input_location, PLUS_EXPR,
-					  gfc_array_index_type, offs, tmp);
+		  offs = gfc_conv_descriptor_offset_get (rse.expr);
+		  for (dim = 0; dim < expr2->rank; ++dim)
+		    {
+		      stride = gfc_conv_descriptor_stride_get (rse.expr,
+							gfc_rank_cst[dim]);
+		      lbound = gfc_conv_descriptor_lbound_get (rse.expr,
+							gfc_rank_cst[dim]);
+		      tmp = fold_build2_loc (input_location, MULT_EXPR,
+					     gfc_array_index_type, stride,
+					     lbound);
+		      offs = fold_build2_loc (input_location, PLUS_EXPR,
+					      gfc_array_index_type, offs, tmp);
+		    }
+		  gfc_conv_descriptor_offset_set (&block, desc, offs);
 		}
-	      gfc_conv_descriptor_offset_set (&block, desc, offs);
-
 	      /* Set the bounds as declared for the LHS and calculate strides as
 		 well as another offset update accordingly.  */
 	      stride = gfc_conv_descriptor_stride_get (rse.expr,
@@ -10784,6 +10815,13 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2)
 
 		  gcc_assert (remap->u.ar.start[dim] && remap->u.ar.end[dim]);
 
+		  if (remap->u.ar.start[dim]->expr_type != EXPR_CONSTANT
+		      || remap->u.ar.start[dim]->expr_type != EXPR_VARIABLE)
+		    gfc_resolve_expr (remap->u.ar.start[dim]);
+		  if (remap->u.ar.end[dim]->expr_type != EXPR_CONSTANT
+		      || remap->u.ar.end[dim]->expr_type != EXPR_VARIABLE)
+		    gfc_resolve_expr (remap->u.ar.end[dim]);
+
 		  /* Convert declared bounds.  */
 		  gfc_init_se (&lower_se, NULL);
 		  gfc_init_se (&upper_se, NULL);
@@ -10859,7 +10897,8 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2)
 
       /* If rank remapping was done, check with -fcheck=bounds that
 	 the target is at least as large as the pointer.  */
-      if (rank_remap && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
+      if (rank_remap && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
+	  && expr2->rank != -1)
 	{
 	  tree lsize, rsize;
 	  tree fault;
diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc
index 86c54970475..450c11c06d7 100644
--- a/gcc/fortran/trans-stmt.cc
+++ b/gcc/fortran/trans-stmt.cc
@@ -1910,6 +1910,20 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
       gfc_add_init_cleanup (block, gfc_finish_block (&se.pre), tmp);
     }
   /* Now all the other kinds of associate variable.  */
+  else if (e->rank == -1 && sym->attr.pointer && sym->assoc->ar)
+    {
+      gfc_expr *expr1 = gfc_lval_expr_from_sym (sym);
+      gfc_free_ref_list (expr1->ref);
+      expr1->ref = gfc_get_ref();
+      expr1->ref->type = REF_ARRAY;
+      expr1->ref->u.ar = *sym->assoc->ar;
+      expr1->ref->u.ar.type = AR_SECTION;
+      gfc_expr *expr2 = gfc_copy_expr (e);
+      tmp = gfc_trans_pointer_assignment (expr1, expr2);
+      gfc_add_init_cleanup (block, tmp, NULL);
+      gfc_free_expr (expr1);
+      gfc_free_expr (expr2);
+    }
   else if ((sym->attr.dimension || sym->attr.codimension) && !class_target
 	   && (sym->as->type == AS_DEFERRED || sym->assoc->variable))
     {
diff --git a/gcc/testsuite/gfortran.dg/associate_3.f03 b/gcc/testsuite/gfortran.dg/associate_3.f03
index dfd5a99500e..7f690f3a75b 100644
--- a/gcc/testsuite/gfortran.dg/associate_3.f03
+++ b/gcc/testsuite/gfortran.dg/associate_3.f03
@@ -9,15 +9,15 @@ PROGRAM main
 
   ASSOCIATE ! { dg-error "Expected association list" }
 
-  ASSOCIATE () ! { dg-error "Expected association" }
+  ASSOCIATE () ! { dg-error "Expected associate name" }
 
   ASSOCIATE (a => 1) 5 ! { dg-error "Junk after ASSOCIATE" }
 
   ASSOCIATE (x =>) ! { dg-error "Invalid association target" }
 
-  ASSOCIATE (=> 5) ! { dg-error "Expected association" }
+  ASSOCIATE (=> 5) ! { dg-error "Expected associate name" }
 
-  ASSOCIATE (x => 5, ) ! { dg-error "Expected association" }
+  ASSOCIATE (x => 5, ) ! { dg-error "Expected associate name" }
 
   myname: ASSOCIATE (a => 1)
   END ASSOCIATE ! { dg-error "Expected block name of 'myname'" }
diff --git a/gcc/testsuite/gfortran.dg/f202y/f202y.exp b/gcc/testsuite/gfortran.dg/f202y/f202y.exp
new file mode 100644
index 00000000000..737a78937a7
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/f202y/f202y.exp
@@ -0,0 +1,57 @@
+# Copyright (C) 2005-2024 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Load support procs.
+load_lib gfortran-dg.exp
+
+# Initialize `dg'.
+dg-init
+
+global gfortran_test_path
+global gfortran_aux_module_flags
+set gfortran_test_path $srcdir/$subdir
+set gfortran_aux_module_flags "-Werror -std=f2023"
+proc dg-compile-aux-modules { args } {
+    global gfortran_test_path
+    global gfortran_aux_module_flags
+    if { [llength $args] != 2 } {
+	error "dg-compile-aux-modules: needs one argument"
+	return
+    }
+
+    set level [info level]
+    if { [info procs dg-save-unknown] != [list] } {
+	rename dg-save-unknown dg-save-unknown-level-$level
+    }
+
+    dg-test $gfortran_test_path/[lindex $args 1] "" $gfortran_aux_module_flags
+    # cleanup-modules is intentionally not invoked here.
+
+    if { [info procs dg-save-unknown-level-$level] != [list] } {
+	rename dg-save-unknown-level-$level dg-save-unknown
+    }
+}
+
+# Main loop.
+gfortran-dg-runtest [lsort \
+       [find $srcdir/$subdir *.\[fF\]{,90,95,03,08} ] ] "" "-Werror"
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/gfortran.dg/f202y/generic_assumed_rank_1.f90 b/gcc/testsuite/gfortran.dg/f202y/generic_assumed_rank_1.f90
new file mode 100644
index 00000000000..aa6f2cee6c4
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/f202y/generic_assumed_rank_1.f90
@@ -0,0 +1,51 @@
+! { dg-do run }
+! { dg-options "-std=f202y -Wsurprising -fcheck=bounds" }
+!
+! Test Reinhold Bader's F202y proposal "Generic processing of assumed rank objects".
+!
+! Contributed by Paul Thomas  <pa...@gcc.gnu.org>
+!
+   real :: x(2,2,2)
+   real, parameter :: xp(*) = [1,2,3,4,5,6,7,8]
+   x = reshape (xp, [2,2,2])
+   call my_sub (x)
+   if (any (reshape (x, [8]) .ne. xp(8:1:-1))) stop 1
+   call my_assumed_size_target (x)
+contains
+   subroutine my_sub (arg)
+     real, target, contiguous :: arg(..)
+     real, allocatable :: y(:)
+     real, pointer :: argp(:,:)
+     integer :: i
+
+     if (size (arg) .lt. 0) return
+
+     if (size (arg) .ne. 8) stop 10
+
+! Check reshape
+     y = reshape (arg, [size (arg)])
+     if (any (y .ne. xp)) stop 20
+
+! Check pointer assignment
+     argp(1:2,1: size(arg)/2) => arg
+     if (size (argp) .ne. size (x)) stop 30
+     if (any ((argp) .ne. reshape (x, [2, size (x)/2]))) stop 31
+
+! Check ASSOCIATE
+     i = size (arg)
+     associate (a(1:2,1:i/2) => arg)
+        if (any (a .ne. argp)) stop 40
+     end associate
+
+     associate (a(1:size(arg)) => arg)
+        if (any (a .ne. xp)) stop 41
+        a = a(8:1:-1)
+     end associate
+   end
+
+   subroutine my_assumed_size_target (arg)
+     real :: arg(2, 2, *)
+     call my_sub (arg)    ! { dg-warning "to an assumed-rank dummy" }
+   end
+end
+! { dg-output "Fortran runtime warning: Assumed rank object arg is associated with an assumed size object" }
diff --git a/gcc/testsuite/gfortran.dg/f202y/generic_assumed_rank_2.f90 b/gcc/testsuite/gfortran.dg/f202y/generic_assumed_rank_2.f90
new file mode 100644
index 00000000000..57af12f2891
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/f202y/generic_assumed_rank_2.f90
@@ -0,0 +1,50 @@
+! { dg-do compile }
+! { dg-options "-Wsurprising" }
+!
+! Test Reinhold Bader's F202y proposal "Generic processing of assumed rank objects".
+!
+! Contributed by Paul Thomas  <pa...@gcc.gnu.org>
+!
+   real :: x(2,2,2)
+   real, parameter :: xp(*) = [1,2,3,4,5,6,7,8]
+   x = reshape (xp, [2,2,2])
+   call my_sub (x)
+   if (any (reshape (x, [8]) .ne. xp(8:1:-1))) stop 1
+   call my_assumed_size_target (x)
+contains
+   subroutine my_sub (arg)
+     real, target, contiguous :: arg(..)
+     real, allocatable :: y(:)
+     real, pointer :: argp(:,:)
+     integer :: i
+
+     if (size (arg) .lt. 0) return
+
+     if (size (arg) .ne. 8) stop 10
+
+! Check reshape
+     y = reshape (arg, [size (arg)]) ! { dg-error "experimental F202y feature" }
+     if (any (y .ne. xp)) stop 20
+
+! Check pointer assignment
+     argp(1:2,1: size(arg)/2) => arg ! { dg-error "experimental F202y feature" }
+     if (size (argp) .ne. size (x)) stop 30
+     if (any ((argp) .ne. reshape (x, [2, size (x)/2]))) stop 31
+
+! Check ASSOCIATE
+     i = size (arg)
+     associate (a(1:2,1:i/2) => arg) ! { dg-error "experimental F202y feature" }
+        if (any (a .ne. argp)) stop 40
+     end associate
+
+     associate (a(1:size(arg)) => arg)  ! { dg-error "experimental F202y feature" }
+        if (any (a .ne. xp)) stop 41
+        a = a(8:1:-1)
+     end associate
+   end
+
+   subroutine my_assumed_size_target (arg)
+     real :: arg(2, 2, *)
+     call my_sub (arg)    ! { dg-warning "to an assumed-rank dummy" }
+   end
+end

Attachment: Change.Logs
Description: Binary data

Reply via email to