diff options
Diffstat (limited to 'gcc/fortran/decl.c')
-rw-r--r-- | gcc/fortran/decl.c | 240 |
1 files changed, 175 insertions, 65 deletions
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c index d23a32946ef..12497808a4e 100644 --- a/gcc/fortran/decl.c +++ b/gcc/fortran/decl.c @@ -231,21 +231,21 @@ syntax: variable-iterator list. */ static match -var_element (gfc_data_variable *new) +var_element (gfc_data_variable *new_var) { match m; gfc_symbol *sym; - memset (new, 0, sizeof (gfc_data_variable)); + memset (new_var, 0, sizeof (gfc_data_variable)); if (gfc_match_char ('(') == MATCH_YES) - return var_list (new); + return var_list (new_var); - m = gfc_match_variable (&new->expr, 0); + m = gfc_match_variable (&new_var->expr, 0); if (m != MATCH_YES) return m; - sym = new->expr->symtree->n.sym; + sym = new_var->expr->symtree->n.sym; if (!sym->attr.function && gfc_current_ns->parent && gfc_current_ns->parent == sym->ns) @@ -262,7 +262,7 @@ var_element (gfc_data_variable *new) sym->name) == FAILURE) return MATCH_ERROR; - if (gfc_add_data (&sym->attr, sym->name, &new->expr->where) == FAILURE) + if (gfc_add_data (&sym->attr, sym->name, &new_var->expr->where) == FAILURE) return MATCH_ERROR; return MATCH_YES; @@ -274,7 +274,7 @@ var_element (gfc_data_variable *new) static match top_var_list (gfc_data *d) { - gfc_data_variable var, *tail, *new; + gfc_data_variable var, *tail, *new_var; match m; tail = NULL; @@ -287,15 +287,15 @@ top_var_list (gfc_data *d) if (m == MATCH_ERROR) return MATCH_ERROR; - new = gfc_get_data_variable (); - *new = var; + new_var = gfc_get_data_variable (); + *new_var = var; if (tail == NULL) - d->var = new; + d->var = new_var; else - tail->next = new; + tail->next = new_var; - tail = new; + tail = new_var; if (gfc_match_char ('/') == MATCH_YES) break; @@ -367,7 +367,7 @@ match_data_constant (gfc_expr **result) return MATCH_ERROR; } else if (sym->attr.flavor == FL_DERIVED) - return gfc_match_structure_constructor (sym, result); + return gfc_match_structure_constructor (sym, result, false); /* Check to see if the value is an initialization array expression. */ if (sym->value->expr_type == EXPR_ARRAY) @@ -404,7 +404,7 @@ match_data_constant (gfc_expr **result) static match top_val_list (gfc_data *data) { - gfc_data_value *new, *tail; + gfc_data_value *new_val, *tail; gfc_expr *expr; match m; @@ -418,15 +418,15 @@ top_val_list (gfc_data *data) if (m == MATCH_ERROR) return MATCH_ERROR; - new = gfc_get_data_value (); - mpz_init (new->repeat); + new_val = gfc_get_data_value (); + mpz_init (new_val->repeat); if (tail == NULL) - data->value = new; + data->value = new_val; else - tail->next = new; + tail->next = new_val; - tail = new; + tail = new_val; if (expr->ts.type != BT_INTEGER || gfc_match_char ('*') != MATCH_YES) { @@ -518,26 +518,26 @@ match_old_style_init (const char *name) match gfc_match_data (void) { - gfc_data *new; + gfc_data *new_data; match m; set_in_match_data (true); for (;;) { - new = gfc_get_data (); - new->where = gfc_current_locus; + new_data = gfc_get_data (); + new_data->where = gfc_current_locus; - m = top_var_list (new); + m = top_var_list (new_data); if (m != MATCH_YES) goto cleanup; - m = top_val_list (new); + m = top_val_list (new_data); if (m != MATCH_YES) goto cleanup; - new->next = gfc_current_ns->data; - gfc_current_ns->data = new; + new_data->next = gfc_current_ns->data; + gfc_current_ns->data = new_data; if (gfc_match_eos () == MATCH_YES) break; @@ -557,7 +557,7 @@ gfc_match_data (void) cleanup: set_in_match_data (false); - gfc_free_data (new); + gfc_free_data (new_data); return MATCH_ERROR; } @@ -762,7 +762,7 @@ get_proc_name (const char *name, gfc_symbol **result, bool module_fcn_entry) (*result)->ts = sym->ts; /* Put the symbol in the procedure namespace so that, should - the ENTRY preceed its specification, the specification + the ENTRY precede its specification, the specification can be applied. */ (*result)->ns = gfc_current_ns; @@ -781,7 +781,7 @@ get_proc_name (const char *name, gfc_symbol **result, bool module_fcn_entry) sym = *result; gfc_current_ns->refs++; - if (sym && !sym->new && gfc_current_state () != COMP_INTERFACE) + if (sym && !sym->gfc_new && gfc_current_state () != COMP_INTERFACE) { /* Trap another encompassed procedure with the same name. All these conditions are necessary to avoid picking up an entry @@ -867,11 +867,11 @@ get_proc_name (const char *name, gfc_symbol **result, bool module_fcn_entry) the compiler could have automatically handled the varying sizes across platforms. */ -try +gfc_try verify_c_interop_param (gfc_symbol *sym) { int is_c_interop = 0; - try retval = SUCCESS; + gfc_try retval = SUCCESS; /* We check implicitly typed variables in symbol.c:gfc_set_default_type(). Don't repeat the checks here. */ @@ -1009,7 +1009,7 @@ verify_c_interop_param (gfc_symbol *sym) /* Function called by variable_decl() that adds a name to the symbol table. */ -static try +static gfc_try build_sym (const char *name, gfc_charlen *cl, gfc_array_spec **as, locus *var_locus) { @@ -1185,7 +1185,7 @@ gfc_free_enum_history (void) /* Function called by variable_decl() that adds an initialization expression to a symbol. */ -static try +static gfc_try add_init_expr_to_sym (const char *name, gfc_expr **initp, locus *var_locus) { symbol_attribute attr; @@ -1362,7 +1362,7 @@ add_init_expr_to_sym (const char *name, gfc_expr **initp, locus *var_locus) /* Function called by variable_decl() that adds a name to a structure being built. */ -static try +static gfc_try build_struct (const char *name, gfc_charlen *cl, gfc_expr **init, gfc_array_spec **as) { @@ -1548,7 +1548,7 @@ variable_decl (int elem) gfc_charlen *cl; locus var_locus; match m; - try t; + gfc_try t; gfc_symbol *sym; locus old_locus; @@ -2786,7 +2786,7 @@ match_attr_spec (void) decl_types d; const char *attr; match m; - try t; + gfc_try t; gfc_clear_attr (¤t_attr); start = gfc_current_locus; @@ -3248,7 +3248,7 @@ cleanup: (J3/04-007, section 15.4.1). If a binding label was given and there is more than one argument (num_idents), it is an error. */ -try +gfc_try set_binding_label (char *dest_label, const char *sym_name, int num_idents) { if (num_idents > 1 && has_name_equals) @@ -3288,10 +3288,10 @@ set_com_block_bind_c (gfc_common_head *com_block, int is_bind_c) /* Verify that the given gfc_typespec is for a C interoperable type. */ -try +gfc_try verify_c_interop (gfc_typespec *ts, const char *name, locus *where) { - try t; + gfc_try t; /* Make sure the kind used is appropriate for the type. The f90_type is unknown if an integer constant was @@ -3326,11 +3326,11 @@ verify_c_interop (gfc_typespec *ts, const char *name, locus *where) interoperable type. Errors will be reported here, if encountered. */ -try +gfc_try verify_com_block_vars_c_interop (gfc_common_head *com_block) { gfc_symbol *curr_sym = NULL; - try retval = SUCCESS; + gfc_try retval = SUCCESS; curr_sym = com_block->head; @@ -3354,11 +3354,11 @@ verify_com_block_vars_c_interop (gfc_common_head *com_block) /* Verify that a given BIND(C) symbol is C interoperable. If it is not, an appropriate error message is reported. */ -try +gfc_try verify_bind_c_sym (gfc_symbol *tmp_sym, gfc_typespec *ts, int is_in_common, gfc_common_head *com_block) { - try retval = SUCCESS; + gfc_try retval = SUCCESS; if (tmp_sym->attr.function && tmp_sym->result != NULL) { @@ -3478,10 +3478,10 @@ verify_bind_c_sym (gfc_symbol *tmp_sym, gfc_typespec *ts, the type is C interoperable. Errors are reported by the functions used to set/test these fields. */ -try +gfc_try set_verify_bind_c_sym (gfc_symbol *tmp_sym, int num_idents) { - try retval = SUCCESS; + gfc_try retval = SUCCESS; /* TODO: Do we need to make sure the vars aren't marked private? */ @@ -3499,10 +3499,10 @@ set_verify_bind_c_sym (gfc_symbol *tmp_sym, int num_idents) /* Set the fields marking the given common block as BIND(C), including a binding label, and report any errors encountered. */ -try +gfc_try set_verify_bind_c_com_block (gfc_common_head *com_block, int num_idents) { - try retval = SUCCESS; + gfc_try retval = SUCCESS; /* destLabel, common name, typespec (which may have binding label). */ if (set_binding_label (com_block->binding_label, com_block->name, num_idents) @@ -3519,7 +3519,7 @@ set_verify_bind_c_com_block (gfc_common_head *com_block, int num_idents) /* Retrieve the list of one or more identifiers that the given bind(c) attribute applies to. */ -try +gfc_try get_bind_c_idents (void) { char name[GFC_MAX_SYMBOL_LEN + 1]; @@ -3792,7 +3792,7 @@ loop: /* Copy attributes matched by gfc_match_prefix() to attributes on a symbol. */ -static try +static gfc_try copy_prefix (symbol_attribute *dest, locus *where) { if (current_attr.pure && gfc_add_pure (dest, where) == FAILURE) @@ -4120,8 +4120,8 @@ match_procedure_decl (void) /* Handle intrinsic procedures. */ if (!(proc_if->attr.external || proc_if->attr.use_assoc || proc_if->attr.if_source == IFSRC_IFBODY) - && (gfc_intrinsic_name (proc_if->name, 0) - || gfc_intrinsic_name (proc_if->name, 1))) + && (gfc_is_intrinsic (proc_if, 0, gfc_current_locus) + || gfc_is_intrinsic (proc_if, 1, gfc_current_locus))) proc_if->attr.intrinsic = 1; if (proc_if->attr.intrinsic && !gfc_intrinsic_actual_ok (proc_if->name, 0)) @@ -4336,6 +4336,22 @@ gfc_match_procedure (void) } +/* Warn if a matched procedure has the same name as an intrinsic; this is + simply a wrapper around gfc_warn_intrinsic_shadow that interprets the current + parser-state-stack to find out whether we're in a module. */ + +static void +warn_intrinsic_shadow (const gfc_symbol* sym, bool func) +{ + bool in_module; + + in_module = (gfc_state_stack->previous + && gfc_state_stack->previous->state == COMP_MODULE); + + gfc_warn_intrinsic_shadow (sym, in_module, func); +} + + /* Match a function declaration. */ match @@ -4460,6 +4476,9 @@ gfc_match_function_decl (void) sym->result = result; } + /* Warn if this procedure has the same name as an intrinsic. */ + warn_intrinsic_shadow (sym, true); + return MATCH_YES; } @@ -4842,6 +4861,9 @@ gfc_match_subroutine (void) if (copy_prefix (&sym->attr, &sym->declared_at) == FAILURE) return MATCH_ERROR; + /* Warn if it has the same name as an intrinsic. */ + warn_intrinsic_shadow (sym, false); + return MATCH_YES; } @@ -5630,7 +5652,7 @@ access_attr_decl (gfc_statement st) interface_type type; gfc_user_op *uop; gfc_symbol *sym; - gfc_intrinsic_op operator; + gfc_intrinsic_op op; match m; if (gfc_match (" ::") == MATCH_NO && gfc_match_space () == MATCH_NO) @@ -5638,7 +5660,7 @@ access_attr_decl (gfc_statement st) for (;;) { - m = gfc_match_generic_spec (&type, name, &operator); + m = gfc_match_generic_spec (&type, name, &op); if (m == MATCH_NO) goto syntax; if (m == MATCH_ERROR) @@ -5662,15 +5684,15 @@ access_attr_decl (gfc_statement st) break; case INTERFACE_INTRINSIC_OP: - if (gfc_current_ns->operator_access[operator] == ACCESS_UNKNOWN) + if (gfc_current_ns->operator_access[op] == ACCESS_UNKNOWN) { - gfc_current_ns->operator_access[operator] = + gfc_current_ns->operator_access[op] = (st == ST_PUBLIC) ? ACCESS_PUBLIC : ACCESS_PRIVATE; } else { gfc_error ("Access specification of the %s operator at %C has " - "already been specified", gfc_op2string (operator)); + "already been specified", gfc_op2string (op)); goto done; } @@ -5770,7 +5792,7 @@ syntax: /* The PRIVATE statement is a bit weird in that it can be an attribute - declaration, but also works as a standlone statement inside of a + declaration, but also works as a standalone statement inside of a type declaration or a module. */ match @@ -6228,6 +6250,49 @@ syntax: } +/* Check a derived type that is being extended. */ +static gfc_symbol* +check_extended_derived_type (char *name) +{ + gfc_symbol *extended; + + if (gfc_find_symbol (name, gfc_current_ns, 1, &extended)) + { + gfc_error ("Ambiguous symbol in TYPE definition at %C"); + return NULL; + } + + if (!extended) + { + gfc_error ("No such symbol in TYPE definition at %C"); + return NULL; + } + + if (extended->attr.flavor != FL_DERIVED) + { + gfc_error ("'%s' in EXTENDS expression at %C is not a " + "derived type", name); + return NULL; + } + + if (extended->attr.is_bind_c) + { + gfc_error ("'%s' cannot be extended at %C because it " + "is BIND(C)", extended->name); + return NULL; + } + + if (extended->attr.sequence) + { + gfc_error ("'%s' cannot be extended at %C because it " + "is a SEQUENCE type", extended->name); + return NULL; + } + + return extended; +} + + /* Match the optional attribute specifiers for a type declaration. Return MATCH_ERROR if an error is encountered in one of the handled attributes (public, private, bind(c)), MATCH_NO if what's found is @@ -6235,7 +6300,7 @@ syntax: checking on attribute conflicts needs to be done. */ match -gfc_get_type_attr_spec (symbol_attribute *attr) +gfc_get_type_attr_spec (symbol_attribute *attr, char *name) { /* See if the derived type is marked as private. */ if (gfc_match (" , private") == MATCH_YES) @@ -6273,6 +6338,11 @@ gfc_get_type_attr_spec (symbol_attribute *attr) /* TODO: attr conflicts need to be checked, probably in symbol.c. */ } + else if (name && gfc_match(" , extends ( %n )", name) == MATCH_YES) + { + if (gfc_add_extension (attr, &gfc_current_locus) == FAILURE) + return MATCH_ERROR; + } else return MATCH_NO; @@ -6289,8 +6359,10 @@ match gfc_match_derived_decl (void) { char name[GFC_MAX_SYMBOL_LEN + 1]; + char parent[GFC_MAX_SYMBOL_LEN + 1]; symbol_attribute attr; gfc_symbol *sym; + gfc_symbol *extended; match m; match is_type_attr_spec = MATCH_NO; bool seen_attr = false; @@ -6298,17 +6370,29 @@ gfc_match_derived_decl (void) if (gfc_current_state () == COMP_DERIVED) return MATCH_NO; + name[0] = '\0'; + parent[0] = '\0'; gfc_clear_attr (&attr); + extended = NULL; do { - is_type_attr_spec = gfc_get_type_attr_spec (&attr); + is_type_attr_spec = gfc_get_type_attr_spec (&attr, parent); if (is_type_attr_spec == MATCH_ERROR) return MATCH_ERROR; if (is_type_attr_spec == MATCH_YES) seen_attr = true; } while (is_type_attr_spec == MATCH_YES); + /* Deal with derived type extensions. The extension attribute has + been added to 'attr' but now the parent type must be found and + checked. */ + if (parent[0]) + extended = check_extended_derived_type (parent); + + if (parent[0] && !extended) + return MATCH_ERROR; + if (gfc_match (" ::") != MATCH_YES && seen_attr) { gfc_error ("Expected :: in TYPE definition at %C"); @@ -6341,7 +6425,7 @@ gfc_match_derived_decl (void) components. The ways this can happen is via a function definition, an INTRINSIC statement or a subtype in another derived type that is a pointer. The first part of the AND clause - is true if a the symbol is not the return value of a function. */ + is true if the symbol is not the return value of a function. */ if (sym->attr.flavor != FL_DERIVED && gfc_add_flavor (&sym->attr, FL_DERIVED, sym->name, NULL) == FAILURE) return MATCH_ERROR; @@ -6361,10 +6445,34 @@ gfc_match_derived_decl (void) if (attr.is_bind_c != 0) sym->attr.is_bind_c = attr.is_bind_c; + /* Construct the f2k_derived namespace if it is not yet there. */ if (!sym->f2k_derived) sym->f2k_derived = gfc_get_namespace (NULL, 0); + + if (extended && !sym->components) + { + gfc_component *p; + gfc_symtree *st; + + /* Add the extended derived type as the first component. */ + gfc_add_component (sym, parent, &p); + sym->attr.extension = attr.extension; + extended->refs++; + gfc_set_sym_referenced (extended); + + p->ts.type = BT_DERIVED; + p->ts.derived = extended; + p->initializer = gfc_default_initializer (&p->ts); + + /* Provide the links between the extended type and its extension. */ + if (!extended->f2k_derived) + extended->f2k_derived = gfc_get_namespace (NULL, 0); + st = gfc_new_symtree (&extended->f2k_derived->sym_root, sym->name); + st->n.sym = sym; + } + gfc_new_block = sym; return MATCH_YES; @@ -6378,7 +6486,7 @@ gfc_match_derived_decl (void) is the case. Since there is no bounds-checking for Cray Pointees, this will be okay. */ -try +gfc_try gfc_mod_pointee_as (gfc_array_spec *as) { as->cray_pointee = true; /* This will be useful to know later. */ @@ -6432,7 +6540,7 @@ enumerator_decl (void) gfc_symbol *sym; locus var_locus; match m; - try t; + gfc_try t; locus old_locus; initializer = NULL; @@ -6515,7 +6623,7 @@ match gfc_match_enumerator_def (void) { match m; - try t; + gfc_try t; gfc_clear_ts (¤t_ts); @@ -6575,6 +6683,7 @@ cleanup: } + /* Match a FINAL declaration inside a derived type. */ match @@ -6655,7 +6764,7 @@ gfc_match_final_decl (void) /* Check if we already have this symbol in the list, this is an error. */ for (f = gfc_current_block ()->f2k_derived->finalizers; f; f = f->next) - if (f->procedure == sym) + if (f->proc_sym == sym) { gfc_error ("'%s' at %C is already defined as FINAL procedure!", name); @@ -6666,7 +6775,8 @@ gfc_match_final_decl (void) gcc_assert (gfc_current_block ()->f2k_derived); ++sym->refs; f = XCNEW (gfc_finalizer); - f->procedure = sym; + f->proc_sym = sym; + f->proc_tree = NULL; f->where = gfc_current_locus; f->next = gfc_current_block ()->f2k_derived->finalizers; gfc_current_block ()->f2k_derived->finalizers = f; |