diff mbox

[Fortran] DEC Compatibility: Default missing exponents to 0 with -fdec

Message ID CAE4aFAnRSSSuDjetNscwmm7xCYGkm6rBZqi1C_X_buWppRh8Bw@mail.gmail.com
State New
Headers show

Commit Message

Fritz Reese Oct. 26, 2016, 2:14 p.m. UTC
All,

Attached is a patch to the GNU Fortran front-end and runtime library
(libgfortran) which accepts real numbers with missing exponents as if
'0' was given as the exponent when the compile flag -fdec is given,
for further compatibility with legacy compilers. By default, GNU
Fortran will reject real constants such as '9e' or '15.2e'. With the
patch and -fdec, such numbers are accepted and treated as '9e0' (9) or
'15.2e0' (15.2), both at compile-time through the front-end and at
runtime through libgfortran.

For compile-time this is trivial. For runtime, An IOPARM_DT flag bit
is added to the usual flags to track whether a program was compiled
with the "default exponent" behavior, which the library can detect at
runtime for programs individually. No space is required in the
st_parameter_dt structure, and the behavior should be
backwards-compatible (by design of the IOPARM structures/flags).

Bootstraps and regtests on x86_64-redhat-linux. OK for trunk?

---
Fritz Reese

From: Fritz Reese <fritzoreese@gmail.com>
Date: Wed, 5 Oct 2016 18:27:56 -0400
Subject: [PATCH] Default missing exponents to 0 with -fdec.

        gcc/fortran/
        * gfortran.texi: Document.
        * gfortran.h (gfc_dt): New field default_exp.
        * primary.c (match_real_constant): Default exponent with -fdec.
        * io.c (match_io): Set dt.default_exp with -fdec.
        * ioparm.def (IOPARM_dt_default_exp): New.
        * trans-io.c (build_dt): Set IOPARM_dt_default_exp with -fdec.

        libgfortran/io/
        * io.h (IOPARM_DT_DEFAULT_EXP): New flag bit.
        * list_read.c (parse_real, read_real): Allow omission of exponent with
        IOPARM_DT_DEFAULT_EXP.
        * read.c (read_f): Ditto.

        gcc/testsuite/gfortran.dg/
        * dec_exp_1.f90, dec_exp_2.f90, dec_exp_3.f90: New testcases.
---
 gcc/fortran/gfortran.h                  |    1 +
 gcc/fortran/gfortran.texi               |   10 ++++++++
 gcc/fortran/io.c                        |    4 +++
 gcc/fortran/ioparm.def                  |    1 +
 gcc/fortran/primary.c                   |   19 ++++++++++++----
 gcc/fortran/trans-io.c                  |    3 ++
 gcc/testsuite/gfortran.dg/dec_exp_1.f90 |   35 +++++++++++++++++++++++++++++++
 gcc/testsuite/gfortran.dg/dec_exp_2.f90 |   13 +++++++++++
 gcc/testsuite/gfortran.dg/dec_exp_3.f90 |   15 +++++++++++++
 libgfortran/io/io.h                     |    1 +
 libgfortran/io/list_read.c              |   22 +++++++++++++++++-
 libgfortran/io/read.c                   |    8 ++++++-
 12 files changed, 124 insertions(+), 8 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/dec_exp_1.f90
 create mode 100644 gcc/testsuite/gfortran.dg/dec_exp_2.f90
 create mode 100644 gcc/testsuite/gfortran.dg/dec_exp_3.f90
diff mbox

Patch

diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index ea4437c..a0dcf6d 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -2336,6 +2336,7 @@  typedef struct
   gfc_expr *io_unit, *format_expr, *rec, *advance, *iostat, *size, *iomsg,
 	   *id, *pos, *asynchronous, *blank, *decimal, *delim, *pad, *round,
 	   *sign, *extra_comma, *dt_io_kind, *udtio;
+  char default_exp;
 
   gfc_symbol *namelist;
   /* A format_label of `format_asterisk' indicates the "*" format */
diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi
index e65c2de..85ab31b 100644
--- a/gcc/fortran/gfortran.texi
+++ b/gcc/fortran/gfortran.texi
@@ -1471,6 +1471,7 @@  compatibility extensions along with those enabled by @option{-std=legacy}.
 * .XOR. operator::
 * Bitwise logical operators::
 * Extended I/O specifiers::
+* Default exponents::
 @end menu
 
 @node Old-style kind specifications
@@ -2696,6 +2697,15 @@  supported on other systems.
 
 @end table
 
