This is the mail archive of the fortran@gcc.gnu.org mailing list for the GNU Fortran project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[gfortran] PATCH: Allow wide boz constants


Currently, we always parse boz-literal-constants as INTEGER*4. This was a
problem for me when I wanted to write testcases for our bit intrinsics, as I
couldn't enter numbers in hexadecimal, which of course makes it much easier to
see what should happen in bit handling.

The fundamental issue with this is that we don't know which type variable a
data constant will be assigned to. I briefly contemplated adding kind suffixes
to boz-literal-constants, like z'44444'_4, but not only is this ugly, it is
also superfluous, as the kind information is certainly redundant, as the boz
constant will always be the initial value of a variable of a fixed type.
Instead I developed this patch, which determines the smallest integer kind
that a given boz-literal-constant of a certain length (measured in characters
of source code) will fit in, and then sets the constant to that kind. Of
course leading zeros will set off this scheme, and we will give the
initialization a bigger kind than required, but as the value will be converted
to the type of the corresponding variable, this works as well. Another special
case is where there are more digits than supported by any integer kind. In
this case this patch sets the value to the largest available integer kind, and
then we will get an error if the value actually overflows that kind.

Built, and verified. When trying to run the testsuite I found out that
something in my tree broke during the last build, so I couldn't yet test this.
Along with this patch I will add new testcases for the bit functions which
will exercise this code. Ok if the testsuite passes?

- Tobi

2004-10-06  Tobias Schlueter  <tobias.schlueter@physik.uni-muenchen.de>

	* primary.c (match_boz_constant): Determine required bit width from
	constant.
Index: primary.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fortran/primary.c,v
retrieving revision 1.12
diff -u -p -r1.12 primary.c
--- primary.c	31 Aug 2004 13:35:01 -0000	1.12
+++ primary.c	6 Oct 2004 17:06:23 -0000
@@ -230,12 +230,15 @@ match_integer_constant (gfc_expr ** resu
 
 
 /* Match a binary, octal or hexadecimal constant that can be found in
-   a DATA statement.  */
+   a DATA statement.  Since we don't know which variable we're going
+   to initialize, we determine the kind of the initialization from the
+   width of the boz constant.  For instance, z'12' will be INTEGER*1,
+   o'01234567' will be INTEGER*2, etc.  */
 
 static match
 match_boz_constant (gfc_expr ** result)
 {
-  int radix, delim, length, x_hex;
+  int radix, delim, length, x_hex, kind, i, num_bits;
   locus old_loc;
   char *buffer;
   gfc_expr *e;
@@ -295,12 +298,38 @@ match_boz_constant (gfc_expr ** result)
   match_digits (0, radix, buffer);
   gfc_next_char ();
 
-  e = gfc_convert_integer (buffer, gfc_default_integer_kind, radix,
-			   &gfc_current_locus);
+  switch (radix)
+    {
+    case 2:
+      num_bits = length;
+      break;
+    case 8:
+      num_bits = length*3;
+      break;
+    case 16:
+      num_bits = length*4;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  for (i = 0; gfc_integer_kinds[i].kind != 0; i++)
+    if (gfc_integer_kinds[i].bit_size > num_bits)
+      break;
+
+  kind = gfc_integer_kinds[i].kind;
+  if (kind == 0)
+    /* Set kind to the largest available kind.  If the boz constant
+       has leading zeros it might still fit in the target variable.
+       Otherwise, it will be an error anyway, as the initialization
+       would have overflowed the target variable.  */ 
+    kind = gfc_integer_kinds[i-1].kind;
+
+  e = gfc_convert_integer (buffer, kind, radix, &gfc_current_locus);
 
   if (gfc_range_check (e) != ARITH_OK)
     {
-      gfc_error ("Integer too big for default integer kind at %C");
+      gfc_error ("Integer too big for all integer kinds at %C");
 
       gfc_free_expr (e);
       return MATCH_ERROR;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]