re PR fortran/25964 (NIST regression on fm311.f)
authorPaul Thomas <pault@gcc.gnu.org>
Thu, 26 Jan 2006 20:19:09 +0000 (20:19 +0000)
committerPaul Thomas <pault@gcc.gnu.org>
Thu, 26 Jan 2006 20:19:09 +0000 (20:19 +0000)
2005-01-26  Paul Thomas  <pault@gcc.gnu.org>

PR fortran/25964
* resolve.c (resolve_function): Exclude statement functions from
global reference checking.

PR fortran/25084
PR fortran/20852
PR fortran/25085
PR fortran/25086
* resolve.c (resolve_function): Declare a gfc_symbol to replace the
references through the symtree to the symbol associated with the
function expresion. Give error on reference to an assumed character
length function is defined in an interface or an external function
that is not a dummy argument.
(resolve_symbol): Give error if an assumed character length function
is array-valued, pointer-valued, pure or recursive. Emit warning
that character(*) value functions are obsolescent in F95.

PR fortran/25416
* trans-expr.c (gfc_conv_function_call): The above patch to resolve.c
prevents any assumed character length function call from getting here
except intrinsics such as SPREAD. In this case, ensure that no
segfault occurs from referencing non-existent charlen->length->
expr_type and provide a backend_decl for the charlen from the charlen
of the first actual argument.

Cure temp name confusion.
* trans-expr.c (gfc_get_interface_mapping_array): Change name of
temporary from "parm" to "ifm" to avoid clash with temp coming from
trans-array.c.

2005-01-26  Paul Thomas  <pault@gcc.gnu.org>

PR fortran/25964
* gfortran.dg/global_references_2.f90: New test.

PR fortran/25084
PR fortran/20852
PR fortran/25085
PR fortran/25086
* gfortran.dg/assumed_charlen_function_1.f90: New test.
* gfortran.dg/assumed_charlen_function_3.f90: New test.

PR fortran/25416
* gfortran.dg/assumed_charlen_function_2.f90: New test.

From-SVN: r110269

gcc/fortran/ChangeLog
gcc/fortran/resolve.c
gcc/fortran/trans-expr.c
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/assumed_charlen_function_1.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/assumed_charlen_function_2.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/assumed_charlen_function_3.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/global_references_2.f90 [new file with mode: 0644]

index 4fa765b94a71f334922c8a344a4f9fc41735884a..7fc7fb0d33b32b2769a5254e01ebaf5faba67c10 100644 (file)
@@ -1,3 +1,35 @@
+2005-01-26  Paul Thomas  <pault@gcc.gnu.org>
+
+       PR fortran/25964
+       * resolve.c (resolve_function): Exclude statement functions from
+       global reference checking.
+
+       PR fortran/25084
+       PR fortran/20852
+       PR fortran/25085
+       PR fortran/25086
+       * resolve.c (resolve_function): Declare a gfc_symbol to replace the
+       references through the symtree to the symbol associated with the
+       function expresion. Give error on reference to an assumed character
+       length function is defined in an interface or an external function
+       that is not a dummy argument.
+       (resolve_symbol): Give error if an assumed character length function
+       is array-valued, pointer-valued, pure or recursive. Emit warning
+       that character(*) value functions are obsolescent in F95.
+
+       PR fortran/25416
+       * trans-expr.c (gfc_conv_function_call): The above patch to resolve.c
+       prevents any assumed character length function call from getting here
+       except intrinsics such as SPREAD. In this case, ensure that no
+       segfault occurs from referencing non-existent charlen->length->
+       expr_type and provide a backend_decl for the charlen from the charlen
+       of the first actual argument.
+
+       Cure temp name confusion.
+       * trans-expr.c (gfc_get_interface_mapping_array): Change name of
+       temporary from "parm" to "ifm" to avoid clash with temp coming from
+       trans-array.c.
+
 2005-01-25  Erik Edelmann  <eedelman@gcc.gnu.org>
 
        PR fortran/25716
