[04/10] fortran: Support clobbering with implicit interfaces [PR105012]

Message ID 20220916202439.549820-5-mikael@gcc.gnu.org
State New
Headers
Series fortran: clobber fixes [PR41453] |

Commit Message

Mikael Morin Sept. 16, 2022, 8:24 p.m. UTC
  From: Harald Anlauf <anlauf@gmx.de>

Before procedure calls, we clobber actual arguments whose associated
dummy is INTENT(OUT).  This only applies to procedures with explicit
interfaces, as the knowledge of the interface is necessary to know
whether an argument has the INTENT(OUT) attribute.

This change also enables clobber generation for procedure calls without
explicit interface, when the procedure has been defined in the same
file because we can use the dummy arguments' characteristics from the
procedure definition in that case.

The knowledge of the dummy characteristics is directly available through
gfc_actual_arglist’s associated_dummy pointers which have been populated
as a side effect of calling gfc_check_externals.

	PR fortran/105012

gcc/fortran/ChangeLog:

	* trans-expr.cc (gfc_conv_procedure_call): Use dummy
	information from associated_dummy if there is no information
	from the procedure interface.

gcc/testsuite/ChangeLog:

	* gfortran.dg/intent_optimize_4.f90: New test.

Co-Authored-By: Mikael Morin <mikael@gcc.gnu.org>
---
 gcc/fortran/trans-expr.cc                     | 19 +++++++++++----
 .../gfortran.dg/intent_optimize_4.f90         | 24 +++++++++++++++++++
 2 files changed, 39 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/intent_optimize_4.f90
  

Patch

diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index a62a3bb642d..2301724729f 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -6505,10 +6505,21 @@  gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
 		    {
 		      gfc_conv_expr_reference (&parmse, e);
 
-		      if (fsym
-			  && fsym->attr.intent == INTENT_OUT
-			  && !fsym->attr.allocatable
-			  && !fsym->attr.pointer
+		      gfc_symbol *dsym = fsym;
+		      gfc_dummy_arg *dummy;
+
+		      /* Use associated dummy as fallback for formal
+			 argument if there is no explicit interface.  */
+		      if (dsym == NULL
+			  && (dummy = arg->associated_dummy)
+			  && dummy->intrinsicness == GFC_NON_INTRINSIC_DUMMY_ARG
+			  && dummy->u.non_intrinsic->sym)
+			dsym = dummy->u.non_intrinsic->sym;
+
+		      if (dsym
+			  && dsym->attr.intent == INTENT_OUT
+			  && !dsym->attr.allocatable
+			  && !dsym->attr.pointer
 			  && e->expr_type == EXPR_VARIABLE
 			  && e->ref == NULL
 			  && e->symtree
diff --git a/gcc/testsuite/gfortran.dg/intent_optimize_4.f90 b/gcc/testsuite/gfortran.dg/intent_optimize_4.f90
new file mode 100644
index 00000000000..2f184bf84a8
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/intent_optimize_4.f90
@@ -0,0 +1,24 @@ 
+! { dg-do run }
+! { dg-additional-options "-fno-inline -fno-ipa-modref -fdump-tree-optimized -fdump-tree-original" }
+!
+! PR fortran/105012
+! Check that the INTENT(OUT) attribute causes one clobber to be emitted in
+! the caller before the call to Y in the *.original dump, and the
+! initialization constant to be optimized away in the *.optimized dump,
+! despite the non-explicit interface if the subroutine with the INTENT(OUT)
+! is declared in the same file.
+
+SUBROUTINE Y (Z)
+      integer, intent(out) :: Z
+      Z = 42
+END SUBROUTINE Y
+PROGRAM TEST
+    integer :: X
+    X = 123456789
+    CALL Y (X)
+    if (X.ne.42) STOP 1
+END PROGRAM
+
+! { dg-final { scan-tree-dump-times "CLOBBER" 1 "original" } }
+! { dg-final { scan-tree-dump "x = {CLOBBER};" "original" } }
+! { dg-final { scan-tree-dump-not "123456789" "optimized" { target __OPTIMIZE__ } } }