diff options
| -rw-r--r-- | gcc/fortran/ChangeLog | 32 | ||||
| -rw-r--r-- | gcc/fortran/resolve.c | 87 | ||||
| -rw-r--r-- | gcc/fortran/trans-expr.c | 35 | ||||
| -rw-r--r-- | gcc/testsuite/ChangeLog | 15 | ||||
| -rw-r--r-- | gcc/testsuite/gfortran.dg/assumed_charlen_function_1.f90 | 83 | ||||
| -rw-r--r-- | gcc/testsuite/gfortran.dg/assumed_charlen_function_2.f90 | 13 | ||||
| -rw-r--r-- | gcc/testsuite/gfortran.dg/assumed_charlen_function_3.f90 | 39 | ||||
| -rw-r--r-- | gcc/testsuite/gfortran.dg/global_references_2.f90 | 10 |
8 files changed, 294 insertions, 20 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 4fa765b..7fc7fb0 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -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 diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index e94a926..99fb2a2 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -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: diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c index b30a121..2322705 100644 --- a/gcc/fortran/trans-expr.c +++ b/gcc/fortran/trans-expr.c @@ -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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7b2477a..f315158 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 index 0000000..c90617d --- /dev/null +++ b/gcc/testsuite/gfortran.dg/assumed_charlen_function_1.f90 @@ -0,0 +1,83 @@ +! { dg-do compile }
+! { dg-options "-std=legacy" }
+! Tests the patch for PRs 25084, 20852, 25085 and 25086, all of
+! which involve assumed character length functions.
+! Compiled from original PR testcases, which were all contributed
+! by Joost VandeVondele <jv244@cam.ac.uk>
+!
+! PR25084 - the error is not here but in any use of .IN.
+! It is OK to define an assumed character length function
+! in an interface but it cannot be invoked (5.1.1.5).
+
+MODULE M1
+ TYPE SET
+ INTEGER CARD
+ END TYPE SET
+END MODULE M1
+
+MODULE INTEGER_SETS
+ INTERFACE OPERATOR (.IN.)
+ FUNCTION ELEMENT(X,A)
+ USE M1
+ CHARACTER(LEN=*) :: ELEMENT
+ INTEGER, INTENT(IN) :: X
+ TYPE(SET), INTENT(IN) :: A
+ END FUNCTION ELEMENT
+ END INTERFACE
+END MODULE
+
+! 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
+!
+! PR20852
+RECURSIVE FUNCTION TEST() ! { dg-error "cannot be recursive" }
+ CHARACTER(LEN=*) :: TEST
+ TEST = ""
+END FUNCTION
+
+!PR25085
+FUNCTION F1() ! { dg-error "cannot be array-valued" }
+ CHARACTER(LEN=*), DIMENSION(10) :: F1
+ F1 = ""
+END FUNCTION F1
+
+!PR25086
+FUNCTION F2() result(f4) ! { dg-error "cannot be pointer-valued" }
+ CHARACTER(LEN=*), POINTER :: f4
+ f4 = ""
+END FUNCTION F2
+
+!PR?????
+pure FUNCTION F3() ! { dg-error "cannot be pure" }
+ CHARACTER(LEN=*) :: F3
+ F3 = ""
+END FUNCTION F3
+
+function not_OK (ch)
+ character(*) not_OK, ch ! OK in an external function
+ not_OK = ch
+end function not_OK
+
+ use INTEGER_SETS
+ use m1
+
+ character(4) :: answer
+ character(*), external :: not_OK
+ integer :: i
+ type (set) :: z
+
+ interface
+ function ext (i)
+ character(*) :: ext
+ integer :: i
+ end function ext
+ end interface
+
+ answer = i.IN.z ! { dg-error "cannot be used|Operands of user operator" }
+ answer = ext (2) ! { dg-error "but cannot be used" }
+
+ answer = not_OK ("unOK") ! { dg-error "since it is not a dummy" }
+
+END
+
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 index 0000000..bd7d713 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/assumed_charlen_function_2.f90 @@ -0,0 +1,13 @@ +! { dg-do compile }
+! Tests the fix for PR25416, which ICED in gfc_conv_function_call, when
+! treating SPREAD in the statement below.
+!
+! Contributed by Ulrich Weigand <uweigand@gcc.gnu.org>
+function bug(self,strvec) result(res)
+ character(*) :: self
+ character(*), dimension(:), intent(in) :: strvec
+ logical(kind=kind(.true.)) :: res
+
+ res = any(index(strvec,spread(self,1,size(strvec))) /= 0)
+end function
+
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 index 0000000..09c9be9 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/assumed_charlen_function_3.f90 @@ -0,0 +1,39 @@ +! { dg-do compile }
+! Tests the patch for PRs 25084, 20852, 25085 and 25086, all of
+! which involve assumed character length functions.
+! This test checks the things that should not emit errors.
+!
+! Contributed by Paul Thomas <pault@gcc.gnu.org>
+!
+function is_OK (ch) ! { dg-warning "is obsolescent in fortran 95" }
+ character(*) is_OK, ch ! OK in an external function
+ is_OK = ch
+end function is_OK
+
+! The warning occurs twice for the next line; for 'more_OK' and for 'fcn';
+function more_OK (ch, fcn) ! { dg-warning "is obsolescent in fortran 95" }
+ character(*) more_OK, ch
+ character (*), external :: fcn ! OK as a dummy argument
+ more_OK = fcn (ch)
+end function more_OK
+
+ character(4) :: answer
+ character(4), external :: is_OK, more_OK
+
+ answer = is_OK ("isOK") ! LEN defined in calling scope
+ print *, answer
+
+ answer = more_OK ("okay", is_OK) ! Actual arg has defined LEN
+ print *, answer
+
+ answer = also_OK ("OKOK")
+ print *, answer
+
+contains
+ function also_OK (ch)
+ character(4) also_OK
+ character(*) ch
+ also_OK = is_OK (ch) ! LEN obtained by host association
+ end function also_OK
+END
+
diff --git a/gcc/testsuite/gfortran.dg/global_references_2.f90 b/gcc/testsuite/gfortran.dg/global_references_2.f90 new file mode 100644 index 0000000..9566698 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/global_references_2.f90 @@ -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 |
