Commit 229c5919 by Tobias Burnus Committed by Tobias Burnus

check.c (check_co_collective): Reject coindexed A args.

2014-10-24  Tobias Burnus  <burnus@net-b.de>

gcc/fortran
        * check.c (check_co_collective): Reject coindexed A args.
        (gfc_check_co_reduce): Add OPERATOR checks.
        * gfortran.texi (_gfortran_caf_co_broadcast,
        * _gfortran_caf_co_max,
        _gfortran_caf_co_min, _gfortran_caf_co_sum,
        _gfortran_caf_co_reduce): Add ABI documentation.
        * intrinsic.texi (CO_REDUCE): Document intrinsic.
        (DPROD): Returns double not single precision.
        * trans-decl.c (gfor_fndecl_co_reduce): New global var.
        (gfc_build_builtin_function_decls): Init it.
        * trans.h (gfor_fndecl_co_reduce): Declare it.
        * trans-intrinsic.c (conv_co_collective,
        gfc_conv_intrinsic_subroutine): Handle CO_REDUCE.

gcc/testsuite/
        * gfortran.dg/coarray_collectives_9.f90: Remove dg-error.
        * gfortran.dg/coarray_collectives_13.f90: New.
        * gfortran.dg/coarray_collectives_14.f90: New.
        * gfortran.dg/coarray_collectives_15.f90: New.
        * gfortran.dg/coarray_collectives_16.f90: New.

