See attached patch.

Regression tested on x86_64.

OK for mainline?

Also since this is fixing a rejects valid, I would like to backport.

Regards,

Jerry
---
Expressions used in stop codes can be functions as long as they resolve to
integer or character.

        PR fortran/126018

gcc/fortran/ChangeLog:

        * match.cc (gfc_match_stopcode): Adjust the f2008 error check.If the
        STOP code expr type is unknown, do not error. It will be checked in
        gfc_resolve_code.
        * resolve.cc (gfc_resolve_code): Add checks for EXEC_STOP and
        EXEC_ERROR_STOP.

gcc/testsuite/ChangeLog:

        * gfortran.dg/stop_function_code_1.f90: New test.
---
From 4263dbe988fea932e4b591c15bccc9ce401d2d3f Mon Sep 17 00:00:00 2001
From: Jerry DeLisle <[email protected]>
Date: Wed, 1 Jul 2026 14:03:23 -0700
Subject: [PATCH] fortran: [PR126018] Fix rejects character function invocation
 as stop code

Expressions used in stop codes can be functions as long as they resolve to
integer or character.

	PR fortran/126018

gcc/fortran/ChangeLog:

	* match.cc (gfc_match_stopcode): Adjust the f2008 error check.If the
	STOP code expr type is unknown, do not error. It will be checked in
	gfc_resolve_code.
	* resolve.cc (gfc_resolve_code): Add checks for EXEC_STOP and
	EXEC_ERROR_STOP.

gcc/testsuite/ChangeLog:

	* gfortran.dg/stop_function_code_1.f90: New test.
---
 gcc/fortran/match.cc                          | 23 +++++++++++--------
 gcc/fortran/resolve.cc                        | 19 +++++++++++++++
 .../gfortran.dg/stop_function_code_1.f90      | 14 +++++++++++
 3 files changed, 46 insertions(+), 10 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/stop_function_code_1.f90

diff --git a/gcc/fortran/match.cc b/gcc/fortran/match.cc
index be376a8c062..7695f746901 100644
--- a/gcc/fortran/match.cc
+++ b/gcc/fortran/match.cc
@@ -3960,19 +3960,22 @@ checks:
 	  goto cleanup;
 	}
 
-      /* Use the machinery for an initialization expression to reduce the
-	 stop-code to a constant.  */
-      gfc_reduce_init_expr (e);
-
-      /* Test for F2008 style STOP stop-code.  */
-      if (e->expr_type != EXPR_CONSTANT && f08)
+      /* If this is F2008, it could be an init expression.  */
+      if (f08)
 	{
-	  gfc_error ("STOP code at %L must be a scalar default CHARACTER or "
-		     "INTEGER constant expression", &e->where);
-	  goto cleanup;
+	  gfc_reduce_init_expr (e);
+	  if (e->expr_type != EXPR_CONSTANT)
+	    {
+	      gfc_error ("STOP code at %L must be a scalar default CHARACTER or "
+			 "INTEGER constant expression", &e->where);
+	      goto cleanup;
+	    }
 	}
 
-      if (!(e->ts.type == BT_CHARACTER || e->ts.type == BT_INTEGER))
+      /* For types known at parse time, check immediately.  For BT_UNKNOWN
+	 (e.g. a forward-referenced contained function) defer to resolve.  */
+      if (e->ts.type != BT_UNKNOWN
+	  && !(e->ts.type == BT_CHARACTER || e->ts.type == BT_INTEGER))
 	{
 	  gfc_error ("STOP code at %L must be either INTEGER or CHARACTER type",
 		     &e->where);
diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc
index 9eb022d608d..4fc7b5a4d74 100644
--- a/gcc/fortran/resolve.cc
+++ b/gcc/fortran/resolve.cc
@@ -14376,6 +14376,25 @@ start:
 
 	case EXEC_STOP:
 	case EXEC_ERROR_STOP:
+	  if (code->expr1 != NULL && t)
+	    {
+	      if (!(code->expr1->ts.type == BT_CHARACTER
+		    || code->expr1->ts.type == BT_INTEGER))
+		gfc_error ("STOP code at %L must be either INTEGER or CHARACTER "
+			   "type", &code->expr1->where);
+	      else if (code->expr1->rank != 0)
+		gfc_error ("STOP code at %L must be scalar",
+			   &code->expr1->where);
+	      else if (code->expr1->ts.type == BT_CHARACTER
+		       && code->expr1->ts.kind != gfc_default_character_kind)
+		gfc_error ("STOP code at %L must be default character KIND=%d",
+			   &code->expr1->where, (int) gfc_default_character_kind);
+	      else if (code->expr1->ts.type == BT_INTEGER
+		       && code->expr1->ts.kind != gfc_default_integer_kind)
+		gfc_notify_std (GFC_STD_F2018, "STOP code at %L must be default "
+				"integer KIND=%d", &code->expr1->where,
+				(int) gfc_default_integer_kind);
+	    }
 	  if (code->expr2 != NULL
 	      && (code->expr2->ts.type != BT_LOGICAL
 		  || code->expr2->rank != 0))
diff --git a/gcc/testsuite/gfortran.dg/stop_function_code_1.f90 b/gcc/testsuite/gfortran.dg/stop_function_code_1.f90
new file mode 100644
index 00000000000..6f69f54e35a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/stop_function_code_1.f90
@@ -0,0 +1,14 @@
+! { dg-do compile }
+! PR fortran/126018 - Stop code may be a function call (CHARACTER or INTEGER)
+program p
+  implicit none
+  error stop character_stop ()   ! was: "must be either INTEGER or CHARACTER"
+  stop integer_stop ()           ! likewise for integer
+contains
+  character (1) function character_stop ()
+    character_stop = "a"
+  end function character_stop
+  integer function integer_stop ()
+    integer_stop = 1
+  end function integer_stop
+end program p
-- 
2.54.0

Reply via email to