From 70cba7da18023282546b9a5d80e976fc3744d732 Mon Sep 17 00:00:00 2001 From: Harald Anlauf Date: Wed, 5 Oct 2022 22:25:14 +0200 Subject: [PATCH] Fortran: reject procedures and procedure pointers as IO element [PR107074] gcc/fortran/ChangeLog: PR fortran/107074 * resolve.cc (resolve_transfer): A procedure, type-bound procedure or a procedure pointer cannot be an element of an IO list. * simplify.cc (gfc_simplify_merge): Do not try to reset array lower bound for scalars. gcc/testsuite/ChangeLog: PR fortran/107074 * gfortran.dg/pr107074.f90: New test. * gfortran.dg/pr107074b.f90: New test. --- gcc/fortran/resolve.cc | 31 +++++++++++++++++++++++++ gcc/fortran/simplify.cc | 3 ++- gcc/testsuite/gfortran.dg/pr107074.f90 | 11 +++++++++ gcc/testsuite/gfortran.dg/pr107074b.f90 | 18 ++++++++++++++ 4 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gfortran.dg/pr107074.f90 create mode 100644 gcc/testsuite/gfortran.dg/pr107074b.f90 diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc index d133bc2d034..d9d101775f6 100644 --- a/gcc/fortran/resolve.cc +++ b/gcc/fortran/resolve.cc @@ -10137,6 +10137,37 @@ resolve_transfer (gfc_code *code) "an assumed-size array", &code->loc); return; } + + /* Check for procedures and procedure pointers. Fortran 2018 has: + + C1233 (R1217) An expression that is an output-item shall not have a + value that is a procedure pointer. + + There does not appear any reason to allow procedure pointers for + input, so we disallow them generally, and we reject procedures. */ + + if (exp->expr_type == EXPR_VARIABLE) + { + /* Check for type-bound procedures. */ + for (ref = exp->ref; ref; ref = ref->next) + if (ref->type == REF_COMPONENT + && ref->u.c.component->attr.flavor == FL_PROCEDURE) + break; + + /* Procedure or procedure pointer? */ + if (exp->ts.type == BT_PROCEDURE + || (ref && ref->u.c.component->attr.flavor == FL_PROCEDURE)) + { + if (exp->symtree->n.sym->attr.proc_pointer + || (ref && ref->u.c.component->attr.proc_pointer)) + gfc_error ("Data transfer element at %L cannot be a procedure " + "pointer", &code->loc); + else + gfc_error ("Data transfer element at %L cannot be a procedure", + &code->loc); + return; + } + } } diff --git a/gcc/fortran/simplify.cc b/gcc/fortran/simplify.cc index 6ac92cf9db8..f0482d349af 100644 --- a/gcc/fortran/simplify.cc +++ b/gcc/fortran/simplify.cc @@ -4915,7 +4915,8 @@ gfc_simplify_merge (gfc_expr *tsource, gfc_expr *fsource, gfc_expr *mask) { result = gfc_copy_expr (mask->value.logical ? tsource : fsource); /* Parenthesis is needed to get lower bounds of 1. */ - result = gfc_get_parentheses (result); + if (result->rank) + result = gfc_get_parentheses (result); gfc_simplify_expr (result, 1); return result; } diff --git a/gcc/testsuite/gfortran.dg/pr107074.f90 b/gcc/testsuite/gfortran.dg/pr107074.f90 new file mode 100644 index 00000000000..1363c285912 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr107074.f90 @@ -0,0 +1,11 @@ +! { dg-do compile } +! PR fortran/107074 - ICE: Bad IO basetype (8) +! Contributed by G.Steinmetz + +program p + implicit none + integer, external :: a + procedure(real), pointer :: b + print *, merge (a, a, .true.) ! { dg-error "procedure" } + print *, merge (b, b, .true.) ! { dg-error "procedure pointer" } +end diff --git a/gcc/testsuite/gfortran.dg/pr107074b.f90 b/gcc/testsuite/gfortran.dg/pr107074b.f90 new file mode 100644 index 00000000000..98c3fc0b90a --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr107074b.f90 @@ -0,0 +1,18 @@ +! { dg-do compile } +! Additional test for PR fortran/107074 +! Contributed by M.Morin + +program p + implicit none + type :: t + procedure(f), pointer, nopass :: b + end type t + type(t) :: a + + interface + real function f() + end function f + end interface + + print *, merge (a%b, a%b, .true.) ! { dg-error "procedure pointer" } +end -- 2.35.3