This is the mail archive of the
fortran@gcc.gnu.org
mailing list for the GNU Fortran project.
Re: Procedure Pointer Components
- From: "Janus Weil" <jaydub66 at googlemail dot com>
- To: "Fortran List" <fortran at gcc dot gnu dot org>
- Cc: "Daniel Kraft" <d at domob dot eu>, "Tobias Burnus" <burnus at net-b dot de>
- Date: Sun, 31 Aug 2008 15:33:11 +0200
- Subject: Re: Procedure Pointer Components
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from:to :subject:cc:in-reply-to:mime-version:content-type:references; bh=Zv4ZkGP/pKOD6GxB5zaJRGR7xlPlxivkViGBoUDuwp0=; b=kzRJJyT3hj8fEQNm7FK+rUP+O686aYA49Wg3+fIPcr1SsbwtoGWSvHlG5LflOxT0+i B6db4xyzc4MLNDvlwitTzyeuQ2jXE+qJUFIk66XZoU0qCMfJsJvlJaekNGmHpcfJeh8Y A99bK4QyxL9SLaJ5pDulj7fRkB276s6x/D0m0=
- Domainkey-signature: a=rsa-sha1; c=nofws; d=googlemail.com; s=gamma; h=message-id:date:from:to:subject:cc:in-reply-to:mime-version :content-type:references; b=f8ZuBTZi02whdKVbV2F1XTUHcNzHhUamTAXkdhp/cPu5BqUlq/BUi2x5YFW2+Of1n0 UUXHM58Yktszdw6NDKcnW0GoAJMc66ke3ZB5fPbGfSONLhBByCUkqE9iQYxmVFtQNPt/ dj3Ftn3vlyJYMnqnkhqJd68Ve6o3qIPjeH9w8=
- References: <854832d40808251540t1bfba140o61115268ab4a42d4@mail.gmail.com> <48B3A301.5030800@domob.eu> <854832d40808252359k45378579vc1646a6f06d16bd7@mail.gmail.com>
Hi all,
here is an updated version of my procedure pointer components patch.
Unfortunately it still does not really handle actual calls to PPCs. To
implement this, I think it would be best to put PPCs into the
f2k_derived namespace (everything else would be really messy). Unless
anyone comes up with an argument why I should not do this, I will try
to implement it now and hope the patch can still make it into 4.4
somehow.
Cheers,
Janus
Index: gcc/testsuite/gfortran.dg/proc_decl_1.f90
===================================================================
--- gcc/testsuite/gfortran.dg/proc_decl_1.f90 (revision 139797)
+++ gcc/testsuite/gfortran.dg/proc_decl_1.f90 (working copy)
@@ -41,7 +41,7 @@ program prog
procedure(amax0) :: my2 ! { dg-error "not allowed in PROCEDURE statement" }
type t
- procedure(),pointer:: p ! { dg-error "not yet implemented" }
+ procedure(),pointer,nopass:: ppc
end type
real f, x
Index: gcc/fortran/trans-expr.c
===================================================================
--- gcc/fortran/trans-expr.c (revision 139797)
+++ gcc/fortran/trans-expr.c (working copy)
@@ -2013,6 +2013,7 @@ gfc_apply_interface_mapping_to_expr (gfc
break;
case EXPR_COMPCALL:
+ case EXPR_PPC:
gcc_unreachable ();
break;
}
@@ -3916,8 +3917,8 @@ gfc_trans_pointer_assignment (gfc_expr *
rse.want_pointer = 1;
gfc_conv_expr (&rse, expr2);
- if (expr1->symtree->n.sym->attr.proc_pointer
- && expr1->symtree->n.sym->attr.dummy)
+ if (is_proc_ptr_comp (expr1) || (expr1->symtree->n.sym->attr.proc_pointer
+ && expr1->symtree->n.sym->attr.dummy))
lse.expr = build_fold_indirect_ref (lse.expr);
gfc_add_block_to_block (&block, &lse.pre);
Index: gcc/fortran/decl.c
===================================================================
--- gcc/fortran/decl.c (revision 139797)
+++ gcc/fortran/decl.c (working copy)
@@ -1435,7 +1435,7 @@ build_struct (const char *name, gfc_char
gfc_constructor *ctor = c->initializer->value.constructor;
bool first = true;
- int first_len;
+ int first_len = -1;
has_ts = (c->initializer->ts.cl
&& c->initializer->ts.cl->length_from_typespec);
@@ -4081,6 +4081,177 @@ gfc_match_suffix (gfc_symbol *sym, gfc_s
}
+/* Match binding attributes for type-bound procedures (ppc=false)
+ or procedure pointer components (ppc=true). */
+
+static match
+match_binding_attributes (gfc_typebound_proc* ba, bool ppc)
+{
+ bool found_passing = false;
+ bool seen_ptr = false;
+ match m;
+
+ /* Intialize to defaults. Do so even before the MATCH_NO check so that in
+ this case the defaults are in there. */
+ ba->access = ACCESS_UNKNOWN;
+ ba->pass_arg = NULL;
+ ba->pass_arg_num = 0;
+ ba->nopass = 0;
+ ba->non_overridable = 0;
+
+ /* If we find a comma, we believe there are binding attributes. */
+ if (gfc_match_char (',') == MATCH_NO)
+ return MATCH_NO;
+
+ do
+ {
+ /* NOPASS flag. */
+ m = gfc_match (" nopass");
+ if (m == MATCH_ERROR)
+ goto error;
+ if (m == MATCH_YES)
+ {
+ if (found_passing)
+ {
+ gfc_error ("Binding attributes already specify passing, illegal"
+ " NOPASS at %C");
+ goto error;
+ }
+
+ found_passing = true;
+ ba->nopass = 1;
+ continue;
+ }
+
+ /* PASS possibly including argument. */
+ m = gfc_match (" pass");
+ if (m == MATCH_ERROR)
+ goto error;
+ if (m == MATCH_YES)
+ {
+ char arg[GFC_MAX_SYMBOL_LEN + 1];
+
+ if (found_passing)
+ {
+ gfc_error ("Binding attributes already specify passing, illegal"
+ " PASS at %C");
+ goto error;
+ }
+
+ m = gfc_match (" ( %n )", arg);
+ if (m == MATCH_ERROR)
+ goto error;
+ if (m == MATCH_YES)
+ ba->pass_arg = xstrdup (arg);
+ gcc_assert ((m == MATCH_YES) == (ba->pass_arg != NULL));
+
+ found_passing = true;
+ ba->nopass = 0;
+ continue;
+ }
+
+ /* Access specifier. */
+
+ m = gfc_match (" public");
+ if (m == MATCH_ERROR)
+ goto error;
+ if (m == MATCH_YES)
+ {
+ if (ba->access != ACCESS_UNKNOWN)
+ {
+ gfc_error ("Duplicate access-specifier at %C");
+ goto error;
+ }
+
+ ba->access = ACCESS_PUBLIC;
+ continue;
+ }
+
+ m = gfc_match (" private");
+ if (m == MATCH_ERROR)
+ goto error;
+ if (m == MATCH_YES)
+ {
+ if (ba->access != ACCESS_UNKNOWN)
+ {
+ gfc_error ("Duplicate access-specifier at %C");
+ goto error;
+ }
+
+ ba->access = ACCESS_PRIVATE;
+ continue;
+ }
+
+ if (!ppc)
+ {
+ /* NON_OVERRIDABLE flag. */
+ m = gfc_match (" non_overridable");
+ if (m == MATCH_ERROR)
+ goto error;
+ if (m == MATCH_YES)
+ {
+ if (ba->non_overridable)
+ {
+ gfc_error ("Duplicate NON_OVERRIDABLE at %C");
+ goto error;
+ }
+
+ ba->non_overridable = 1;
+ continue;
+ }
+
+ /* DEFERRED flag. */
+ /* TODO: Handle really once implemented. */
+ m = gfc_match (" deferred");
+ if (m == MATCH_ERROR)
+ goto error;
+ if (m == MATCH_YES)
+ {
+ gfc_error ("DEFERRED not yet implemented at %C");
+ goto error;
+ }
+ }
+
+ if (ppc)
+ {
+ /* POINTER flag. */
+ m = gfc_match (" pointer");
+ if (m == MATCH_ERROR)
+ goto error;
+ if (m == MATCH_YES)
+ {
+ if (seen_ptr)
+ {
+ gfc_error ("Duplicate POINTER attribute at %C");
+ goto error;
+ }
+
+ seen_ptr = true;
+ continue;
+ }
+ }
+
+ /* Nothing matching found. */
+ gfc_error ("Expected binding attribute at %C");
+ goto error;
+ }
+ while (gfc_match_char (',') == MATCH_YES);
+
+ if (ppc && !seen_ptr)
+ {
+ gfc_error ("POINTER attribute is required for procedure pointer component"
+ " at %C");
+ goto error;
+ }
+
+ return MATCH_YES;
+
+error:
+ gfc_free (ba->pass_arg);
+ return MATCH_ERROR;
+}
+
+
/* Match a PROCEDURE declaration (R1211). */
static match
@@ -4089,6 +4260,7 @@ match_procedure_decl (void)
match m;
locus old_loc, entry_loc;
gfc_symbol *sym, *proc_if = NULL;
+ gfc_typespec ts;
int num;
gfc_expr *initializer = NULL;
@@ -4165,11 +4337,42 @@ got_ts:
}
/* Parse attributes. */
- m = match_attr_spec();
- if (m == MATCH_ERROR)
- return MATCH_ERROR;
+ if (gfc_current_state () != COMP_DERIVED)
+ {
+ m = match_attr_spec();
+ if (m == MATCH_ERROR)
+ return MATCH_ERROR;
+ }
+ else
+ {
+ gfc_typebound_proc* tb = XCNEW (gfc_typebound_proc);
+ tb->where = gfc_current_locus;
+ m = match_binding_attributes (tb, true);
+ gfc_clear_attr (¤t_attr);
+ current_attr.proc_pointer = 1;
+ current_attr.access = tb->access;
+ if (m == MATCH_ERROR)
+ return m;
+
+ /* Match the colons. */
+ m = gfc_match (" ::");
+ if (m == MATCH_ERROR)
+ return m;
+ if (m != MATCH_YES)
+ {
+ gfc_error ("Expected '::' after binding-attributes at %C");
+ return MATCH_ERROR;
+ }
+
+ if (!tb->nopass && proc_if == NULL)
+ {
+ gfc_error("Procedure with NOPASS or with explicit interface required at %C");
+ return MATCH_ERROR;
+ }
+ }
/* Get procedure symbols. */
+ ts = current_ts;
for(num=1;;num++)
{
m = gfc_match_symbol (&sym, 0);
@@ -4220,18 +4423,18 @@ got_ts:
sym->ts.interface = proc_if;
sym->attr.untyped = 1;
}
- else if (current_ts.type != BT_UNKNOWN)
+ else if (ts.type != BT_UNKNOWN)
{
- sym->ts = current_ts;
+ sym->ts = ts;
sym->ts.interface = gfc_new_symbol ("", gfc_current_ns);
- sym->ts.interface->ts = current_ts;
+ sym->ts.interface->ts = ts;
sym->ts.interface->attr.function = 1;
sym->attr.function = sym->ts.interface->attr.function;
}
if (gfc_match (" =>") == MATCH_YES)
{
- if (!current_attr.pointer)
+ if (!current_attr.pointer && !current_attr.proc_pointer)
{
gfc_error ("Initialization at %C isn't for a pointer variable");
m = MATCH_ERROR;
@@ -4255,13 +4458,22 @@ got_ts:
if (m != MATCH_YES)
goto cleanup;
- if (add_init_expr_to_sym (sym->name, &initializer, &gfc_current_locus)
- != SUCCESS)
+ if (gfc_current_state () != COMP_DERIVED
+ && add_init_expr_to_sym (sym->name, &initializer,
+ &gfc_current_locus)
+ != SUCCESS)
goto cleanup;
-
}
- gfc_set_sym_referenced (sym);
+ if (gfc_current_state () != COMP_DERIVED)
+ gfc_set_sym_referenced (sym);
+ else
+ {
+ current_ts = sym->ts;
+ if (build_struct (sym->name, sym->ts.cl, &initializer, &sym->as)
+ != SUCCESS)
+ goto cleanup;
+ }
if (gfc_match_eos () == MATCH_YES)
return MATCH_YES;
@@ -4339,15 +4551,12 @@ gfc_match_procedure (void)
case COMP_MODULE:
case COMP_SUBROUTINE:
case COMP_FUNCTION:
+ case COMP_DERIVED:
m = match_procedure_decl ();
break;
case COMP_INTERFACE:
m = match_procedure_in_interface ();
break;
- case COMP_DERIVED:
- gfc_error ("Fortran 2003: Procedure components at %C are not yet"
- " implemented in gfortran");
- return MATCH_ERROR;
case COMP_DERIVED_CONTAINS:
m = match_procedure_in_type ();
break;
@@ -6718,146 +6927,6 @@ cleanup:
}
-/* Match binding attributes. */
-
-static match
-match_binding_attributes (gfc_typebound_proc* ba)
-{
- bool found_passing = false;
- match m;
-
- /* Intialize to defaults. Do so even before the MATCH_NO check so that in
- this case the defaults are in there. */
- ba->access = ACCESS_UNKNOWN;
- ba->pass_arg = NULL;
- ba->pass_arg_num = 0;
- ba->nopass = 0;
- ba->non_overridable = 0;
-
- /* If we find a comma, we believe there are binding attributes. */
- if (gfc_match_char (',') == MATCH_NO)
- return MATCH_NO;
-
- do
- {
- /* NOPASS flag. */
- m = gfc_match (" nopass");
- if (m == MATCH_ERROR)
- goto error;
- if (m == MATCH_YES)
- {
- if (found_passing)
- {
- gfc_error ("Binding attributes already specify passing, illegal"
- " NOPASS at %C");
- goto error;
- }
-
- found_passing = true;
- ba->nopass = 1;
- continue;
- }
-
- /* NON_OVERRIDABLE flag. */
- m = gfc_match (" non_overridable");
- if (m == MATCH_ERROR)
- goto error;
- if (m == MATCH_YES)
- {
- if (ba->non_overridable)
- {
- gfc_error ("Duplicate NON_OVERRIDABLE at %C");
- goto error;
- }
-
- ba->non_overridable = 1;
- continue;
- }
-
- /* DEFERRED flag. */
- /* TODO: Handle really once implemented. */
- m = gfc_match (" deferred");
- if (m == MATCH_ERROR)
- goto error;
- if (m == MATCH_YES)
- {
- gfc_error ("DEFERRED not yet implemented at %C");
- goto error;
- }
-
- /* PASS possibly including argument. */
- m = gfc_match (" pass");
- if (m == MATCH_ERROR)
- goto error;
- if (m == MATCH_YES)
- {
- char arg[GFC_MAX_SYMBOL_LEN + 1];
-
- if (found_passing)
- {
- gfc_error ("Binding attributes already specify passing, illegal"
- " PASS at %C");
- goto error;
- }
-
- m = gfc_match (" ( %n )", arg);
- if (m == MATCH_ERROR)
- goto error;
- if (m == MATCH_YES)
- ba->pass_arg = xstrdup (arg);
- gcc_assert ((m == MATCH_YES) == (ba->pass_arg != NULL));
-
- found_passing = true;
- ba->nopass = 0;
- continue;
- }
-
- /* Access specifier. */
-
- m = gfc_match (" public");
- if (m == MATCH_ERROR)
- goto error;
- if (m == MATCH_YES)
- {
- if (ba->access != ACCESS_UNKNOWN)
- {
- gfc_error ("Duplicate access-specifier at %C");
- goto error;
- }
-
- ba->access = ACCESS_PUBLIC;
- continue;
- }
-
- m = gfc_match (" private");
- if (m == MATCH_ERROR)
- goto error;
- if (m == MATCH_YES)
- {
- if (ba->access != ACCESS_UNKNOWN)
- {
- gfc_error ("Duplicate access-specifier at %C");
- goto error;
- }
-
- ba->access = ACCESS_PRIVATE;
- continue;
- }
-
- /* Nothing matching found. */
- gfc_error ("Expected binding attribute at %C");
- goto error;
- }
- while (gfc_match_char (',') == MATCH_YES);
-
- return MATCH_YES;
-
-error:
- gfc_free (ba->pass_arg);
- return MATCH_ERROR;
-}
-
-
/* Match a PROCEDURE specific binding inside a derived type. */
static match
@@ -6892,7 +6961,7 @@ match_procedure_in_type (void)
tb->where = gfc_current_locus;
/* Match binding attributes. */
- m = match_binding_attributes (tb);
+ m = match_binding_attributes (tb, false);
if (m == MATCH_ERROR)
return m;
seen_attrs = (m == MATCH_YES);
Index: gcc/fortran/gfortran.h
===================================================================
--- gcc/fortran/gfortran.h (revision 139797)
+++ gcc/fortran/gfortran.h (working copy)
@@ -151,7 +151,7 @@ bt;
/* Expression node types. */
typedef enum
{ EXPR_OP = 1, EXPR_FUNCTION, EXPR_CONSTANT, EXPR_VARIABLE,
- EXPR_SUBSTRING, EXPR_STRUCTURE, EXPR_ARRAY, EXPR_NULL, EXPR_COMPCALL
+ EXPR_SUBSTRING, EXPR_STRUCTURE, EXPR_ARRAY, EXPR_NULL, EXPR_COMPCALL, EXPR_PPC
}
expr_t;
@@ -841,6 +841,8 @@ typedef struct gfc_component
locus loc;
struct gfc_expr *initializer;
struct gfc_component *next;
+
+ struct gfc_formal_arglist *formal;
}
gfc_component;
@@ -1818,7 +1820,7 @@ typedef enum
EXEC_GOTO, EXEC_CALL, EXEC_COMPCALL, EXEC_ASSIGN_CALL, EXEC_RETURN,
EXEC_ENTRY, EXEC_PAUSE, EXEC_STOP, EXEC_CONTINUE, EXEC_INIT_ASSIGN,
EXEC_IF, EXEC_ARITHMETIC_IF, EXEC_DO, EXEC_DO_WHILE, EXEC_SELECT,
- EXEC_FORALL, EXEC_WHERE, EXEC_CYCLE, EXEC_EXIT,
+ EXEC_FORALL, EXEC_WHERE, EXEC_CYCLE, EXEC_EXIT, EXEC_CALL_PPC,
EXEC_ALLOCATE, EXEC_DEALLOCATE,
EXEC_OPEN, EXEC_CLOSE, EXEC_WAIT,
EXEC_READ, EXEC_WRITE, EXEC_IOLENGTH, EXEC_TRANSFER, EXEC_DT_END,
@@ -2408,6 +2410,8 @@ void gfc_expr_set_symbols_referenced (gf
gfc_try gfc_expr_check_typed (gfc_expr*, gfc_namespace*, bool);
+bool is_proc_ptr_comp (gfc_expr *);
+
/* st.c */
extern gfc_code new_st;
@@ -2513,6 +2517,7 @@ symbol_attribute gfc_expr_attr (gfc_expr
match gfc_match_rvalue (gfc_expr **);
match gfc_match_varspec (gfc_expr*, int, bool);
int gfc_check_digit (char, int);
+match gfc_match_comp (gfc_expr *);
/* trans.c */
void gfc_generate_code (gfc_namespace *);
Index: gcc/fortran/trans-stmt.c
===================================================================
--- gcc/fortran/trans-stmt.c (revision 139797)
+++ gcc/fortran/trans-stmt.c (working copy)
@@ -417,6 +417,63 @@ gfc_trans_call (gfc_code * code, bool de
}
+/* Translate a CALL statement with a procedure pointer components. */
+
+tree
+gfc_trans_call_ppc (gfc_code * code)
+{
+
+ gfc_se se;
+ /*gfc_ss * ss;*/
+ int has_alternate_specifier;
+
+ /* A CALL starts a new block because the actual arguments may have to
+ be evaluated first. */
+ gfc_init_se (&se, NULL);
+ gfc_start_block (&se.pre);
+
+ /*gcc_assert (code->resolved_sym);
+
+ ss = gfc_ss_terminator;
+ if (code->resolved_sym->attr.elemental)
+ ss = gfc_walk_elemental_function_args (ss, code->ext.actual, GFC_SS_REFERENCE);*/
+
+ /* Is not an elemental subroutine call with array valued arguments. */
+ /*if (ss == gfc_ss_terminator)
+ {*/
+
+ /* Translate the call. */
+ has_alternate_specifier
+ = gfc_conv_function_call (&se, code->resolved_sym, code->expr->value.function.actual,
+ NULL_TREE);
+
+ /* A subroutine without side-effect, by definition, does nothing! */
+ TREE_SIDE_EFFECTS (se.expr) = 1;
+
+ /* Chain the pieces together and return the block. */
+ if (has_alternate_specifier)
+ {
+ gfc_code *select_code;
+ gfc_symbol *sym;
+ select_code = code->next;
+ gcc_assert(select_code->op == EXEC_SELECT);
+ sym = select_code->expr->symtree->n.sym;
+ se.expr = convert (gfc_typenode_for_spec (&sym->ts), se.expr);
+ if (sym->backend_decl == NULL)
+ sym->backend_decl = gfc_get_symbol_decl (sym);
+ gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
+ }
+ else
+ gfc_add_expr_to_block (&se.pre, se.expr);
+
+ gfc_add_block_to_block (&se.pre, &se.post);
+ /*}*/
+
+ return gfc_finish_block (&se.pre);
+
+}
+
+
/* Translate the RETURN statement. */
tree
Index: gcc/fortran/expr.c
===================================================================
--- gcc/fortran/expr.c (revision 139797)
+++ gcc/fortran/expr.c (working copy)
@@ -182,6 +182,7 @@ free_expr0 (gfc_expr *e)
break;
case EXPR_COMPCALL:
+ case EXPR_PPC:
gfc_free_actual_arglist (e->value.compcall.actual);
break;
@@ -507,6 +508,7 @@ gfc_copy_expr (gfc_expr *p)
break;
case EXPR_COMPCALL:
+ case EXPR_PPC:
q->value.compcall.actual =
gfc_copy_actual_arglist (p->value.compcall.actual);
q->value.compcall.tbp = p->value.compcall.tbp;
@@ -1682,6 +1684,7 @@ gfc_simplify_expr (gfc_expr *p, int type
break;
case EXPR_COMPCALL:
+ case EXPR_PPC:
gcc_unreachable ();
break;
}
@@ -2890,7 +2893,7 @@ gfc_check_pointer_assign (gfc_expr *lval
symbol_attribute attr;
gfc_ref *ref;
int is_pure;
- int pointer, check_intent_in;
+ int pointer, check_intent_in, proc_pointer;
if (lvalue->symtree->n.sym->ts.type == BT_UNKNOWN
&& !lvalue->symtree->n.sym->attr.proc_pointer)
@@ -2913,16 +2916,18 @@ gfc_check_pointer_assign (gfc_expr *lval
/* Check INTENT(IN), unless the object itself is the component or
sub-component of a pointer. */
check_intent_in = 1;
- pointer = lvalue->symtree->n.sym->attr.pointer
- | lvalue->symtree->n.sym->attr.proc_pointer;
+ pointer = lvalue->symtree->n.sym->attr.pointer;
+ proc_pointer = lvalue->symtree->n.sym->attr.proc_pointer;
for (ref = lvalue->ref; ref; ref = ref->next)
{
- if (pointer)
+ if (pointer || proc_pointer)
check_intent_in = 0;
if (ref->type == REF_COMPONENT && ref->u.c.component->attr.pointer)
pointer = 1;
+ else if (ref->type == REF_COMPONENT && ref->u.c.component->attr.proc_pointer)
+ proc_pointer = 1;
}
if (check_intent_in && lvalue->symtree->n.sym->attr.intent == INTENT_IN)
@@ -2932,7 +2937,7 @@ gfc_check_pointer_assign (gfc_expr *lval
return FAILURE;
}
- if (!pointer)
+ if (!pointer && !proc_pointer)
{
gfc_error ("Pointer assignment to non-POINTER at %L", &lvalue->where);
return FAILURE;
@@ -2954,7 +2959,7 @@ gfc_check_pointer_assign (gfc_expr *lval
return SUCCESS;
/* TODO checks on rvalue for a procedure pointer assignment. */
- if (lvalue->symtree->n.sym->attr.proc_pointer)
+ if (proc_pointer)
return SUCCESS;
if (!gfc_compare_types (&lvalue->ts, &rvalue->ts))
@@ -3281,6 +3286,26 @@ gfc_expr_set_symbols_referenced (gfc_exp
gfc_traverse_expr (expr, NULL, expr_set_symbols_referenced, 0);
}
+bool
+is_proc_ptr_comp (gfc_expr *expr)
+{
+ gfc_ref *r;
+ bool ppc = false;
+ for (r = expr->ref; r; r = r->next)
+ {
+ switch (r->type)
+ {
+ case REF_COMPONENT:
+ ppc = r->u.c.component->attr.proc_pointer;
+ break;
+ default:
+ /* Do nothing. */
+ break;
+ }
+ }
+ return ppc;
+}
+
/* Walk an expression tree and check each variable encountered for being typed.
If strict is not set, a top-level variable is tolerated untyped in -std=gnu
Index: gcc/fortran/module.c
===================================================================
--- gcc/fortran/module.c (revision 139797)
+++ gcc/fortran/module.c (working copy)
@@ -3032,6 +3032,7 @@ mio_expr (gfc_expr **ep)
break;
case EXPR_COMPCALL:
+ case EXPR_PPC:
gcc_unreachable ();
break;
}
Index: gcc/fortran/trans.c
===================================================================
--- gcc/fortran/trans.c (revision 139797)
+++ gcc/fortran/trans.c (working copy)
@@ -1052,6 +1052,12 @@ gfc_trans_code (gfc_code * code)
res = gfc_trans_call (code, true);
break;
+ case EXEC_CALL_PPC:
+ gfc_error ("PPC call not implemented");
+ return build_empty_stmt ();
+ /*res = gfc_trans_call_ppc (code);*/
+ break;
+
case EXEC_RETURN:
res = gfc_trans_return (code);
break;
Index: gcc/fortran/trans-types.c
===================================================================
--- gcc/fortran/trans-types.c (revision 139797)
+++ gcc/fortran/trans-types.c (working copy)
@@ -1879,6 +1879,8 @@ gfc_get_derived_type (gfc_symbol * deriv
{
if (c->ts.type == BT_DERIVED)
field_type = c->ts.derived->backend_decl;
+ else if (c->attr.proc_pointer)
+ field_type = pfunc_type_node;
else
{
if (c->ts.type == BT_CHARACTER)
Index: gcc/fortran/resolve.c
===================================================================
--- gcc/fortran/resolve.c (revision 139797)
+++ gcc/fortran/resolve.c (working copy)
@@ -835,7 +835,8 @@ resolve_structure_cons (gfc_expr *expr)
}
if (cons->expr->expr_type == EXPR_NULL
- && !(comp->attr.pointer || comp->attr.allocatable))
+ && !(comp->attr.pointer || comp->attr.allocatable
+ || comp->attr.proc_pointer))
{
t = FAILURE;
gfc_error ("The NULL in the derived type constructor at %L is "
@@ -4465,6 +4466,11 @@ gfc_resolve_expr (gfc_expr *e)
t = SUCCESS;
break;
+ case EXPR_PPC:
+ /* TODO: Resolve procedure pointer components. */
+ t = SUCCESS;
+ break;
+
case EXPR_ARRAY:
t = FAILURE;
if (resolve_ref (e) == FAILURE)
@@ -6452,6 +6458,10 @@ resolve_code (gfc_code *code, gfc_namesp
resolve_typebound_call (code);
break;
+ case EXEC_CALL_PPC:
+ /* TODO: Resolve calls to procedure pointer components. */
+ break;
+
case EXEC_SELECT:
/* Select is complicated. Also, a SELECT construct could be
a transformed computed GOTO. */
@@ -8123,6 +8133,32 @@ resolve_fl_derived (gfc_symbol *sym)
for (c = sym->components; c != NULL; c = c->next)
{
+ if (c->attr.proc_pointer && c->ts.interface
+ /*&& c->attr.if_source != IFSRC_DECL*/)
+ {
+ if (c->ts.interface->attr.procedure)
+ gfc_error ("Interface '%s', used by procedure '%s' at %L, is "
+ "declared in a later PROCEDURE statement",
+ sym->ts.interface->name, sym->name,&sym->declared_at);
+
+ /* Get the attributes from the interface (now resolved). */
+ if (c->ts.interface->attr.if_source || c->ts.interface->attr.intrinsic)
+ {
+ gfc_symbol *ifc = c->ts.interface;
+ c->ts = ifc->ts;
+ c->ts.interface = ifc;
+ c->attr = ifc->attr;
+ c->as = gfc_copy_array_spec (c->as);
+/*TODO: copy_formal_args (sym, ifc); */
+ }
+ else if (c->ts.interface->name[0] != '\0')
+ {
+ gfc_error ("Interface '%s' of procedure '%s' at %L must be explicit",
+ c->ts.interface->name, c->name, &c->loc);
+ return FAILURE;
+ }
+ }
+
/* If this type is an extension, see if this component has the same name
as an inherited type-bound procedure. */
if (super_type
Index: gcc/fortran/st.c
===================================================================
--- gcc/fortran/st.c (revision 139797)
+++ gcc/fortran/st.c (working copy)
@@ -109,6 +109,7 @@ gfc_free_statement (gfc_code *p)
break;
case EXEC_COMPCALL:
+ case EXEC_CALL_PPC:
gfc_free_expr (p->expr);
case EXEC_CALL:
case EXEC_ASSIGN_CALL:
Index: gcc/fortran/match.c
===================================================================
--- gcc/fortran/match.c (revision 139797)
+++ gcc/fortran/match.c (working copy)
@@ -1330,6 +1330,7 @@ match
gfc_match_pointer_assignment (void)
{
gfc_expr *lvalue, *rvalue;
+ gfc_ref *ref;
locus old_loc;
match m;
@@ -1348,6 +1349,10 @@ gfc_match_pointer_assignment (void)
if (lvalue->symtree->n.sym->attr.proc_pointer)
gfc_matching_procptr_assignment = 1;
+ for (ref = lvalue->ref; ref; ref = ref->next)
+ if (ref->type == REF_COMPONENT && ref->u.c.component->attr.proc_pointer)
+ gfc_matching_procptr_assignment = 1;
+
m = gfc_match (" %e%t", &rvalue);
gfc_matching_procptr_assignment = 0;
if (m != MATCH_YES)
@@ -2538,13 +2543,21 @@ match_typebound_call (gfc_symtree* varst
return MATCH_ERROR;
}
- if (base->expr_type != EXPR_COMPCALL)
+ /*if (base->expr_type != EXPR_COMPCALL)
{
gfc_error ("Expected type-bound procedure reference at %C");
return MATCH_ERROR;
- }
+ }*/
- new_st.op = EXEC_COMPCALL;
+ if (base->expr_type == EXPR_COMPCALL)
+ new_st.op = EXEC_COMPCALL;
+ else if (base->expr_type == EXPR_PPC)
+ new_st.op = EXEC_CALL_PPC;
+ else
+ {
+ gfc_error ("Expected TBP or PPC at %C");
+ return MATCH_ERROR;
+ }
new_st.expr = base;
return MATCH_YES;
Index: gcc/fortran/parse.c
===================================================================
--- gcc/fortran/parse.c (revision 139797)
+++ gcc/fortran/parse.c (working copy)
@@ -1866,15 +1866,11 @@ parse_derived (void)
unexpected_eof ();
case ST_DATA_DECL:
+ case ST_PROCEDURE:
accept_statement (st);
seen_component = 1;
break;
- case ST_PROCEDURE:
- gfc_error ("PROCEDURE binding at %C must be inside CONTAINS");
- error_flag = 1;
- break;
-
case ST_FINAL:
gfc_error ("FINAL declaration at %C must be inside CONTAINS");
error_flag = 1;
@@ -1980,7 +1976,7 @@ endType:
}
/* Look for pointer components. */
- if (c->attr.pointer
+ if (c->attr.pointer || c->attr.proc_pointer
|| (c->ts.type == BT_DERIVED && c->ts.derived->attr.pointer_comp))
{
sym->attr.pointer_comp = 1;
Index: gcc/fortran/primary.c
===================================================================
--- gcc/fortran/primary.c (revision 139797)
+++ gcc/fortran/primary.c (working copy)
@@ -1819,6 +1819,13 @@ gfc_match_varspec (gfc_expr *primary, in
primary->ts = component->ts;
+ if (sub_flag && component->attr.proc_pointer)
+ {
+ primary->expr_type = EXPR_PPC;
+ m = gfc_match_actual_arglist(component->attr.subroutine, &primary->value.compcall.actual);
+ break;
+ }
+
if (component->as != NULL)
{
tail = extend_ref (primary, tail);
@@ -1915,7 +1922,7 @@ gfc_variable_attr (gfc_expr *expr, gfc_t
allocatable = attr.allocatable;
target = attr.target;
- if (pointer)
+ if (pointer || attr.proc_pointer)
target = 1;
if (ts != NULL && expr->ts.type == BT_UNKNOWN)
@@ -1961,7 +1968,7 @@ gfc_variable_attr (gfc_expr *expr, gfc_t
pointer = ref->u.c.component->attr.pointer;
allocatable = ref->u.c.component->attr.allocatable;
- if (pointer)
+ if (pointer || attr.proc_pointer)
target = 1;
break;