index e94a92653306c7fe23a662e6f7d5e8341afe0969..99fb2a2dd84a58792edde752ae2d647f6440298d 100644 (file)
@@ -1183,17 +1183,21 @@ static try
 resolve_function (gfc_expr * expr)
 {
   gfc_actual_arglist *arg;
+  gfc_symbol * sym;
   const char *name;
   try t;
   int temp;
 
-  /* If the procedure is not internal or module, it must be external and
-     should be checked for usage.  */
-  if (expr->symtree && expr->symtree->n.sym
-       && !expr->symtree->n.sym->attr.dummy
-       && !expr->symtree->n.sym->attr.contained
-       && !expr->symtree->n.sym->attr.use_assoc)
-    resolve_global_procedure (expr->symtree->n.sym, &expr->where, 0);
+  sym = NULL;
+  if (expr->symtree)
+    sym = expr->symtree->n.sym;
+
+  /* If the procedure is not internal, a statement function or a module
+     procedure,it must be external and should be checked for usage.  */
+  if (sym && !sym->attr.dummy && !sym->attr.contained
+       && sym->attr.proc != PROC_ST_FUNCTION
+       && !sym->attr.use_assoc)
+    resolve_global_procedure (sym, &expr->where, 0);
 
   /* Switch off assumed size checking and do this again for certain kinds
      of procedure, once the procedure itself is resolved.  */
@@ -1205,19 +1209,44 @@ resolve_function (gfc_expr * expr)
   /* Resume assumed_size checking. */
   need_full_assumed_size--;
 
+  if (sym && sym->ts.type == BT_CHARACTER
+         && sym->ts.cl && sym->ts.cl->length == NULL)
+    {
+      if (sym->attr.if_source == IFSRC_IFBODY)
+       {
+         /* This follows from a slightly odd requirement at 5.1.1.5 in the
+            standard that allows assumed character length functions to be
+            declared in interfaces but not used.  Picking up the symbol here,
+            rather than resolve_symbol, accomplishes that.  */
+         gfc_error ("Function '%s' can be declared in an interface to "
+                    "return CHARACTER(*) but cannot be used at %L",
+                    sym->name, &expr->where);
+         return FAILURE;
+       }
+
+      /* Internal procedures are taken care of in resolve_contained_fntype.  */
+      if (!sym->attr.dummy && !sym->attr.contained)
+       {
+         gfc_error ("Function '%s' is declared CHARACTER(*) and cannot "
+                    "be used at %L since it is not a dummy argument",
+                    sym->name, &expr->where);
+         return FAILURE;
+       }
+    }
+
 /* See if function is already resolved.  */
 
   if (expr->value.function.name != NULL)
     {
       if (expr->ts.type == BT_UNKNOWN)
-       expr->ts = expr->symtree->n.sym->ts;
+       expr->ts = sym->ts;
       t = SUCCESS;
     }
   else
     {
       /* Apply the rules of section 14.1.2.  */
 
-      switch (procedure_kind (expr->symtree->n.sym))
+      switch (procedure_kind (sym))
        {
        case PTYPE_GENERIC:
          t = resolve_generic_f (expr);
@@ -4862,6 +4891,46 @@ resolve_symbol (gfc_symbol * sym)
          return;
        }
 
+      /* 5.1.1.5 of the Standard: A function name declared with an asterisk
+        char-len-param shall not be array-valued, pointer-valued, recursive
+        or pure.  ....snip... A character value of * may only be used in the
+        following ways: (i) Dummy arg of procedure - dummy associates with
+        actual length; (ii) To declare a named constant; or (iii) External
+        function - but length must be declared in calling scoping unit.  */
+      if (sym->attr.function
+           && sym->ts.type == BT_CHARACTER
+           && sym->ts.cl && sym->ts.cl->length == NULL)
+       {
+         if ((sym->as && sym->as->rank) || (sym->attr.pointer)
+                || (sym->attr.recursive) || (sym->attr.pure))
+           {
+             if (sym->as && sym->as->rank)
+               gfc_error ("CHARACTER(*) function '%s' at %L cannot be "
+                          "array-valued", sym->name, &sym->declared_at);
+
+             if (sym->attr.pointer)
+               gfc_error ("CHARACTER(*) function '%s' at %L cannot be "
+                          "pointer-valued", sym->name, &sym->declared_at);
+
+             if (sym->attr.pure)
+               gfc_error ("CHARACTER(*) function '%s' at %L cannot be "
+                          "pure", sym->name, &sym->declared_at);
+
+             if (sym->attr.recursive)
+               gfc_error ("CHARACTER(*) function '%s' at %L cannot be "
+                          "recursive", sym->name, &sym->declared_at);
+
+             return;
+           }
+
+         /* Appendix B.2 of the standard.  Contained functions give an
+            error anyway.  Fixed-form is likely to be F77/legacy.  */
+         if (!sym->attr.contained && gfc_current_form != FORM_FIXED)
+           gfc_notify_std (GFC_STD_F95_OBS, "CHARACTER(*) function "
+                           "'%s' at %L is obsolescent in fortran 95",
+                           sym->name, &sym->declared_at);
+       }
+
       break;
 
     case FL_DERIVED:
index b30a12182241b15b23f13923cfadd0d9957fd580..232270514b863f274d72e7a1ddf360bd736a3947 100644 (file)
@@ -1224,7 +1224,7 @@ gfc_get_interface_mapping_array (stmtblock_t * block, gfc_symbol * sym,
   type = gfc_typenode_for_spec (&sym->ts);
   type = gfc_get_nodesc_array_type (type, sym->as, packed);
 
-  var = gfc_create_var (type, "parm");
+  var = gfc_create_var (type, "ifm");
   gfc_add_modify_expr (block, var, fold_convert (type, data));
 
   return var;
@@ -1807,8 +1807,10 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym,
 
   gfc_init_interface_mapping (&mapping);
   need_interface_mapping = ((sym->ts.type == BT_CHARACTER
-                            && sym->ts.cl->length->expr_type != EXPR_CONSTANT)
-                           || sym->attr.dimension);
+                                 && sym->ts.cl->length
+                                 && sym->ts.cl->length->expr_type
+                                               != EXPR_CONSTANT)
+                             || sym->attr.dimension);
   formal = sym->formal;
   /* Evaluate the arguments.  */
   for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
@@ -1905,19 +1907,30 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym,
   ts = sym->ts;
   if (ts.type == BT_CHARACTER)
     {
-      /* Calculate the length of the returned string.  */
-      gfc_init_se (&parmse, NULL);
-      if (need_interface_mapping)
-       gfc_apply_interface_mapping (&mapping, &parmse, sym->ts.cl->length);
+      if (sym->ts.cl->length == NULL)
+       {
+         /* Assumed character length results are not allowed by 5.1.1.5 of the
+            standard and are trapped in resolve.c; except in the case of SPREAD
+            (and other intrinsics?).  In this case, we take the character length
+            of the first argument for the result.  */
+         cl.backend_decl = TREE_VALUE (stringargs);
+       }
       else
-       gfc_conv_expr (&parmse, sym->ts.cl->length);
-      gfc_add_block_to_block (&se->pre, &parmse.pre);
-      gfc_add_block_to_block (&se->post, &parmse.post);
+       {
+         /* Calculate the length of the returned string.  */
+         gfc_init_se (&parmse, NULL);
+         if (need_interface_mapping)
+           gfc_apply_interface_mapping (&mapping, &parmse, sym->ts.cl->length);
+         else
+           gfc_conv_expr (&parmse, sym->ts.cl->length);
+         gfc_add_block_to_block (&se->pre, &parmse.pre);
+         gfc_add_block_to_block (&se->post, &parmse.post);
+         cl.backend_decl = fold_convert (gfc_charlen_type_node, parmse.expr);
+       }
 
       /* Set up a charlen structure for it.  */
       cl.next = NULL;
       cl.length = NULL;
-      cl.backend_decl = fold_convert (gfc_charlen_type_node, parmse.expr);
       ts.cl = &cl;
 
       len = cl.backend_decl;
index 7b2477a1216bf63044e7f0ae71fff60bb19099d6..f315158448c53d67cd355fc850c68921a2cd26f2 100644 (file)
@@ -1,3 +1,18 @@
+2005-01-26  Paul Thomas  <pault@gcc.gnu.org>
+
+       PR fortran/25964
+       * gfortran.dg/global_references_2.f90: New test.
+
+       PR fortran/25084
+       PR fortran/20852
+       PR fortran/25085
+       PR fortran/25086
+       * gfortran.dg/assumed_charlen_function_1.f90: New test.
+       * gfortran.dg/assumed_charlen_function_3.f90: New test.
+
+       PR fortran/25416
+       * gfortran.dg/assumed_charlen_function_2.f90: New test.
+
 2006-01-26  Alexandre Oliva  <aoliva@redhat.com>
 
        PR c/25892
diff --git a/gcc/testsuite/gfortran.dg/assumed_charlen_function_1.f90 b/gcc/testsuite/gfortran.dg/assumed_charlen_function_1.f90
new file mode 100644 (file)
index 0000000..c90617d
--- /dev/null
@@ -0,0 +1,83 @@
+! { dg-do compile }\r
+! { dg-options "-std=legacy" }\r
+! Tests the patch for PRs 25084, 20852, 25085 and 25086, all of\r
+! which involve assumed character length functions.\r
+! Compiled from original PR testcases, which were all contributed\r
+! by Joost VandeVondele  <jv244@cam.ac.uk>\r
+!\r
+! PR25084 - the error is not here but in any use of .IN.\r
+! It is OK to define an assumed character length function\r
+! in an interface but it cannot be invoked (5.1.1.5).\r
+\r
+MODULE M1\r
+ TYPE  SET\r
+  INTEGER  CARD\r
+ END  TYPE  SET\r
+END MODULE M1\r
+\r
+MODULE  INTEGER_SETS\r
+ INTERFACE  OPERATOR  (.IN.)\r
+  FUNCTION ELEMENT(X,A)\r
+     USE M1\r
+     CHARACTER(LEN=*)      :: ELEMENT\r
+     INTEGER, INTENT(IN)   ::  X\r
+     TYPE(SET), INTENT(IN) ::   A\r
+  END FUNCTION ELEMENT\r
+ END  INTERFACE\r
+END MODULE\r
+\r
+! 5.1.1.5 of the Standard: A function name declared with an asterisk\r
+! char-len-param shall not be array-valued, pointer-valued, recursive\r
+! or pure\r
+! \r
+! PR20852\r
+RECURSIVE FUNCTION TEST() ! { dg-error "cannot be recursive" }\r
+ CHARACTER(LEN=*) :: TEST\r
+ TEST = ""\r
+END FUNCTION\r
+\r
+!PR25085\r
+FUNCTION F1()             ! { dg-error "cannot be array-valued" }\r
+  CHARACTER(LEN=*), DIMENSION(10) :: F1\r
+  F1 = ""\r
+END FUNCTION F1\r
+\r
+!PR25086\r
+FUNCTION F2() result(f4)  ! { dg-error "cannot be pointer-valued" }\r
+  CHARACTER(LEN=*), POINTER  :: f4\r
+  f4 = ""\r
+END FUNCTION F2\r
+\r
+!PR?????\r
+pure FUNCTION F3()        ! { dg-error "cannot be pure" }\r
+  CHARACTER(LEN=*)  :: F3\r
+  F3 = ""\r
+END FUNCTION F3\r
+\r
+function not_OK (ch)\r
+  character(*) not_OK, ch ! OK in an external function\r
+  not_OK = ch\r
+end function not_OK\r
+\r
+  use INTEGER_SETS\r
+  use m1\r
+\r
+  character(4) :: answer\r
+  character(*), external :: not_OK\r
+  integer :: i\r
+  type (set) :: z\r
+\r
+  interface\r
+    function ext (i)\r
+      character(*) :: ext\r
+      integer :: i\r
+    end function ext\r
+  end interface\r
+\r
+  answer = i.IN.z   ! { dg-error "cannot be used|Operands of user operator" }\r
+  answer = ext (2)  ! { dg-error "but cannot be used" }\r
+\r
+  answer = not_OK ("unOK") ! { dg-error "since it is not a dummy" }\r
+\r
+END\r
+\r
diff --git a/gcc/testsuite/gfortran.dg/assumed_charlen_function_2.f90 b/gcc/testsuite/gfortran.dg/assumed_charlen_function_2.f90
new file mode 100644 (file)
index 0000000..bd7d713
--- /dev/null
@@ -0,0 +1,13 @@
+! { dg-do compile }\r
+! Tests the fix for PR25416, which ICED in gfc_conv_function_call, when\r
+! treating SPREAD in the statement below.\r
+!\r
+! Contributed by Ulrich Weigand  <uweigand@gcc.gnu.org>\r
+function bug(self,strvec) result(res)\r
+  character(*) :: self\r
+  character(*), dimension(:), intent(in) :: strvec\r
+  logical(kind=kind(.true.)) :: res\r
+\r
+  res = any(index(strvec,spread(self,1,size(strvec))) /= 0)\r
+end function\r
+\r
diff --git a/gcc/testsuite/gfortran.dg/assumed_charlen_function_3.f90 b/gcc/testsuite/gfortran.dg/assumed_charlen_function_3.f90
new file mode 100644 (file)
index 0000000..09c9be9
--- /dev/null
@@ -0,0 +1,39 @@
+! { dg-do compile }\r
+! Tests the patch for PRs 25084, 20852, 25085 and 25086, all of\r
+! which involve assumed character length functions.\r
+! This test checks the things that should not emit errors.\r
+!\r
+! Contributed by Paul Thomas  <pault@gcc.gnu.org>\r
+!\r
+function is_OK (ch)                ! { dg-warning "is obsolescent in fortran 95" }\r
+  character(*) is_OK, ch           ! OK in an external function\r
+  is_OK = ch\r
+end function is_OK\r
+\r
+! The warning occurs twice for the next line; for 'more_OK' and for 'fcn';\r
+function more_OK (ch, fcn)         ! { dg-warning "is obsolescent in fortran 95" }\r
+  character(*) more_OK, ch\r
+  character (*), external :: fcn   ! OK as a dummy argument\r
+  more_OK = fcn (ch)\r
+end function more_OK\r
+\r
+  character(4) :: answer\r
+  character(4), external :: is_OK, more_OK\r
+\r
+  answer = is_OK ("isOK")          ! LEN defined in calling scope\r
+  print *, answer\r
+\r
+  answer = more_OK ("okay", is_OK) ! Actual arg has defined LEN\r
+  print *, answer\r
+\r
+  answer = also_OK ("OKOK")\r
+  print *, answer\r
+\r
+contains\r
+  function also_OK (ch)\r
+    character(4) also_OK\r
+    character(*) ch\r
+    also_OK = is_OK (ch)            ! LEN obtained by host association\r
+  end function also_OK\r
+END\r
+\r
diff --git a/gcc/testsuite/gfortran.dg/global_references_2.f90 b/gcc/testsuite/gfortran.dg/global_references_2.f90
new file mode 100644 (file)
index 0000000..9566698
--- /dev/null
@@ -0,0 +1,10 @@
+! { dg-do compile }
+! This program tests the patch for PR25964. This is a
+! regression that would not allow a common block and a statement
+! to share the same name.
+!
+! Contributed by Paul Thomas  <pault@gcc.gnu.org>
+  common /foo/ a, b, c
+  foo (x) = x + 1.0
+  print *, foo (0.0)
+  end
\ No newline at end of file