aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authorPaul Thomas <pault@gcc.gnu.org>2005-10-17 20:52:37 +0000
committerPaul Thomas <pault@gcc.gnu.org>2005-10-17 20:52:37 +0000
commit4213f93b6aea64f4ea5f8a539a3f0ad912bec1d2 (patch)
tree69e1371af15ca815b604fa39a051f202ee0a4764 /gcc/fortran
parentbe3914df4cc863fa52e3b74ad84ee683a4621e76 (diff)
downloadgcc-4213f93b6aea64f4ea5f8a539a3f0ad912bec1d2.zip
gcc-4213f93b6aea64f4ea5f8a539a3f0ad912bec1d2.tar.gz
gcc-4213f93b6aea64f4ea5f8a539a3f0ad912bec1d2.tar.bz2
re PR fortran/23446 (Valid internal subprogram array argument declaration is not accepted.)
2005-10-17 Paul Thomas <pault@gcc.gnu.org> PR fortran/23446 * gfortran.h: Primitive for gfc_is_formal_arg. * resolve.c(gfc_is_formal_arg): New function to signal across several function calls that formal argument lists are being processed. (resolve_formal_arglist): Set/reset the flag for gfc_is_formal_arg. *expr.c(check_restricted): Add check, via gfc_is_formal_arg, if symbol is part of an formal argument declaration. PR fortran/21459 * decl.c (add_init_expr_to_sym): Make a new character length for each variable, when the expression is NULL and link to cl_list. PR fortran/20866 * match.c (recursive_stmt_fcn): New function that tests if a statement function resurses through itself or other other statement functions. (gfc_match_st_function): Call recursive_stmt_fcn to check if this is recursive and to raise error if so. PR fortran/20849 PR fortran/20853 * resolve.c (resolve_symbol): Errors for assumed size arrays with default initializer and for external objects with an initializer. PR fortran/20837 * decl.c (match_attr_spec): Prevent PUBLIC from being used outside a module. 2005-10-17 Paul Thomas <pault@gcc.gnu.org> PR fortran/23446 * gfortran.dg/host_dummy_index_1.f90: New test. PR fortran/21459 gfortran.dg/automatic_char_len_2.f90: New test. PR fortran/20866 gfortran.dg/recursive_statement_functions.f90: New test. PR fortran/20853 gfortran.dg/assumed_size_dt_dummy.f90: New test. PR fortran/20849 gfortran.dg/external_initializer.f90: New test. PR fortran/20837 non_module_public.f90: New test. From-SVN: r105518
Diffstat (limited to 'gcc/fortran')
-rw-r--r--gcc/fortran/ChangeLog33
-rw-r--r--gcc/fortran/decl.c21
-rw-r--r--gcc/fortran/expr.c6
-rw-r--r--gcc/fortran/gfortran.h1
-rw-r--r--gcc/fortran/match.c89
-rw-r--r--gcc/fortran/resolve.c42
6 files changed, 191 insertions, 1 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index dca2ef2..ff6246a 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,36 @@
+2005-10-17 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/23446
+ * gfortran.h: Primitive for gfc_is_formal_arg.
+ * resolve.c(gfc_is_formal_arg): New function to signal across
+ several function calls that formal argument lists are being
+ processed.
+ (resolve_formal_arglist): Set/reset the flag for gfc_is_formal_arg.
+ *expr.c(check_restricted): Add check, via gfc_is_formal_arg, if
+ symbol is part of an formal argument declaration.
+
+ PR fortran/21459
+ * decl.c (add_init_expr_to_sym): Make a new character
+ length for each variable, when the expression is NULL
+ and link to cl_list.
+
+ PR fortran/20866
+ * match.c (recursive_stmt_fcn): New function that tests if
+ a statement function resurses through itself or other other
+ statement functions.
+ (gfc_match_st_function): Call recursive_stmt_fcn to check
+ if this is recursive and to raise error if so.
+
+ PR fortran/20849
+ PR fortran/20853
+ * resolve.c (resolve_symbol): Errors for assumed size arrays
+ with default initializer and for external objects with an
+ initializer.
+
+ PR fortran/20837
+ * decl.c (match_attr_spec): Prevent PUBLIC from being used
+ outside a module.
+
2005-10-16 Erik Edelmann <erik.edelmann@iki.fi>
PR 22273
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 20d1f8a..21f1089 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -746,6 +746,13 @@ add_init_expr_to_sym (const char *name, gfc_expr ** initp,
/* Update symbol character length according initializer. */
if (sym->ts.cl->length == NULL)
{
+ /* If there are multiple CHARACTER variables declared on
+ the same line, we don't want them to share the same
+ length. */
+ sym->ts.cl = gfc_get_charlen ();
+ sym->ts.cl->next = gfc_current_ns->cl_list;
+ gfc_current_ns->cl_list = sym->ts.cl;
+
if (init->expr_type == EXPR_CONSTANT)
sym->ts.cl->length =
gfc_int_expr (init->value.character.length);
@@ -1867,6 +1874,20 @@ match_attr_spec (void)
goto cleanup;
}
+ if ((d == DECL_PRIVATE || d == DECL_PUBLIC)
+ && gfc_current_state () != COMP_MODULE)
+ {
+ if (d == DECL_PRIVATE)
+ attr = "PRIVATE";
+ else
+ attr = "PUBLIC";
+
+ gfc_error ("%s attribute at %L is not allowed outside of a MODULE",
+ attr, &seen_at[d]);
+ m = MATCH_ERROR;
+ goto cleanup;
+ }
+
switch (d)
{
case DECL_ALLOCATABLE:
diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c
index 16d35c4..ebfd848 100644
--- a/gcc/fortran/expr.c
+++ b/gcc/fortran/expr.c
@@ -1673,12 +1673,16 @@ check_restricted (gfc_expr * e)
break;
}
+ /* gfc_is_formal_arg broadcasts that a formal argument list is being processed
+ in resolve.c(resolve_formal_arglist). This is done so that host associated
+ dummy array indices are accepted (PR23446). */
if (sym->attr.in_common
|| sym->attr.use_assoc
|| sym->attr.dummy
|| sym->ns != gfc_current_ns
|| (sym->ns->proc_name != NULL
- && sym->ns->proc_name->attr.flavor == FL_MODULE))
+ && sym->ns->proc_name->attr.flavor == FL_MODULE)
+ || gfc_is_formal_arg ())
{
t = SUCCESS;
break;
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 63b4b93..8947613 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -1805,6 +1805,7 @@ int gfc_elemental (gfc_symbol *);
try gfc_resolve_iterator (gfc_iterator *, bool);
try gfc_resolve_index (gfc_expr *, int);
try gfc_resolve_dim_arg (gfc_expr *);
+int gfc_is_formal_arg (void);
/* array.c */
void gfc_free_array_spec (gfc_array_spec *);
diff --git a/gcc/fortran/match.c b/gcc/fortran/match.c
index 3f94874..eac5697 100644
--- a/gcc/fortran/match.c
+++ b/gcc/fortran/match.c
@@ -2700,6 +2700,88 @@ cleanup:
return MATCH_ERROR;
}
+/* Check that a statement function is not recursive. This is done by looking
+ for the statement function symbol(sym) by looking recursively through its
+ expression(e). If a reference to sym is found, true is returned. */
+static bool
+recursive_stmt_fcn (gfc_expr *e, gfc_symbol *sym)
+{
+ gfc_actual_arglist *arg;
+ gfc_ref *ref;
+ int i;
+
+ if (e == NULL)
+ return false;
+
+ switch (e->expr_type)
+ {
+ case EXPR_FUNCTION:
+ for (arg = e->value.function.actual; arg; arg = arg->next)
+ {
+ if (sym->name == arg->name
+ || recursive_stmt_fcn (arg->expr, sym))
+ return true;
+ }
+
+ /* Check the name before testing for nested recursion! */
+ if (sym->name == e->symtree->n.sym->name)
+ return true;
+
+ /* Catch recursion via other statement functions. */
+ if (e->symtree->n.sym->attr.proc == PROC_ST_FUNCTION
+ && e->symtree->n.sym->value
+ && recursive_stmt_fcn (e->symtree->n.sym->value, sym))
+ return true;
+
+ break;
+
+ case EXPR_VARIABLE:
+ if (sym->name == e->symtree->n.sym->name)
+ return true;
+ break;
+
+ case EXPR_OP:
+ if (recursive_stmt_fcn (e->value.op.op1, sym)
+ || recursive_stmt_fcn (e->value.op.op2, sym))
+ return true;
+ break;
+
+ default:
+ break;
+ }
+
+ /* Component references do not need to be checked. */
+ if (e->ref)
+ {
+ for (ref = e->ref; ref; ref = ref->next)
+ {
+ switch (ref->type)
+ {
+ case REF_ARRAY:
+ for (i = 0; i < ref->u.ar.dimen; i++)
+ {
+ if (recursive_stmt_fcn (ref->u.ar.start[i], sym)
+ || recursive_stmt_fcn (ref->u.ar.end[i], sym)
+ || recursive_stmt_fcn (ref->u.ar.stride[i], sym))
+ return true;
+ }
+ break;
+
+ case REF_SUBSTRING:
+ if (recursive_stmt_fcn (ref->u.ss.start, sym)
+ || recursive_stmt_fcn (ref->u.ss.end, sym))
+ return true;
+
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ return false;
+}
+
/* Match a statement function declaration. It is so easy to match
non-statement function statements with a MATCH_ERROR as opposed to
@@ -2734,6 +2816,13 @@ gfc_match_st_function (void)
if (m == MATCH_ERROR)
return m;
+ if (recursive_stmt_fcn (expr, sym))
+ {
+ gfc_error ("Statement function at %L is recursive",
+ &expr->where);
+ return MATCH_ERROR;
+ }
+
sym->value = expr;
return MATCH_YES;
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index 5de16ba..66ebd86 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -50,6 +50,16 @@ static code_stack *cs_base = NULL;
static int forall_flag;
+/* Nonzero if we are processing a formal arglist. The corresponding function
+ resets the flag each time that it is read. */
+static int formal_arg_flag = 0;
+
+int
+gfc_is_formal_arg (void)
+{
+ return formal_arg_flag;
+}
+
/* Resolve types of formal argument lists. These have to be done early so that
the formal argument lists of module procedures can be copied to the
containing module before the individual procedures are resolved
@@ -78,6 +88,8 @@ resolve_formal_arglist (gfc_symbol * proc)
|| (sym->as && sym->as->rank > 0))
proc->attr.always_explicit = 1;
+ formal_arg_flag = 1;
+
for (f = proc->formal; f; f = f->next)
{
sym = f->sym;
@@ -224,6 +236,7 @@ resolve_formal_arglist (gfc_symbol * proc)
}
}
}
+ formal_arg_flag = 0;
}
@@ -4301,6 +4314,26 @@ resolve_symbol (gfc_symbol * sym)
}
}
+ /* An assumed-size array with INTENT(OUT) shall not be of a type for which
+ default initialization is defined (5.1.2.4.4). */
+ if (sym->ts.type == BT_DERIVED
+ && sym->attr.dummy
+ && sym->attr.intent == INTENT_OUT
+ && sym->as->type == AS_ASSUMED_SIZE)
+ {
+ for (c = sym->ts.derived->components; c; c = c->next)
+ {
+ if (c->initializer)
+ {
+ gfc_error ("The INTENT(OUT) dummy argument '%s' at %L is "
+ "ASSUMED SIZE and so cannot have a default initializer",
+ sym->name, &sym->declared_at);
+ return;
+ }
+ }
+ }
+
+
/* Ensure that derived type formal arguments of a public procedure
are not of a private type. */
if (sym->attr.flavor == FL_PROCEDURE
@@ -4427,6 +4460,15 @@ resolve_symbol (gfc_symbol * sym)
break;
default:
+
+ /* An external symbol falls through to here if it is not referenced. */
+ if (sym->attr.external && sym->value)
+ {
+ gfc_error ("External object at %L may not have an initializer",
+ &sym->declared_at);
+ return;
+ }
+
break;
}