Commit e1633d82 by Daniel Franke

re PR fortran/29962 (Initialization expressions)

gcc/fortran:
2007-07-22  Daniel Franke  <franke.daniel@gmail.com>

	PR fortran/29962
	PR fortran/31253
	PR fortran/31265
	PR fortran/31639
	* gfortran.h (gfc_intrinsic_sym): Changed members elemental, pure,
	generic, specific, actual_ok, noreturn into bits of a bitfield, 
	added bits for inquiry, transformational, conversion.
	* check.c (non_init_transformational): Removed, removed all callers.
	* intrinsic.c (enum class): New.
	(add_sym*): Replaced argument elemetal by enum class. Changed all
	callers.
	(add_functions): Assign appropriate classes to intrinsic functions.
	(add_subroutines): Assign appropriate classes to intrinsic subroutines.
	(add_conv): Set conversion attribute.
	(gfc_init_expr_extensions): Removed, removed all callers.
	(gfc_intrinsic_func_interface): Reimplemented check for non-standard
	initializatione expressions.
	* expr.c (check_specification_function): New.
	(gfc_is_constant_expr): Added check for specification functions.
	(check_init_expr_arguments): New.
	(check_inquiry): Changed return value to MATCH, added checks for
	inquiry functions defined by F2003.
	(check_transformational): New.
	(check_null): New.
	(check_elemental): New.
	(check_conversion): New.
	(check_init_expr): Call new check functions, add more specific error
	messages.

gcc/testsuite:
2007-07-22  Daniel Franke  <franke.daniel@gmail.com>

	PR fortran/29962
	* gfortran.dg/array_initializer_1.f90: Removed warning.
	* gfortran.dg/initialization_1.f90: Adjusted messages.
	* gfortran.dg/nested_modules_6.f90: Removed warning.

	PR fortran/31253
	* gfortran.dg/initialization_7.f90: New test.

	PR fortran/31639
	* gfortran.dg/initialization_8.f90: New test.

