diff options
author | Tobias Burnus <burnus@gcc.gnu.org> | 2011-11-16 22:37:43 +0100 |
---|---|---|
committer | Tobias Burnus <burnus@gcc.gnu.org> | 2011-11-16 22:37:43 +0100 |
commit | c3f34952484cfe374448d5021dfb7dedf138c9ab (patch) | |
tree | 61a919d8cae4728618964335046a765c914ca292 /gcc/fortran/symbol.c | |
parent | 16e835bb5c484dfd735d5ee24c023ace800d0332 (diff) | |
download | gcc-c3f34952484cfe374448d5021dfb7dedf138c9ab.zip gcc-c3f34952484cfe374448d5021dfb7dedf138c9ab.tar.gz gcc-c3f34952484cfe374448d5021dfb7dedf138c9ab.tar.bz2 |
re PR fortran/39427 (F2003: Procedures with same name as types/type constructors)
gcc/fortran
2011-11-16 Tobias Burnus <burnus@net-b.de>
PR fortran/39427
PR fortran/37829
* decl.c (match_data_constant, match_data_constant,
* variable_decl,
gfc_match_decl_type_spec, access_attr_decl,
check_extended_derived_type, gfc_match_derived_decl,
gfc_match_derived_decl, gfc_match_derived_decl) Modified to deal
with DT constructors.
* gfortran.h (gfc_find_dt_in_generic,
gfc_convert_to_structure_constructor): New function prototypes.
* interface.c (check_interface0, check_interface1,
gfc_search_interface): Ignore DT constructors in generic list.
* match.h (gfc_match_structure_constructor): Update prototype.
* match.c (match_derived_type_spec): Ensure that one uses the DT
not the generic function.
* module.c (MOD_VERSION): Bump.
(dt_lower_string, dt_upper_string): New functions.
(find_use_name_n, find_use_operator, compare_true_names,
find_true_name, add_true_name, fix_mio_expr, load_needed,
read_module, write_dt_extensions, write_symbol): Changes to deal with
different symtree vs. sym names.
(create_derived_type): Create also generic procedure.
* parse.c (gfc_fixup_sibling_symbols): Don't regard DT and
* generic
function as the same.
* primary.c (gfc_convert_to_structure_constructor): New
* function.
(gfc_match_structure_constructor): Restructured; calls
gfc_convert_to_structure_constructor.
(build_actual_constructor, gfc_match_rvalue): Update for DT generic
functions.
* resolve.c (resolve_formal_arglist, resolve_structure_cons,
is_illegal_recursion, resolve_generic_f, resolve_variable,
resolve_fl_variable_derived, resolve_fl_derived0,
resolve_symbol): Handle DT and DT generic constructors.
* symbol.c (gfc_use_derived, gfc_undo_symbols,
gen_special_c_interop_ptr, gen_cptr_param,
generate_isocbinding_symbol, gfc_get_derived_super_type): Handle
derived-types, which are hidden in the generic type.
(gfc_find_dt_in_generic): New function
* trans-array.c (gfc_conv_array_initializer): Replace
* FL_PARAMETER
expr by actual value.
* trans-decl.c (gfc_get_module_backend_decl,
* gfc_trans_use_stmts):
Ensure that we use the DT and not the generic function.
* trans-types.c (gfc_get_derived_type): Ensure that we use the
* DT
and not the generic procedure.
gcc/testsuite/
2011-11-16 Tobias Burnus <burnus@net-b.de>
PR fortran/39427
PR fortran/37829
* gfortran.dg/constructor_1.f90: New.
* gfortran.dg/constructor_2.f90: New.
* gfortran.dg/constructor_3.f90: New.
* gfortran.dg/constructor_4.f90: New.
* gfortran.dg/constructor_5.f90: New.
* gfortran.dg/constructor_6.f90: New.
* gfortran.dg/use_only_5.f90: New.
* gfortran.dg/c_ptr_tests_17.f90: New.
* gfortran.dg/c_ptr_tests_18.f90: New.
* gfortran.dg/used_types_25.f90: New.
* gfortran.dg/used_types_26.f90: New
* gfortran.dg/type_decl_3.f90: New.
* gfortran.dg/function_types_3.f90: Update dg-error.
* gfortran.dg/result_1.f90: Ditto.
* gfortran.dg/structure_constructor_3.f03: Ditto.
* gfortran.dg/structure_constructor_4.f03: Ditto.
From-SVN: r181425
Diffstat (limited to 'gcc/fortran/symbol.c')
-rw-r--r-- | gcc/fortran/symbol.c | 244 |
1 files changed, 168 insertions, 76 deletions
diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c index 33ec706..9bd6ed4 100644 --- a/gcc/fortran/symbol.c +++ b/gcc/fortran/symbol.c @@ -1949,6 +1949,9 @@ gfc_use_derived (gfc_symbol *sym) if (!sym) return NULL; + if (sym->attr.generic) + sym = gfc_find_dt_in_generic (sym); + if (sym->components != NULL || sym->attr.zero_comp) return sym; /* Already defined. */ @@ -2880,7 +2883,15 @@ gfc_undo_symbols (void) } } - gfc_delete_symtree (&p->ns->sym_root, p->name); + /* The derived type is saved in the symtree with the first + letter capitalized; the all lower-case version to the + derived type contains its associated generic function. */ + if (p->attr.flavor == FL_DERIVED) + gfc_delete_symtree (&p->ns->sym_root, gfc_get_string ("%c%s", + (char) TOUPPER ((unsigned char) p->name[0]), + &p->name[1])); + else + gfc_delete_symtree (&p->ns->sym_root, p->name); gfc_release_symbol (p); continue; @@ -3773,15 +3784,15 @@ gen_special_c_interop_ptr (int ptr_id, const char *ptr_name, that has arg(s) of the missing type. In this case, a regular version of the thing should have been put in the current ns. */ + generate_isocbinding_symbol (module_name, ptr_id == ISOCBINDING_NULL_PTR ? ISOCBINDING_PTR : ISOCBINDING_FUNPTR, (const char *) (ptr_id == ISOCBINDING_NULL_PTR - ? "_gfortran_iso_c_binding_c_ptr" - : "_gfortran_iso_c_binding_c_funptr")); - + ? "c_ptr" + : "c_funptr")); tmp_sym->ts.u.derived = - get_iso_c_binding_dt (ptr_id == ISOCBINDING_NULL_PTR - ? ISOCBINDING_PTR : ISOCBINDING_FUNPTR); + get_iso_c_binding_dt (ptr_id == ISOCBINDING_NULL_PTR + ? ISOCBINDING_PTR : ISOCBINDING_FUNPTR); } /* Module name is some mangled version of iso_c_binding. */ @@ -3859,9 +3870,9 @@ gen_cptr_param (gfc_formal_arglist **head, const char *c_ptr_type = NULL; if (iso_c_sym_id == ISOCBINDING_F_PROCPOINTER) - c_ptr_type = "_gfortran_iso_c_binding_c_funptr"; + c_ptr_type = "c_funptr"; else - c_ptr_type = "_gfortran_iso_c_binding_c_ptr"; + c_ptr_type = "c_ptr"; if(c_ptr_name == NULL) c_ptr_in = "gfc_cptr__"; @@ -4338,19 +4349,31 @@ generate_isocbinding_symbol (const char *mod_name, iso_c_binding_symbol s, : c_interop_kinds_table[s].name; gfc_symtree *tmp_symtree = NULL; gfc_symbol *tmp_sym = NULL; - gfc_dt_list **dt_list_ptr = NULL; - gfc_component *tmp_comp = NULL; - char comp_name[(GFC_MAX_SYMBOL_LEN * 2) + 1]; int index; if (gfc_notification_std (std_for_isocbinding_symbol (s)) == ERROR) return; + tmp_symtree = gfc_find_symtree (gfc_current_ns->sym_root, name); - /* Already exists in this scope so don't re-add it. - TODO: we should probably check that it's really the same symbol. */ - if (tmp_symtree != NULL) - return; + /* Already exists in this scope so don't re-add it. */ + if (tmp_symtree != NULL && (tmp_sym = tmp_symtree->n.sym) != NULL + && (!tmp_sym->attr.generic + || (tmp_sym = gfc_find_dt_in_generic (tmp_sym)) != NULL) + && tmp_sym->from_intmod == INTMOD_ISO_C_BINDING) + { + if (tmp_sym->attr.flavor == FL_DERIVED + && !get_iso_c_binding_dt (tmp_sym->intmod_sym_id)) + { + gfc_dt_list *dt_list; + dt_list = gfc_get_dt_list (); + dt_list->derived = tmp_sym; + dt_list->next = gfc_derived_types; + gfc_derived_types = dt_list; + } + + return; + } /* Create the sym tree in the current ns. */ gfc_get_sym_tree (name, gfc_current_ns, &tmp_symtree, false); @@ -4443,64 +4466,112 @@ generate_isocbinding_symbol (const char *mod_name, iso_c_binding_symbol s, case ISOCBINDING_PTR: case ISOCBINDING_FUNPTR: - - /* Initialize an integer constant expression node. */ - tmp_sym->attr.flavor = FL_DERIVED; - tmp_sym->ts.is_c_interop = 1; - tmp_sym->attr.is_c_interop = 1; - tmp_sym->attr.is_iso_c = 1; - tmp_sym->ts.is_iso_c = 1; - tmp_sym->ts.type = BT_DERIVED; - - /* A derived type must have the bind attribute to be - interoperable (J3/04-007, Section 15.2.3), even though - the binding label is not used. */ - tmp_sym->attr.is_bind_c = 1; - - tmp_sym->attr.referenced = 1; - - tmp_sym->ts.u.derived = tmp_sym; - - /* Add the symbol created for the derived type to the current ns. */ - dt_list_ptr = &(gfc_derived_types); - while (*dt_list_ptr != NULL && (*dt_list_ptr)->next != NULL) - dt_list_ptr = &((*dt_list_ptr)->next); - - /* There is already at least one derived type in the list, so append - the one we're currently building for c_ptr or c_funptr. */ - if (*dt_list_ptr != NULL) - dt_list_ptr = &((*dt_list_ptr)->next); - (*dt_list_ptr) = gfc_get_dt_list (); - (*dt_list_ptr)->derived = tmp_sym; - (*dt_list_ptr)->next = NULL; - - /* Set up the component of the derived type, which will be - an integer with kind equal to c_ptr_size. Mangle the name of - the field for the c_address to prevent the curious user from - trying to access it from Fortran. */ - sprintf (comp_name, "__%s_%s", tmp_sym->name, "c_address"); - gfc_add_component (tmp_sym, comp_name, &tmp_comp); - if (tmp_comp == NULL) + { + gfc_interface *intr, *head; + gfc_symbol *dt_sym; + const char *hidden_name; + gfc_dt_list **dt_list_ptr = NULL; + gfc_component *tmp_comp = NULL; + char comp_name[(GFC_MAX_SYMBOL_LEN * 2) + 1]; + + hidden_name = gfc_get_string ("%c%s", + (char) TOUPPER ((unsigned char) tmp_sym->name[0]), + &tmp_sym->name[1]); + + /* Generate real derived type. */ + tmp_symtree = gfc_find_symtree (gfc_current_ns->sym_root, + hidden_name); + + if (tmp_symtree != NULL) + gcc_unreachable (); + gfc_get_sym_tree (hidden_name, gfc_current_ns, &tmp_symtree, false); + if (tmp_symtree) + dt_sym = tmp_symtree->n.sym; + else + gcc_unreachable (); + + /* Generate an artificial generic function. */ + dt_sym->name = gfc_get_string (tmp_sym->name); + head = tmp_sym->generic; + intr = gfc_get_interface (); + intr->sym = dt_sym; + intr->where = gfc_current_locus; + intr->next = head; + tmp_sym->generic = intr; + + if (!tmp_sym->attr.generic + && gfc_add_generic (&tmp_sym->attr, tmp_sym->name, NULL) + == FAILURE) + return; + + if (!tmp_sym->attr.function + && gfc_add_function (&tmp_sym->attr, tmp_sym->name, NULL) + == FAILURE) + return; + + /* Say what module this symbol belongs to. */ + dt_sym->module = gfc_get_string (mod_name); + dt_sym->from_intmod = INTMOD_ISO_C_BINDING; + dt_sym->intmod_sym_id = s; + + /* Initialize an integer constant expression node. */ + dt_sym->attr.flavor = FL_DERIVED; + dt_sym->ts.is_c_interop = 1; + dt_sym->attr.is_c_interop = 1; + dt_sym->attr.is_iso_c = 1; + dt_sym->ts.is_iso_c = 1; + dt_sym->ts.type = BT_DERIVED; + + /* A derived type must have the bind attribute to be + interoperable (J3/04-007, Section 15.2.3), even though + the binding label is not used. */ + dt_sym->attr.is_bind_c = 1; + + dt_sym->attr.referenced = 1; + dt_sym->ts.u.derived = dt_sym; + + /* Add the symbol created for the derived type to the current ns. */ + dt_list_ptr = &(gfc_derived_types); + while (*dt_list_ptr != NULL && (*dt_list_ptr)->next != NULL) + dt_list_ptr = &((*dt_list_ptr)->next); + + /* There is already at least one derived type in the list, so append + the one we're currently building for c_ptr or c_funptr. */ + if (*dt_list_ptr != NULL) + dt_list_ptr = &((*dt_list_ptr)->next); + (*dt_list_ptr) = gfc_get_dt_list (); + (*dt_list_ptr)->derived = dt_sym; + (*dt_list_ptr)->next = NULL; + + /* Set up the component of the derived type, which will be + an integer with kind equal to c_ptr_size. Mangle the name of + the field for the c_address to prevent the curious user from + trying to access it from Fortran. */ + sprintf (comp_name, "__%s_%s", dt_sym->name, "c_address"); + gfc_add_component (dt_sym, comp_name, &tmp_comp); + if (tmp_comp == NULL) gfc_internal_error ("generate_isocbinding_symbol(): Unable to " "create component for c_address"); - tmp_comp->ts.type = BT_INTEGER; + tmp_comp->ts.type = BT_INTEGER; - /* Set this because the module will need to read/write this field. */ - tmp_comp->ts.f90_type = BT_INTEGER; + /* Set this because the module will need to read/write this field. */ + tmp_comp->ts.f90_type = BT_INTEGER; - /* The kinds for c_ptr and c_funptr are the same. */ - index = get_c_kind ("c_ptr", c_interop_kinds_table); - tmp_comp->ts.kind = c_interop_kinds_table[index].value; + /* The kinds for c_ptr and c_funptr are the same. */ + index = get_c_kind ("c_ptr", c_interop_kinds_table); + tmp_comp->ts.kind = c_interop_kinds_table[index].value; - tmp_comp->attr.pointer = 0; - tmp_comp->attr.dimension = 0; + tmp_comp->attr.pointer = 0; + tmp_comp->attr.dimension = 0; - /* Mark the component as C interoperable. */ - tmp_comp->ts.is_c_interop = 1; + /* Mark the component as C interoperable. */ + tmp_comp->ts.is_c_interop = 1; + + /* Make it use associated (iso_c_binding module). */ + dt_sym->attr.use_assoc = 1; + } - /* Make it use associated (iso_c_binding module). */ - tmp_sym->attr.use_assoc = 1; break; case ISOCBINDING_NULL_PTR: @@ -4550,21 +4621,20 @@ generate_isocbinding_symbol (const char *mod_name, iso_c_binding_symbol s, tmp_sym->ts.u.derived = get_iso_c_binding_dt (ISOCBINDING_FUNPTR); - if (tmp_sym->ts.u.derived == NULL) - { + if (tmp_sym->ts.u.derived == NULL) + { /* Create the necessary derived type so we can continue processing the file. */ - generate_isocbinding_symbol + generate_isocbinding_symbol (mod_name, s == ISOCBINDING_FUNLOC - ? ISOCBINDING_FUNPTR : ISOCBINDING_PTR, - (const char *)(s == ISOCBINDING_FUNLOC - ? "_gfortran_iso_c_binding_c_funptr" - : "_gfortran_iso_c_binding_c_ptr")); + ? ISOCBINDING_FUNPTR : ISOCBINDING_PTR, + (const char *)(s == ISOCBINDING_FUNLOC + ? "c_funptr" : "c_ptr")); tmp_sym->ts.u.derived = - get_iso_c_binding_dt (s == ISOCBINDING_FUNLOC - ? ISOCBINDING_FUNPTR - : ISOCBINDING_PTR); - } + get_iso_c_binding_dt (s == ISOCBINDING_FUNLOC + ? ISOCBINDING_FUNPTR + : ISOCBINDING_PTR); + } /* The function result is itself (no result clause). */ tmp_sym->result = tmp_sym; @@ -4712,6 +4782,9 @@ gfc_get_typebound_proc (gfc_typebound_proc *tb0) gfc_symbol* gfc_get_derived_super_type (gfc_symbol* derived) { + if (derived && derived->attr.generic) + derived = gfc_find_dt_in_generic (derived); + if (!derived->attr.extension) return NULL; @@ -4719,6 +4792,9 @@ gfc_get_derived_super_type (gfc_symbol* derived) gcc_assert (derived->components->ts.type == BT_DERIVED); gcc_assert (derived->components->ts.u.derived); + if (derived->components->ts.u.derived->attr.generic) + return gfc_find_dt_in_generic (derived->components->ts.u.derived); + return derived->components->ts.u.derived; } @@ -4814,3 +4890,19 @@ gfc_is_associate_pointer (gfc_symbol* sym) return true; } + + +gfc_symbol * +gfc_find_dt_in_generic (gfc_symbol *sym) +{ + gfc_interface *intr = NULL; + + if (!sym || sym->attr.flavor == FL_DERIVED) + return sym; + + if (sym->attr.generic) + for (intr = (sym ? sym->generic : NULL); intr; intr = intr->next) + if (intr->sym->attr.flavor == FL_DERIVED) + break; + return intr ? intr->sym : NULL; +} |