+@node Default exponents
+@subsection Default exponents
+@cindex exponent
+
+For compatibility, GNU Fortran supports a default exponent of zero in real
+constants with @option{-fdec}.  For example, @code{9e} would be
+interpreted as @code{9e0}, rather than an error.
+
+
 @node Extensions not implemented in GNU Fortran
 @section Extensions not implemented in GNU Fortran
 @cindex extensions, not implemented
diff --git a/gcc/fortran/io.c b/gcc/fortran/io.c
index dce0f7c..5f50969 100644
--- a/gcc/fortran/io.c
+++ b/gcc/fortran/io.c
@@ -4163,6 +4163,10 @@  get_io_list:
 	goto syntax;
     }
 
+  /* See if we want to use defaults for missing exponents in real transfers.  */
+  if (flag_dec)
+    dt->default_exp = 1;
+
   /* A full IO statement has been matched.  Check the constraints.  spec_end is
      supplied for cases where no locus is supplied.  */
   m = check_io_constraints (k, dt, io_code, &spec_end);
diff --git a/gcc/fortran/ioparm.def b/gcc/fortran/ioparm.def
index f1bf733..4669187 100644
--- a/gcc/fortran/ioparm.def
+++ b/gcc/fortran/ioparm.def
@@ -118,4 +118,5 @@  IOPARM (dt,      round,		1 << 23, char2)
 IOPARM (dt,      sign,		1 << 24, char1)
 #define IOPARM_dt_f2003		      (1 << 25)
 #define IOPARM_dt_dtio		      (1 << 26)
+#define IOPARM_dt_default_exp	      (1 << 27)
 IOPARM (dt,      u,		0,	 pad)
diff --git a/gcc/fortran/primary.c b/gcc/fortran/primary.c
index bcbaeaa..bf84824 100644
--- a/gcc/fortran/primary.c
+++ b/gcc/fortran/primary.c
@@ -483,7 +483,7 @@  backup:
 static match
 match_real_constant (gfc_expr **result, int signflag)
 {
-  int kind, count, seen_dp, seen_digits, is_iso_c;
+  int kind, count, seen_dp, seen_digits, is_iso_c, default_exponent;
   locus old_loc, temp_loc;
   char *p, *buffer, c, exp_char;
   gfc_expr *e;
@@ -494,6 +494,7 @@  match_real_constant (gfc_expr **result, int signflag)
 
   e = NULL;
 
+  default_exponent = 0;
   count = 0;
   seen_dp = 0;
   seen_digits = 0;
@@ -575,8 +576,14 @@  match_real_constant (gfc_expr **result, int signflag)
 
   if (!ISDIGIT (c))
     {
-      gfc_error ("Missing exponent in real number at %C");
-      return MATCH_ERROR;
+      /* With -fdec, default exponent to 0 instead of complaining.  */
+      if (flag_dec)
+	default_exponent = 1;
+      else
+	{
+	  gfc_error ("Missing exponent in real number at %C");
+	  return MATCH_ERROR;
+	}
     }
 
   while (ISDIGIT (c))
@@ -597,8 +604,8 @@  done:
   gfc_current_locus = old_loc;
   gfc_gobble_whitespace ();
 
-  buffer = (char *) alloca (count + 1);
-  memset (buffer, '\0', count + 1);
+  buffer = (char *) alloca (count + default_exponent + 1);
+  memset (buffer, '\0', count + default_exponent + 1);
 
   p = buffer;
   c = gfc_next_ascii_char ();
@@ -621,6 +628,8 @@  done:
 
       c = gfc_next_ascii_char ();
     }
+  if (default_exponent)
+    *p++ = '0';
 
   kind = get_kind (&is_iso_c);
   if (kind == -1)
diff --git a/gcc/fortran/trans-io.c b/gcc/fortran/trans-io.c
index 285e551..253a5ac 100644
--- a/gcc/fortran/trans-io.c
+++ b/gcc/fortran/trans-io.c
@@ -1911,6 +1911,9 @@  build_dt (tree function, gfc_code * code)
       if (dt->udtio)
 	mask |= IOPARM_dt_dtio;
 
