summaryrefslogtreecommitdiffstats
path: root/gcc/fortran/resolve.c
diff options
context:
space:
mode:
authorjanus <janus@138bc75d-0d04-0410-961f-82ee72b054a4>2009-07-25 11:56:35 +0000
committerjanus <janus@138bc75d-0d04-0410-961f-82ee72b054a4>2009-07-25 11:56:35 +0000
commitfe9b08a2c2202c07f1f02f83e8dfac36923b6662 (patch)
tree5f96889c85c7f39e41827b1e710416e711dd6077 /gcc/fortran/resolve.c
parent75d716e297bc9012a549da20ef1fa6180d8f050e (diff)
downloadppe42-gcc-fe9b08a2c2202c07f1f02f83e8dfac36923b6662.tar.gz
ppe42-gcc-fe9b08a2c2202c07f1f02f83e8dfac36923b6662.zip
2009-07-25 Janus Weil <janus@gcc.gnu.org>
PR fortran/39630 * decl.c (match_ppc_decl): Implement the PASS attribute for procedure pointer components. (match_binding_attributes): Ditto. * gfortran.h (gfc_component): Add member 'tb'. (gfc_typebound_proc): Add member 'ppc' and make 'pass_arg' const. * module.c (MOD_VERSION): Bump module version. (binding_ppc): New string constants. (mio_component): Only use formal args if component is a procedure pointer and add 'tb' member. (mio_typebound_proc): Include pass_arg and take care of procedure pointer components. * resolve.c (update_arglist_pass): Add argument 'name' and take care of optional arguments. (extract_ppc_passed_object): New function, analogous to extract_compcall_passed_object, but for procedure pointer components. (update_ppc_arglist): New function, analogous to update_compcall_arglist, but for procedure pointer components. (resolve_typebound_generic_call): Added argument to update_arglist_pass. (resolve_ppc_call, resolve_expr_ppc): Take care of PASS attribute. (resolve_fl_derived): Check the PASS argument for procedure pointer components. * symbol.c (verify_bind_c_derived_type): Reject procedure pointer components in BIND(C) types. 2009-07-25 Janus Weil <janus@gcc.gnu.org> PR fortran/39630 * gfortran.dg/proc_ptr_comp_3.f90: Modified. * gfortran.dg/proc_ptr_comp_pass_1.f90: New. * gfortran.dg/proc_ptr_comp_pass_2.f90: New. * gfortran.dg/proc_ptr_comp_pass_3.f90: New. * gfortran.dg/proc_ptr_comp_pass_4.f90: New. * gfortran.dg/proc_ptr_comp_pass_5.f90: New. * gfortran.dg/typebound_call_10.f03: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@150078 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fortran/resolve.c')
-rw-r--r--gcc/fortran/resolve.c191
1 files changed, 183 insertions, 8 deletions
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index e09167b1be2..aaab554d4de 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -4535,7 +4535,8 @@ fixup_charlen (gfc_expr *e)
procedures at the right position. */
static gfc_actual_arglist*
-update_arglist_pass (gfc_actual_arglist* lst, gfc_expr* po, unsigned argpos)
+update_arglist_pass (gfc_actual_arglist* lst, gfc_expr* po, unsigned argpos,
+ const char *name)
{
gcc_assert (argpos > 0);
@@ -4546,14 +4547,16 @@ update_arglist_pass (gfc_actual_arglist* lst, gfc_expr* po, unsigned argpos)
result = gfc_get_actual_arglist ();
result->expr = po;
result->next = lst;
+ if (name)
+ result->name = name;
return result;
}
- gcc_assert (lst);
- gcc_assert (argpos > 1);
-
- lst->next = update_arglist_pass (lst->next, po, argpos - 1);
+ if (lst)
+ lst->next = update_arglist_pass (lst->next, po, argpos - 1, name);
+ else
+ lst = update_arglist_pass (NULL, po, argpos - 1, name);
return lst;
}
@@ -4611,7 +4614,74 @@ update_compcall_arglist (gfc_expr* e)
gcc_assert (tbp->pass_arg_num > 0);
e->value.compcall.actual = update_arglist_pass (e->value.compcall.actual, po,
- tbp->pass_arg_num);
+ tbp->pass_arg_num,
+ tbp->pass_arg);
+
+ return SUCCESS;
+}
+
+
+/* Extract the passed object from a PPC call (a copy of it). */
+
+static gfc_expr*
+extract_ppc_passed_object (gfc_expr *e)
+{
+ gfc_expr *po;
+ gfc_ref **ref;
+
+ po = gfc_get_expr ();
+ po->expr_type = EXPR_VARIABLE;
+ po->symtree = e->symtree;
+ po->ref = gfc_copy_ref (e->ref);
+
+ /* Remove PPC reference. */
+ ref = &po->ref;
+ while ((*ref)->next)
+ (*ref) = (*ref)->next;
+ gfc_free_ref_list (*ref);
+ *ref = NULL;
+
+ if (gfc_resolve_expr (po) == FAILURE)
+ return NULL;
+
+ return po;
+}
+
+
+/* Update the actual arglist of a procedure pointer component to include the
+ passed-object. */
+
+static gfc_try
+update_ppc_arglist (gfc_expr* e)
+{
+ gfc_expr* po;
+ gfc_component *ppc;
+ gfc_typebound_proc* tb;
+
+ if (!gfc_is_proc_ptr_comp (e, &ppc))
+ return FAILURE;
+
+ tb = ppc->tb;
+
+ if (tb->error)
+ return FAILURE;
+ else if (tb->nopass)
+ return SUCCESS;
+
+ po = extract_ppc_passed_object (e);
+ if (!po)
+ return FAILURE;
+
+ if (po->rank > 0)
+ {
+ gfc_error ("Passed-object at %L must be scalar", &e->where);
+ return FAILURE;
+ }
+
+ gcc_assert (tb->pass_arg_num > 0);
+ e->value.compcall.actual = update_arglist_pass (e->value.compcall.actual, po,
+ tb->pass_arg_num,
+ tb->pass_arg);
return SUCCESS;
}
@@ -4714,7 +4784,8 @@ resolve_typebound_generic_call (gfc_expr* e)
gcc_assert (g->specific->pass_arg_num > 0);
gcc_assert (!g->specific->error);
- args = update_arglist_pass (args, po, g->specific->pass_arg_num);
+ args = update_arglist_pass (args, po, g->specific->pass_arg_num,
+ g->specific->pass_arg);
}
resolve_actual_arglist (args, target->attr.proc,
is_external_proc (target) && !target->formal);
@@ -4836,7 +4907,6 @@ resolve_ppc_call (gfc_code* c)
c->resolved_sym = c->expr1->symtree->n.sym;
c->expr1->expr_type = EXPR_VARIABLE;
- c->ext.actual = c->expr1->value.compcall.actual;
if (!comp->attr.subroutine)
gfc_add_subroutine (&comp->attr, comp->name, &c->expr1->where);
@@ -4844,6 +4914,11 @@ resolve_ppc_call (gfc_code* c)
if (resolve_ref (c->expr1) == FAILURE)
return FAILURE;
+ if (update_ppc_arglist (c->expr1) == FAILURE)
+ return FAILURE;
+
+ c->ext.actual = c->expr1->value.compcall.actual;
+
if (resolve_actual_arglist (c->ext.actual, comp->attr.proc,
comp->formal == NULL) == FAILURE)
return FAILURE;
@@ -4880,6 +4955,9 @@ resolve_expr_ppc (gfc_expr* e)
comp->formal == NULL) == FAILURE)
return FAILURE;
+ if (update_ppc_arglist (e) == FAILURE)
+ return FAILURE;
+
gfc_ppc_use (comp, &e->value.compcall.actual, &e->where);
return SUCCESS;
@@ -9095,6 +9173,103 @@ resolve_fl_derived (gfc_symbol *sym)
c->attr.implicit_type = 1;
}
+ /* Procedure pointer components: Check PASS arg. */
+ if (c->attr.proc_pointer && !c->tb->nopass && c->tb->pass_arg_num == 0)
+ {
+ gfc_symbol* me_arg;
+
+ if (c->tb->pass_arg)
+ {
+ gfc_formal_arglist* i;
+
+ /* If an explicit passing argument name is given, walk the arg-list
+ and look for it. */
+
+ me_arg = NULL;
+ c->tb->pass_arg_num = 1;
+ for (i = c->formal; i; i = i->next)
+ {
+ if (!strcmp (i->sym->name, c->tb->pass_arg))
+ {
+ me_arg = i->sym;
+ break;
+ }
+ c->tb->pass_arg_num++;
+ }
+
+ if (!me_arg)
+ {
+ gfc_error ("Procedure pointer component '%s' with PASS(%s) "
+ "at %L has no argument '%s'", c->name,
+ c->tb->pass_arg, &c->loc, c->tb->pass_arg);
+ c->tb->error = 1;
+ return FAILURE;
+ }
+ }
+ else
+ {
+ /* Otherwise, take the first one; there should in fact be at least
+ one. */
+ c->tb->pass_arg_num = 1;
+ if (!c->formal)
+ {
+ gfc_error ("Procedure pointer component '%s' with PASS at %L "
+ "must have at least one argument",
+ c->name, &c->loc);
+ c->tb->error = 1;
+ return FAILURE;
+ }
+ me_arg = c->formal->sym;
+ }
+
+ /* Now check that the argument-type matches. */
+ gcc_assert (me_arg);
+ if (me_arg->ts.type != BT_DERIVED
+ || me_arg->ts.derived != sym)
+ {
+ gfc_error ("Argument '%s' of '%s' with PASS(%s) at %L must be of"
+ " the derived type '%s'", me_arg->name, c->name,
+ me_arg->name, &c->loc, sym->name);
+ c->tb->error = 1;
+ return FAILURE;
+ }
+
+ /* Check for C453. */
+ if (me_arg->attr.dimension)
+ {
+ gfc_error ("Argument '%s' of '%s' with PASS(%s) at %L "
+ "must be scalar", me_arg->name, c->name, me_arg->name,
+ &c->loc);
+ c->tb->error = 1;
+ return FAILURE;
+ }
+
+ if (me_arg->attr.pointer)
+ {
+ gfc_error ("Argument '%s' of '%s' with PASS(%s) at %L "
+ "may not have the POINTER attribute", me_arg->name,
+ c->name, me_arg->name, &c->loc);
+ c->tb->error = 1;
+ return FAILURE;
+ }
+
+ if (me_arg->attr.allocatable)
+ {
+ gfc_error ("Argument '%s' of '%s' with PASS(%s) at %L "
+ "may not be ALLOCATABLE", me_arg->name, c->name,
+ me_arg->name, &c->loc);
+ c->tb->error = 1;
+ return FAILURE;
+ }
+
+ /* TODO: Make this an error once CLASS is implemented. */
+ if (!sym->attr.sequence)
+ gfc_warning ("Polymorphic entities are not yet implemented,"
+ " non-polymorphic passed-object dummy argument of '%s'"
+ " at %L accepted", c->name, &c->loc);
+
+ }
+
/* Check type-spec if this is not the parent-type component. */
if ((!sym->attr.extension || c != sym->components)
&& resolve_typespec_used (&c->ts, &c->loc, c->name) == FAILURE)
OpenPOWER on IntegriCloud