Commit aa08038d by Erik Edelmann

re PR fortran/16136 (Conflicting attributes ALLOCATABLE, DUMMY (F2003))

fortran/
2005-03-05  Erik Edelmann  <eedelman@gcc.gnu.org>

        PR fortran/16136
        * symbol.c (conf_std): New macro.
        (check_conflict): Use it to allow ALLOCATABLE dummy
        arguments for F2003.
        * trans-expr.c (gfc_conv_function_call): Pass the
        address of the array descriptor when dummy argument is
        ALLOCATABLE.
        * interface.c (compare_allocatable): New function.
        (compare_actual_formal): Use it.
        resolve.c (resolve_deallocate_expr,
        resolve_allocate_expr): Check that INTENT(IN) variables
        aren't (de)allocated.
        * gfortran.texi (Fortran 2003 status): List ALLOCATABLE
        dummy arguments as supported.

testsuite/
2005-03-05  Erik Edelmann  <eedelman@gcc.gnu.org>

        PR fortran/16136
        * allocatable_dummy_1.f90: New.
        * allocatable_dummy_2.f90: New.

From-SVN: r111741
parent 68c9b7d6
2005-03-05 Erik Edelmann <eedelman@gcc.gnu.org>
PR fortran/16136
* symbol.c (conf_std): New macro.
(check_conflict): Use it to allow ALLOCATABLE dummy
arguments for F2003.
* trans-expr.c (gfc_conv_function_call): Pass the
address of the array descriptor when dummy argument is
ALLOCATABLE.
* interface.c (compare_allocatable): New function.
(compare_actual_formal): Use it.
* resolve.c (resolve_deallocate_expr,
resolve_allocate_expr): Check that INTENT(IN) variables
aren't (de)allocated.
* gfortran.texi (Fortran 2003 status): List ALLOCATABLE
dummy arguments as supported.
2006-03-03 Roger Sayle <roger@eyesopen.com> 2006-03-03 Roger Sayle <roger@eyesopen.com>
* dependency.c (gfc_check_element_vs_element): Revert last change. * dependency.c (gfc_check_element_vs_element): Revert last change.
......
...@@ -1331,6 +1331,10 @@ Support for the declaration of enumeration constants via the ...@@ -1331,6 +1331,10 @@ Support for the declaration of enumeration constants via the
@command{gcc} is guaranteed also for the case where the @command{gcc} is guaranteed also for the case where the
@command{-fshort-enums} command line option is given. @command{-fshort-enums} command line option is given.
@item
@cindex @code{ALLOCATABLE} dummy arguments
The @code{ALLOCATABLE} attribute for dummy arguments.
@end itemize @end itemize
......
...@@ -1065,6 +1065,26 @@ symbol_rank (gfc_symbol * sym) ...@@ -1065,6 +1065,26 @@ symbol_rank (gfc_symbol * sym)
/* Given a symbol of a formal argument list and an expression, if the /* Given a symbol of a formal argument list and an expression, if the
formal argument is allocatable, check that the actual argument is
allocatable. Returns nonzero if compatible, zero if not compatible. */
static int
compare_allocatable (gfc_symbol * formal, gfc_expr * actual)
{
symbol_attribute attr;
if (formal->attr.allocatable)
{
attr = gfc_expr_attr (actual);
if (!attr.allocatable)
return 0;
}
return 1;
}
/* Given a symbol of a formal argument list and an expression, if the
formal argument is a pointer, see if the actual argument is a formal argument is a pointer, see if the actual argument is a
pointer. Returns nonzero if compatible, zero if not compatible. */ pointer. Returns nonzero if compatible, zero if not compatible. */
...@@ -1276,6 +1296,15 @@ compare_actual_formal (gfc_actual_arglist ** ap, ...@@ -1276,6 +1296,15 @@ compare_actual_formal (gfc_actual_arglist ** ap,
return 0; return 0;
} }
if (a->expr->expr_type != EXPR_NULL
&& compare_allocatable (f->sym, a->expr) == 0)
{
if (where)
gfc_error ("Actual argument for '%s' must be ALLOCATABLE at %L",
f->sym->name, &a->expr->where);
return 0;
}
/* Check intent = OUT/INOUT for definable actual argument. */ /* Check intent = OUT/INOUT for definable actual argument. */
if (a->expr->expr_type != EXPR_VARIABLE if (a->expr->expr_type != EXPR_VARIABLE
&& (f->sym->attr.intent == INTENT_OUT && (f->sym->attr.intent == INTENT_OUT
......
...@@ -2914,6 +2914,13 @@ resolve_deallocate_expr (gfc_expr * e) ...@@ -2914,6 +2914,13 @@ resolve_deallocate_expr (gfc_expr * e)
"ALLOCATABLE or a POINTER", &e->where); "ALLOCATABLE or a POINTER", &e->where);
} }
if (e->symtree->n.sym->attr.intent == INTENT_IN)
{
gfc_error ("Can't deallocate INTENT(IN) variable '%s' at %L",
e->symtree->n.sym->name, &e->where);
return FAILURE;
}
return SUCCESS; return SUCCESS;
} }
...@@ -3015,6 +3022,13 @@ resolve_allocate_expr (gfc_expr * e, gfc_code * code) ...@@ -3015,6 +3022,13 @@ resolve_allocate_expr (gfc_expr * e, gfc_code * code)
return FAILURE; return FAILURE;
} }
if (e->symtree->n.sym->attr.intent == INTENT_IN)
{
gfc_error ("Can't allocate INTENT(IN) variable '%s' at %L",
e->symtree->n.sym->name, &e->where);
return FAILURE;
}
/* Add default initializer for those derived types that need them. */ /* Add default initializer for those derived types that need them. */
if (e->ts.type == BT_DERIVED && (init_e = gfc_default_initializer (&e->ts))) if (e->ts.type == BT_DERIVED && (init_e = gfc_default_initializer (&e->ts)))
{ {
......
...@@ -251,6 +251,13 @@ gfc_set_default_type (gfc_symbol * sym, int error_flag, gfc_namespace * ns) ...@@ -251,6 +251,13 @@ gfc_set_default_type (gfc_symbol * sym, int error_flag, gfc_namespace * ns)
#define conf(a, b) if (attr->a && attr->b) { a1 = a; a2 = b; goto conflict; } #define conf(a, b) if (attr->a && attr->b) { a1 = a; a2 = b; goto conflict; }
#define conf2(a) if (attr->a) { a2 = a; goto conflict; } #define conf2(a) if (attr->a) { a2 = a; goto conflict; }
#define conf_std(a, b, std) if (attr->a && attr->b)\
{\
a1 = a;\
a2 = b;\
standard = std;\
goto conflict_std;\
}
static try static try
check_conflict (symbol_attribute * attr, const char * name, locus * where) check_conflict (symbol_attribute * attr, const char * name, locus * where)
...@@ -268,6 +275,7 @@ check_conflict (symbol_attribute * attr, const char * name, locus * where) ...@@ -268,6 +275,7 @@ check_conflict (symbol_attribute * attr, const char * name, locus * where)
static const char *threadprivate = "THREADPRIVATE"; static const char *threadprivate = "THREADPRIVATE";
const char *a1, *a2; const char *a1, *a2;
int standard;
if (where == NULL) if (where == NULL)
where = &gfc_current_locus; where = &gfc_current_locus;
...@@ -328,7 +336,7 @@ check_conflict (symbol_attribute * attr, const char * name, locus * where) ...@@ -328,7 +336,7 @@ check_conflict (symbol_attribute * attr, const char * name, locus * where)
} }
conf (allocatable, pointer); conf (allocatable, pointer);
conf (allocatable, dummy); /* TODO: Allowed in Fortran 200x. */ conf_std (allocatable, dummy, GFC_STD_F2003);
conf (allocatable, function); /* TODO: Allowed in Fortran 200x. */ conf (allocatable, function); /* TODO: Allowed in Fortran 200x. */
conf (allocatable, result); /* TODO: Allowed in Fortran 200x. */ conf (allocatable, result); /* TODO: Allowed in Fortran 200x. */
conf (elemental, recursive); conf (elemental, recursive);
...@@ -519,10 +527,25 @@ conflict: ...@@ -519,10 +527,25 @@ conflict:
a1, a2, name, where); a1, a2, name, where);
return FAILURE; return FAILURE;
conflict_std:
if (name == NULL)
{
return gfc_notify_std (standard, "In the selected standard, %s attribute "
"conflicts with %s attribute at %L", a1, a2,
where);
}
else
{
return gfc_notify_std (standard, "In the selected standard, %s attribute "
"conflicts with %s attribute in '%s' at %L",
a1, a2, name, where);
}
} }
#undef conf #undef conf
#undef conf2 #undef conf2
#undef conf_std
/* Mark a symbol as referenced. */ /* Mark a symbol as referenced. */
......
...@@ -1870,16 +1870,15 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym, ...@@ -1870,16 +1870,15 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym,
} }
else else
{ {
/* If the procedure requires an explicit interface, the /* If the procedure requires an explicit interface, the actual
actual argument is passed according to the argument is passed according to the corresponding formal
corresponding formal argument. If the corresponding argument. If the corresponding formal argument is a POINTER,
formal argument is a POINTER or assumed shape, we do ALLOCATABLE or assumed shape, we do not use g77's calling
not use g77's calling convention, and pass the convention, and pass the address of the array descriptor
address of the array descriptor instead. Otherwise we instead. Otherwise we use g77's calling convention. */
use g77's calling convention. */
int f; int f;
f = (formal != NULL) f = (formal != NULL)
&& !formal->sym->attr.pointer && !(formal->sym->attr.pointer || formal->sym->attr.allocatable)
&& formal->sym->as->type != AS_ASSUMED_SHAPE; && formal->sym->as->type != AS_ASSUMED_SHAPE;
f = f || !sym->attr.always_explicit; f = f || !sym->attr.always_explicit;
if (arg->expr->expr_type == EXPR_VARIABLE if (arg->expr->expr_type == EXPR_VARIABLE
......
2005-03-05 Erik Edelmann <eedelman@gcc.gnu.org>
PR fortran/16136
* allocatable_dummy_1.f90: New.
* allocatable_dummy_2.f90: New.
2006-03-05 Jerry DeLisle <jvdelisle@gcc.gnu.org> 2006-03-05 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR libgfortran/26554 PR libgfortran/26554
! { dg-do run }
! Test procedures with allocatable dummy arguments
program alloc_dummy
implicit none
integer, allocatable :: a(:)
call init(a)
if (.NOT.allocated(a)) call abort()
if (.NOT.all(a == [ 1, 2, 3 ])) call abort()
call kill(a)
if (allocated(a)) call abort()
contains
subroutine init(x)
integer, allocatable, intent(out) :: x(:)
allocate(x(3))
x = [ 1, 2, 3 ]
end subroutine init
subroutine kill(x)
integer, allocatable, intent(out) :: x(:)
deallocate(x)
end subroutine kill
end program alloc_dummy
! { dg-do compile }
! Check a few constraints for ALLOCATABLE dummy arguments.
program alloc_dummy
implicit none
integer :: a(5)
call init(a) ! { dg-error "must be ALLOCATABLE" }
contains
subroutine init(x)
integer, allocatable, intent(out) :: x(:)
end subroutine init
subroutine init2(x)
integer, allocatable, intent(in) :: x(:)
allocate(x(3)) ! { dg-error "Can't allocate" }
end subroutine init2
subroutine kill(x)
integer, allocatable, intent(in) :: x(:)
deallocate(x) ! { dg-error "Can't deallocate" }
end subroutine kill
end program alloc_dummy
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