diff options
author | Daniel Kraft <d@domob.eu> | 2008-09-01 12:55:50 +0200 |
---|---|---|
committer | Daniel Kraft <domob@gcc.gnu.org> | 2008-09-01 12:55:50 +0200 |
commit | a64a8f2f267e1151d2c873aa3e02c7abe4fd4990 (patch) | |
tree | 66c5e272b10868f7048d89734fa754d3d8f51f9d | |
parent | f69bbb461b3a00afe8156ae949fb7014332bb3a1 (diff) | |
download | gcc-a64a8f2f267e1151d2c873aa3e02c7abe4fd4990.zip gcc-a64a8f2f267e1151d2c873aa3e02c7abe4fd4990.tar.gz gcc-a64a8f2f267e1151d2c873aa3e02c7abe4fd4990.tar.bz2 |
gfc-internals.texi (F2003 OOP), [...]): New chapter and section to document the internals of type-bound procedures.
2008-09-01 Daniel Kraft <d@domob.eu>
* gfc-internals.texi (F2003 OOP), (Type-bound Procedures): New chapter
and section to document the internals of type-bound procedures.
(gfc_expr): Document EXPR_COMPCALL.
* gfortran.h (struct gfc_expr): Remove unused `derived' from compcall.
* dump-parse-tree.c (show_compcall): New method.
(show_expr): Call it for EXPR_COMPCALL.
(show_typebound), (show_f2k_derived): New methods.
(show_symbol): Call show_f2k_derived.
(show_code_node): Handle EXEC_COMPCALL.
* primary.c (gfc_match_varspec): Don't initialize removed `derived' in
primary->value.compcall.
From-SVN: r139857
-rw-r--r-- | gcc/fortran/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/fortran/dump-parse-tree.c | 102 | ||||
-rw-r--r-- | gcc/fortran/gfc-internals.texi | 98 | ||||
-rw-r--r-- | gcc/fortran/gfortran.h | 1 | ||||
-rw-r--r-- | gcc/fortran/primary.c | 1 |
5 files changed, 214 insertions, 2 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 36da100..92a0d35 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,17 @@ +2008-09-01 Daniel Kraft <d@domob.eu> + + * gfc-internals.texi (F2003 OOP), (Type-bound Procedures): New chapter + and section to document the internals of type-bound procedures. + (gfc_expr): Document EXPR_COMPCALL. + * gfortran.h (struct gfc_expr): Remove unused `derived' from compcall. + * dump-parse-tree.c (show_compcall): New method. + (show_expr): Call it for EXPR_COMPCALL. + (show_typebound), (show_f2k_derived): New methods. + (show_symbol): Call show_f2k_derived. + (show_code_node): Handle EXEC_COMPCALL. + * primary.c (gfc_match_varspec): Don't initialize removed `derived' in + primary->value.compcall. + 2008-08-31 Richard Guenther <rguenther@suse.de> * trans-expr.c (gfc_trans_string_copy): Use the correct types diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c index c829ebd..05d32c2 100644 --- a/gcc/fortran/dump-parse-tree.c +++ b/gcc/fortran/dump-parse-tree.c @@ -316,6 +316,22 @@ show_char_const (const gfc_char_t *c, int length) fputc ('\'', dumpfile); } + +/* Show a component-call expression. */ + +static void +show_compcall (gfc_expr* p) +{ + gcc_assert (p->expr_type == EXPR_COMPCALL); + + fprintf (dumpfile, "%s", p->symtree->n.sym->name); + show_ref (p->ref); + fprintf (dumpfile, "%s", p->value.compcall.name); + + show_actual_arglist (p->value.compcall.actual); +} + + /* Show an expression. */ static void @@ -539,6 +555,10 @@ show_expr (gfc_expr *p) break; + case EXPR_COMPCALL: + show_compcall (p); + break; + default: gfc_internal_error ("show_expr(): Don't know how to show expr"); } @@ -646,6 +666,76 @@ show_components (gfc_symbol *sym) } +/* Show the f2k_derived namespace with procedure bindings. */ + +static void +show_typebound (gfc_symtree* st) +{ + if (!st->typebound) + return; + + show_indent (); + + if (st->typebound->is_generic) + fputs ("GENERIC", dumpfile); + else + { + fputs ("PROCEDURE, ", dumpfile); + if (st->typebound->nopass) + fputs ("NOPASS", dumpfile); + else + { + if (st->typebound->pass_arg) + fprintf (dumpfile, "PASS(%s)", st->typebound->pass_arg); + else + fputs ("PASS", dumpfile); + } + if (st->typebound->non_overridable) + fputs (", NON_OVERRIDABLE", dumpfile); + } + + if (st->typebound->access == ACCESS_PUBLIC) + fputs (", PUBLIC", dumpfile); + else + fputs (", PRIVATE", dumpfile); + + fprintf (dumpfile, " :: %s => ", st->n.sym->name); + + if (st->typebound->is_generic) + { + gfc_tbp_generic* g; + for (g = st->typebound->u.generic; g; g = g->next) + { + fputs (g->specific_st->name, dumpfile); + if (g->next) + fputs (", ", dumpfile); + } + } + else + fputs (st->typebound->u.specific->n.sym->name, dumpfile); +} + +static void +show_f2k_derived (gfc_namespace* f2k) +{ + gfc_finalizer* f; + + ++show_level; + + /* Finalizer bindings. */ + for (f = f2k->finalizers; f; f = f->next) + { + show_indent (); + fprintf (dumpfile, "FINAL %s", f->proc_sym->name); + } + + /* Type-bound procedures. */ + gfc_traverse_symtree (f2k->sym_root, &show_typebound); + + --show_level; +} + + /* Show a symbol. If a symbol is an ENTRY, SUBROUTINE or FUNCTION, we show the interface. Information needed to reconstruct the list of specific interfaces associated with a generic symbol is done within @@ -701,6 +791,13 @@ show_symbol (gfc_symbol *sym) show_components (sym); } + if (sym->f2k_derived) + { + show_indent (); + fputs ("Procedure bindings:\n", dumpfile); + show_f2k_derived (sym->f2k_derived); + } + if (sym->formal) { show_indent (); @@ -1110,6 +1207,11 @@ show_code_node (int level, gfc_code *c) show_actual_arglist (c->ext.actual); break; + case EXEC_COMPCALL: + fputs ("CALL ", dumpfile); + show_compcall (c->expr); + break; + case EXEC_RETURN: fputs ("RETURN ", dumpfile); if (c->expr) diff --git a/gcc/fortran/gfc-internals.texi b/gcc/fortran/gfc-internals.texi index e73d3b5..9cb5a54 100644 --- a/gcc/fortran/gfc-internals.texi +++ b/gcc/fortran/gfc-internals.texi @@ -118,6 +118,7 @@ not accurately reflect the status of the most recent GNU Fortran compiler. * User Interface:: Code that Interacts with the User. * Frontend Data Structures:: Data structures used by the frontend +* Object Orientation:: Internals of Fortran 2003 OOP features. * LibGFortran:: The LibGFortran Runtime Library. * GNU Free Documentation License:: How you can copy and share this manual. @@ -466,6 +467,13 @@ function symbol if the call is to an intrinsic or external function, respectively. These values are determined during resolution-phase from the structure's @code{symtree} member. +A special case of function calls are ``component calls'' to type-bound +procedures; those have the @code{expr_type} @code{EXPR_COMPCALL} with +@code{value.compcall} containing the argument list and the procedure called, +while @code{symtree} and @code{ref} describe the object on which the procedure +was called in the same way as a @code{EXPR_VARIABLE} expression would. +@xref{Type-bound Procedures}. + @subsection Array- and Structure-Constructors @@ -552,6 +560,96 @@ substring reference as described in the subsection above. @c --------------------------------------------------------------------- +@c F2003 OOP +@c --------------------------------------------------------------------- + +@node Object Orientation +@chapter Internals of Fortran 2003 OOP Features + +@menu +* Type-bound Procedures:: Type-bound procedures. +@end menu + + +@c Type-bound procedures +@c --------------------- + +@node Type-bound Procedures +@section Type-bound Procedures + +Type-bound procedures are stored in the @code{sym_root} of the namespace +@code{f2k_derived} associated with the derived-type symbol as @code{gfc_symtree} +nodes. The name and symbol of these symtrees corresponds to the binding-name +of the procedure, i.e. the name that is used to call it from the context of an +object of the derived-type. + +In addition, those and only those symtrees representing a type-bound procedure +have their @code{typebound} member set; @code{typebound} points to a struct of +type @code{gfc_typebound_proc} containing the additional data needed: The +binding attributes (like @code{PASS} and @code{NOPASS}, @code{NON_OVERRIDABLE} +or the access-specifier), the binding's target(s) and, if the current binding +overrides or extends an inherited binding of the same name, @code{overridden} +points to this binding's @code{gfc_typebound_proc} structure. + + +@subsection Specific Bindings +@c -------------------------- + +For specific bindings (declared with @code{PROCEDURE}), if they have a +passed-object argument, the passed-object dummy argument is first saved by its +name, and later during resolution phase the corresponding argument is looked for +and its position remembered as @code{pass_arg_num} in @code{gfc_typebound_proc}. +The binding's target procedure is pointed-to by @code{u.specific}. + +At the moment, all type-bound procedure calls are statically dispatched and +transformed into ordinary procedure calls at resolution time; their actual +argument list is updated to include at the right position the passed-object +argument, if applicable, and then a simple procedure call to the binding's +target procedure is built. To handle dynamic dispatch in the future, this will +be extended to allow special code generation during the trans-phase to dispatch +based on the object's dynamic type. + + +@subsection Generic Bindings +@c ------------------------- + +Bindings declared as @code{GENERIC} store the specific bindings they target as +a linked list using nodes of type @code{gfc_tbp_generic} in @code{u.generic}. +For each specific target, the parser records its symtree and during resolution +this symtree is bound to the corresponding @code{gfc_typebound_proc} structure +of the specific target. + +Calls to generic bindings are handled entirely in the resolution-phase, where +for the actual argument list present the matching specific binding is found +and the call's target procedure (@code{value.compcall.tbp}) is re-pointed to +the found specific binding and this call is subsequently handled by the logic +for specific binding calls. + + +@subsection Calls to Type-bound Procedures +@c --------------------------------------- + +Calls to type-bound procedures are stored in the parse-tree as @code{gfc_expr} +nodes of type @code{EXPR_COMPCALL}. Their @code{value.compcall.actual} saves +the actual argument list of the call and @code{value.compcall.tbp} points to the +@code{gfc_typebound_proc} structure of the binding to be called. The object +in whose context the procedure was called is saved by combination of +@code{symtree} and @code{ref}, as if the expression was of type +@code{EXPR_VARIABLE}. + +For code like this: +@smallexample +CALL myobj%procedure (arg1, arg2) +@end smallexample +@noindent +the @code{CALL} is represented in the parse-tree as a @code{gfc_code} node of +type @code{EXEC_COMPCALL}. The @code{expr} member of this node holds an +expression of type @code{EXPR_COMPCALL} of the same structure as mentioned above +except that its target procedure is of course a @code{SUBROUTINE} and not a +@code{FUNCTION}. + + +@c --------------------------------------------------------------------- @c LibGFortran @c --------------------------------------------------------------------- diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 9020029..400ef39 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -1593,7 +1593,6 @@ typedef struct gfc_expr { gfc_actual_arglist* actual; gfc_typebound_proc* tbp; - gfc_symbol* derived; const char* name; } compcall; diff --git a/gcc/fortran/primary.c b/gcc/fortran/primary.c index 3a72dda..c187749 100644 --- a/gcc/fortran/primary.c +++ b/gcc/fortran/primary.c @@ -1779,7 +1779,6 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, bool sub_flag) primary->expr_type = EXPR_COMPCALL; primary->value.compcall.tbp = tbp->typebound; - primary->value.compcall.derived = sym; primary->value.compcall.name = tbp->name; gcc_assert (primary->symtree->n.sym->attr.referenced); if (tbp_sym) |