From-SVN: r126826
parent 4195a767
......@@ -398,18 +398,6 @@ identical_dimen_shape (gfc_expr *a, int ai, gfc_expr *b, int bi)
}
/* Error return for transformational intrinsics not allowed in
initialization expressions. */
static try
non_init_transformational (void)
{
gfc_error ("transformational intrinsic '%s' at %L is not permitted "
"in an initialization expression", gfc_current_intrinsic,
gfc_current_intrinsic_where);
return FAILURE;
}
/***** Check functions *****/
/* Check subroutine suitable for intrinsics taking a real argument and
......@@ -489,9 +477,6 @@ gfc_check_all_any (gfc_expr *mask, gfc_expr *dim)
if (dim_check (dim, 1, 1) == FAILURE)
return FAILURE;
if (gfc_init_expr)
return non_init_transformational ();
return SUCCESS;
}
......@@ -809,9 +794,6 @@ gfc_check_count (gfc_expr *mask, gfc_expr *dim)
if (dim_check (dim, 1, 1) == FAILURE)
return FAILURE;
if (gfc_init_expr)
return non_init_transformational ();
return SUCCESS;
}
......@@ -835,9 +817,6 @@ gfc_check_cshift (gfc_expr *array, gfc_expr *shift, gfc_expr *dim)
if (dim_check (dim, 2, 1) == FAILURE)
return FAILURE;
if (gfc_init_expr)
return non_init_transformational ();
return SUCCESS;
}
......@@ -937,9 +916,6 @@ gfc_check_dot_product (gfc_expr *vector_a, gfc_expr *vector_b)
return FAILURE;
}
if (gfc_init_expr)
return non_init_transformational ();
return SUCCESS;
}
......@@ -975,9 +951,6 @@ gfc_check_eoshift (gfc_expr *array, gfc_expr *shift, gfc_expr *boundary,
if (dim_check (dim, 1, 1) == FAILURE)
return FAILURE;
if (gfc_init_expr)
return non_init_transformational ();
return SUCCESS;
}
......@@ -1648,9 +1621,6 @@ gfc_check_matmul (gfc_expr *matrix_a, gfc_expr *matrix_b)
return FAILURE;
}
if (gfc_init_expr)
return non_init_transformational ();
return SUCCESS;
}
......@@ -1709,9 +1679,6 @@ gfc_check_minloc_maxloc (gfc_actual_arglist *ap)
return FAILURE;
}
if (gfc_init_expr)
return non_init_transformational ();
return SUCCESS;
}
......@@ -1779,9 +1746,6 @@ gfc_check_minval_maxval (gfc_actual_arglist *ap)
|| array_check (ap->expr, 0) == FAILURE)
return FAILURE;
if (gfc_init_expr)
return non_init_transformational ();
return check_reduction (ap);
}
......@@ -1793,9 +1757,6 @@ gfc_check_product_sum (gfc_actual_arglist *ap)
|| array_check (ap->expr, 0) == FAILURE)
return FAILURE;
if (gfc_init_expr)
return non_init_transformational ();
return check_reduction (ap);
}
......@@ -1948,9 +1909,6 @@ gfc_check_pack (gfc_expr *array, gfc_expr *mask, gfc_expr *vector)
/* TODO: More constraints here. */
}
if (gfc_init_expr)
return non_init_transformational ();
return SUCCESS;
}
......@@ -2374,9 +2332,6 @@ gfc_check_spread (gfc_expr *source, gfc_expr *dim, gfc_expr *ncopies)
if (scalar_check (ncopies, 2) == FAILURE)
return FAILURE;
if (gfc_init_expr)
return non_init_transformational ();
return SUCCESS;
}
......@@ -2637,9 +2592,6 @@ gfc_check_transpose (gfc_expr *matrix)
if (rank_check (matrix, 0, 2) == FAILURE)
return FAILURE;
if (gfc_init_expr)
return non_init_transformational ();
return SUCCESS;
}
......@@ -2678,9 +2630,6 @@ gfc_check_unpack (gfc_expr *vector, gfc_expr *mask, gfc_expr *field)
if (same_type_check (vector, 0, field, 2) == FAILURE)
return FAILURE;
if (gfc_init_expr)
return non_init_transformational ();
return SUCCESS;
}
......
......@@ -689,6 +689,27 @@ done:
}
static match
check_specification_function (gfc_expr *e)
{
gfc_symbol *sym;
sym = e->symtree->n.sym;
/* F95, 7.1.6.2; F2003, 7.1.7 */
if (sym
&& sym->attr.function
&& sym->attr.pure
&& !sym->attr.intrinsic
&& !sym->attr.recursive
&& sym->attr.proc != PROC_INTERNAL
&& sym->attr.proc != PROC_ST_FUNCTION
&& sym->attr.proc != PROC_UNKNOWN
&& sym->formal == NULL)
return MATCH_YES;
return MATCH_NO;
}
/* Function to determine if an expression is constant or not. This
function expects that the expression has already been simplified. */
......@@ -715,6 +736,13 @@ gfc_is_constant_expr (gfc_expr *e)
break;
case EXPR_FUNCTION:
/* Specification functions are constant. */
if (check_specification_function (e) == MATCH_YES)
{
rv = 1;
break;
}
/* Call to intrinsic with at least one argument. */
rv = 0;
if (e->value.function.isym && e->value.function.actual)
......@@ -1849,69 +1877,184 @@ not_numeric:
}
static match
check_init_expr_arguments (gfc_expr *e)
{
gfc_actual_arglist *ap;
for (ap = e->value.function.actual; ap; ap = ap->next)
if (check_init_expr (ap->expr) == FAILURE)
return MATCH_ERROR;
return MATCH_YES;
}
/* Certain inquiry functions are specifically allowed to have variable
arguments, which is an exception to the normal requirement that an
initialization function have initialization arguments. We head off
this problem here. */
/* F95, 7.1.6.1, Initialization expressions, (7)
F2003, 7.1.7 Initialization expression, (8) */
static try
static match
check_inquiry (gfc_expr *e, int not_restricted)
{
const char *name;
const char *const *functions;
static const char *const inquiry_func_f95[] = {
"lbound", "shape", "size", "ubound",
"bit_size", "len", "kind",
"digits", "epsilon", "huge", "maxexponent", "minexponent",
"precision", "radix", "range", "tiny",
NULL
};
/* FIXME: This should be moved into the intrinsic definitions,
to eliminate this ugly hack. */
static const char * const inquiry_function[] = {
"digits", "epsilon", "huge", "kind", "len", "maxexponent", "minexponent",
"precision", "radix", "range", "tiny", "bit_size", "size", "shape",
"lbound", "ubound", NULL
static const char *const inquiry_func_f2003[] = {
"lbound", "shape", "size", "ubound",
"bit_size", "len", "kind",
"digits", "epsilon", "huge", "maxexponent", "minexponent",
"precision", "radix", "range", "tiny",
"new_line", NULL
};
int i;
gfc_actual_arglist *ap;
if (!e->value.function.isym
|| !e->value.function.isym->inquiry)
return MATCH_NO;
/* An undeclared parameter will get us here (PR25018). */
if (e->symtree == NULL)
return FAILURE;
return MATCH_NO;
name = e->symtree->n.sym->name;
for (i = 0; inquiry_function[i]; i++)
if (strcmp (inquiry_function[i], name) == 0)
break;
if (inquiry_function[i] == NULL)
return FAILURE;
functions = (gfc_option.warn_std & GFC_STD_F2003)
? inquiry_func_f2003 : inquiry_func_f95;
e = e->value.function.actual->expr;
for (i = 0; functions[i]; i++)
if (strcmp (functions[i], name) == 0)
break;
if (e == NULL || e->expr_type != EXPR_VARIABLE)
return FAILURE;
if (functions[i] == NULL)
{
gfc_error ("Inquiry function '%s' at %L is not permitted "
"in an initialization expression", name, &e->where);
return MATCH_ERROR;
}
/* At this point we have an inquiry function with a variable argument. The
type of the variable might be undefined, but we need it now, because the
arguments of these functions are allowed to be undefined. */
arguments of these functions are not allowed to be undefined. */
for (ap = e->value.function.actual; ap; ap = ap->next)
{
if (!ap->expr)
continue;
if (e->ts.type == BT_UNKNOWN)
if (ap->expr->ts.type == BT_UNKNOWN)
{
if (e->symtree->n.sym->ts.type == BT_UNKNOWN
&& gfc_set_default_type (e->symtree->n.sym, 0, gfc_current_ns)
if (ap->expr->symtree->n.sym->ts.type == BT_UNKNOWN
&& gfc_set_default_type (ap->expr->symtree->n.sym, 0, gfc_current_ns)
== FAILURE)
return FAILURE;
return MATCH_NO;
e->ts = e->symtree->n.sym->ts;
ap->expr->ts = ap->expr->symtree->n.sym->ts;
}
/* Assumed character length will not reduce to a constant expression
with LEN, as required by the standard. */
if (i == 4 && not_restricted
&& e->symtree->n.sym->ts.type == BT_CHARACTER
&& e->symtree->n.sym->ts.cl->length == NULL)
gfc_notify_std (GFC_STD_GNU, "assumed character length "
if (i == 5 && not_restricted
&& ap->expr->symtree->n.sym->ts.type == BT_CHARACTER
&& ap->expr->symtree->n.sym->ts.cl->length == NULL)
{
if (gfc_notify_std (GFC_STD_GNU, "assumed character length "
"variable '%s' in constant expression at %L",
e->symtree->n.sym->name, &e->where);
e->symtree->n.sym->name, &e->where) == FAILURE)
return MATCH_ERROR;
}
else if (not_restricted && check_init_expr (ap->expr) == FAILURE)
return MATCH_ERROR;
}
return SUCCESS;
return MATCH_YES;
}
/* F95, 7.1.6.1, Initialization expressions, (5)
F2003, 7.1.7 Initialization expression, (5) */
static match
check_transformational (gfc_expr *e)
{
static const char * const trans_func_f95[] = {
"repeat", "reshape", "selected_int_kind",
"selected_real_kind", "transfer", "trim", NULL
};
int i;
const char *name;
if (!e->value.function.isym
|| !e->value.function.isym->transformational)
return MATCH_NO;
name = e->symtree->n.sym->name;
/* NULL() is dealt with below. */
if (strcmp ("null", name) == 0)
return MATCH_NO;
for (i = 0; trans_func_f95[i]; i++)
if (strcmp (trans_func_f95[i], name) == 0)
break;
if (trans_func_f95[i] == NULL
&& gfc_notify_std (GFC_STD_F2003,
"transformational intrinsic '%s' at %L is not permitted "
"in an initialization expression", name, &e->where) == FAILURE)
return MATCH_ERROR;
return check_init_expr_arguments (e);
}
/* F95, 7.1.6.1, Initialization expressions, (6)
F2003, 7.1.7 Initialization expression, (6) */
static match
check_null (gfc_expr *e)
{
if (strcmp ("null", e->symtree->n.sym->name) != 0)
return MATCH_NO;
return check_init_expr_arguments (e);
}
static match
check_elemental (gfc_expr *e)
{
if (!e->value.function.isym
|| !e->value.function.isym->elemental)
return MATCH_NO;
if ((e->ts.type != BT_INTEGER || e->ts.type != BT_CHARACTER)
&& gfc_notify_std (GFC_STD_F2003, "Extension: Evaluation of "
"nonstandard initialization expression at %L",
&e->where) == FAILURE)
return MATCH_ERROR;
return check_init_expr_arguments (e);
}
static match
check_conversion (gfc_expr *e)
{
if (!e->value.function.isym
|| !e->value.function.isym->conversion)
return MATCH_NO;
return check_init_expr_arguments (e);
}
......@@ -1925,7 +2068,6 @@ check_inquiry (gfc_expr *e, int not_restricted)
static try
check_init_expr (gfc_expr *e)
{
gfc_actual_arglist *ap;
match m;
try t;
gfc_intrinsic_sym *isym;
......@@ -1943,17 +2085,28 @@ check_init_expr (gfc_expr *e)
break;
case EXPR_FUNCTION:
t = SUCCESS;
t = FAILURE;
if (check_inquiry (e, 1) != SUCCESS)
if ((m = check_specification_function (e)) != MATCH_YES)
{
t = SUCCESS;
for (ap = e->value.function.actual; ap; ap = ap->next)
if (check_init_expr (ap->expr) == FAILURE)
if ((m = gfc_intrinsic_func_interface (e, 0)) != MATCH_YES)
{
t = FAILURE;
gfc_error ("Function '%s' in initialization expression at %L "
"must be an intrinsic or a specification function",
e->symtree->n.sym->name, &e->where);
break;
}
if ((m = check_conversion (e)) == MATCH_NO
&& (m = check_inquiry (e, 1)) == MATCH_NO
&& (m = check_null (e)) == MATCH_NO
&& (m = check_transformational (e)) == MATCH_NO
&& (m = check_elemental (e)) == MATCH_NO)
{
gfc_error ("Intrinsic function '%s' at %L is not permitted "
"in an initialization expression",
e->symtree->n.sym->name, &e->where);
m = MATCH_ERROR;
}
/* Try to scalarize an elemental intrinsic function that has an
......@@ -1962,23 +2115,14 @@ check_init_expr (gfc_expr *e)
if (isym && isym->elemental
&& e->value.function.actual->expr->expr_type == EXPR_ARRAY)
{
if (scalarize_intrinsic_call (e) == SUCCESS)
if ((t = scalarize_intrinsic_call (e)) == SUCCESS)
break;
}
if (t == SUCCESS)
{
m = gfc_intrinsic_func_interface (e, 0);
if (m == MATCH_NO)
gfc_error ("Function '%s' in initialization expression at %L "
"must be an intrinsic function",
e->symtree->n.sym->name, &e->where);
if (m != MATCH_YES)
t = FAILURE;
}
if (m == MATCH_YES)
t = SUCCESS;
break;
case EXPR_VARIABLE:
......@@ -1996,10 +2140,39 @@ check_init_expr (gfc_expr *e)
if (gfc_in_match_data ())
break;
t = FAILURE;
if (e->symtree->n.sym->as)
{
switch (e->symtree->n.sym->as->type)
{
case AS_ASSUMED_SIZE:
gfc_error ("assumed size array '%s' at %L is not permitted "
"in an initialization expression",
e->symtree->n.sym->name, &e->where);
break;
case AS_ASSUMED_SHAPE:
gfc_error ("assumed shape array '%s' at %L is not permitted "
"in an initialization expression",
e->symtree->n.sym->name, &e->where);
break;
case AS_DEFERRED:
gfc_error ("deferred array '%s' at %L is not permitted "
"in an initialization expression",
e->symtree->n.sym->name, &e->where);
break;
default:
gcc_unreachable();
}
}
else
gfc_error ("Parameter '%s' at %L has not been declared or is "
"a variable, which does not reduce to a constant "
"expression", e->symtree->n.sym->name, &e->where);
t = FAILURE;
break;
case EXPR_CONSTANT:
......@@ -2078,7 +2251,7 @@ gfc_match_init_expr (gfc_expr **result)
/* Not all inquiry functions are simplified to constant expressions
so it is necessary to call check_inquiry again. */
if (!gfc_is_constant_expr (expr) && check_inquiry (expr, 1) == FAILURE
if (!gfc_is_constant_expr (expr) && check_inquiry (expr, 1) != MATCH_YES
&& !gfc_in_match_data ())
{
gfc_error ("Initialization expression didn't reduce %C");
......@@ -2161,7 +2334,7 @@ static try
restricted_intrinsic (gfc_expr *e)
{
/* TODO: Check constraints on inquiry functions. 7.1.6.2 (7). */
if (check_inquiry (e, 0) == SUCCESS)
if (check_inquiry (e, 0) == MATCH_YES)
return SUCCESS;
return restricted_args (e->value.function.actual);
......
......@@ -1392,7 +1392,10 @@ typedef struct gfc_intrinsic_sym
const char *name, *lib_name;
gfc_intrinsic_arg *formal;
gfc_typespec ts;
int elemental, pure, generic, specific, actual_ok, standard, noreturn;
unsigned elemental:1, inquiry:1, transformational:1, pure:1,
generic:1, specific:1, actual_ok:1, noreturn:1, conversion:1;
int standard;
gfc_simplify_f simplify;
gfc_check_f check;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -12,8 +12,7 @@
real, parameter :: z(2) = x(2:3, 3) + 1
real, parameter :: r(6) = (/(x(i:i +1, i), i = 1,3)/)
real, parameter :: s(12) = (/((x(i, i:j-1:-1), i = 3,4), j = 2,3)/)
real, parameter :: t(8) = (/(z, &
real (i)**3, y(i), i = 2, 3)/) ! { dg-warning "nonstandard" }
real, parameter :: t(8) = (/(z, real (i)**3, y(i), i = 2, 3)/)
integer, parameter :: ii = 4
......
......@@ -27,8 +27,8 @@ contains
integer :: l1 = len (ch1) ! { dg-warning "assumed character length variable" }
! These are warnings because they are gfortran extensions.
integer :: m3 = size (x, 1) ! { dg-warning "Evaluation of nonstandard initialization" }
integer :: m4(2) = shape (z) ! { dg-warning "Evaluation of nonstandard initialization" }
integer :: m3 = size (x, 1) ! { dg-error "assumed size array" }
integer :: m4(2) = shape (z)
! This does not depend on non-constant properties.
real(8) :: big = huge (x)
......
! { dg-do compile }
!
! PR fortran/31253 -- ICE on invlid initialization expression
! Contributed by: Mikael Morin <mikael DOT morin AT tele2 DOT fr>
!
subroutine probleme(p)
real(kind=8), dimension(:) :: p
integer :: nx = size(p, 1) ! { dg-error "deferred array" }
integer :: nix
nix = nx
end subroutine
! { dg-do compile }
! PR fortran/31639 -- ICE on invalid initialization expression
function f()
integer :: i = irand() ! { dg-error "not permitted in an initialization expression" }
f = i
end function
......@@ -28,7 +28,7 @@ module vamp_rest
end module vamp_rest
use vamp_rest
real :: x(2, 2) = reshape ([1.,2.,3.,4.], [2,2]) ! { dg-warning "nonstandard" }
real :: x(2, 2) = reshape ([1.,2.,3.,4.], [2,2])
print *, s_last
print *, diag (x)
end
......
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