From-SVN: r216678
parent 763206be
2014-10-24 Tobias Burnus <burnus@net-b.de>
* check.c (check_co_collective): Reject coindexed A args.
(gfc_check_co_reduce): Add OPERATOR checks.
* gfortran.texi (_gfortran_caf_co_broadcast, _gfortran_caf_co_max,
_gfortran_caf_co_min, _gfortran_caf_co_sum,
_gfortran_caf_co_reduce): Add ABI documentation.
* intrinsic.texi (CO_REDUCE): Document intrinsic.
(DPROD): Returns double not single precision.
* trans-decl.c (gfor_fndecl_co_reduce): New global var.
(gfc_build_builtin_function_decls): Init it.
* trans.h (gfor_fndecl_co_reduce): Declare it.
* trans-intrinsic.c (conv_co_collective,
gfc_conv_intrinsic_subroutine): Handle CO_REDUCE.
2014-10-19 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
PR fortran/48979
......
......@@ -1433,6 +1433,13 @@ check_co_collective (gfc_expr *a, gfc_expr *image_idx, gfc_expr *stat,
return false;
}
if (gfc_is_coindexed (a))
{
gfc_error ("The A argument at %L to the intrinsic %s shall not be "
"coindexed", &a->where, gfc_current_intrinsic);
return false;
}
if (image_idx != NULL)
{
if (!type_check (image_idx, co_reduce ? 2 : 1, BT_INTEGER))
......@@ -1490,10 +1497,10 @@ gfc_check_co_broadcast (gfc_expr *a, gfc_expr *source_image, gfc_expr *stat,
{
if (a->ts.type == BT_CLASS || gfc_expr_attr (a).alloc_comp)
{
gfc_error ("Support for the A argument at %L which is polymorphic A "
"argument or has allocatable components is not yet "
"implemented", &a->where);
return false;
gfc_error ("Support for the A argument at %L which is polymorphic A "
"argument or has allocatable components is not yet "
"implemented", &a->where);
return false;
}
return check_co_collective (a, source_image, stat, errmsg, false);
}
......@@ -1504,38 +1511,164 @@ gfc_check_co_reduce (gfc_expr *a, gfc_expr *op, gfc_expr *result_image,
gfc_expr *stat, gfc_expr *errmsg)
{
symbol_attribute attr;
gfc_formal_arglist *formal;
gfc_symbol *sym;
if (a->ts.type == BT_CLASS)
{
gfc_error ("The A argument at %L of CO_REDUCE shall not be polymorphic",
&a->where);
return false;
gfc_error ("The A argument at %L of CO_REDUCE shall not be polymorphic",
&a->where);
return false;
}
if (gfc_expr_attr (a).alloc_comp)
{
gfc_error ("Support for the A argument at %L with allocatable components"
" is not yet implemented", &a->where);
return false;
gfc_error ("Support for the A argument at %L with allocatable components"
" is not yet implemented", &a->where);
return false;
}
if (!check_co_collective (a, result_image, stat, errmsg, true))
return false;
if (!gfc_resolve_expr (op))
return false;
attr = gfc_expr_attr (op);
if (!attr.pure || !attr.function)
{
gfc_error ("OPERATOR argument at %L must be a PURE function",
&op->where);
return false;
gfc_error ("OPERATOR argument at %L must be a PURE function",
&op->where);
return false;
}
if (!check_co_collective (a, result_image, stat, errmsg, true))
return false;
if (attr.intrinsic)
{
/* None of the intrinsics fulfills the criteria of taking two arguments,
returning the same type and kind as the arguments and being permitted
as actual argument. */
gfc_error ("Intrinsic function %s at %L is not permitted for CO_REDUCE",
op->symtree->n.sym->name, &op->where);
return false;
}
/* FIXME: After J3/WG5 has decided what they actually exactly want, more
checks such as same-argument checks have to be added, implemented and
intrinsic.texi upated. */
if (gfc_is_proc_ptr_comp (op))
{
gfc_component *comp = gfc_get_proc_ptr_comp (op);
sym = comp->ts.interface;
}
else
sym = op->symtree->n.sym;
gfc_error("CO_REDUCE at %L is not yet implemented", &a->where);
return false;
formal = sym->formal;
if (!formal || !formal->next || formal->next->next)
{
gfc_error ("The function passed as OPERATOR at %L shall have two "
"arguments", &op->where);
return false;
}
if (sym->result->ts.type == BT_UNKNOWN)
gfc_set_default_type (sym->result, 0, NULL);
if (!gfc_compare_types (&a->ts, &sym->result->ts))
{
gfc_error ("A argument at %L has type %s but the function passed as "
"OPERATOR at %L returns %s",
&a->where, gfc_typename (&a->ts), &op->where,
gfc_typename (&sym->result->ts));
return false;
}
if (!gfc_compare_types (&a->ts, &formal->sym->ts)
|| !gfc_compare_types (&a->ts, &formal->next->sym->ts))
{
gfc_error ("The function passed as OPERATOR at %L has arguments of type "
"%s and %s but shall have type %s", &op->where,
gfc_typename (&formal->sym->ts),
gfc_typename (&formal->next->sym->ts), gfc_typename (&a->ts));
return false;
}
if (op->rank || attr.allocatable || attr.pointer || formal->sym->as
|| formal->next->sym->as || formal->sym->attr.allocatable
|| formal->next->sym->attr.allocatable || formal->sym->attr.pointer
|| formal->next->sym->attr.pointer)
{
gfc_error ("The function passed as OPERATOR at %L shall have scalar "
"nonallocatable nonpointer arguments and return a "
"nonallocatable nonpointer scalar", &op->where);
return false;
}
if (formal->sym->attr.value != formal->next->sym->attr.value)
{
gfc_error ("The function passed as OPERATOR at %L shall have the VALUE "
"attribute either for none or both arguments", &op->where);
return false;
}
if (formal->sym->attr.target != formal->next->sym->attr.target)
{
gfc_error ("The function passed as OPERATOR at %L shall have the TARGET "
"attribute either for none or both arguments", &op->where);
return false;
}
if (formal->sym->attr.asynchronous != formal->next->sym->attr.asynchronous)
{
gfc_error ("The function passed as OPERATOR at %L shall have the "
"ASYNCHRONOUS attribute either for none or both arguments",
&op->where);
return false;
}
if (formal->sym->attr.optional || formal->next->sym->attr.optional)
{
gfc_error ("The function passed as OPERATOR at %L shall not have the "
"OPTIONAL attribute for either of the arguments", &op->where);
return false;
}
if (a->ts.type == BT_CHARACTER)
{
gfc_charlen *cl;
unsigned long actual_size, formal_size1, formal_size2, result_size;
cl = a->ts.u.cl;
actual_size = cl && cl->length && cl->length->expr_type == EXPR_CONSTANT
? mpz_get_ui (cl->length->value.integer) : 0;
cl = formal->sym->ts.u.cl;
formal_size1 = cl && cl->length && cl->length->expr_type == EXPR_CONSTANT
? mpz_get_ui (cl->length->value.integer) : 0;
cl = formal->next->sym->ts.u.cl;
formal_size2 = cl && cl->length && cl->length->expr_type == EXPR_CONSTANT
? mpz_get_ui (cl->length->value.integer) : 0;
cl = sym->ts.u.cl;
result_size = cl && cl->length && cl->length->expr_type == EXPR_CONSTANT
? mpz_get_ui (cl->length->value.integer) : 0;
if (actual_size
&& ((formal_size1 && actual_size != formal_size1)
|| (formal_size2 && actual_size != formal_size2)))
{
gfc_error ("The character length of the A argument at %L and of the "
"arguments of the OPERATOR at %L shall be the same",
&a->where, &op->where);
return false;
}
if (actual_size && result_size && actual_size != result_size)
{
gfc_error ("The character length of the A argument at %L and of the "
"function result of the OPERATOR at %L shall be the same",
&a->where, &op->where);
return false;
}
}
return true;
}
......
......@@ -3238,6 +3238,11 @@ caf_register_t;
* _gfortran_caf_sendget:: Sending data between remote images
* _gfortran_caf_lock:: Locking a lock variable
* _gfortran_caf_unlock:: Unlocking a lock variable
* _gfortran_caf_co_broadcast:: Sending data to all images
* _gfortran_caf_co_max:: Collective maximum reduction
* _gfortran_caf_co_min:: Collective minimum reduction
* _gfortran_caf_co_sum:: Collective summing reduction
* _gfortran_caf_co_reduce:: Generic collective reduction
@end menu
......@@ -3680,6 +3685,191 @@ images for critical-block locking variables.
@node _gfortran_caf_co_broadcast
@subsection @code{_gfortran_caf_co_broadcast} --- Sending data to all images
@cindex Coarray, _gfortran_caf_co_broadcast
@table @asis
@item @emph{Description}:
Distribute a value from a given image to all other images in the team. Has to
be called collectively.
@item @emph{Syntax}:
@code{void _gfortran_caf_co_broadcast (gfc_descriptor_t *a,
int source_image, int *stat, char *errmsg, int errmsg_len)}
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
@item @var{a} @tab intent(inout) And array descriptor with the data to be
breoadcasted (on @var{source_image}) or to be received (other images).
@item @var{source_image} @tab The ID of the image from which the data should
be taken.
@item @var{stat} @tab intent(out) Stores the status STAT= and my may be NULL.
@item @var{errmsg} @tab intent(out) When an error occurs, this will be set to
an error message; may be NULL
@item @var{errmsg_len} @tab the buffer size of errmsg.
@end multitable
@end table
@node _gfortran_caf_co_max
@subsection @code{_gfortran_caf_co_max} --- Collective maximum reduction
@cindex Coarray, _gfortran_caf_co_max
@table @asis
@item @emph{Description}:
Calculates the for the each array element of the variable @var{a} the maximum
value for that element in the current team; if @var{result_image} has the
value 0, the result shall be stored on all images, otherwise, only on the
specified image. This function operates on numeric values and character
strings.
@item @emph{Syntax}:
@code{void _gfortran_caf_co_max (gfc_descriptor_t *a, int result_image,
int *stat, char *errmsg, int a_len, int errmsg_len)}
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
@item @var{a} @tab intent(inout) And array descriptor with the data to be
breoadcasted (on @var{source_image}) or to be received (other images).
@item @var{result_image} @tab The ID of the image to which the reduced
value should be copied to; if zero, it has to be copied to all images.
@item @var{stat} @tab intent(out) Stores the status STAT= and my may be NULL.
@item @var{errmsg} @tab intent(out) When an error occurs, this will be set to
an error message; may be NULL
@item @var{a_len} @tab The string length of argument @var{a}.
@item @var{errmsg_len} @tab the buffer size of errmsg.
@end multitable
@item @emph{NOTES}
If @var{result_image} is nonzero, the value on all images except of the
specified one become undefined; hence, the library may make use of this.
@end table
@node _gfortran_caf_co_min
@subsection @code{_gfortran_caf_co_min} --- Collective minimum reduction
@cindex Coarray, _gfortran_caf_co_min
@table @asis
@item @emph{Description}:
Calculates the for the each array element of the variable @var{a} the minimum
value for that element in the current team; if @var{result_image} has the
value 0, the result shall be stored on all images, otherwise, only on the
specified image. This function operates on numeric values and character
strings.
@item @emph{Syntax}:
@code{void _gfortran_caf_co_min (gfc_descriptor_t *a, int result_image,
int *stat, char *errmsg, int a_len, int errmsg_len)}
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
@item @var{a} @tab intent(inout) And array descriptor with the data to be
breoadcasted (on @var{source_image}) or to be received (other images).
@item @var{result_image} @tab The ID of the image to which the reduced
value should be copied to; if zero, it has to be copied to all images.
@item @var{stat} @tab intent(out) Stores the status STAT= and my may be NULL.
@item @var{errmsg} @tab intent(out) When an error occurs, this will be set to
an error message; may be NULL
@item @var{a_len} @tab The string length of argument @var{a}.
@item @var{errmsg_len} @tab the buffer size of errmsg.
@end multitable
@item @emph{NOTES}
If @var{result_image} is nonzero, the value on all images except of the
specified one become undefined; hence, the library may make use of this.
@end table
@node _gfortran_caf_co_sum
@subsection @code{_gfortran_caf_co_sum} --- Collective summing reduction
@cindex Coarray, _gfortran_caf_co_sum
@table @asis
@item @emph{Description}:
Calculates the for the each array element of the variable @var{a} the sum
value for that element in the current team; if @var{result_image} has the
value 0, the result shall be stored on all images, otherwise, only on the
specified image. This function operates on numeric values.
@item @emph{Syntax}:
@code{void _gfortran_caf_co_sum (gfc_descriptor_t *a, int result_image,
int *stat, char *errmsg, int errmsg_len)}
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
@item @var{a} @tab intent(inout) And array descriptor with the data to be
breoadcasted (on @var{source_image}) or to be received (other images).
@item @var{result_image} @tab The ID of the image to which the reduced
value should be copied to; if zero, it has to be copied to all images.
@item @var{stat} @tab intent(out) Stores the status STAT= and my may be NULL.
@item @var{errmsg} @tab intent(out) When an error occurs, this will be set to
an error message; may be NULL
@item @var{errmsg_len} @tab the buffer size of errmsg.
@end multitable
@item @emph{NOTES}
If @var{result_image} is nonzero, the value on all images except of the
specified one become undefined; hence, the library may make use of this.
@end table
@node _gfortran_caf_co_reduce
@subsection @code{_gfortran_caf_co_reduce} --- Generic collective reduction
@cindex Coarray, _gfortran_caf_co_reduce
@table @asis
@item @emph{Description}:
Calculates the for the each array element of the variable @var{a} the reduction
value for that element in the current team; if @var{result_image} has the
value 0, the result shall be stored on all images, otherwise, only on the
specified image. The @var{opr} is a pure function doing a mathematically
commutative and associative operation.
The @var{opr_flags} denote the following; the values are bitwise ored.
@code{GFC_CAF_BYREF} (1) if the result should be returned
by value; @code{GFC_CAF_HIDDENLEN} (2) whether the result and argument
string lengths shall be specified as hidden argument;
@code{GFC_CAF_ARG_VALUE} (4) whether the arguments shall be passed by value,
@code{GFC_CAF_ARG_DESC} (8) whether the arguments shall be passed by descriptor.
@item @emph{Syntax}:
@code{void _gfortran_caf_co_reduce (gfc_descriptor_t *a,
void * (*opr) (void *, void *), int opr_flags, int result_image,
int *stat, char *errmsg, int a_len, int errmsg_len)}
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
@item @var{opr} @tab Function pointer to the reduction function.
@item @var{opr_flags} @tab Flags regarding the reduction function
@item @var{a} @tab intent(inout) And array descriptor with the data to be
breoadcasted (on @var{source_image}) or to be received (other images).
@item @var{result_image} @tab The ID of the image to which the reduced
value should be copied to; if zero, it has to be copied to all images.
@item @var{stat} @tab intent(out) Stores the status STAT= and my may be NULL.
@item @var{errmsg} @tab intent(out) When an error occurs, this will be set to
an error message; may be NULL
@item @var{a_len} @tab The string length of argument @var{a}.
@item @var{errmsg_len} @tab the buffer size of errmsg.
@end multitable
@item @emph{NOTES}
If @var{result_image} is nonzero, the value on all images except of the
specified one become undefined; hence, the library may make use of this.
For character arguments, the result is passed as first argument, followed
by the result string length, next come the two string arguments, followed
by the two hidden arguments. With C binding, there are no hidden arguments
and by-reference passing and either only a single character is passed or
an array descriptor.
@end table
@c Intrinsic Procedures
@c ---------------------------------------------------------------------
......
......@@ -98,6 +98,7 @@ Some basic guidelines for editing this document:
* @code{CO_BROADCAST}: CO_BROADCAST, Copy a value to all images the current set of images
* @code{CO_MAX}: CO_MAX, Maximal value on the current set of images
* @code{CO_MIN}: CO_MIN, Minimal value on the current set of images
* @code{CO_REDUCE}: CO_REDUCE, Reduction of values on the current set of images
* @code{CO_SUM}: CO_SUM, Sum of values on the current set of images
* @code{COMMAND_ARGUMENT_COUNT}: COMMAND_ARGUMENT_COUNT, Get number of command line arguments
* @code{COMPILER_OPTIONS}: COMPILER_OPTIONS, Options passed to the compiler
......@@ -3340,7 +3341,7 @@ end program test
@end smallexample
@item @emph{See also}:
@ref{CO_MAX}, @ref{CO_MIN}, @ref{CO_SUM}
@ref{CO_MAX}, @ref{CO_MIN}, @ref{CO_SUM}, @ref{CO_REDUCE}
@end table
......@@ -3354,7 +3355,7 @@ end program test
@item @emph{Description}:
@code{CO_MAX} determines element-wise the maximal value of @var{A} on all
images of the current team. If @var{RESULT_IMAGE} is present, the maximum
values are returned on in @var{A} on the specified image only and the value
values are returned in @var{A} on the specified image only and the value
of @var{A} on the other images become undefined. If @var{RESULT_IMAGE} is
not present, the value is returned on all images. If the execution was
successful and @var{STAT} is present, it is assigned the value zero. If the
......@@ -3394,7 +3395,7 @@ end program test
@end smallexample
@item @emph{See also}:
@ref{CO_MIN}, @ref{CO_SUM}, @ref{CO_BROADCAST}
@ref{CO_MIN}, @ref{CO_SUM}, @ref{CO_REDUCE}, @ref{CO_BROADCAST}
@end table
......@@ -3408,7 +3409,7 @@ end program test
@item @emph{Description}:
@code{CO_MIN} determines element-wise the minimal value of @var{A} on all
images of the current team. If @var{RESULT_IMAGE} is present, the minimal
values are returned on in @var{A} on the specified image only and the value
values are returned in @var{A} on the specified image only and the value
of @var{A} on the other images become undefined. If @var{RESULT_IMAGE} is
not present, the value is returned on all images. If the execution was
successful and @var{STAT} is present, it is assigned the value zero. If the
......@@ -3448,7 +3449,87 @@ end program test
@end smallexample
@item @emph{See also}:
@ref{CO_MAX}, @ref{CO_SUM}, @ref{CO_BROADCAST}
@ref{CO_MAX}, @ref{CO_SUM}, @ref{CO_REDUCE}, @ref{CO_BROADCAST}
@end table
@node CO_REDUCE
@section @code{CO_REDUCE} --- Reduction of values on the current set of images
@fnindex CO_REDUCE
@cindex Collectives, generic reduction
@table @asis
@item @emph{Description}:
@code{CO_REDUCE} determines element-wise the reduction of the value of @var{A}
on all images of the current team. The pure function passed as @var{OPERATOR}
is used to pairwise reduce the values of @var{A} by passing either the value
of @var{A} of different images or the result values of such a reduction as
argument. If @var{A} is an array, the deduction is done element wise. If
@var{RESULT_IMAGE} is present, the result values are returned in @var{A} on
the specified image only and the value of @var{A} on the other images become
undefined. If @var{RESULT_IMAGE} is not present, the value is returned on all
images. If the execution was successful and @var{STAT} is present, it is
assigned the value zero. If the execution failed, @var{STAT} gets assigned
a nonzero value and, if present, @var{ERRMSG} gets assigned a value describing
the occurred error.
@item @emph{Standard}:
Technical Specification (TS) 18508 or later
@item @emph{Class}:
Collective subroutine
@item @emph{Syntax}:
@code{CALL CO_REDUCE(A, OPERATOR, [, RESULT_IMAGE, STAT, ERRMSG])}
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
@item @var{A} @tab is an @code{INTENT(INOUT)} argument and shall be
nonpolymorphic. If it is allocatable, it shall be allocated; if it is a pointer,
it shall be associated. @var{A} shall have the same type and type parameters on
all images of the team; if it is an array, it shall have the same shape on all
images.
@item @var{OPERATOR} @tab pure function with two scalar nonallocatable
arguments, which shall be nonpolymorphic and have the same type and type
parameters as @var{A}. The function shall return a nonallocatable scalar of
the same type and type parameters as @var{A}. The function shall be the same on
all images and with regards to the arguments mathematically commutative and
associative. Note that @var{OPERATOR} may not be an elemental function, unless
it is an intrisic function.
@item @var{RESULT_IMAGE} @tab (optional) a scalar integer expression; if
present, it shall have the same the same value on all images and refer to an
image of the current team.
@item @var{STAT} @tab (optional) a scalar integer variable
@item @var{ERRMSG} @tab (optional) a scalar character variable
@end multitable
@item @emph{Example}:
@smallexample
program test
integer :: val
val = this_image ()
call co_reduce (val, result_image=1, operator=myprod)
if (this_image() == 1) then
write(*,*) "Product value", val ! prints num_images() factorial
end if
contains
pure function myprod(a, b)
integer, value :: a, b
integer :: myprod
myprod = a * b
end function myprod
end program test
@end smallexample
@item @emph{Note}:
While the rules permit in principle an intrinsic function, none of the
intrinsics in the standard fulfill the criteria of having a specific
function, which takes two arguments of the same type and returning that
type as result.
@item @emph{See also}:
@ref{CO_MIN}, @ref{CO_MAX}, @ref{CO_SUM}, @ref{CO_BROADCAST}
@end table
......@@ -3462,7 +3543,7 @@ end program test
@item @emph{Description}:
@code{CO_SUM} sums up the values of each element of @var{A} on all
images of the current team. If @var{RESULT_IMAGE} is present, the summed-up
values are returned on in @var{A} on the specified image only and the value
values are returned in @var{A} on the specified image only and the value
of @var{A} on the other images become undefined. If @var{RESULT_IMAGE} is
not present, the value is returned on all images. If the execution was
successful and @var{STAT} is present, it is assigned the value zero. If the
......@@ -3502,7 +3583,7 @@ end program test
@end smallexample
@item @emph{See also}:
@ref{CO_MAX}, @ref{CO_MIN}, @ref{CO_BROADCAST}
@ref{CO_MAX}, @ref{CO_MIN}, @ref{CO_REDUCE}, @ref{CO_BROADCAST}
@end table
......@@ -3671,7 +3752,7 @@ value is of default @code{COMPLEX} type.
If @var{X} and @var{Y} are of @code{REAL} type, or one is of @code{REAL}
type and one is of @code{INTEGER} type, then the return value is of
@code{COMPLEX} type with a kind equal to that of the @code{REAL}
argument with the highest precision.
argument with the highest precision.
@item @emph{Example}:
@smallexample
......@@ -3689,7 +3770,7 @@ end program test_complex
@node CONJG
@section @code{CONJG} --- Complex conjugate function
@section @code{CONJG} --- Complex conjugate function
@fnindex CONJG
@fnindex DCONJG
@cindex complex conjugate
......@@ -3739,7 +3820,7 @@ end program test_conjg
@node COS
@section @code{COS} --- Cosine function
@section @code{COS} --- Cosine function
@fnindex COS
@fnindex DCOS
@fnindex CCOS
......@@ -3798,7 +3879,7 @@ Inverse function: @ref{ACOS}
@node COSH
@section @code{COSH} --- Hyperbolic cosine function
@section @code{COSH} --- Hyperbolic cosine function
@fnindex COSH
@fnindex DCOSH
@cindex hyperbolic cosine
......@@ -4166,7 +4247,7 @@ end program test_time_and_date
@node DBLE
@section @code{DBLE} --- Double conversion function
@section @code{DBLE} --- Double conversion function
@fnindex DBLE
@cindex conversion, to real
......@@ -4448,7 +4529,7 @@ end program test_dprod
@item @emph{Specific names}:
@multitable @columnfractions .20 .20 .20 .25
@item Name @tab Argument @tab Return type @tab Standard
@item @code{DPROD(X,Y)} @tab @code{REAL(4) X, Y} @tab @code{REAL(4)} @tab Fortran 77 and later
@item @code{DPROD(X,Y)} @tab @code{REAL(4) X, Y} @tab @code{REAL(8)} @tab Fortran 77 and later
@end multitable
@end table
......
......@@ -130,6 +130,14 @@ typedef enum
GFC_CAF_ATOMIC_XOR
} libcaf_atomic_codes;
/* For CO_REDUCE. */
#define GFC_CAF_BYREF (1<<0)
#define GFC_CAF_HIDDENLEN (1<<1)
#define GFC_CAF_ARG_VALUE (1<<2)
#define GFC_CAF_ARG_DESC (1<<3)
/* Default unit number for preconnected standard input and output. */
#define GFC_STDIN_UNIT_NUMBER 5
#define GFC_STDOUT_UNIT_NUMBER 6
......
......@@ -153,6 +153,7 @@ tree gfor_fndecl_caf_unlock;
tree gfor_fndecl_co_broadcast;
tree gfor_fndecl_co_max;
tree gfor_fndecl_co_min;
tree gfor_fndecl_co_reduce;
tree gfor_fndecl_co_sum;
......@@ -3445,6 +3446,14 @@ gfc_build_builtin_function_decls (void)
void_type_node, 6, pvoid_type_node, integer_type_node,
pint_type, pchar_type_node, integer_type_node, integer_type_node);
gfor_fndecl_co_reduce = gfc_build_library_function_decl_with_spec (
get_identifier (PREFIX("caf_co_reduce")), "W.R.WW",
void_type_node, 8, pvoid_type_node,
build_pointer_type (build_varargs_function_type_list (void_type_node,
NULL_TREE)),
integer_type_node, integer_type_node, pint_type, pchar_type_node,
integer_type_node, integer_type_node);
gfor_fndecl_co_sum = gfc_build_library_function_decl_with_spec (
get_identifier (PREFIX("caf_co_sum")), "W.WW",
void_type_node, 5, pvoid_type_node, integer_type_node,
......
......@@ -8563,15 +8563,31 @@ conv_co_collective (gfc_code *code)
gfc_se argse;
stmtblock_t block, post_block;
tree fndecl, array, strlen, image_index, stat, errmsg, errmsg_len;
gfc_expr *image_idx_expr, *stat_expr, *errmsg_expr, *opr_expr;
gfc_start_block (&block);
gfc_init_block (&post_block);
if (code->resolved_isym->id == GFC_ISYM_CO_REDUCE)
{
opr_expr = code->ext.actual->next->expr;
image_idx_expr = code->ext.actual->next->next->expr;
stat_expr = code->ext.actual->next->next->next->expr;
errmsg_expr = code->ext.actual->next->next->next->next->expr;
}
else
{
opr_expr = NULL;
image_idx_expr = code->ext.actual->next->expr;
stat_expr = code->ext.actual->next->next->expr;
errmsg_expr = code->ext.actual->next->next->next->expr;
}
/* stat. */
if (code->ext.actual->next->next->expr)
if (stat_expr)
{
gfc_init_se (&argse, NULL);
gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
gfc_conv_expr (&argse, stat_expr);
gfc_add_block_to_block (&block, &argse.pre);
gfc_add_block_to_block (&post_block, &argse.post);
stat = argse.expr;
......@@ -8620,10 +8636,10 @@ conv_co_collective (gfc_code *code)
strlen = integer_zero_node;
/* image_index. */
if (code->ext.actual->next->expr)
if (image_idx_expr)
{
gfc_init_se (&argse, NULL);
gfc_conv_expr (&argse, code->ext.actual->next->expr);
gfc_conv_expr (&argse, image_idx_expr);
gfc_add_block_to_block (&block, &argse.pre);
gfc_add_block_to_block (&post_block, &argse.post);
image_index = fold_convert (integer_type_node, argse.expr);
......@@ -8632,10 +8648,10 @@ conv_co_collective (gfc_code *code)
image_index = integer_zero_node;
/* errmsg. */
if (code->ext.actual->next->next->next->expr)
if (errmsg_expr)
{
gfc_init_se (&argse, NULL);
gfc_conv_expr (&argse, code->ext.actual->next->next->next->expr);
gfc_conv_expr (&argse, errmsg_expr);
gfc_add_block_to_block (&block, &argse.pre);
gfc_add_block_to_block (&post_block, &argse.post);
errmsg = argse.expr;
......@@ -8659,6 +8675,9 @@ conv_co_collective (gfc_code *code)
case GFC_ISYM_CO_MIN:
fndecl = gfor_fndecl_co_min;
break;
case GFC_ISYM_CO_REDUCE:
fndecl = gfor_fndecl_co_reduce;
break;
case GFC_ISYM_CO_SUM:
fndecl = gfor_fndecl_co_sum;
break;
......@@ -8670,9 +8689,44 @@ conv_co_collective (gfc_code *code)
|| code->resolved_isym->id == GFC_ISYM_CO_BROADCAST)
fndecl = build_call_expr_loc (input_location, fndecl, 5, array,
image_index, stat, errmsg, errmsg_len);
else
else if (code->resolved_isym->id != GFC_ISYM_CO_REDUCE)
fndecl = build_call_expr_loc (input_location, fndecl, 6, array, image_index,
stat, errmsg, strlen, errmsg_len);
else
{
tree opr, opr_flags;
// FIXME: Handle TS29113's bind(C) strings with descriptor.
int opr_flag_int;
if (gfc_is_proc_ptr_comp (opr_expr))
{
gfc_symbol *sym = gfc_get_proc_ptr_comp (opr_expr)->ts.interface;
opr_flag_int = sym->attr.dimension
|| (sym->ts.type == BT_CHARACTER
&& !sym->attr.is_bind_c)
? GFC_CAF_BYREF : 0;
opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
&& !sym->attr.is_bind_c
? GFC_CAF_HIDDENLEN : 0;
opr_flag_int |= sym->formal->sym->attr.value ? GFC_CAF_ARG_VALUE : 0;
}
else
{
opr_flag_int = gfc_return_by_reference (opr_expr->symtree->n.sym)
? GFC_CAF_BYREF : 0;
opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
&& !opr_expr->symtree->n.sym->attr.is_bind_c
? GFC_CAF_HIDDENLEN : 0;
opr_flag_int |= opr_expr->symtree->n.sym->formal->sym->attr.value
? GFC_CAF_ARG_VALUE : 0;
}
opr_flags = build_int_cst (integer_type_node, opr_flag_int);
gfc_conv_expr (&argse, opr_expr);
opr = gfc_build_addr_expr (NULL_TREE, argse.expr);
fndecl = build_call_expr_loc (input_location, fndecl, 8, array, opr, opr_flags,
image_index, stat, errmsg, strlen, errmsg_len);
}
gfc_add_expr_to_block (&block, fndecl);
gfc_add_block_to_block (&block, &post_block);
......@@ -9386,12 +9440,10 @@ gfc_conv_intrinsic_subroutine (gfc_code *code)
res = conv_caf_send (code);
break;
case GFC_ISYM_CO_REDUCE:
gcc_unreachable ();
break;
case GFC_ISYM_CO_BROADCAST:
case GFC_ISYM_CO_MIN:
case GFC_ISYM_CO_MAX:
case GFC_ISYM_CO_REDUCE:
case GFC_ISYM_CO_SUM:
res = conv_co_collective (code);
break;
......
......@@ -742,6 +742,7 @@ extern GTY(()) tree gfor_fndecl_caf_unlock;
extern GTY(()) tree gfor_fndecl_co_broadcast;
extern GTY(()) tree gfor_fndecl_co_max;
extern GTY(()) tree gfor_fndecl_co_min;
extern GTY(()) tree gfor_fndecl_co_reduce;
extern GTY(()) tree gfor_fndecl_co_sum;
......
2014-10-24 Tobias Burnus <burnus@net-b.de>
* gfortran.dg/coarray_collectives_9.f90: Remove dg-error.
* gfortran.dg/coarray_collectives_13.f90: New.
* gfortran.dg/coarray_collectives_14.f90: New.
* gfortran.dg/coarray_collectives_15.f90: New.
* gfortran.dg/coarray_collectives_16.f90: New.
2014-10-24 Jiong Wang <jiong.wang@arm.com>
* gcc.target/arm/aapcs/abitest.h: Declare memcpy.
......
! { dg-do compile }
! { dg-options "-fcoarray=single -std=f2008" }
!
!
! CO_REDUCE/CO_BROADCAST
!
program test
implicit none
intrinsic co_reduce ! { dg-error "is not available in the current standard settings but new in TS 29113/TS 18508." }
intrinsic co_broadcast ! { dg-error "is not available in the current standard settings but new in TS 29113/TS 18508." }
end program test
! { dg-do compile }
! { dg-options "-fcoarray=single -fmax-errors=80" }
!
!
! CO_REDUCE (plus CO_MIN/MAX/SUM/BROADCAST)
!
program test
implicit none (external, type)
intrinsic co_reduce
intrinsic co_broadcast
intrinsic co_min
intrinsic co_max
intrinsic co_sum
intrinsic dprod
external ext
type t
procedure(), nopass :: ext
procedure(valid), nopass :: valid
procedure(sub), nopass :: sub
procedure(nonpure), nopass :: nonpure
procedure(arg1), nopass :: arg1
procedure(arg2), nopass :: arg2
procedure(elem), nopass :: elem
procedure(realo), nopass :: realo
procedure(int8), nopass :: int8
procedure(arr), nopass :: arr
procedure(ptr), nopass :: ptr
procedure(alloc), nopass :: alloc
procedure(opt), nopass :: opt
procedure(val), nopass :: val
procedure(async), nopass :: async
procedure(tgt), nopass :: tgt
procedure(char44), nopass :: char44
procedure(char34), nopass :: char34
end type t
type(t) :: dt
integer :: caf[*]
character(len=3) :: c3
character(len=4) :: c4
call co_min(caf[1]) ! { dg-error "shall not be coindexed" }
call co_max(caf[1]) ! { dg-error "shall not be coindexed" }
call co_sum(caf[1]) ! { dg-error "shall not be coindexed" }
call co_broadcast(caf[1], source_image=1) ! { dg-error "shall not be coindexed" }
call co_reduce(caf[1], valid) ! { dg-error "shall not be coindexed" }
call co_reduce(caf, valid) ! OK
call co_reduce(caf, dt%valid) ! OK
call co_reduce(caf, dprod) ! { dg-error "is not permitted for CO_REDUCE" }
call co_reduce(caf, ext) ! { dg-error "must be a PURE function" }
call co_reduce(caf, dt%ext) ! { dg-error "must be a PURE function" }
call co_reduce(caf, sub) ! { dg-error "must be a PURE function" }
call co_reduce(caf, dt%sub) ! { dg-error "must be a PURE function" }
call co_reduce(caf, nonpure) ! { dg-error "must be a PURE function" }
call co_reduce(caf, dt%nonpure) ! { dg-error "must be a PURE function" }
call co_reduce(caf, arg1) ! { dg-error "shall have two arguments" }
call co_reduce(caf, dt%arg1) ! { dg-error "shall have two arguments" }
call co_reduce(caf, arg3) ! { dg-error "shall have two arguments" }
call co_reduce(caf, dt%arg3) ! { dg-error "shall have two arguments" }
call co_reduce(caf, elem) ! { dg-error "ELEMENTAL non-INTRINSIC procedure 'elem' is not allowed as an actual argument" }
call co_reduce(caf, dt%elem) ! { dg-error "ELEMENTAL non-INTRINSIC procedure 'elem' is not allowed as an actual argument" }
call co_reduce(caf, realo) ! { dg-error "A argument at .1. has type INTEGER.4. but the function passed as OPERATOR at .2. returns REAL.4." }
call co_reduce(caf, dt%realo) ! { dg-error "A argument at .1. has type INTEGER.4. but the function passed as OPERATOR at .2. returns REAL.4." }
call co_reduce(caf, int8) ! { dg-error "A argument at .1. has type INTEGER.4. but the function passed as OPERATOR at .2. returns INTEGER.8." }
call co_reduce(caf, dt%int8) ! { dg-error "A argument at .1. has type INTEGER.4. but the function passed as OPERATOR at .2. returns INTEGER.8." }
call co_reduce(caf, arr) ! { dg-error "scalar nonallocatable nonpointer arguments and return a nonallocatable nonpointer scalar" }
call co_reduce(caf, dt%arr) ! { dg-error "scalar nonallocatable nonpointer arguments and return a nonallocatable nonpointer scalar" }
call co_reduce(caf, ptr) ! { dg-error "scalar nonallocatable nonpointer arguments and return a nonallocatable nonpointer scalar" }
call co_reduce(caf, dt%ptr) ! { dg-error "scalar nonallocatable nonpointer arguments and return a nonallocatable nonpointer scalar" }
call co_reduce(caf, alloc) ! { dg-error "scalar nonallocatable nonpointer arguments and return a nonallocatable nonpointer scalar" }
call co_reduce(caf, dt%alloc) ! { dg-error "scalar nonallocatable nonpointer arguments and return a nonallocatable nonpointer scalar" }
call co_reduce(caf, opt) ! { dg-error "shall not have the OPTIONAL attribute for either of the arguments" }
call co_reduce(caf, dt%opt) ! { dg-error "shall not have the OPTIONAL attribute for either of the arguments" }
call co_reduce(caf, val) ! { dg-error "shall have the VALUE attribute either for none or both arguments" }
call co_reduce(caf, dt%val) ! { dg-error "shall have the VALUE attribute either for none or both arguments" }
call co_reduce(caf, async) ! { dg-error "shall have the ASYNCHRONOUS attribute either for none or both arguments" }
call co_reduce(caf, dt%async) ! { dg-error "shall have the ASYNCHRONOUS attribute either for none or both arguments" }
call co_reduce(caf, tgt) ! { dg-error "shall have the TARGET attribute either for none or both arguments" }
call co_reduce(caf, dt%tgt) ! { dg-error "shall have the TARGET attribute either for none or both arguments" }
call co_reduce(c4, char44) ! OK
call co_reduce(c4, dt%char44) ! OK
call co_reduce(c3, char34) ! { dg-error "character length of the A argument at .1. and of the arguments of the OPERATOR at .2. shall be the same" }
call co_reduce(c3, dt%char34) ! { dg-error "character length of the A argument at .1. and of the arguments of the OPERATOR at .2. shall be the same" }
call co_reduce(c4, char34) ! { dg-error "The character length of the A argument at .1. and of the function result of the OPERATOR at .2. shall be the same" }
call co_reduce(c4, dt%char34) ! { dg-error "The character length of the A argument at .1. and of the function result of the OPERATOR at .2. shall be the same" }
contains
pure integer function valid(x,y)
integer, value :: x, y
end function valid
impure integer function nonpure(x,y)
integer, value :: x, y
end function nonpure
pure subroutine sub()
end subroutine sub
pure integer function arg3(x, y, z)
integer, value :: x, y, z
end function arg3
pure integer function arg1(x)
integer, value :: x
end function arg1
pure elemental integer function elem(x,y)
integer, value :: x, y
end function elem
pure real function realo(x,y)
integer, value :: x, y
end function realo
pure integer(8) function int8(x,y)
integer, value :: x, y
end function int8
pure integer function arr(x,y)
integer, intent(in) :: x(:), y
end function arr
pure integer function ptr(x,y)
integer, intent(in), pointer :: x, y
end function ptr
pure integer function alloc(x,y)
integer, intent(in), allocatable :: x, y
end function alloc
pure integer function opt(x,y)
integer, intent(in) :: x, y
optional :: x, y
end function opt
pure integer function val(x,y)
integer, value :: x
integer, intent(in) :: y
end function val
pure integer function tgt(x,y)
integer, intent(in) :: x, y
target :: x
end function tgt
pure integer function async(x,y)
integer, intent(in) :: x, y
asynchronous :: y
end function async
pure character(4) function char44(x,y)
character(len=4), value :: x, y
end function char44
pure character(3) function char34(x,y)
character(len=4), value :: x, y
end function char34
end program test
! { dg-do compile }
! { dg-options "-fdump-tree-original -fcoarray=single" }
!
! CO_REDUCE
!
program test
implicit none
intrinsic co_reduce
integer :: stat1
real :: val
call co_reduce(val, valid, result_image=1, stat=stat1)
contains
pure real function valid(x,y)
real, value :: x, y
valid = x * y
end function valid
end program test
! { dg-final { scan-tree-dump-times "stat1 = 0;" 1 "original" } }
! { dg-final { cleanup-tree-dump "original" } }
! { dg-do compile }
! { dg-options "-fdump-tree-original -fcoarray=lib" }
!
! CO_REDUCE
!
program test
implicit none
intrinsic co_max
integer :: stat1, stat2, stat3
character(len=6) :: errmesg1
character(len=7) :: errmesg2
character(len=8) :: errmesg3
real :: val1
complex, allocatable :: val2(:)
character(len=99) :: val3
integer :: res
call co_reduce(val1, operator=fr, result_image=num_images(), stat=stat1, errmsg=errmesg1)
call co_reduce(val2, operator=gz, result_image=4, stat=stat2, errmsg=errmesg2)
call co_reduce(val3, operator=hc, result_image=res,stat=stat3, errmsg=errmesg3)
contains
pure real function fr(x,y)
real, value :: x, y
fr = x * y
end function fr
pure complex function gz(x,y)
complex, intent(in):: x, y
gz = x *y
end function gz
pure character(len=99) function hc(x,y)
character(len=99), intent(in):: x, y
hc = x(1:50) // y(1:49)
end function hc
end program test
! { dg-final { scan-tree-dump-times "_gfortran_caf_co_reduce \\(&desc.., &fr, 4, _gfortran_caf_num_images \\(0, -1\\), &stat1, errmesg1, 0, 6\\);" 1 "original" } }
! { dg-final { scan-tree-dump-times "_gfortran_caf_co_reduce \\(&val2, &gz, 0, 4, &stat2, errmesg2, 0, 7\\);" 1 "original" } }
! { dg-final { scan-tree-dump-times "_gfortran_caf_co_reduce \\(&desc.., &hc, 1, res, &stat3, errmesg3, 99, 8\\);" 1 "original" } }
! { dg-final { cleanup-tree-dump "original" } }
......@@ -49,8 +49,8 @@ program test
call co_reduce(val, red_f, stat=[1,2]) ! { dg-error "must be a scalar" }
call co_reduce(val, red_f, stat=1.0) ! { dg-error "must be INTEGER" }
call co_reduce(val, red_f, stat=1) ! { dg-error "must be a variable" }
call co_reduce(val, red_f, stat=i, result_image=1) ! { dg-error "CO_REDUCE at \\(1\\) is not yet implemented" }
call co_reduce(val, red_f, stat=i, errmsg=errmsg, result_image=1) ! { dg-error "CO_REDUCE at \\(1\\) is not yet implemented" }
call co_reduce(val, red_f, stat=i, result_image=1) ! OK
call co_reduce(val, red_f, stat=i, errmsg=errmsg, result_image=1) ! OK
call co_reduce(val, red_f, stat=i, errmsg=[errmsg], result_image=1) ! { dg-error "must be a scalar" }
call co_reduce(val, red_f, stat=i, errmsg=5, result_image=1) ! { dg-error "must be CHARACTER" }
call co_reduce(val, red_f, errmsg="abc") ! { dg-error "must be a variable" }
......
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