| Index: gcc/gcc/fortran/module.c
|
| diff --git a/gcc/gcc/fortran/module.c b/gcc/gcc/fortran/module.c
|
| index bb4b3738554993ad2950eb5c13906b00368a9be3..0fc1921417280c9ae7a5ad76d87fce48cb91609e 100644
|
| --- a/gcc/gcc/fortran/module.c
|
| +++ b/gcc/gcc/fortran/module.c
|
| @@ -1,6 +1,7 @@
|
| /* Handle modules, which amounts to loading and saving symbols and
|
| their attendant structures.
|
| - Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
| + Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
|
| + 2009, 2010
|
| Free Software Foundation, Inc.
|
| Contributed by Andy Vaught
|
|
|
| @@ -77,7 +78,7 @@ along with GCC; see the file COPYING3. If not see
|
|
|
| /* Don't put any single quote (') in MOD_VERSION,
|
| if yout want it to be recognized. */
|
| -#define MOD_VERSION "0"
|
| +#define MOD_VERSION "4"
|
|
|
|
|
| /* Structure that describes a position within a module file. */
|
| @@ -119,6 +120,20 @@ fixup_t;
|
|
|
| /* Structure for holding extra info needed for pointers being read. */
|
|
|
| +enum gfc_rsym_state
|
| +{
|
| + UNUSED,
|
| + NEEDED,
|
| + USED
|
| +};
|
| +
|
| +enum gfc_wsym_state
|
| +{
|
| + UNREFERENCED = 0,
|
| + NEEDS_WRITE,
|
| + WRITTEN
|
| +};
|
| +
|
| typedef struct pointer_info
|
| {
|
| BBT_HEADER (pointer_info);
|
| @@ -138,9 +153,7 @@ typedef struct pointer_info
|
| {
|
| gfc_symbol *sym;
|
| char true_name[GFC_MAX_SYMBOL_LEN + 1], module[GFC_MAX_SYMBOL_LEN + 1];
|
| - enum
|
| - { UNUSED, NEEDED, USED }
|
| - state;
|
| + enum gfc_rsym_state state;
|
| int ns, referenced, renamed;
|
| module_locus where;
|
| fixup_t *stfixup;
|
| @@ -152,9 +165,7 @@ typedef struct pointer_info
|
| struct
|
| {
|
| gfc_symbol *sym;
|
| - enum
|
| - { UNREFERENCED = 0, NEEDS_WRITE, WRITTEN }
|
| - state;
|
| + enum gfc_wsym_state state;
|
| }
|
| wsym;
|
| }
|
| @@ -731,8 +742,7 @@ static int
|
| number_use_names (const char *name, bool interface)
|
| {
|
| int i = 0;
|
| - const char *c;
|
| - c = find_use_name_n (name, &i, interface);
|
| + find_use_name_n (name, &i, interface);
|
| return i;
|
| }
|
|
|
| @@ -1451,6 +1461,25 @@ mio_integer (int *ip)
|
| }
|
|
|
|
|
| +/* Read or write a gfc_intrinsic_op value. */
|
| +
|
| +static void
|
| +mio_intrinsic_op (gfc_intrinsic_op* op)
|
| +{
|
| + /* FIXME: Would be nicer to do this via the operators symbolic name. */
|
| + if (iomode == IO_OUTPUT)
|
| + {
|
| + int converted = (int) *op;
|
| + write_atom (ATOM_INTEGER, &converted);
|
| + }
|
| + else
|
| + {
|
| + require_atom (ATOM_INTEGER);
|
| + *op = (gfc_intrinsic_op) atom_int;
|
| + }
|
| +}
|
| +
|
| +
|
| /* Read or write a character pointer that points to a string on the heap. */
|
|
|
| static const char *
|
| @@ -1643,13 +1672,14 @@ typedef enum
|
| AB_CRAY_POINTER, AB_CRAY_POINTEE, AB_THREADPRIVATE, AB_ALLOC_COMP,
|
| AB_POINTER_COMP, AB_PRIVATE_COMP, AB_VALUE, AB_VOLATILE, AB_PROTECTED,
|
| AB_IS_BIND_C, AB_IS_C_INTEROP, AB_IS_ISO_C, AB_ABSTRACT, AB_ZERO_COMP,
|
| - AB_EXTENSION, AB_PROCEDURE, AB_PROC_POINTER
|
| + AB_IS_CLASS, AB_PROCEDURE, AB_PROC_POINTER, AB_ASYNCHRONOUS
|
| }
|
| ab_attribute;
|
|
|
| static const mstring attr_bits[] =
|
| {
|
| minit ("ALLOCATABLE", AB_ALLOCATABLE),
|
| + minit ("ASYNCHRONOUS", AB_ASYNCHRONOUS),
|
| minit ("DIMENSION", AB_DIMENSION),
|
| minit ("EXTERNAL", AB_EXTERNAL),
|
| minit ("INTRINSIC", AB_INTRINSIC),
|
| @@ -1683,7 +1713,7 @@ static const mstring attr_bits[] =
|
| minit ("ZERO_COMP", AB_ZERO_COMP),
|
| minit ("PROTECTED", AB_PROTECTED),
|
| minit ("ABSTRACT", AB_ABSTRACT),
|
| - minit ("EXTENSION", AB_EXTENSION),
|
| + minit ("IS_CLASS", AB_IS_CLASS),
|
| minit ("PROCEDURE", AB_PROCEDURE),
|
| minit ("PROC_POINTER", AB_PROC_POINTER),
|
| minit (NULL, -1)
|
| @@ -1700,6 +1730,7 @@ static const mstring binding_overriding[] =
|
| {
|
| minit ("OVERRIDABLE", 0),
|
| minit ("NON_OVERRIDABLE", 1),
|
| + minit ("DEFERRED", 2),
|
| minit (NULL, -1)
|
| };
|
| static const mstring binding_generic[] =
|
| @@ -1708,7 +1739,12 @@ static const mstring binding_generic[] =
|
| minit ("GENERIC", 1),
|
| minit (NULL, -1)
|
| };
|
| -
|
| +static const mstring binding_ppc[] =
|
| +{
|
| + minit ("NO_PPC", 0),
|
| + minit ("PPC", 1),
|
| + minit (NULL, -1)
|
| +};
|
|
|
| /* Specialization of mio_name. */
|
| DECL_MIO_NAME (ab_attribute)
|
| @@ -1736,6 +1772,7 @@ static void
|
| mio_symbol_attribute (symbol_attribute *attr)
|
| {
|
| atom_type t;
|
| + unsigned ext_attr,extension_level;
|
|
|
| mio_lparen ();
|
|
|
| @@ -1744,11 +1781,21 @@ mio_symbol_attribute (symbol_attribute *attr)
|
| attr->proc = MIO_NAME (procedure_type) (attr->proc, procedures);
|
| attr->if_source = MIO_NAME (ifsrc) (attr->if_source, ifsrc_types);
|
| attr->save = MIO_NAME (save_state) (attr->save, save_status);
|
| +
|
| + ext_attr = attr->ext_attr;
|
| + mio_integer ((int *) &ext_attr);
|
| + attr->ext_attr = ext_attr;
|
| +
|
| + extension_level = attr->extension;
|
| + mio_integer ((int *) &extension_level);
|
| + attr->extension = extension_level;
|
|
|
| if (iomode == IO_OUTPUT)
|
| {
|
| if (attr->allocatable)
|
| MIO_NAME (ab_attribute) (AB_ALLOCATABLE, attr_bits);
|
| + if (attr->asynchronous)
|
| + MIO_NAME (ab_attribute) (AB_ASYNCHRONOUS, attr_bits);
|
| if (attr->dimension)
|
| MIO_NAME (ab_attribute) (AB_DIMENSION, attr_bits);
|
| if (attr->external)
|
| @@ -1819,8 +1866,8 @@ mio_symbol_attribute (symbol_attribute *attr)
|
| MIO_NAME (ab_attribute) (AB_PRIVATE_COMP, attr_bits);
|
| if (attr->zero_comp)
|
| MIO_NAME (ab_attribute) (AB_ZERO_COMP, attr_bits);
|
| - if (attr->extension)
|
| - MIO_NAME (ab_attribute) (AB_EXTENSION, attr_bits);
|
| + if (attr->is_class)
|
| + MIO_NAME (ab_attribute) (AB_IS_CLASS, attr_bits);
|
| if (attr->procedure)
|
| MIO_NAME (ab_attribute) (AB_PROCEDURE, attr_bits);
|
| if (attr->proc_pointer)
|
| @@ -1844,6 +1891,9 @@ mio_symbol_attribute (symbol_attribute *attr)
|
| case AB_ALLOCATABLE:
|
| attr->allocatable = 1;
|
| break;
|
| + case AB_ASYNCHRONOUS:
|
| + attr->asynchronous = 1;
|
| + break;
|
| case AB_DIMENSION:
|
| attr->dimension = 1;
|
| break;
|
| @@ -1943,8 +1993,8 @@ mio_symbol_attribute (symbol_attribute *attr)
|
| case AB_ZERO_COMP:
|
| attr->zero_comp = 1;
|
| break;
|
| - case AB_EXTENSION:
|
| - attr->extension = 1;
|
| + case AB_IS_CLASS:
|
| + attr->is_class = 1;
|
| break;
|
| case AB_PROCEDURE:
|
| attr->procedure = 1;
|
| @@ -1965,6 +2015,7 @@ static const mstring bt_types[] = {
|
| minit ("LOGICAL", BT_LOGICAL),
|
| minit ("CHARACTER", BT_CHARACTER),
|
| minit ("DERIVED", BT_DERIVED),
|
| + minit ("CLASS", BT_CLASS),
|
| minit ("PROCEDURE", BT_PROCEDURE),
|
| minit ("UNKNOWN", BT_UNKNOWN),
|
| minit ("VOID", BT_VOID),
|
| @@ -1989,13 +2040,9 @@ mio_charlen (gfc_charlen **clp)
|
| {
|
| if (peek_atom () != ATOM_RPAREN)
|
| {
|
| - cl = gfc_get_charlen ();
|
| + cl = gfc_new_charlen (gfc_current_ns, NULL);
|
| mio_expr (&cl->length);
|
| -
|
| *clp = cl;
|
| -
|
| - cl->next = gfc_current_ns->cl_list;
|
| - gfc_current_ns->cl_list = cl;
|
| }
|
| }
|
|
|
| @@ -2019,10 +2066,10 @@ mio_typespec (gfc_typespec *ts)
|
|
|
| ts->type = MIO_NAME (bt) (ts->type, bt_types);
|
|
|
| - if (ts->type != BT_DERIVED)
|
| + if (ts->type != BT_DERIVED && ts->type != BT_CLASS)
|
| mio_integer (&ts->kind);
|
| else
|
| - mio_symbol_ref (&ts->derived);
|
| + mio_symbol_ref (&ts->u.derived);
|
|
|
| /* Add info for C interop and is_iso_c. */
|
| mio_integer (&ts->is_c_interop);
|
| @@ -2038,12 +2085,12 @@ mio_typespec (gfc_typespec *ts)
|
|
|
| if (ts->type != BT_CHARACTER)
|
| {
|
| - /* ts->cl is only valid for BT_CHARACTER. */
|
| + /* ts->u.cl is only valid for BT_CHARACTER. */
|
| mio_lparen ();
|
| mio_rparen ();
|
| }
|
| else
|
| - mio_charlen (&ts->cl);
|
| + mio_charlen (&ts->u.cl);
|
|
|
| mio_rparen ();
|
| }
|
| @@ -2161,7 +2208,7 @@ mio_array_ref (gfc_array_ref *ar)
|
| for (i = 0; i < ar->dimen; i++)
|
| {
|
| require_atom (ATOM_INTEGER);
|
| - ar->dimen_type[i] = atom_int;
|
| + ar->dimen_type[i] = (enum gfc_array_ref_dimen_type) atom_int;
|
| }
|
| }
|
|
|
| @@ -2251,11 +2298,16 @@ mio_component_ref (gfc_component **cp, gfc_symbol *sym)
|
| }
|
|
|
|
|
| +static void mio_namespace_ref (gfc_namespace **nsp);
|
| +static void mio_formal_arglist (gfc_formal_arglist **formal);
|
| +static void mio_typebound_proc (gfc_typebound_proc** proc);
|
| +
|
| static void
|
| mio_component (gfc_component *c)
|
| {
|
| pointer_info *p;
|
| int n;
|
| + gfc_formal_arglist *formal;
|
|
|
| mio_lparen ();
|
|
|
| @@ -2282,6 +2334,35 @@ mio_component (gfc_component *c)
|
| c->attr.access = MIO_NAME (gfc_access) (c->attr.access, access_types);
|
|
|
| mio_expr (&c->initializer);
|
| +
|
| + if (c->attr.proc_pointer)
|
| + {
|
| + if (iomode == IO_OUTPUT)
|
| + {
|
| + formal = c->formal;
|
| + while (formal && !formal->sym)
|
| + formal = formal->next;
|
| +
|
| + if (formal)
|
| + mio_namespace_ref (&formal->sym->ns);
|
| + else
|
| + mio_namespace_ref (&c->formal_ns);
|
| + }
|
| + else
|
| + {
|
| + mio_namespace_ref (&c->formal_ns);
|
| + /* TODO: if (c->formal_ns)
|
| + {
|
| + c->formal_ns->proc_name = c;
|
| + c->refs++;
|
| + }*/
|
| + }
|
| +
|
| + mio_formal_arglist (&c->formal);
|
| +
|
| + mio_typebound_proc (&c->tb);
|
| + }
|
| +
|
| mio_rparen ();
|
| }
|
|
|
| @@ -2375,7 +2456,7 @@ mio_actual_arglist (gfc_actual_arglist **ap)
|
| /* Read and write formal argument lists. */
|
|
|
| static void
|
| -mio_formal_arglist (gfc_symbol *sym)
|
| +mio_formal_arglist (gfc_formal_arglist **formal)
|
| {
|
| gfc_formal_arglist *f, *tail;
|
|
|
| @@ -2383,20 +2464,20 @@ mio_formal_arglist (gfc_symbol *sym)
|
|
|
| if (iomode == IO_OUTPUT)
|
| {
|
| - for (f = sym->formal; f; f = f->next)
|
| + for (f = *formal; f; f = f->next)
|
| mio_symbol_ref (&f->sym);
|
| }
|
| else
|
| {
|
| - sym->formal = tail = NULL;
|
| + *formal = tail = NULL;
|
|
|
| while (peek_atom () != ATOM_RPAREN)
|
| {
|
| f = gfc_get_formal_arglist ();
|
| mio_symbol_ref (&f->sym);
|
|
|
| - if (sym->formal == NULL)
|
| - sym->formal = f;
|
| + if (*formal == NULL)
|
| + *formal = f;
|
| else
|
| tail->next = f;
|
|
|
| @@ -2846,6 +2927,8 @@ fix_mio_expr (gfc_expr *e)
|
| }
|
| else if (e->expr_type == EXPR_FUNCTION && e->value.function.name)
|
| {
|
| + gfc_symbol *sym;
|
| +
|
| /* In some circumstances, a function used in an initialization
|
| expression, in one use associated module, can fail to be
|
| coupled to its symtree when used in a specification
|
| @@ -2853,6 +2936,19 @@ fix_mio_expr (gfc_expr *e)
|
| fname = e->value.function.esym ? e->value.function.esym->name
|
| : e->value.function.isym->name;
|
| e->symtree = gfc_find_symtree (gfc_current_ns->sym_root, fname);
|
| +
|
| + if (e->symtree)
|
| + return;
|
| +
|
| + /* This is probably a reference to a private procedure from another
|
| + module. To prevent a segfault, make a generic with no specific
|
| + instances. If this module is used, without the required
|
| + specific coming from somewhere, the appropriate error message
|
| + is issued. */
|
| + gfc_get_symbol (fname, gfc_current_ns, &sym);
|
| + sym->attr.flavor = FL_PROCEDURE;
|
| + sym->attr.generic = 1;
|
| + e->symtree = gfc_find_symtree (gfc_current_ns->sym_root, fname);
|
| }
|
| }
|
|
|
| @@ -3016,8 +3112,8 @@ mio_expr (gfc_expr **ep)
|
|
|
| case BT_COMPLEX:
|
| gfc_set_model_kind (e->ts.kind);
|
| - mio_gmp_real (&e->value.complex.r);
|
| - mio_gmp_real (&e->value.complex.i);
|
| + mio_gmp_real (&mpc_realref (e->value.complex));
|
| + mio_gmp_real (&mpc_imagref (e->value.complex));
|
| break;
|
|
|
| case BT_LOGICAL:
|
| @@ -3042,6 +3138,7 @@ mio_expr (gfc_expr **ep)
|
| break;
|
|
|
| case EXPR_COMPCALL:
|
| + case EXPR_PPC:
|
| gcc_unreachable ();
|
| break;
|
| }
|
| @@ -3205,6 +3302,7 @@ static void
|
| mio_typebound_proc (gfc_typebound_proc** proc)
|
| {
|
| int flag;
|
| + int overriding_flag;
|
|
|
| if (iomode == IO_INPUT)
|
| {
|
| @@ -3217,13 +3315,19 @@ mio_typebound_proc (gfc_typebound_proc** proc)
|
|
|
| (*proc)->access = MIO_NAME (gfc_access) ((*proc)->access, access_types);
|
|
|
| + /* IO the NON_OVERRIDABLE/DEFERRED combination. */
|
| + gcc_assert (!((*proc)->deferred && (*proc)->non_overridable));
|
| + overriding_flag = ((*proc)->deferred << 1) | (*proc)->non_overridable;
|
| + overriding_flag = mio_name (overriding_flag, binding_overriding);
|
| + (*proc)->deferred = ((overriding_flag & 2) != 0);
|
| + (*proc)->non_overridable = ((overriding_flag & 1) != 0);
|
| + gcc_assert (!((*proc)->deferred && (*proc)->non_overridable));
|
| +
|
| (*proc)->nopass = mio_name ((*proc)->nopass, binding_passing);
|
| - (*proc)->non_overridable = mio_name ((*proc)->non_overridable,
|
| - binding_overriding);
|
| (*proc)->is_generic = mio_name ((*proc)->is_generic, binding_generic);
|
| + (*proc)->ppc = mio_name((*proc)->ppc, binding_ppc);
|
|
|
| - if (iomode == IO_INPUT)
|
| - (*proc)->pass_arg = NULL;
|
| + mio_pool_string (&((*proc)->pass_arg));
|
|
|
| flag = (int) (*proc)->pass_arg_num;
|
| mio_integer (&flag);
|
| @@ -3243,12 +3347,14 @@ mio_typebound_proc (gfc_typebound_proc** proc)
|
| (*proc)->u.generic = NULL;
|
| while (peek_atom () != ATOM_RPAREN)
|
| {
|
| + gfc_symtree** sym_root;
|
| +
|
| g = gfc_get_tbp_generic ();
|
| g->specific = NULL;
|
|
|
| require_atom (ATOM_STRING);
|
| - gfc_get_sym_tree (atom_string, current_f2k_derived,
|
| - &g->specific_st);
|
| + sym_root = ¤t_f2k_derived->tb_sym_root;
|
| + g->specific_st = gfc_get_tbp_symtree (sym_root, atom_string);
|
| gfc_free (atom_string);
|
|
|
| g->next = (*proc)->u.generic;
|
| @@ -3258,16 +3364,17 @@ mio_typebound_proc (gfc_typebound_proc** proc)
|
|
|
| mio_rparen ();
|
| }
|
| - else
|
| + else if (!(*proc)->ppc)
|
| mio_symtree_ref (&(*proc)->u.specific);
|
|
|
| mio_rparen ();
|
| }
|
|
|
| +/* Walker-callback function for this purpose. */
|
| static void
|
| mio_typebound_symtree (gfc_symtree* st)
|
| {
|
| - if (iomode == IO_OUTPUT && !st->typebound)
|
| + if (iomode == IO_OUTPUT && !st->n.tb)
|
| return;
|
|
|
| if (iomode == IO_OUTPUT)
|
| @@ -3277,7 +3384,34 @@ mio_typebound_symtree (gfc_symtree* st)
|
| }
|
| /* For IO_INPUT, the above is done in mio_f2k_derived. */
|
|
|
| - mio_typebound_proc (&st->typebound);
|
| + mio_typebound_proc (&st->n.tb);
|
| + mio_rparen ();
|
| +}
|
| +
|
| +/* IO a full symtree (in all depth). */
|
| +static void
|
| +mio_full_typebound_tree (gfc_symtree** root)
|
| +{
|
| + mio_lparen ();
|
| +
|
| + if (iomode == IO_OUTPUT)
|
| + gfc_traverse_symtree (*root, &mio_typebound_symtree);
|
| + else
|
| + {
|
| + while (peek_atom () == ATOM_LPAREN)
|
| + {
|
| + gfc_symtree* st;
|
| +
|
| + mio_lparen ();
|
| +
|
| + require_atom (ATOM_STRING);
|
| + st = gfc_get_tbp_symtree (root, atom_string);
|
| + gfc_free (atom_string);
|
| +
|
| + mio_typebound_symtree (st);
|
| + }
|
| + }
|
| +
|
| mio_rparen ();
|
| }
|
|
|
| @@ -3319,7 +3453,7 @@ mio_f2k_derived (gfc_namespace *f2k)
|
| f2k->finalizers = NULL;
|
| while (peek_atom () != ATOM_RPAREN)
|
| {
|
| - gfc_finalizer *cur;
|
| + gfc_finalizer *cur = NULL;
|
| mio_finalizer (&cur);
|
| cur->next = f2k->finalizers;
|
| f2k->finalizers = cur;
|
| @@ -3328,24 +3462,40 @@ mio_f2k_derived (gfc_namespace *f2k)
|
| mio_rparen ();
|
|
|
| /* Handle type-bound procedures. */
|
| + mio_full_typebound_tree (&f2k->tb_sym_root);
|
| +
|
| + /* Type-bound user operators. */
|
| + mio_full_typebound_tree (&f2k->tb_uop_root);
|
| +
|
| + /* Type-bound intrinsic operators. */
|
| mio_lparen ();
|
| if (iomode == IO_OUTPUT)
|
| - gfc_traverse_symtree (f2k->sym_root, &mio_typebound_symtree);
|
| - else
|
| {
|
| - while (peek_atom () == ATOM_LPAREN)
|
| + int op;
|
| + for (op = GFC_INTRINSIC_BEGIN; op != GFC_INTRINSIC_END; ++op)
|
| {
|
| - gfc_symtree* st;
|
| -
|
| - mio_lparen ();
|
| + gfc_intrinsic_op realop;
|
|
|
| - require_atom (ATOM_STRING);
|
| - gfc_get_sym_tree (atom_string, f2k, &st);
|
| - gfc_free (atom_string);
|
| + if (op == INTRINSIC_USER || !f2k->tb_op[op])
|
| + continue;
|
|
|
| - mio_typebound_symtree (st);
|
| + mio_lparen ();
|
| + realop = (gfc_intrinsic_op) op;
|
| + mio_intrinsic_op (&realop);
|
| + mio_typebound_proc (&f2k->tb_op[op]);
|
| + mio_rparen ();
|
| }
|
| }
|
| + else
|
| + while (peek_atom () != ATOM_RPAREN)
|
| + {
|
| + gfc_intrinsic_op op = GFC_INTRINSIC_BEGIN; /* Silence GCC. */
|
| +
|
| + mio_lparen ();
|
| + mio_intrinsic_op (&op);
|
| + mio_typebound_proc (&f2k->tb_op[op]);
|
| + mio_rparen ();
|
| + }
|
| mio_rparen ();
|
| }
|
|
|
| @@ -3382,26 +3532,13 @@ mio_symbol (gfc_symbol *sym)
|
| {
|
| int intmod = INTMOD_NONE;
|
|
|
| - gfc_formal_arglist *formal;
|
| -
|
| mio_lparen ();
|
|
|
| mio_symbol_attribute (&sym->attr);
|
| mio_typespec (&sym->ts);
|
|
|
| - /* Contained procedures don't have formal namespaces. Instead we output the
|
| - procedure namespace. The will contain the formal arguments. */
|
| if (iomode == IO_OUTPUT)
|
| - {
|
| - formal = sym->formal;
|
| - while (formal && !formal->sym)
|
| - formal = formal->next;
|
| -
|
| - if (formal)
|
| - mio_namespace_ref (&formal->sym->ns);
|
| - else
|
| - mio_namespace_ref (&sym->formal_ns);
|
| - }
|
| + mio_namespace_ref (&sym->formal_ns);
|
| else
|
| {
|
| mio_namespace_ref (&sym->formal_ns);
|
| @@ -3415,7 +3552,7 @@ mio_symbol (gfc_symbol *sym)
|
| /* Save/restore common block links. */
|
| mio_symbol_ref (&sym->common_next);
|
|
|
| - mio_formal_arglist (sym);
|
| + mio_formal_arglist (&sym->formal);
|
|
|
| if (sym->attr.flavor == FL_PARAMETER)
|
| mio_expr (&sym->value);
|
| @@ -3452,11 +3589,14 @@ mio_symbol (gfc_symbol *sym)
|
| else
|
| {
|
| mio_integer (&intmod);
|
| - sym->from_intmod = intmod;
|
| + sym->from_intmod = (intmod_id) intmod;
|
| }
|
|
|
| mio_integer (&(sym->intmod_sym_id));
|
| -
|
| +
|
| + if (sym->attr.flavor == FL_DERIVED)
|
| + mio_integer (&(sym->hash_value));
|
| +
|
| mio_rparen ();
|
| }
|
|
|
| @@ -3626,8 +3766,9 @@ load_generic_interfaces (void)
|
| const char *p;
|
| char name[GFC_MAX_SYMBOL_LEN + 1], module[GFC_MAX_SYMBOL_LEN + 1];
|
| gfc_symbol *sym;
|
| - gfc_interface *generic = NULL;
|
| + gfc_interface *generic = NULL, *gen = NULL;
|
| int n, i, renamed;
|
| + bool ambiguous_set = false;
|
|
|
| mio_lparen ();
|
|
|
| @@ -3712,9 +3853,13 @@ load_generic_interfaces (void)
|
| sym = st->n.sym;
|
|
|
| if (st && !sym->attr.generic
|
| + && !st->ambiguous
|
| && sym->module
|
| && strcmp(module, sym->module))
|
| - st->ambiguous = 1;
|
| + {
|
| + ambiguous_set = true;
|
| + st->ambiguous = 1;
|
| + }
|
| }
|
|
|
| sym->attr.use_only = only_flag;
|
| @@ -3730,6 +3875,26 @@ load_generic_interfaces (void)
|
| sym->generic = generic;
|
| sym->attr.generic_copy = 1;
|
| }
|
| +
|
| + /* If a procedure that is not generic has generic interfaces
|
| + that include itself, it is generic! We need to take care
|
| + to retain symbols ambiguous that were already so. */
|
| + if (sym->attr.use_assoc
|
| + && !sym->attr.generic
|
| + && sym->attr.flavor == FL_PROCEDURE)
|
| + {
|
| + for (gen = generic; gen; gen = gen->next)
|
| + {
|
| + if (gen->sym == sym)
|
| + {
|
| + sym->attr.generic = 1;
|
| + if (ambiguous_set)
|
| + st->ambiguous = 0;
|
| + break;
|
| + }
|
| + }
|
| + }
|
| +
|
| }
|
| }
|
|
|
| @@ -3852,6 +4017,71 @@ load_equiv (void)
|
| }
|
|
|
|
|
| +/* This function loads the sym_root of f2k_derived with the extensions to
|
| + the derived type. */
|
| +static void
|
| +load_derived_extensions (void)
|
| +{
|
| + int symbol, j;
|
| + gfc_symbol *derived;
|
| + gfc_symbol *dt;
|
| + gfc_symtree *st;
|
| + pointer_info *info;
|
| + char name[GFC_MAX_SYMBOL_LEN + 1];
|
| + char module[GFC_MAX_SYMBOL_LEN + 1];
|
| + const char *p;
|
| +
|
| + mio_lparen ();
|
| + while (peek_atom () != ATOM_RPAREN)
|
| + {
|
| + mio_lparen ();
|
| + mio_integer (&symbol);
|
| + info = get_integer (symbol);
|
| + derived = info->u.rsym.sym;
|
| +
|
| + /* This one is not being loaded. */
|
| + if (!info || !derived)
|
| + {
|
| + while (peek_atom () != ATOM_RPAREN)
|
| + skip_list ();
|
| + continue;
|
| + }
|
| +
|
| + gcc_assert (derived->attr.flavor == FL_DERIVED);
|
| + if (derived->f2k_derived == NULL)
|
| + derived->f2k_derived = gfc_get_namespace (NULL, 0);
|
| +
|
| + while (peek_atom () != ATOM_RPAREN)
|
| + {
|
| + mio_lparen ();
|
| + mio_internal_string (name);
|
| + mio_internal_string (module);
|
| +
|
| + /* Only use one use name to find the symbol. */
|
| + j = 1;
|
| + p = find_use_name_n (name, &j, false);
|
| + if (p)
|
| + {
|
| + st = gfc_find_symtree (gfc_current_ns->sym_root, p);
|
| + dt = st->n.sym;
|
| + st = gfc_find_symtree (derived->f2k_derived->sym_root, name);
|
| + if (st == NULL)
|
| + {
|
| + /* Only use the real name in f2k_derived to ensure a single
|
| + symtree. */
|
| + st = gfc_new_symtree (&derived->f2k_derived->sym_root, name);
|
| + st->n.sym = dt;
|
| + st->n.sym->refs++;
|
| + }
|
| + }
|
| + mio_rparen ();
|
| + }
|
| + mio_rparen ();
|
| + }
|
| + mio_rparen ();
|
| +}
|
| +
|
| +
|
| /* Recursive function to traverse the pointer_info tree and load a
|
| needed symbol. We return nonzero if we load a symbol and stop the
|
| traversal, because the act of loading can alter the tree. */
|
| @@ -3993,10 +4223,10 @@ check_for_ambiguous (gfc_symbol *st_sym, pointer_info *info)
|
| static void
|
| read_module (void)
|
| {
|
| - module_locus operator_interfaces, user_operators;
|
| + module_locus operator_interfaces, user_operators, extensions;
|
| const char *p;
|
| char name[GFC_MAX_SYMBOL_LEN + 1];
|
| - gfc_intrinsic_op i;
|
| + int i;
|
| int ambiguous, j, nuse, symbol;
|
| pointer_info *info, *q;
|
| gfc_use_rename *u;
|
| @@ -4010,10 +4240,13 @@ read_module (void)
|
| skip_list ();
|
| skip_list ();
|
|
|
| - /* Skip commons and equivalences for now. */
|
| + /* Skip commons, equivalences and derived type extensions for now. */
|
| skip_list ();
|
| skip_list ();
|
|
|
| + get_module_locus (&extensions);
|
| + skip_list ();
|
| +
|
| mio_lparen ();
|
|
|
| /* Create the fixup nodes for all the symbols. */
|
| @@ -4204,7 +4437,7 @@ read_module (void)
|
|
|
| if (only_flag)
|
| {
|
| - u = find_use_operator (i);
|
| + u = find_use_operator ((gfc_intrinsic_op) i);
|
|
|
| if (u == NULL)
|
| {
|
| @@ -4264,7 +4497,10 @@ read_module (void)
|
| module_name);
|
| }
|
|
|
| - gfc_check_interfaces (gfc_current_ns);
|
| + /* Now we should be in a position to fill f2k_derived with derived type
|
| + extensions, since everything has been loaded. */
|
| + set_module_locus (&extensions);
|
| + load_derived_extensions ();
|
|
|
| /* Clean up symbol nodes that were never loaded, create references
|
| to hidden symbols. */
|
| @@ -4474,6 +4710,40 @@ write_equiv (void)
|
| }
|
|
|
|
|
| +/* Write derived type extensions to the module. */
|
| +
|
| +static void
|
| +write_dt_extensions (gfc_symtree *st)
|
| +{
|
| + if (!gfc_check_access (st->n.sym->attr.access,
|
| + st->n.sym->ns->default_access))
|
| + return;
|
| +
|
| + mio_lparen ();
|
| + mio_pool_string (&st->n.sym->name);
|
| + if (st->n.sym->module != NULL)
|
| + mio_pool_string (&st->n.sym->module);
|
| + else
|
| + mio_internal_string (module_name);
|
| + mio_rparen ();
|
| +}
|
| +
|
| +static void
|
| +write_derived_extensions (gfc_symtree *st)
|
| +{
|
| + if (!((st->n.sym->attr.flavor == FL_DERIVED)
|
| + && (st->n.sym->f2k_derived != NULL)
|
| + && (st->n.sym->f2k_derived->sym_root != NULL)))
|
| + return;
|
| +
|
| + mio_lparen ();
|
| + mio_symbol_ref (&(st->n.sym));
|
| + gfc_traverse_symtree (st->n.sym->f2k_derived->sym_root,
|
| + write_dt_extensions);
|
| + mio_rparen ();
|
| +}
|
| +
|
| +
|
| /* Write a symbol to the module. */
|
|
|
| static void
|
| @@ -4656,7 +4926,7 @@ write_symtree (gfc_symtree *st)
|
| static void
|
| write_module (void)
|
| {
|
| - gfc_intrinsic_op i;
|
| + int i;
|
|
|
| /* Write the operator interfaces. */
|
| mio_lparen ();
|
| @@ -4700,6 +4970,13 @@ write_module (void)
|
| write_char ('\n');
|
| write_char ('\n');
|
|
|
| + mio_lparen ();
|
| + gfc_traverse_symtree (gfc_current_ns->sym_root,
|
| + write_derived_extensions);
|
| + mio_rparen ();
|
| + write_char ('\n');
|
| + write_char ('\n');
|
| +
|
| /* Write symbol information. First we traverse all symbols in the
|
| primary namespace, writing those that need to be written.
|
| Sometimes writing one symbol will cause another to need to be
|
| @@ -4956,7 +5233,8 @@ import_iso_c_binding_module (void)
|
| if (mod_symtree == NULL)
|
| {
|
| /* symtree doesn't already exist in current namespace. */
|
| - gfc_get_sym_tree (iso_c_module_name, gfc_current_ns, &mod_symtree);
|
| + gfc_get_sym_tree (iso_c_module_name, gfc_current_ns, &mod_symtree,
|
| + false);
|
|
|
| if (mod_symtree != NULL)
|
| mod_sym = mod_symtree->n.sym;
|
| @@ -4990,7 +5268,9 @@ import_iso_c_binding_module (void)
|
| continue;
|
| }
|
|
|
| - generate_isocbinding_symbol (iso_c_module_name, i, u->local_name);
|
| + generate_isocbinding_symbol (iso_c_module_name,
|
| + (iso_c_binding_symbol) i,
|
| + u->local_name);
|
| }
|
| }
|
| else
|
| @@ -5007,7 +5287,9 @@ import_iso_c_binding_module (void)
|
| break;
|
| }
|
| }
|
| - generate_isocbinding_symbol (iso_c_module_name, i, local_name);
|
| + generate_isocbinding_symbol (iso_c_module_name,
|
| + (iso_c_binding_symbol) i,
|
| + local_name);
|
| }
|
|
|
| for (u = gfc_rename_list; u; u = u->next)
|
| @@ -5040,7 +5322,7 @@ create_int_parameter (const char *name, int value, const char *modname,
|
| gfc_error ("Symbol '%s' already declared", name);
|
| }
|
|
|
| - gfc_get_sym_tree (name, gfc_current_ns, &tmp_symtree);
|
| + gfc_get_sym_tree (name, gfc_current_ns, &tmp_symtree, false);
|
| sym = tmp_symtree->n.sym;
|
|
|
| sym->module = gfc_get_string (modname);
|
| @@ -5081,7 +5363,7 @@ use_iso_fortran_env_module (void)
|
| mod_symtree = gfc_find_symtree (gfc_current_ns->sym_root, mod);
|
| if (mod_symtree == NULL)
|
| {
|
| - gfc_get_sym_tree (mod, gfc_current_ns, &mod_symtree);
|
| + gfc_get_sym_tree (mod, gfc_current_ns, &mod_symtree, false);
|
| gcc_assert (mod_symtree);
|
| mod_sym = mod_symtree->n.sym;
|
|
|
| @@ -5254,9 +5536,9 @@ gfc_use_module (void)
|
|
|
| if (strcmp (atom_string, MOD_VERSION))
|
| {
|
| - gfc_fatal_error ("Wrong module version '%s' (expected '"
|
| - MOD_VERSION "') for file '%s' opened"
|
| - " at %C", atom_string, filename);
|
| + gfc_fatal_error ("Wrong module version '%s' (expected '%s') "
|
| + "for file '%s' opened at %C", atom_string,
|
| + MOD_VERSION, filename);
|
| }
|
| }
|
|
|
|
|