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
 
 

Reply via email to