Commit 52bf62f9 by Daniel Kraft Committed by Daniel Kraft

re PR fortran/38936 ([F03] ASSOCIATE construct / improved SELECT TYPE (a=>expr))

2010-08-15  Daniel Kraft  <d@domob.eu>

	PR fortran/38936
	* gfortran.h (gfc_find_proc_namespace): New method.
	* expr.c (gfc_build_intrinsic_call): No need to build symtree messing
	around with namespace.
	* symbol.c (gfc_find_proc_namespace): New method.
	* trans-decl.c (gfc_build_qualified_array): Use it for correct
	value of nest.
	* primary.c (gfc_match_varspec): Handle associate-names as arrays.
	* parse.c (parse_associate): Removed assignment-generation here...
	* resolve.c (resolve_block_construct): ...and added it here.
	(resolve_variable): Handle names that are arrays but were not parsed
	as such because of association.
	(resolve_code): Fix BLOCK resolution.
	(resolve_symbol): Generate array-spec for associate-names.

2010-08-15  Daniel Kraft  <d@domob.eu>

	PR fortran/38936
	* gfortran.dg/associate_1.f03: Enable test for array expressions.
	* gfortran.dg/associate_3.f03: Clarify comment.
	* gfortran.dg/associate_5.f03: New test.
	* gfortran.dg/associate_6.f03: New test.

