This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Patch, fortran] PR18578, PR18579, PR20857 and PR20885 - Constraints on INTENT(OUT and INOUT)


:ADDPATCH fortran:

This patch implements the obvious constraints on the use of INTENT(OUT and INOUT). ie: that the actual argument should be a variable ("definable" in the standard) and that INTENT(OUT) variables should be defined or intialized before they are used or before return from the procedure. Several testuite progams had to be modified, by adding assignments to INTENT(OUT) variables, so that unintended error messages were not produced. The patch is straightforward. The use of two new attributes, was_actual and was_lvalue should be noted.

Regtested on Athlon/FC3. OK for 4.2 and 4.1?

Paul

2006-01-29 Paul Thomas <pault@gcc.gnu.org>

   PR fortran/18578
   PR fortran/18579
   PR fortran/20857
   PR fortran/20885
   * interface.c (compare_actual_formal): Error for INTENT(OUT or INOUT)
   if actual argument is not a variable.
   resolve.c (resolve_symbol): Warning if INTENT(OUT) has never been an
   lvalue and was not initialized.
   * gfortran.h: Add attribute bitfields was_lvalue and was_actual.
   * match.c (gfc_match_assignment): Set lvalue was_lvalue attribute.
   * primary.c (gfc_match_actual_arglist): Set was_actual attribute.
   (gfc_match_rvalue): If has not been an lvalue, warning, if, as well,
   has never been an actual argument, error on rvalue being used
   undefined.

2006-01-29 Paul Thomas <pault@gcc.gnu.org>

   PR fortran/18578
   PR fortran/18579
   PR fortran/20857
   PR fortran/20885
   * gfortran.dg/intent_1.f90: New test.
   * gfortran.dg/assumed_dummy_2.f90: Assign to INTENT(OUT) to suppress
   unintended error.
   * gfortran.dg/assumed_size_dt_dummy.f90: The same.
   * gfortran.dg/generic_3.f90: The same.
   * gfortran.dg/spec_expr_2.f90: The same.

Index: gcc/fortran/interface.c
===================================================================
*** gcc/fortran/interface.c	(revision 110364)
--- gcc/fortran/interface.c	(working copy)
*************** compare_actual_formal (gfc_actual_arglis
*** 1273,1278 ****
--- 1273,1288 ----
  	  return 0;
  	}
  
+       /* Check intent = OUT/INOUT for definable actual argument.  */
+       if (a->expr->expr_type != EXPR_VARIABLE
+ 	     && (f->sym->attr.intent == INTENT_OUT
+ 		   || f->sym->attr.intent == INTENT_INOUT))
+ 	{
+ 	  gfc_error ("Actual argument at %L must be definable to "
+ 		     "match dummy INTENT = OUT/INOUT", &a->expr->where);
+           return 0;
+         }
+ 
      match:
        if (a == actual)
  	na = i;
Index: gcc/fortran/gfortran.h
===================================================================
*** gcc/fortran/gfortran.h	(revision 110365)
--- gcc/fortran/gfortran.h	(working copy)
*************** typedef struct
*** 483,488 ****
--- 483,493 ----
       modification of type or type parameters is permitted.  */
    unsigned referenced:1;
  
+   /* Set if the symbol has been an lvalue or an actual argument.  Used to
+      check INTENT usage.  */
+   unsigned was_lvalue:1;
+   unsigned was_actual:1;
+ 
    /* Set if the is the symbol for the main program.  This is the least
       cumbersome way to communicate this function property without
       strcmp'ing with __MAIN everywhere.  */
Index: gcc/fortran/resolve.c
===================================================================
*** gcc/fortran/resolve.c	(revision 110364)
--- gcc/fortran/resolve.c	(working copy)
*************** resolve_symbol (gfc_symbol * sym)
*** 4747,4752 ****
--- 4747,4760 ----
  	}
      }
  
+   /* Warn if an INTENT(OUT) variable has never been an l-value.  */
+   if (sym->attr.dummy
+ 	&& !sym->attr.use_assoc
+ 	&& sym->attr.intent == INTENT_OUT
+ 	&& !sym->attr.was_lvalue
+ 	&& sym->value == NULL)
+     gfc_warning ("The INTENT(OUT) dummy argument '%s' at %L might be "
+ 		     "undefined.", sym->name, &sym->declared_at);
  
    /* Ensure that derived type formal arguments of a public procedure
       are not of a private type.  */
