diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index e982bc4a03e265c80fb547ccb70036ec99288315..23e5c66222875a6a3e077737351226cfeffbdeca 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,53 @@ +2005-01-21 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/25124 + PR fortran/25625 + * decl.c (get_proc_name): If there is an existing + symbol in the encompassing namespace, call errors + if it is a procedure of the same name or the kind + field is set, indicating a type declaration. + + PR fortran/20881 + PR fortran/23308 + PR fortran/25538 + PR fortran/25710 + * decl.c (add_global_entry): New function to check + for existing global symbol with this name and to + create new one if none exists. + (gfc_match_entry): Call add_global_entry before + matching argument lists for subroutine and function + entries. + * gfortran.h: Prototype for existing function, + global_used. + * resolve.c (resolve_global_procedure): New function + to check global symbols for procedures. + (resolve_call, resolve_function): Calls to this + new function for non-contained and non-module + procedures. + * match.c (match_common): Add check for existing + global symbol, creat one if none exists and emit + error if there is a clash. + * parse.c (global_used): Remove static and use the + gsymbol name rather than the new_block name, so that + the function can be called from resolve.c. + (parse_block_data, parse_module, add_global_procedure): + Improve checks for existing gsymbols. Emit error if + already defined or if references were to another type. + Set defined flag. + + PR fortran/PR24276 + * trans-expr.c (gfc_conv_aliased_arg): New function called by + gfc_conv_function_call that coverts an expression for an aliased + component reference to a derived type array into a temporary array + of the same type as the component. The temporary is passed as an + actual argument for the procedure call and is copied back to the + derived type after the call. + (is_aliased_array): New function that detects an array reference + that is followed by a component reference. + (gfc_conv_function_call): Detect an aliased actual argument with + is_aliased_array and convert it to a temporary and back again + using gfc_conv_aliased_arg. + 2006-01-19 Tobias Schlâ—¯ter <tobias.schlueter@physik.uni-muenchen.de> * gfortranspec.c: Update copyright years. diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c index e786b318927783896e2438cd019d19943e0ad15b..282ca730aa40cf8467ec4fc2bfebf7a8e63e2246 100644 --- a/gcc/fortran/decl.c +++ b/gcc/fortran/decl.c @@ -603,17 +603,38 @@ get_proc_name (const char *name, gfc_symbol ** result) int rc; if (gfc_current_ns->parent == NULL) - return gfc_get_symbol (name, NULL, result); + rc = gfc_get_symbol (name, NULL, result); + else + rc = gfc_get_symbol (name, gfc_current_ns->parent, result); - rc = gfc_get_symbol (name, gfc_current_ns->parent, result); - if (*result == NULL) - return rc; + sym = *result; - /* ??? Deal with ENTRY problem */ + if (sym && !sym->new && gfc_current_state () != COMP_INTERFACE) + { + /* Trap another encompassed procedure with the same name. */ + if (sym->attr.flavor != 0 + && sym->attr.proc != 0 + && (sym->attr.subroutine || sym->attr.function)) + gfc_error_now ("Procedure '%s' at %C is already defined at %L", + name, &sym->declared_at); + + /* Trap declarations of attributes in encompassing scope. The + signature for this is that ts.kind is set. Legitimate + references only set ts.type. */ + if (sym->ts.kind != 0 + && sym->attr.proc == 0 + && gfc_current_ns->parent != NULL + && sym->attr.access == 0) + gfc_error_now ("Procedure '%s' at %C has an explicit interface" + " and must not have attributes declared at %L", + name, &sym->declared_at); + } + + if (gfc_current_ns->parent == NULL || *result == NULL) + return rc; st = gfc_new_symtree (&gfc_current_ns->sym_root, name); - sym = *result; st->n.sym = sym; sym->refs++; @@ -2606,6 +2627,29 @@ cleanup: return m; } +/* This is mostly a copy of parse.c(add_global_procedure) but modified to pass the + name of the entry, rather than the gfc_current_block name, and to return false + upon finding an existing global entry. */ + +static bool +add_global_entry (const char * name, int sub) +{ + gfc_gsymbol *s; + + s = gfc_get_gsymbol(name); + + if (s->defined + || (s->type != GSYM_UNKNOWN && s->type != (sub ? GSYM_SUBROUTINE : GSYM_FUNCTION))) + global_used(s, NULL); + else + { + s->type = sub ? GSYM_SUBROUTINE : GSYM_FUNCTION; + s->where = gfc_current_locus; + s->defined = 1; + return true; + } + return false; +} /* Match an ENTRY statement. */ @@ -2697,6 +2741,9 @@ gfc_match_entry (void) if (state == COMP_SUBROUTINE) { /* An entry in a subroutine. */ + if (!add_global_entry (name, 1)) + return MATCH_ERROR; + m = gfc_match_formal_arglist (entry, 0, 1); if (m != MATCH_YES) return MATCH_ERROR; @@ -2716,6 +2763,9 @@ gfc_match_entry (void) ENTRY f() RESULT (r) can't be written as ENTRY f RESULT (r). */ + if (!add_global_entry (name, 0)) + return MATCH_ERROR; + old_loc = gfc_current_locus; if (gfc_match_eos () == MATCH_YES) { diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index b00a9b35b538162e2fd40dddd522a1085c31f71b..9e5d303afd27ea48182ac970cd3854b22692b933 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -1962,5 +1962,6 @@ void gfc_show_namespace (gfc_namespace *); /* parse.c */ try gfc_parse_file (void); +void global_used (gfc_gsymbol *, locus *); #endif /* GCC_GFORTRAN_H */ diff --git a/gcc/fortran/match.c b/gcc/fortran/match.c index 7dd4e1a8c63f4ab70f4f6764e4611b53cd8ed58b..40355d21aabf6306e97deab8443413cf26d2bc28 100644 --- a/gcc/fortran/match.c +++ b/gcc/fortran/match.c @@ -2250,6 +2250,7 @@ gfc_match_common (void) gfc_array_spec *as; gfc_equiv * e1, * e2; match m; + gfc_gsymbol *gsym; old_blank_common = gfc_current_ns->blank_common.head; if (old_blank_common) @@ -2266,6 +2267,23 @@ gfc_match_common (void) if (m == MATCH_ERROR) goto cleanup; + gsym = gfc_get_gsymbol (name); + if (gsym->type != GSYM_UNKNOWN && gsym->type != GSYM_COMMON) + { + gfc_error ("Symbol '%s' at %C is already an external symbol that is not COMMON", + sym->name); + goto cleanup; + } + + if (gsym->type == GSYM_UNKNOWN) + { + gsym->type = GSYM_COMMON; + gsym->where = gfc_current_locus; + gsym->defined = 1; + } + + gsym->used = 1; + if (name[0] == '\0') { t = &gfc_current_ns->blank_common; diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c index 6fd3322dbc12bff0c73176518a31d2ee760be677..4fb690baa0ac5baea0ba4dcfb3898b2870b2f3da 100644 --- a/gcc/fortran/parse.c +++ b/gcc/fortran/parse.c @@ -1,5 +1,5 @@ /* Main parser. - Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, + Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. Contributed by Andy Vaught @@ -2396,7 +2396,7 @@ done: /* Come here to complain about a global symbol already in use as something else. */ -static void +void global_used (gfc_gsymbol *sym, locus *where) { const char *name; @@ -2430,7 +2430,7 @@ global_used (gfc_gsymbol *sym, locus *where) } gfc_error("Global name '%s' at %L is already being used as a %s at %L", - gfc_new_block->name, where, name, &sym->where); + sym->name, where, name, &sym->where); } @@ -2461,12 +2461,13 @@ parse_block_data (void) else { s = gfc_get_gsymbol (gfc_new_block->name); - if (s->type != GSYM_UNKNOWN) + if (s->defined || (s->type != GSYM_UNKNOWN && s->type != GSYM_BLOCK_DATA)) global_used(s, NULL); else { s->type = GSYM_BLOCK_DATA; s->where = gfc_current_locus; + s->defined = 1; } } @@ -2491,12 +2492,13 @@ parse_module (void) gfc_gsymbol *s; s = gfc_get_gsymbol (gfc_new_block->name); - if (s->type != GSYM_UNKNOWN) + if (s->defined || (s->type != GSYM_UNKNOWN && s->type != GSYM_MODULE)) global_used(s, NULL); else { s->type = GSYM_MODULE; s->where = gfc_current_locus; + s->defined = 1; } st = parse_spec (ST_NONE); @@ -2535,12 +2537,14 @@ add_global_procedure (int sub) s = gfc_get_gsymbol(gfc_new_block->name); - if (s->type != GSYM_UNKNOWN) + if (s->defined + || (s->type != GSYM_UNKNOWN && s->type != (sub ? GSYM_SUBROUTINE : GSYM_FUNCTION))) global_used(s, NULL); else { s->type = sub ? GSYM_SUBROUTINE : GSYM_FUNCTION; s->where = gfc_current_locus; + s->defined = 1; } } @@ -2556,12 +2560,13 @@ add_global_program (void) return; s = gfc_get_gsymbol (gfc_new_block->name); - if (s->type != GSYM_UNKNOWN) + if (s->defined || (s->type != GSYM_UNKNOWN && s->type != GSYM_PROGRAM)) global_used(s, NULL); else { s->type = GSYM_PROGRAM; s->where = gfc_current_locus; + s->defined = 1; } } diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index af9531679262110ac700d69a9520ca714dd8dd57..1d8a71b371db1b421de66a6d8a19fb4610b54379 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -885,6 +885,36 @@ find_noncopying_intrinsics (gfc_symbol * fnsym, gfc_actual_arglist * actual) ap->expr->inline_noncopying_intrinsic = 1; } +/* This function does the checking of references to global procedures + as defined in sections 18.1 and 14.1, respectively, of the Fortran + 77 and 95 standards. It checks for a gsymbol for the name, making + one if it does not already exist. If it already exists, then the + reference being resolved must correspond to the type of gsymbol. + Otherwise, the new symbol is equipped with the attributes of the + reference. The corresponding code that is called in creating + global entities is parse.c. */ + +static void +resolve_global_procedure (gfc_symbol *sym, locus *where, int sub) +{ + gfc_gsymbol * gsym; + uint type; + + type = sub ? GSYM_SUBROUTINE : GSYM_FUNCTION; + + gsym = gfc_get_gsymbol (sym->name); + + if ((gsym->type != GSYM_UNKNOWN && gsym->type != type)) + global_used (gsym, where); + + if (gsym->type == GSYM_UNKNOWN) + { + gsym->type = type; + gsym->where = *where; + } + + gsym->used = 1; +} /************* Function resolution *************/ @@ -1157,6 +1187,14 @@ resolve_function (gfc_expr * expr) try t; int temp; + /* If the procedure is not internal or module, it must be external and + should be checked for usage. */ + if (expr->symtree && expr->symtree->n.sym + && !expr->symtree->n.sym->attr.dummy + && !expr->symtree->n.sym->attr.contained + && !expr->symtree->n.sym->attr.use_assoc) + resolve_global_procedure (expr->symtree->n.sym, &expr->where, 0); + /* Switch off assumed size checking and do this again for certain kinds of procedure, once the procedure itself is resolved. */ need_full_assumed_size++; @@ -1511,6 +1549,14 @@ resolve_call (gfc_code * c) { try t; + /* If the procedure is not internal or module, it must be external and + should be checked for usage. */ + if (c->symtree && c->symtree->n.sym + && !c->symtree->n.sym->attr.dummy + && !c->symtree->n.sym->attr.contained + && !c->symtree->n.sym->attr.use_assoc) + resolve_global_procedure (c->symtree->n.sym, &c->loc, 1); + /* Switch off assumed size checking and do this again for certain kinds of procedure, once the procedure itself is resolved. */ need_full_assumed_size++; @@ -4805,6 +4851,18 @@ resolve_symbol (gfc_symbol * sym) } break; + case FL_PROCEDURE: + /* An external symbol may not have an intializer because it is taken to be + a procedure. */ + if (sym->attr.external && sym->value) + { + gfc_error ("External object '%s' at %L may not have an initializer", + sym->name, &sym->declared_at); + return; + } + + break; + case FL_DERIVED: /* Add derived type to the derived type list. */ { @@ -4818,14 +4876,6 @@ resolve_symbol (gfc_symbol * sym) default: - /* An external symbol falls through to here if it is not referenced. */ - if (sym->attr.external && sym->value) - { - gfc_error ("External object '%s' at %L may not have an initializer", - sym->name, &sym->declared_at); - return; - } - break; } diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c index 880994abcad65890c88217494059aa1ad606af28..b30a12182241b15b23f13923cfadd0d9957fd580 100644 --- a/gcc/fortran/trans-expr.c +++ b/gcc/fortran/trans-expr.c @@ -1529,6 +1529,226 @@ gfc_apply_interface_mapping (gfc_interface_mapping * mapping, gfc_free_expr (expr); } +/* Returns a reference to a temporary array into which a component of + an actual argument derived type array is copied and then returned + after the function call. + TODO Get rid of this kludge, when array descriptors are capable of + handling aliased arrays. */ + +static void +gfc_conv_aliased_arg (gfc_se * parmse, gfc_expr * expr, int g77) +{ + gfc_se lse; + gfc_se rse; + gfc_ss *lss; + gfc_ss *rss; + gfc_loopinfo loop; + gfc_loopinfo loop2; + gfc_ss_info *info; + tree offset; + tree tmp_index; + tree tmp; + tree base_type; + stmtblock_t body; + int n; + + gcc_assert (expr->expr_type == EXPR_VARIABLE); + + gfc_init_se (&lse, NULL); + gfc_init_se (&rse, NULL); + + /* Walk the argument expression. */ + rss = gfc_walk_expr (expr); + + gcc_assert (rss != gfc_ss_terminator); + + /* Initialize the scalarizer. */ + gfc_init_loopinfo (&loop); + gfc_add_ss_to_loop (&loop, rss); + + /* Calculate the bounds of the scalarization. */ + gfc_conv_ss_startstride (&loop); + + /* Build an ss for the temporary. */ + base_type = gfc_typenode_for_spec (&expr->ts); + if (GFC_ARRAY_TYPE_P (base_type) + || GFC_DESCRIPTOR_TYPE_P (base_type)) + base_type = gfc_get_element_type (base_type); + + loop.temp_ss = gfc_get_ss ();; + loop.temp_ss->type = GFC_SS_TEMP; + loop.temp_ss->data.temp.type = base_type; + + if (expr->ts.type == BT_CHARACTER) + loop.temp_ss->string_length = expr->ts.cl->backend_decl; + + loop.temp_ss->data.temp.dimen = loop.dimen; + loop.temp_ss->next = gfc_ss_terminator; + + /* Associate the SS with the loop. */ + gfc_add_ss_to_loop (&loop, loop.temp_ss); + + /* Setup the scalarizing loops. */ + gfc_conv_loop_setup (&loop); + + /* Pass the temporary descriptor back to the caller. */ + info = &loop.temp_ss->data.info; + parmse->expr = info->descriptor; + + /* Setup the gfc_se structures. */ + gfc_copy_loopinfo_to_se (&lse, &loop); + gfc_copy_loopinfo_to_se (&rse, &loop); + + rse.ss = rss; + lse.ss = loop.temp_ss; + gfc_mark_ss_chain_used (rss, 1); + gfc_mark_ss_chain_used (loop.temp_ss, 1); + + /* Start the scalarized loop body. */ + gfc_start_scalarized_body (&loop, &body); + + /* Translate the expression. */ + gfc_conv_expr (&rse, expr); + + gfc_conv_tmp_array_ref (&lse); + gfc_advance_se_ss_chain (&lse); + + tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts.type); + gfc_add_expr_to_block (&body, tmp); + + gcc_assert (rse.ss == gfc_ss_terminator); + + gfc_trans_scalarizing_loops (&loop, &body); + + /* Add the post block after the second loop, so that any + freeing of allocated memory is done at the right time. */ + gfc_add_block_to_block (&parmse->pre, &loop.pre); + + /**********Copy the temporary back again.*********/ + + gfc_init_se (&lse, NULL); + gfc_init_se (&rse, NULL); + + /* Walk the argument expression. */ + lss = gfc_walk_expr (expr); + rse.ss = loop.temp_ss; + lse.ss = lss; + + /* Initialize the scalarizer. */ + gfc_init_loopinfo (&loop2); + gfc_add_ss_to_loop (&loop2, lss); + + /* Calculate the bounds of the scalarization. */ + gfc_conv_ss_startstride (&loop2); + + /* Setup the scalarizing loops. */ + gfc_conv_loop_setup (&loop2); + + gfc_copy_loopinfo_to_se (&lse, &loop2); + gfc_copy_loopinfo_to_se (&rse, &loop2); + + gfc_mark_ss_chain_used (lss, 1); + gfc_mark_ss_chain_used (loop.temp_ss, 1); + + /* Declare the variable to hold the temporary offset and start the + scalarized loop body. */ + offset = gfc_create_var (gfc_array_index_type, NULL); + gfc_start_scalarized_body (&loop2, &body); + + /* Build the offsets for the temporary from the loop variables. The + temporary array has lbounds of zero and strides of one in all + dimensions, so this is very simple. The offset is only computed + outside the innermost loop, so the overall transfer could be + optimised further. */ + info = &rse.ss->data.info; + + tmp_index = gfc_index_zero_node; + for (n = info->dimen - 1; n > 0; n--) + { + tree tmp_str; + tmp = rse.loop->loopvar[n]; + tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, + tmp, rse.loop->from[n]); + tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type, + tmp, tmp_index); + + tmp_str = fold_build2 (MINUS_EXPR, gfc_array_index_type, + rse.loop->to[n-1], rse.loop->from[n-1]); + tmp_str = fold_build2 (PLUS_EXPR, gfc_array_index_type, + tmp_str, gfc_index_one_node); + + tmp_index = fold_build2 (MULT_EXPR, gfc_array_index_type, + tmp, tmp_str); + } + + tmp_index = fold_build2 (MINUS_EXPR, gfc_array_index_type, + tmp_index, rse.loop->from[0]); + gfc_add_modify_expr (&rse.loop->code[0], offset, tmp_index); + + tmp_index = fold_build2 (PLUS_EXPR, gfc_array_index_type, + rse.loop->loopvar[0], offset); + + /* Now use the offset for the reference. */ + tmp = build_fold_indirect_ref (info->data); + rse.expr = gfc_build_array_ref (tmp, tmp_index); + + if (expr->ts.type == BT_CHARACTER) + rse.string_length = expr->ts.cl->backend_decl; + + gfc_conv_expr (&lse, expr); + + gcc_assert (lse.ss == gfc_ss_terminator); + + tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts.type); + gfc_add_expr_to_block (&body, tmp); + + /* Generate the copying loops. */ + gfc_trans_scalarizing_loops (&loop2, &body); + + /* Wrap the whole thing up by adding the second loop to the post-block + and following it by the post-block of the fist loop. In this way, + if the temporary needs freeing, it is done after use! */ + gfc_add_block_to_block (&parmse->post, &loop2.pre); + gfc_add_block_to_block (&parmse->post, &loop2.post); + + gfc_add_block_to_block (&parmse->post, &loop.post); + + gfc_cleanup_loop (&loop); + gfc_cleanup_loop (&loop2); + + /* Pass the string length to the argument expression. */ + if (expr->ts.type == BT_CHARACTER) + parmse->string_length = expr->ts.cl->backend_decl; + + /* We want either the address for the data or the address of the descriptor, + depending on the mode of passing array arguments. */ + if (g77) + parmse->expr = gfc_conv_descriptor_data_get (parmse->expr); + else + parmse->expr = build_fold_addr_expr (parmse->expr); + + return; +} + +/* Is true if the last array reference is followed by a component reference. */ + +static bool +is_aliased_array (gfc_expr * e) +{ + gfc_ref * ref; + bool seen_array; + + seen_array = false; + for (ref = e->ref; ref; ref = ref->next) + { + if (ref->type == REF_ARRAY) + seen_array = true; + + if (ref->next == NULL && ref->type == REF_COMPONENT) + return seen_array; + } + return false; +} /* Generate code for a procedure call. Note can return se->post != NULL. If se->direct_byref is set then se->expr contains the return parameter. @@ -1655,7 +1875,15 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym, && !formal->sym->attr.pointer && formal->sym->as->type != AS_ASSUMED_SHAPE; f = f || !sym->attr.always_explicit; - gfc_conv_array_parameter (&parmse, arg->expr, argss, f); + if (arg->expr->expr_type == EXPR_VARIABLE + && is_aliased_array (arg->expr)) + /* The actual argument is a component reference to an + array of derived types. In this case, the argument + is converted to a temporary, which is passed and then + written back after the procedure call. */ + gfc_conv_aliased_arg (&parmse, arg->expr, f); + else + gfc_conv_array_parameter (&parmse, arg->expr, argss, f); } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b53833bfdf3108f83e5e3956b0bae3254f759585..7c28e0ee25b0f817985676dc1feacdf75ac8e77b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,20 @@ +2005-01-21 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/25124 + PR fortran/25625 + * gfortran.dg/internal_references_1.f90: New test. + PR fortran/20881 + PR fortran/23308 + PR fortran/25538 + PR fortran/25710 + * gfortran.dg/global_references_1.f90: New test. + * gfortran.dg/g77/19990905-1.f: Restore the error that + there is a clash between the common block name and + the name of a subroutine reference. + + PR fortran/PR24276 + * gfortran.dg/aliasing_dummy_1.f90: New test. + 2006-01-21 Alan Modra <amodra@bigpond.net.au> * gcc.dg/vmx/1b-01.c: Warning fix. diff --git a/gcc/testsuite/gfortran.dg/aliasing_dummy_1.f90 b/gcc/testsuite/gfortran.dg/aliasing_dummy_1.f90 new file mode 100644 index 0000000000000000000000000000000000000000..0d0b588fc105c30387e9eb8947c8332d25e015b7 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/aliasing_dummy_1.f90 @@ -0,0 +1,64 @@ +! { dg-do run } +! This tests the fix for PR24276, which originated from the Loren P. Meissner example, +! Array_List. The PR concerns dummy argument aliassing of components of arrays of derived +! types as arrays of the type of the component. gfortran would compile and run this +! example but the stride used did not match the actual argument. This test case exercises +! a procedure call (to foo2, below) that is identical to Array_List's. +! +! Contributed by Paul Thomas <pault@gcc.gnu.org> + +program test_lex + type :: dtype + integer :: n + character*5 :: word + end type dtype + + type :: list + type(dtype), dimension(4) :: list + integer :: l = 4 + end type list + + type(list) :: table + type(dtype) :: elist(2,2) + + table%list = (/dtype (1 , "one "), dtype (2 , "two "), dtype (3 , "three"), dtype (4 , "four ")/) + +! Test 1D with assumed shape (original bug) and assumed size. + call bar (table, 2, 4) + if (any (table%list%word.ne.(/"one ","i= 2","three","i= 4"/))) call abort () + + elist = reshape (table%list, (/2,2/)) + +! Check 2D is OK with assumed shape and assumed size. + call foo3 (elist%word, 1) + call foo1 (elist%word, 3) + if (any (elist%word.ne.reshape ((/"i= 1","i= 2","i= 3","i= 4"/), (/2,2/)))) call abort () + +contains + + subroutine bar (table, n, m) + type(list) :: table + integer n, m + call foo1 (table%list(:table%l)%word, n) + call foo2 (table%list(:table%l)%word, m) + end subroutine bar + + subroutine foo1 (slist, i) + character(*), dimension(*) :: slist + integer i + write (slist(i), '(2hi=,i3)') i + end subroutine foo1 + + subroutine foo2 (slist, i) + character(5), dimension(:) :: slist + integer i + write (slist(i), '(2hi=,i3)') i + end subroutine foo2 + + subroutine foo3 (slist, i) + character(5), dimension(:,:) :: slist + integer i + write (slist(1,1), '(2hi=,i3)') i + end subroutine foo3 + +end program test_lex \ No newline at end of file diff --git a/gcc/testsuite/gfortran.dg/g77/19990905-1.f b/gcc/testsuite/gfortran.dg/g77/19990905-1.f index 42de812e0bbdc91add824299ca673bc304f75ede..b69d66ed266ac742d3a30d0175487e9dd39f020b 100644 --- a/gcc/testsuite/gfortran.dg/g77/19990905-1.f +++ b/gcc/testsuite/gfortran.dg/g77/19990905-1.f @@ -12,8 +12,8 @@ c Invalid declaration of or reference to symbol `foo' at (2) [initially seen at * =foo7.f in Burley's g77 test suite. subroutine x real a(n) - common /foo/n + common /foo/n ! { dg-error "is already being used as a COMMON" } continue entry y(a) - call foo(a(1)) + call foo(a(1)) ! { dg-error "is already being used as a COMMON" } end diff --git a/gcc/testsuite/gfortran.dg/global_references_1.f90 b/gcc/testsuite/gfortran.dg/global_references_1.f90 new file mode 100644 index 0000000000000000000000000000000000000000..d8728d3b08db156f1de96f932f95793f9ab8a503 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/global_references_1.f90 @@ -0,0 +1,98 @@ +! { dg-do compile } +! This program tests the patch for PRs 20881, 23308, 25538 & 25710 +! Assembled from PRs by Paul Thomas <pault@gcc.gnu.org> +module m +contains + subroutine g(x) ! Local entity + REAL :: x + x = 1.0 + end subroutine g +end module m +! Error only appears once but testsuite associates with both lines. +function f(x) ! { dg-error "is already being used as a FUNCTION" } + REAL :: f, x + f = x +end function f + +function g(x) ! Global entity + REAL :: g, x + g = x + +! PR25710========================================================== +! Lahey -2607-S: "SOURCE.F90", line 26: +! Function 'f' cannot be referenced as a subroutine. The previous +! definition is in 'line 12'. + + call f(g) ! { dg-error "is already being used as a FUNCTION" } +end function g +! Error only appears once but testsuite associates with both lines. +function h(x) ! { dg-error "is already being used as a FUNCTION" } + REAL :: h, x + h = x +end function h + +SUBROUTINE TT() + CHARACTER(LEN=10), EXTERNAL :: j + CHARACTER(LEN=10) :: T +! PR20881=========================================================== +! Error only appears once but testsuite associates with both lines. + T = j () ! { dg-error "is already being used as a FUNCTION" } + print *, T +END SUBROUTINE TT + + use m ! Main program + real x + integer a(10) + +! PR23308=========================================================== +! Lahey - 2604-S: "SOURCE.F90", line 52: +! The name 'foo' cannot be specified as both external procedure name +! and common block name. The previous appearance is in 'line 68'. +! Error only appears once but testsuite associates with both lines. + common /foo/ a ! { dg-error "is already being used as a COMMON" } + + call f (x) ! OK - reference to local entity + call g (x) ! -ditto- + +! PR25710=========================================================== +! Lahey - 2607-S: "SOURCE.F90", line 62: +! Function 'h' cannot be referenced as a subroutine. The previous +! definition is in 'line 29'. + + call h (x) ! { dg-error "is already being used as a FUNCTION" } + +! PR23308=========================================================== +! Lahey - 2521-S: "SOURCE.F90", line 68: Intrinsic procedure name or +! external procedure name same as common block name 'foo'. + + call foo () ! { dg-error "is already being used as a COMMON" } + +contains + SUBROUTINE f (x) ! Local entity + real x + x = 2 + end SUBROUTINE f +end + +! PR20881=========================================================== +! Lahey - 2636-S: "SOURCE.F90", line 81: +! Subroutine 'j' is previously referenced as a function in 'line 39'. + +SUBROUTINE j (x) ! { dg-error "is already being used as a FUNCTION" } + integer a(10) + common /bar/ a ! Global entity foo + real x + x = bar(1.0) ! OK for local procedure to have common block name +contains + function bar (x) + real bar, x + bar = 2.0*x + end function bar +END SUBROUTINE j + +! PR25538=========================================================== +! would ICE with entry and procedure having same names. + subroutine link2 (namef) ! { dg-error "is already being used as a SUBROUTINE" } + entry link2 (nameg) ! { dg-error "is already being used as a SUBROUTINE" } + return + end diff --git a/gcc/testsuite/gfortran.dg/internal_references_1.f90 b/gcc/testsuite/gfortran.dg/internal_references_1.f90 new file mode 100644 index 0000000000000000000000000000000000000000..461fbfa92c9e4379259212014cec3df80861adad --- /dev/null +++ b/gcc/testsuite/gfortran.dg/internal_references_1.f90 @@ -0,0 +1,36 @@ +! { dg-do compile } +! This tests the patch for PRs 24327, 25024 & 25625, which +! are all connected with references to internal procedures. +! This is a composite of the PR testcases; and each is +! labelled by PR. +! +! Contributed by Paul Thomas <pault@gcc.gnu.org> +! +! PR25625 - would neglect to point out that there were 2 subroutines p. +module m + implicit none +contains + + subroutine p (i) ! { dg-error "is already defined" } + integer :: i + end subroutine + + subroutine p (i) ! { dg-error "is already defined" } + integer :: i + end subroutine +end module +! +! PR25124 - would happily ignore the declaration of foo in the main program. +program test +real :: foo, x ! { dg-error "explicit interface and must not have attributes declared" } +x = bar () ! This is OK because it is a regular reference. +x = foo () +contains + function foo () ! { dg-error "explicit interface and must not have attributes declared" } + foo = 1.0 + end function foo + function bar () + bar = 1.0 + end function bar +end program test +