From-SVN: r163268
parent 5fc265c1
2010-08-15 Daniel Kraft <d@domob.eu>
PR fortran/38936
* gfortran.h (gfc_find_proc_namespace): New method.
* expr.c (gfc_build_intrinsic_call): No need to build symtree messing
around with namespace.
* symbol.c (gfc_find_proc_namespace): New method.
* trans-decl.c (gfc_build_qualified_array): Use it for correct
value of nest.
* primary.c (gfc_match_varspec): Handle associate-names as arrays.
* parse.c (parse_associate): Removed assignment-generation here...
* resolve.c (resolve_block_construct): ...and added it here.
(resolve_variable): Handle names that are arrays but were not parsed
as such because of association.
(resolve_code): Fix BLOCK resolution.
(resolve_symbol): Generate array-spec for associate-names.
2010-08-15 Tobias Burnus <burnus@net-b.de> 2010-08-15 Tobias Burnus <burnus@net-b.de>
PR fortran/45211 PR fortran/45211
......
...@@ -4221,7 +4221,6 @@ gfc_build_intrinsic_call (const char* name, locus where, unsigned numarg, ...) ...@@ -4221,7 +4221,6 @@ gfc_build_intrinsic_call (const char* name, locus where, unsigned numarg, ...)
result->expr_type = EXPR_FUNCTION; result->expr_type = EXPR_FUNCTION;
result->ts = isym->ts; result->ts = isym->ts;
result->where = where; result->where = where;
gfc_get_ha_sym_tree (isym->name, &result->symtree);
result->value.function.name = name; result->value.function.name = name;
result->value.function.isym = isym; result->value.function.isym = isym;
......
...@@ -2577,6 +2577,7 @@ void gfc_copy_formal_args_ppc (gfc_component *, gfc_symbol *); ...@@ -2577,6 +2577,7 @@ void gfc_copy_formal_args_ppc (gfc_component *, gfc_symbol *);
void gfc_free_finalizer (gfc_finalizer *el); /* Needed in resolve.c, too */ void gfc_free_finalizer (gfc_finalizer *el); /* Needed in resolve.c, too */
gfc_try gfc_check_symbol_typed (gfc_symbol*, gfc_namespace*, bool, locus); gfc_try gfc_check_symbol_typed (gfc_symbol*, gfc_namespace*, bool, locus);
gfc_namespace* gfc_find_proc_namespace (gfc_namespace*);
/* intrinsic.c -- true if working in an init-expr, false otherwise. */ /* intrinsic.c -- true if working in an init-expr, false otherwise. */
extern bool gfc_init_expr_flag; extern bool gfc_init_expr_flag;
......
...@@ -3206,7 +3206,6 @@ parse_associate (void) ...@@ -3206,7 +3206,6 @@ parse_associate (void)
gfc_state_data s; gfc_state_data s;
gfc_statement st; gfc_statement st;
gfc_association_list* a; gfc_association_list* a;
gfc_code* assignTail;
gfc_notify_std (GFC_STD_F2003, "Fortran 2003: ASSOCIATE construct at %C"); gfc_notify_std (GFC_STD_F2003, "Fortran 2003: ASSOCIATE construct at %C");
...@@ -3216,46 +3215,24 @@ parse_associate (void) ...@@ -3216,46 +3215,24 @@ parse_associate (void)
new_st.ext.block.ns = my_ns; new_st.ext.block.ns = my_ns;
gcc_assert (new_st.ext.block.assoc); gcc_assert (new_st.ext.block.assoc);
/* Add all associations to expressions as BLOCK variables, and create /* Add all associate-names as BLOCK variables. There values will be assigned
assignments to them giving their values. */ to them during resolution of the ASSOCIATE construct. */
gfc_current_ns = my_ns; gfc_current_ns = my_ns;
assignTail = NULL;
for (a = new_st.ext.block.assoc; a; a = a->next) for (a = new_st.ext.block.assoc; a; a = a->next)
if (!a->variable) {
{ if (a->variable)
gfc_code* newAssign; {
gfc_error ("Association to variables is not yet supported at %C");
if (gfc_get_sym_tree (a->name, NULL, &a->st, false)) return;
gcc_unreachable (); }
/* Note that in certain cases, the target-expression's type is not yet if (gfc_get_sym_tree (a->name, NULL, &a->st, false))
known and so we have to adapt the symbol's ts also during resolution gcc_unreachable ();
for these cases. */
a->st->n.sym->ts = a->target->ts; a->st->n.sym->attr.flavor = FL_VARIABLE;
a->st->n.sym->attr.flavor = FL_VARIABLE; a->st->n.sym->assoc = a;
a->st->n.sym->assoc = a; gfc_set_sym_referenced (a->st->n.sym);
gfc_set_sym_referenced (a->st->n.sym); }
/* Create the assignment to calculate the expression and set it. */
newAssign = gfc_get_code ();
newAssign->op = EXEC_ASSIGN;
newAssign->loc = gfc_current_locus;
newAssign->expr1 = gfc_get_variable_expr (a->st);
newAssign->expr2 = a->target;
/* Hang it in. */
if (assignTail)
assignTail->next = newAssign;
else
gfc_current_ns->code = newAssign;
assignTail = newAssign;
}
else
{
gfc_error ("Association to variables is not yet supported at %C");
return;
}
gcc_assert (assignTail);
accept_statement (ST_ASSOCIATE); accept_statement (ST_ASSOCIATE);
push_state (&s, COMP_ASSOCIATE, my_ns->proc_name); push_state (&s, COMP_ASSOCIATE, my_ns->proc_name);
...@@ -3269,7 +3246,7 @@ loop: ...@@ -3269,7 +3246,7 @@ loop:
case_end: case_end:
accept_statement (st); accept_statement (st);
assignTail->next = gfc_state_stack->head; my_ns->code = gfc_state_stack->head;
break; break;
default: default:
......
...@@ -1748,6 +1748,13 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, bool sub_flag, ...@@ -1748,6 +1748,13 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, bool sub_flag,
} }
} }
/* For associate names, we may not yet know whether they are arrays or not.
Thus if we have one and parentheses follow, we have to assume that it
actually is one for now. The final decision will be made at
resolution time, of course. */
if (sym->assoc && gfc_peek_ascii_char () == '(')
sym->attr.dimension = 1;
if ((equiv_flag && gfc_peek_ascii_char () == '(') if ((equiv_flag && gfc_peek_ascii_char () == '(')
|| gfc_peek_ascii_char () == '[' || sym->attr.codimension || gfc_peek_ascii_char () == '[' || sym->attr.codimension
|| (sym->attr.dimension && !sym->attr.proc_pointer || (sym->attr.dimension && !sym->attr.proc_pointer
......
...@@ -4814,11 +4814,26 @@ resolve_variable (gfc_expr *e) ...@@ -4814,11 +4814,26 @@ resolve_variable (gfc_expr *e)
if (e->symtree == NULL) if (e->symtree == NULL)
return FAILURE; return FAILURE;
sym = e->symtree->n.sym;
/* If this is an associate-name, it may be parsed with references in error
even though the target is scalar. Fail directly in this case. */
if (sym->assoc && !sym->attr.dimension && e->ref)
return FAILURE;
/* On the other hand, the parser may not have known this is an array;
in this case, we have to add a FULL reference. */
if (sym->assoc && sym->attr.dimension && !e->ref)
{
e->ref = gfc_get_ref ();
e->ref->type = REF_ARRAY;
e->ref->u.ar.type = AR_FULL;
e->ref->u.ar.dimen = 0;
}
if (e->ref && resolve_ref (e) == FAILURE) if (e->ref && resolve_ref (e) == FAILURE)
return FAILURE; return FAILURE;
sym = e->symtree->n.sym;
if (sym->attr.flavor == FL_PROCEDURE if (sym->attr.flavor == FL_PROCEDURE
&& (!sym->attr.function && (!sym->attr.function
|| (sym->attr.function && sym->result || (sym->attr.function && sym->result
...@@ -8276,11 +8291,43 @@ gfc_resolve_forall (gfc_code *code, gfc_namespace *ns, int forall_save) ...@@ -8276,11 +8291,43 @@ gfc_resolve_forall (gfc_code *code, gfc_namespace *ns, int forall_save)
static void static void
resolve_block_construct (gfc_code* code) resolve_block_construct (gfc_code* code)
{ {
/* For an ASSOCIATE block, the associations (and their targets) are already
resolved during gfc_resolve_symbol. */
/* Resolve the BLOCK's namespace. */ /* Resolve the BLOCK's namespace. */
gfc_resolve (code->ext.block.ns); gfc_resolve (code->ext.block.ns);
/* For an ASSOCIATE block, the associations (and their targets) are already
resolved during gfc_resolve_symbol. Here, we have to add code
to assign expression values to the variables associated to expressions. */
if (code->ext.block.assoc)
{
gfc_association_list* a;
gfc_code* assignTail;
gfc_code* assignHead;
assignHead = assignTail = NULL;
for (a = code->ext.block.assoc; a; a = a->next)
if (!a->variable)
{
gfc_code* newAssign;
newAssign = gfc_get_code ();
newAssign->op = EXEC_ASSIGN;
newAssign->loc = gfc_current_locus;
newAssign->expr1 = gfc_lval_expr_from_sym (a->st->n.sym);
newAssign->expr2 = a->target;
if (!assignHead)
assignHead = newAssign;
else
{
gcc_assert (assignTail);
assignTail->next = newAssign;
}
assignTail = newAssign;
}
assignTail->next = code->ext.block.ns->code;
code->ext.block.ns->code = assignHead;
}
} }
...@@ -8765,7 +8812,7 @@ resolve_code (gfc_code *code, gfc_namespace *ns) ...@@ -8765,7 +8812,7 @@ resolve_code (gfc_code *code, gfc_namespace *ns)
break; break;
case EXEC_BLOCK: case EXEC_BLOCK:
gfc_resolve (code->ext.block.ns); resolve_block_construct (code);
break; break;
case EXEC_DO: case EXEC_DO:
...@@ -11651,6 +11698,54 @@ resolve_symbol (gfc_symbol *sym) ...@@ -11651,6 +11698,54 @@ resolve_symbol (gfc_symbol *sym)
sym->ts = sym->assoc->target->ts; sym->ts = sym->assoc->target->ts;
gcc_assert (sym->ts.type != BT_UNKNOWN); gcc_assert (sym->ts.type != BT_UNKNOWN);
if (sym->attr.dimension && sym->assoc->target->rank == 0)
{
gfc_error ("Associate-name '%s' at %L is used as array",
sym->name, &sym->declared_at);
sym->attr.dimension = 0;
return;
}
if (sym->assoc->target->rank > 0)
sym->attr.dimension = 1;
if (sym->attr.dimension)
{
int dim;
sym->as = gfc_get_array_spec ();
sym->as->rank = sym->assoc->target->rank;
sym->as->type = AS_EXPLICIT;
/* Target must not be coindexed, thus the associate-variable
has no corank. */
sym->as->corank = 0;
for (dim = 0; dim < sym->assoc->target->rank; ++dim)
{
gfc_expr* dim_expr;
gfc_expr* e;
dim_expr = gfc_get_constant_expr (BT_INTEGER,
gfc_default_integer_kind,
&sym->declared_at);
mpz_set_si (dim_expr->value.integer, dim + 1);
e = gfc_build_intrinsic_call ("lbound", sym->declared_at, 3,
gfc_copy_expr (sym->assoc->target),
gfc_copy_expr (dim_expr), NULL);
gfc_resolve_expr (e);
sym->as->lower[dim] = e;
e = gfc_build_intrinsic_call ("ubound", sym->declared_at, 3,
gfc_copy_expr (sym->assoc->target),
gfc_copy_expr (dim_expr), NULL);
gfc_resolve_expr (e);
sym->as->upper[dim] = e;
gfc_free_expr (dim_expr);
}
}
} }
/* Assign default type to symbols that need one and don't have one. */ /* Assign default type to symbols that need one and don't have one. */
......
...@@ -4742,3 +4742,19 @@ gfc_type_compatible (gfc_typespec *ts1, gfc_typespec *ts2) ...@@ -4742,3 +4742,19 @@ gfc_type_compatible (gfc_typespec *ts1, gfc_typespec *ts2)
else else
return 0; return 0;
} }
/* Find the parent-namespace of the current function. If we're inside
BLOCK constructs, it may not be the current one. */
gfc_namespace*
gfc_find_proc_namespace (gfc_namespace* ns)
{
while (ns->construct_entities)
{
ns = ns->parent;
gcc_assert (ns);
}
return ns;
}
...@@ -658,6 +658,7 @@ gfc_build_qualified_array (tree decl, gfc_symbol * sym) ...@@ -658,6 +658,7 @@ gfc_build_qualified_array (tree decl, gfc_symbol * sym)
tree type; tree type;
int dim; int dim;
int nest; int nest;
gfc_namespace* procns;
type = TREE_TYPE (decl); type = TREE_TYPE (decl);
...@@ -666,7 +667,8 @@ gfc_build_qualified_array (tree decl, gfc_symbol * sym) ...@@ -666,7 +667,8 @@ gfc_build_qualified_array (tree decl, gfc_symbol * sym)
return; return;
gcc_assert (GFC_ARRAY_TYPE_P (type)); gcc_assert (GFC_ARRAY_TYPE_P (type));
nest = (sym->ns->proc_name->backend_decl != current_function_decl) procns = gfc_find_proc_namespace (sym->ns);
nest = (procns->proc_name->backend_decl != current_function_decl)
&& !sym->attr.contained; && !sym->attr.contained;
for (dim = 0; dim < GFC_TYPE_ARRAY_RANK (type); dim++) for (dim = 0; dim < GFC_TYPE_ARRAY_RANK (type); dim++)
......
2010-08-15 Daniel Kraft <d@domob.eu>
PR fortran/38936
* gfortran.dg/associate_1.f03: Enable test for array expressions.
* gfortran.dg/associate_3.f03: Clarify comment.
* gfortran.dg/associate_5.f03: New test.
* gfortran.dg/associate_6.f03: New test.
2010-08-15 Tobias Burnus <burnus@net-b.de> 2010-08-15 Tobias Burnus <burnus@net-b.de>
PR fortran/45211 PR fortran/45211
......
...@@ -24,13 +24,15 @@ PROGRAM main ...@@ -24,13 +24,15 @@ PROGRAM main
! TODO: Test association to derived types. ! TODO: Test association to derived types.
! Test association to arrays. ! Test association to arrays.
! TODO: Enable when working. ALLOCATE (arr(3))
!ALLOCATE (arr(3)) arr = (/ 1, 2, 3 /)
!arr = (/ 1, 2, 3 /) ASSOCIATE (doubled => 2 * arr, xyz => func ())
!ASSOCIATE (doubled => 2 * arr) IF (SIZE (doubled) /= SIZE (arr)) CALL abort ()
! IF (doubled(1) /= 2 .OR. doubled(2) /= 4 .OR. doubled(3) /= 6) & IF (doubled(1) /= 2 .OR. doubled(2) /= 4 .OR. doubled(3) /= 6) &
! CALL abort () CALL abort ()
!END ASSOCIATE
IF (ANY (xyz /= (/ 1, 3, 5 /))) CALL abort ()
END ASSOCIATE
! Named and nested associate. ! Named and nested associate.
myname: ASSOCIATE (x => a - b * c) myname: ASSOCIATE (x => a - b * c)
...@@ -46,4 +48,12 @@ PROGRAM main ...@@ -46,4 +48,12 @@ PROGRAM main
IF (x /= 2 .OR. y /= 1) CALL abort () IF (x /= 2 .OR. y /= 1) CALL abort ()
END ASSOCIATE END ASSOCIATE
END ASSOCIATE END ASSOCIATE
CONTAINS
FUNCTION func ()
INTEGER :: func(3)
func = (/ 1, 3, 5 /)
END FUNCTION func
END PROGRAM main END PROGRAM main
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
! { dg-options "-std=f2003" } ! { dg-options "-std=f2003" }
! PR fortran/38936 ! PR fortran/38936
! Check for errors with ASSOCIATE. ! Check for errors with ASSOCIATE during parsing.
PROGRAM main PROGRAM main
IMPLICIT NONE IMPLICIT NONE
......
! { dg-do compile }
! { dg-options "-std=f2003" }
! PR fortran/38936
! Check for errors with ASSOCIATE during resolution.
PROGRAM main
IMPLICIT NONE
ASSOCIATE (a => 5) ! { dg-error "is used as array" }
PRINT *, a(3)
END ASSOCIATE
END PROGRAM main
! { dg-do compile }
! { dg-options "-std=f2003 -fdump-tree-original" }
! PR fortran/38936
! Check that array expression association (with correct bounds) works for
! complicated expressions.
! Contributed by Daniel Kraft, d@domob.eu.
! FIXME: XFAIL'ed because this is not yet implemented 'correctly'.
MODULE m
IMPLICIT NONE
CONTAINS
PURE FUNCTION func (n)
INTEGER, INTENT(IN) :: n
INTEGER :: func(2 : n+1)
INTEGER :: i
func = (/ (i, i = 1, n) /)
END FUNCTION func
END MODULE m
PROGRAM main
USE :: m
IMPLICIT NONE
ASSOCIATE (arr => func (4))
! func should only be called once here, not again for the bounds!
END ASSOCIATE
END PROGRAM main
! { dg-final { cleanup-modules "m" } }
! { dg-final { scan-tree-dump-times "func" 2 "original" { xfail *-*-* } } }
! { dg-final { cleanup-tree-dump "original" } }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment