On Tue, Jan 08, 2019 at 10:27:25PM +0100, Thomas Koenig wrote:
> Hi Steve,
>
> > Well, that was quick. Moving code around is problematic.
>
> Thanks for checking. The patch is OK for trunk.
>
Thanks. I decided to see if long term approach would work.
It almost does. The attached patch put ieee_selected_real_kind
into the table of intrinsic functions. It automatically gets
us a generic routine with argument chekcing and simplification.
This just works:
program foo
use ieee_arithmetic, only : ieee_selected_real_kind
integer, parameter :: n = ieee_selected_real_kind(6_2)
i = 6
print *, n, ieee_selected_real_kind(6_8), ieee_selected_real_kind(i)
end program foo
Now, the downside. I can't finesse rename on USE. This does not
work, and I'm stuck at the moment.
subroutine bar
use ieee_arithmetic, only : isrk => ieee_selected_real_kind
integer, parameter :: n = isrk(6)
i = 6
print *, n, isrk(6), isrk(i)
end subroutine bar
If anyone has an idea, I would be quite happy to hear about it.
--
Steve
Index: gcc/fortran/check.c
===================================================================
--- gcc/fortran/check.c (revision 268106)
+++ gcc/fortran/check.c (working copy)
@@ -4426,6 +4426,59 @@ gfc_check_selected_real_kind (gfc_expr *p, gfc_expr *r
bool
+gfc_check_ieee_selected_real_kind (gfc_expr *p, gfc_expr *r, gfc_expr *radix)
+{
+ gfc_intrinsic_sym *sym;
+
+ sym = gfc_find_function ("ieee_selected_real_kind");
+ if (!sym->ieee)
+ {
+ gfc_warning_now (0, "check: whoops at %C");
+ return false;
+ }
+
+ if (p == NULL && r == NULL
+ && !gfc_notify_std (GFC_STD_F2008, "%qs with neither %<P%> nor %<R%> "
+ "argument at %L", gfc_current_intrinsic,
+ gfc_current_intrinsic_where))
+ return false;
+
+ if (p)
+ {
+ if (!type_check (p, 0, BT_INTEGER))
+ return false;
+
+ if (!scalar_check (p, 0))
+ return false;
+ }
+
+ if (r)
+ {
+ if (!type_check (r, 1, BT_INTEGER))
+ return false;
+
+ if (!scalar_check (r, 1))
+ return false;
+ }
+
+ if (radix)
+ {
+ if (!gfc_notify_std (GFC_STD_F2008, "%qs intrinsic with "
+ "RADIX argument at %L", gfc_current_intrinsic,
+ &radix->where))
+ return false;
+
+ if (!type_check (radix, 1, BT_INTEGER))
+ return false;
+
+ if (!scalar_check (radix, 1))
+ return false;
+ }
+
+ return true;
+}
+
+bool
gfc_check_set_exponent (gfc_expr *x, gfc_expr *i)
{
if (!type_check (x, 0, BT_REAL))
Index: gcc/fortran/gfortran.h
===================================================================
--- gcc/fortran/gfortran.h (revision 268106)
+++ gcc/fortran/gfortran.h (working copy)
@@ -592,7 +592,7 @@ enum gfc_isym_id
GFC_ISYM_SPREAD,
GFC_ISYM_SQRT,
GFC_ISYM_SRAND,
- GFC_ISYM_SR_KIND,
+ GFC_ISYM_SR_KIND, GFC_ISYM_IEEE_SR_KIND,
GFC_ISYM_STAT,
GFC_ISYM_STOPPED_IMAGES,
GFC_ISYM_STORAGE_SIZE,
@@ -2071,7 +2071,7 @@ typedef struct gfc_intrinsic_sym
gfc_typespec ts;
unsigned elemental:1, inquiry:1, transformational:1, pure:1,
generic:1, specific:1, actual_ok:1, noreturn:1, conversion:1,
- from_module:1, vararg:1;
+ from_module:1, vararg:1, ieee:1;
int standard;
Index: gcc/fortran/intrinsic.c
===================================================================
--- gcc/fortran/intrinsic.c (revision 268106)
+++ gcc/fortran/intrinsic.c (working copy)
@@ -2891,6 +2891,15 @@ add_functions (void)
make_generic ("selected_real_kind", GFC_ISYM_SR_KIND, GFC_STD_F95);
+ add_sym_3 ("ieee_selected_real_kind", GFC_ISYM_IEEE_SR_KIND,
+ CLASS_TRANSFORMATIONAL, ACTUAL_NO, BT_INTEGER, di, GFC_STD_F95,
+ gfc_check_ieee_selected_real_kind,
+ gfc_simplify_ieee_selected_real_kind, NULL,
+ p, BT_INTEGER, di, OPTIONAL, r, BT_INTEGER, di, OPTIONAL,
+ "radix", BT_INTEGER, di, OPTIONAL);
+
+ make_generic ("ieee_selected_real_kind", GFC_ISYM_IEEE_SR_KIND, GFC_STD_F95);
+
add_sym_2 ("set_exponent", GFC_ISYM_SET_EXPONENT, CLASS_ELEMENTAL, ACTUAL_NO, BT_REAL, dr, GFC_STD_F95,
gfc_check_set_exponent, gfc_simplify_set_exponent,
gfc_resolve_set_exponent,
Index: gcc/fortran/intrinsic.h
===================================================================
--- gcc/fortran/intrinsic.h (revision 268106)
+++ gcc/fortran/intrinsic.h (working copy)
@@ -150,6 +150,8 @@ bool gfc_check_secnds (gfc_expr *);
bool gfc_check_selected_char_kind (gfc_expr *);
bool gfc_check_selected_int_kind (gfc_expr *);
bool gfc_check_selected_real_kind (gfc_expr *, gfc_expr *, gfc_expr *);
+bool gfc_check_ieee_selected_real_kind (gfc_expr *, gfc_expr *, gfc_expr *);
+
bool gfc_check_set_exponent (gfc_expr *, gfc_expr *);
bool gfc_check_shape (gfc_expr *, gfc_expr *);
bool gfc_check_shift (gfc_expr *, gfc_expr *);
@@ -397,6 +399,8 @@ gfc_expr *gfc_simplify_scan (gfc_expr *, gfc_expr *, g
gfc_expr *gfc_simplify_selected_char_kind (gfc_expr *);
gfc_expr *gfc_simplify_selected_int_kind (gfc_expr *);
gfc_expr *gfc_simplify_selected_real_kind (gfc_expr *, gfc_expr *, gfc_expr *);
+gfc_expr *gfc_simplify_ieee_selected_real_kind (gfc_expr *, gfc_expr *,
+ gfc_expr *);
gfc_expr *gfc_simplify_set_exponent (gfc_expr *, gfc_expr *);
gfc_expr *gfc_simplify_sign (gfc_expr *, gfc_expr *);
gfc_expr *gfc_simplify_shape (gfc_expr *, gfc_expr *);
Index: gcc/fortran/module.c
===================================================================
--- gcc/fortran/module.c (revision 268106)
+++ gcc/fortran/module.c (working copy)
@@ -5401,6 +5401,12 @@ read_module (void)
if (u->found)
continue;
+ /* Special case for ieee_selected_real_kind, which doesn't actually
+ appear in module. */
+ if (strcmp(module_name, "ieee_arithmetic") == 0
+ && strcmp(u->use_name, "ieee_selected_real_kind") == 0)
+ continue;
+
if (u->op == INTRINSIC_NONE)
{
gfc_error ("Symbol %qs referenced at %L not found in module %qs",
@@ -7020,7 +7026,13 @@ gfc_use_module (gfc_use_list *module)
&& gfc_notify_std (GFC_STD_F2003,
"IEEE_ARITHMETIC module at %C"))
{
+ gfc_intrinsic_sym *sym;
+
current_intmod = INTMOD_IEEE_ARITHMETIC;
+
+ /* Mark functions in intrinsic function table as ieee. */
+ sym = gfc_find_function ("ieee_selected_real_kind");
+ sym->ieee = 1;
}
}
Index: gcc/fortran/simplify.c
===================================================================
--- gcc/fortran/simplify.c (revision 268106)
+++ gcc/fortran/simplify.c (working copy)
@@ -7079,6 +7079,84 @@ gfc_simplify_selected_real_kind (gfc_expr *p, gfc_expr
gfc_expr *
+gfc_simplify_ieee_selected_real_kind (gfc_expr *p, gfc_expr *r, gfc_expr *rdx)
+{
+ bool saw_p, saw_r, saw_radix;
+ int i, kind, precision, radix, range;
+ locus *loc = &gfc_current_locus;
+ gfc_intrinsic_sym *sym;
+
+ sym = gfc_find_function ("ieee_selected_real_kind");
+ if (!sym->ieee)
+ {
+ gfc_warning (0, "simplify: whoops at %C");
+ return NULL;
+ }
+
+ precision = range = radix = 0;
+
+ if (p)
+ {
+ if (p->expr_type != EXPR_CONSTANT || gfc_extract_int (p, &precision))
+ return NULL;
+ loc = &p->where;
+ }
+
+ if (r)
+ {
+ if (r->expr_type != EXPR_CONSTANT || gfc_extract_int (r, &range))
+ return NULL;
+
+ if (!loc)
+ loc = &r->where;
+ }
+
+ if (rdx)
+ {
+ if (rdx->expr_type != EXPR_CONSTANT || gfc_extract_int (rdx, &radix))
+ return NULL;
+
+ if (!loc)
+ loc = &rdx->where;
+ }
+
+ kind = INT_MAX;
+ saw_p = saw_r = saw_radix = false;
+
+ for (i = 0; gfc_real_kinds[i].kind != 0; i++)
+ {
+ if (gfc_real_kinds[i].precision >= precision)
+ saw_p = true;
+
+ if (gfc_real_kinds[i].range >= range)
+ saw_r = true;
+
+ if (radix == 0 || gfc_real_kinds[i].radix == radix)
+ saw_radix = true;
+
+ if (saw_p && saw_r && saw_radix && gfc_real_kinds[i].kind < kind)
+ kind = gfc_real_kinds[i].kind;
+ }
+
+ if (kind == INT_MAX)
+ {
+ if (saw_radix && saw_r && !saw_p)
+ kind = -1;
+ else if (saw_radix && saw_p && !saw_r)
+ kind = -2;
+ else if (saw_radix && !saw_p && !saw_r)
+ kind = -3;
+ else if (saw_radix)
+ kind = -4;
+ else
+ kind = -5;
+ }
+
+ return gfc_get_int_expr (gfc_default_integer_kind, loc, kind);
+}
+
+
+gfc_expr *
gfc_simplify_set_exponent (gfc_expr *x, gfc_expr *i)
{
gfc_expr *result;
Index: gcc/fortran/trans-intrinsic.c
===================================================================
--- gcc/fortran/trans-intrinsic.c (revision 268106)
+++ gcc/fortran/trans-intrinsic.c (working copy)
@@ -9521,6 +9521,7 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * e
break;
case GFC_ISYM_SR_KIND:
+ case GFC_ISYM_IEEE_SR_KIND:
gfc_conv_intrinsic_sr_kind (se, expr);
break;
Index: libgfortran/ieee/ieee_arithmetic.F90
===================================================================
--- libgfortran/ieee/ieee_arithmetic.F90 (revision 268106)
+++ libgfortran/ieee/ieee_arithmetic.F90 (working copy)
@@ -732,7 +732,6 @@ REM_MACRO(4,4,4)
! Public declarations for contained procedures
public :: IEEE_GET_ROUNDING_MODE, IEEE_SET_ROUNDING_MODE
public :: IEEE_GET_UNDERFLOW_MODE, IEEE_SET_UNDERFLOW_MODE
- public :: IEEE_SELECTED_REAL_KIND
! IEEE_SUPPORT_ROUNDING
@@ -830,21 +829,6 @@ contains
implicit none
type(IEEE_ROUND_TYPE), intent(in) :: X, Y
res = (X%hidden /= Y%hidden)
- end function
-
-
- ! IEEE_SELECTED_REAL_KIND
-
- integer function IEEE_SELECTED_REAL_KIND (P, R, RADIX) result(res)
- implicit none
- integer, intent(in), optional :: P, R, RADIX
-
- ! Currently, if IEEE is supported and this module is built, it means
- ! all our floating-point types conform to IEEE. Hence, we simply call
- ! SELECTED_REAL_KIND.
-
- res = SELECTED_REAL_KIND (P, R, RADIX)
-
end function