+      if (dt->default_exp)
+	mask |= IOPARM_dt_default_exp;
+
       if (dt->namelist)
 	{
 	  if (dt->format_expr || dt->format_label)
diff --git a/gcc/testsuite/gfortran.dg/dec_exp_1.f90 b/gcc/testsuite/gfortran.dg/dec_exp_1.f90
new file mode 100644
index 0000000..c8b395a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/dec_exp_1.f90
@@ -0,0 +1,35 @@ 
+! { dg-do run }
+! { dg-options "-fdec" }
+!
+! Test support for providing a default exponent of zero when unspecified in
+! real constants with -fdec.
+!
+
+subroutine asserteq (rexp, ract, msg)
+  real, intent(in) :: rexp, ract
+  character(*), intent(in) :: msg
+  if (rexp .ne. ract) then
+    write (*, '(A,F12.6,F12.6)') msg, rexp, ract
+    call abort()
+  endif
+end subroutine
+
+implicit none
+
+real, parameter :: r1 = 8e0
+real, parameter :: r2 = 8e ! { equivalent to 8e0 }
+real, volatile :: r3, r4
+character(2) :: s
+r3 = 8e ! { equivalent to 8e0 }
+s = '8e'
+
+read (s, *) r4
+
+call asserteq (r1, r2, "[const]")
+call asserteq (r1, r3, "[vol. ]")
+call asserteq (r1, r4, "[read ]")
+
+r4 = 8e + 48e
+call asserteq (56e, r4, "[sum ]")
+
+end
diff --git a/gcc/testsuite/gfortran.dg/dec_exp_2.f90 b/gcc/testsuite/gfortran.dg/dec_exp_2.f90
new file mode 100644
index 0000000..9137aab
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/dec_exp_2.f90
@@ -0,0 +1,13 @@ 
+! { dg-do compile }
+! { dg-options "" }
+!
+! Make sure we still see an error for missing exponents without -fdec.
+!
+
+implicit none
+
+real, parameter :: r1 = 8e ! { dg-error "Missing exponent" }
+real, volatile :: r2
+r2 = 8e ! { dg-error "Missing exponent" }
+
+end
diff --git a/gcc/testsuite/gfortran.dg/dec_exp_3.f90 b/gcc/testsuite/gfortran.dg/dec_exp_3.f90
new file mode 100644
index 0000000..34835a7
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/dec_exp_3.f90
@@ -0,0 +1,15 @@ 
+! { dg-do run "xfail *-*-*" }
+! { dg-options "" }
+!
+! Make sure we still see an error for missing exponents without -fdec.
+!
+
+implicit none
+
+real :: r
+character(2) :: s
+s = '8e'
+
+read (s, *) r ! { XFAIL "Bad real number" }
+
+end
diff --git a/libgfortran/io/io.h b/libgfortran/io/io.h
index 7a54849..cd0a26f 100644
--- a/libgfortran/io/io.h
+++ b/libgfortran/io/io.h
@@ -443,6 +443,7 @@  st_parameter_inquire;
 #define IOPARM_DT_HAS_SIGN			(1 << 24)
 #define IOPARM_DT_HAS_F2003                     (1 << 25)
 #define IOPARM_DT_HAS_UDTIO                     (1 << 26)
+#define IOPARM_DT_DEFAULT_EXP			(1 << 27)
 /* Internal use bit.  */
 #define IOPARM_DT_IONML_SET			(1u << 31)
 
diff --git a/libgfortran/io/list_read.c b/libgfortran/io/list_read.c
index f258c9d..a35beb8 100644
--- a/libgfortran/io/list_read.c
+++ b/libgfortran/io/list_read.c
@@ -1374,7 +1374,16 @@  parse_real (st_parameter_dt *dtp, void *buffer, int length)
 
  exp2:
   if (!isdigit (c))
-    goto bad_exponent;
+    {
+      /* Extension: allow default exponent of 0 when omitted.  */
+      if (dtp->common.flags & IOPARM_DT_DEFAULT_EXP)
+	{
+	  push_char (dtp, '0');
+	  goto done;
+	}
+      else
+	goto bad_exponent;
+    }
 
   push_char (dtp, c);
 
@@ -1816,7 +1825,16 @@  read_real (st_parameter_dt *dtp, void * dest, int length)
 
  exp2:
   if (!isdigit (c))
-    goto bad_exponent;
+    {
+      /* Extension: allow default exponent of 0 when omitted.  */
+      if (dtp->common.flags & IOPARM_DT_DEFAULT_EXP)
+	{
+	  push_char (dtp, '0');
+	  goto done;
+	}
+      else
+	goto bad_exponent;
+    }
 
   push_char (dtp, c);
 
diff --git a/libgfortran/io/read.c b/libgfortran/io/read.c
index 23b6f64..508b3a0 100644
--- a/libgfortran/io/read.c
+++ b/libgfortran/io/read.c
@@ -1087,7 +1087,13 @@  exponent:
      the d parameter before explict conversion takes place.  */
 
   if (w == 0)
-    goto bad_float;
+    {
+      /* Extension: allow default exponent of 0 when omitted.  */
+      if (dtp->common.flags & IOPARM_DT_DEFAULT_EXP)
+	goto done;
+      else
+	goto bad_float;
+    }
 
   if (dtp->u.p.blank_status == BLANK_UNSPECIFIED)
     {