+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
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. */
/* 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);
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:
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;
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)
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;
+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
--- /dev/null
+! { 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
--- /dev/null
+! { 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
--- /dev/null
+! { 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
--- /dev/null
+! { 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