Index: gcc/fortran/match.c
===================================================================
*** gcc/fortran/match.c	(revision 110364)
--- gcc/fortran/match.c	(working copy)
*************** gfc_match_assignment (void)
*** 859,864 ****
--- 859,865 ----
      goto cleanup;
  
    gfc_set_sym_referenced (lvalue->symtree->n.sym);
+   lvalue->symtree->n.sym->attr.was_lvalue = 1;
  
    new_st.op = EXEC_ASSIGN;
    new_st.expr = lvalue;
Index: gcc/fortran/primary.c
===================================================================
*** gcc/fortran/primary.c	(revision 110364)
--- gcc/fortran/primary.c	(working copy)
*************** gfc_match_actual_arglist (int sub_flag, 
*** 1521,1526 ****
--- 1521,1529 ----
  	}
  
      next:
+       if (tail->expr && tail->expr->expr_type == EXPR_VARIABLE)
+ 	tail->expr->symtree->n.sym->attr.was_actual = 1;
+ 
        if (gfc_match_char (')') == MATCH_YES)
  	break;
        if (gfc_match_char (',') != MATCH_YES)
*************** gfc_match_rvalue (gfc_expr ** result)
*** 1929,1934 ****
--- 1932,1952 ----
    e = NULL;
    where = gfc_current_locus;
  
+   if (sym->attr.intent == INTENT_OUT
+ 	&& !sym->value
+ 	&& !sym->attr.was_lvalue)
+     {
+       if (!sym->attr.was_actual)
+ 	{
+ 	  gfc_error ("Variable '%s' with INTENT(OUT) is being used "
+ 		     "uninitialized at %L.", sym->name, &where);
+ 	  return MATCH_ERROR;
+ 	}
+       else
+ 	gfc_warning ("Variable '%s' with INTENT(OUT) might be used "
+ 		     "uninitialized at %L.", sym->name, &where);
+     }
+ 
    gfc_set_sym_referenced (sym);
  
    if (sym->attr.function && sym->result == sym)
Index: gcc/testsuite/gfortran.dg/assumed_dummy_2.f90
===================================================================
*** gcc/testsuite/gfortran.dg/assumed_dummy_2.f90	(revision 110364)
--- gcc/testsuite/gfortran.dg/assumed_dummy_2.f90	(working copy)
*************** contains
*** 9,15 ****
    end subroutine foo
    subroutine bar (arr)
      double precision :: arr(5,*)
!     call foo (arr)	! { dg-error "cannot be an assumed-size array" }
      call foo (arr (:, :8))
    end subroutine
  end
--- 9,15 ----
    end subroutine foo
    subroutine bar (arr)
      double precision :: arr(5,*)
!     call foo (arr)   ! { dg-error "cannot be an assumed-size array" }
      call foo (arr (:, :8))
    end subroutine
  end
Index: gcc/testsuite/gfortran.dg/assumed_size_dt_dummy.f90
===================================================================
*** gcc/testsuite/gfortran.dg/assumed_size_dt_dummy.f90	(revision 110364)
--- gcc/testsuite/gfortran.dg/assumed_size_dt_dummy.f90	(working copy)
*************** CONTAINS
*** 10,15 ****
--- 10,18 ----
    SUBROUTINE try (A, B) ! { dg-error "cannot have a default initializer" }
      TYPE(init), DIMENSION(*), INTENT(OUT) :: A
      TYPE(init)              , INTENT(OUT) :: B ! PR24440 => segfault
+     TYPE(init)                            :: C
+     A(1) = C
+     B = C
    END SUBROUTINE try
  END MODULE TEST
  
Index: gcc/testsuite/gfortran.dg/spec_expr_2.f90
===================================================================
*** gcc/testsuite/gfortran.dg/spec_expr_2.f90	(revision 110364)
--- gcc/testsuite/gfortran.dg/spec_expr_2.f90	(working copy)
***************
*** 4,7 ****
--- 4,8 ----
  subroutine lecligne (ligne)
      character(len=*), intent(out) :: ligne
      character(len=len(ligne)) :: comment
+     ligne = "" ! To prevent INTENT(OUT) undefined warning.
  end subroutine lecligne
Index: gcc/testsuite/gfortran.dg/generic_3.f90
===================================================================
*** gcc/testsuite/gfortran.dg/generic_3.f90	(revision 110364)
--- gcc/testsuite/gfortran.dg/generic_3.f90	(working copy)
*************** contains
*** 9,14 ****
--- 9,16 ----
      double precision, intent(out)    :: y
      double precision, intent(out)    :: dy(:)
      integer,          intent(in)     :: ma
+     y = 0d0
+     dy = 0d0
    end subroutine gauss
  end module fit_functions
  

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]