This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC 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]

[PATCH] Fortran -- Handle BOZ in accordance with F2008/2015.


All,

I have spent the last few days trying to reconcile the various Fortran
standards' requirements for handling BOZ.  The short story is that J3
over the last 27 years has made incompatible changes to the interpretation
of a BOZ (under some circumstances).  The interpretations in F2008 and
F2015 now treat a boz-literal-constant as a sequence of bits.  Unfortunately,
due to quirks in how BOZ are currently implemented in gfortran and a boat
load of documented and undocumented extensions, bringing gfortran into 
agreement with F2008/F2015 led to a rewrite of BOZ handling.  In the 
rewrite I have made no attempt to use the -std= option to try to maintain
the incompatibilities between standards.

On x86_64-*-freebsd, the attached patch gives

tail gcc/testsuite/gfortran/gfortran.sum

                === gfortran Summary ===

# of expected passes            45888
# of unexpected failures        4
# of unexpected successes       6
# of expected failures          97
# of unsupported tests          79
/home/sgk/gcc/obj/gcc/gfortran  version 8.0.0 20170927 (experimental) (GCC)

The 4 unexpected failures are not related to this patch.

2017-10-06  Steven G. Kargl  <kargl@gcc.gnu.org>

	PR fortran/45513
	PR fortran/54072
	PR fortran/81509
	* array.c (resolve_array_list): Handle an array descriptor
	with BOZ elements.
	* check.c (numeric_check): Error for BOZ when numeric type is expected.
	(numeric_or_boz_check): New function.  Check for numeric or BOZ arg.
	(int_or_boz_check): New function.  Check for INTEGER or BOZ arg.
	(gfc_check_bge_bgt_ble_blt): Use int_or_boz_check.
	(gfc_check_cmplx): Use numeric_or_boz_check.
	(gfc_check_complex): Permit BOZ arguments.
	(gfc_check_dcmplx): Use numeric_or_boz_check.
	(gfc_check_dble): Allow BOZ argument.
	(boz_args_check): New function.  Disallow two BOZ arguments.
	(gfc_boz2int): New function.  In-place conversion of BOZ to INTEGER.
	(gfc_check_dshift): Use int_or_boz_check, boz_args_check, gfc_boz2int.
	(gfc_check_iand): Renamed to ...
	(gfc_check_iand_ieor_ior): ... this.  Use int_or_boz_check,
	boz_args_check, and gfc_boz2int.  Convert gfc_notify_std to gfc_error.
	(gfc_check_ieor, gfc_check_ior): Removed function.
	(gfc_check_int): Use numeric_or_boz_check 
	(gfc_check_merge_bits): Use int_or_boz_check, boz_args_check,
	gfc_boz2int
	(gfc_check_real): Allow BOZ.  Use numeric_or_boz_check.
	(gfc_check_and): Allow BOZ. Use boz_args_check and gfc_boz2int
	* data.c (gfc_assign_data_value): Implement F2008/F2015 sematics for
	for BOZ in data statement.
	* expr.c (gfc_get_expr): Set boz component of gfc_expr to NULL.
	(gfc_copy_expr, free_expr0): Cope new boz component.
	(gfc_check_assign): Replace old is_boz checks with BT_BOZ checks.
	Use gfc_boz2int.
	* gfortran.h (gfc_expr): Remove is_boz component.  Add boz
	component. Add prototyp gfc_boz2int.
	* intrinsic.c (add_functions): Use gfc_check_iand_ieor_ior
	in place of gfc_check_iand, gfc_check_ieor, and gfc_check_ior.
	* intrinsic.h: Add prototype for gfc_check_iand_ieor_ior.
	Remove prototypes for gfc_check_iand, gfc_check_ieor, gfc_check_ior.
	* intrinsic.texi: Document (some) changes.
	* iresolve.c(gfc_resolve_iand,gfc_resolve_ieor,gfc_resolve_ior): Mark
	j with ATTRIBUTE_UNUSED. Make IAND, IEOR, IOR
	conform to F2008/2015.
	* libgfortran.h: Add new basic type BT_BOZ.
	* primary.c (match_boz_constant): Remove old handling of BOZ.
	Cache BOZ string in gfc_expr's boz component.
 	* resolve.c (resolve_operator): Allow BOZ in binary 
	numeric and rational operators.  Use gfc_boz2int or gfc_convert_boz
	as needed.
	(resolve_allocate_expr): Split declaration and initialization.
	(resolve_ordinary_assign): Replace is_boz checks with BT_BOZ checks.
	* simplify.c (convert_boz): Replace BT_INTEGER with BT_BOZ
	(simplify_cmplx): Rearrange allow simplication of individual args.
	Convert BOZ as needed.
	(gfc_simplify_complex): Account of args with BT_BOZ.
 	(gfc_simplify_float): Replace is_boz check with BT_BOZ check.
	(simplify_intconv): In-place conversin of boz to INTEGER.
	* target-memory.c (boz2int): New function.  Conversion of 
	boz to INTEGER with widest decimal range.
	(gfc_convert_boz): Use it.  Remove clearly is_boz.

2017-10-06  Steven G. Kargl  <kargl@gcc.gnu.org>

	PR fortran/45513
	PR fortran/54072
	PR fortran/81509
	* gfortran.dg/achar_5.f90: Remove BOZ arg tests.
	* gfortran.dg/boz_4.f90: Delete test as it no longer applies.
	* gfortran.dg/graphite/id-26.f03:  Fix test.
	* gfortran.dg/pr81509_1.f90: New test.
	* gfortran.dg/pr81509_2.f90: New test.
	* gfortran.dg/unf_io_convert_2.f90: Fix test.
Index: gcc/fortran/array.c
===================================================================
--- gcc/fortran/array.c	(revision 253236)
+++ gcc/fortran/array.c	(working copy)
@@ -1896,10 +1896,12 @@ find_symbol_in_expr (gfc_symbol *sym, gfc_expr *expr, 
 static bool
 resolve_array_list (gfc_constructor_base base)
 {
+  bool saw_boz;
   bool t;
   gfc_constructor *c;
   gfc_iterator *iter;
 
+  saw_boz = false;
   t = true;
 
   for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
@@ -1942,11 +1944,46 @@ resolve_array_list (gfc_constructor_base base)
       if (!gfc_resolve_expr (c->expr))
 	t = false;
 
+      if (c->expr->ts.type == BT_BOZ)
+	saw_boz = true;
+
       if (UNLIMITED_POLY (c->expr))
 	{
 	  gfc_error ("Array constructor value at %L shall not be unlimited "
 		     "polymorphic [F2008: C4106]", &c->expr->where);
 	  t = false;
+	}
+    }
+
+  /* If an array contains a BT_BOZ, then array elements need to be converted
+     an INTEGER.  This is an GNU Fortran extension.  Mixing BOZ and non-BOZ
+     entities is not permitted.  */
+  if (saw_boz)
+    {
+      bt type = BT_UNKNOWN;
+
+      c = gfc_constructor_first (base);
+      for (; c; c = gfc_constructor_next (c))
+	if (c->expr->ts.type != BT_BOZ)
+	  {
+	    gfc_error ("Type mismatch at %L with elements in an array "
+		       "constructor due to a boz-literal-constant array element",
+		       &c->expr->where);
+	    return false;
+	  }
+
+      /* All elements are BT_BOZ, so convert to INTEGER.  */
+      if (type == BT_UNKNOWN)
+	{
+	  gfc_expr *e;
+	  c = gfc_constructor_first (base);
+	  for (; c; c = gfc_constructor_next (c))
+	    {
+	      e = gfc_get_constant_expr (BT_INTEGER, gfc_max_integer_kind,
+					&c->expr->where);
+	      gfc_boz2int (c->expr, e);
+	      gfc_free_expr (e);
+	    }
 	}
     }
 
Index: gcc/fortran/check.c
===================================================================
--- gcc/fortran/check.c	(revision 253236)
+++ gcc/fortran/check.c	(working copy)
@@ -93,7 +93,47 @@ numeric_check (gfc_expr *e, int n)
 
 error:
 
-  gfc_error ("%qs argument of %qs intrinsic at %L must have a numeric type",
+  if (e->ts.type == BT_BOZ)
+    gfc_error ("%qs argument of %qs intrinsic at %L cannot be a "
+		"boz-literal-constant", gfc_current_intrinsic_arg[n]->name,
+		gfc_current_intrinsic, &e->where);
+  else
+    gfc_error ("%qs argument of %qs intrinsic at %L must have a numeric type",
+		gfc_current_intrinsic_arg[n]->name, gfc_current_intrinsic,
+		&e->where);
+
+  return false;
+}
+
+/* Check that the expression is a numeric type or boz-literal-constant.  */
+
+static bool
+numeric_or_boz_check (gfc_expr *e, int n)
+{
+  /* Users sometime use a subroutine designator as an actual argument to
+     an intrinsic subprogram that expects an argument with a numeric type.  */
+  if (e->symtree && e->symtree->n.sym->attr.subroutine)
+    goto error;
+
+  if (e->ts.type == BT_BOZ || e->ts.type == BT_COMPLEX
+      || e->ts.type == BT_INTEGER || e->ts.type == BT_REAL)
+    return true;
+
+  /* If the expression has not got a type, check if its namespace can
+     offer a default type.  */
+  if ((e->expr_type == EXPR_VARIABLE || e->expr_type == EXPR_FUNCTION)
+	&& e->symtree->n.sym->ts.type == BT_UNKNOWN
+	&& gfc_set_default_type (e->symtree->n.sym, 0, e->symtree->n.sym->ns)
+	&& gfc_numeric_ts (&e->symtree->n.sym->ts))
+    {
+      e->ts = e->symtree->n.sym->ts;
+      return true;
+    }
+
+error:
+
+  gfc_error ("%qs argument of %qs intrinsic at %L must either have a numeric "
+	     "type or be a boz-literal-constant",
 	     gfc_current_intrinsic_arg[n]->name, gfc_current_intrinsic,
 	     &e->where);
 
@@ -118,6 +158,22 @@ int_or_real_check (gfc_expr *e, int n)
 }
 
 
+/* Check that an expression is integer or boz-literal-constant.  */
+
+static bool
+int_or_boz_check (gfc_expr *e, int n)
+{
+  if (e->ts.type != BT_INTEGER && e->ts.type != BT_BOZ)
+    {
+      gfc_error ("%qs argument of %qs intrinsic at %L must be INTEGER or a "
+		 "boz-literal-constant", gfc_current_intrinsic_arg[n]->name,
+		 gfc_current_intrinsic, &e->where);
+      return false;
+    }
+
+  return true;
+}
+
 /* Check that an expression is real or complex.  */
 
 static bool
@@ -1404,10 +1460,10 @@ gfc_check_bessel_n2 (gfc_expr *n1, gfc_expr *n2, gfc_e
 bool
 gfc_check_bge_bgt_ble_blt (gfc_expr *i, gfc_expr *j)
 {
-  if (!type_check (i, 0, BT_INTEGER))
+  if (!int_or_boz_check (i, 0))
     return false;
 
-  if (!type_check (j, 1, BT_INTEGER))
+  if (!int_or_boz_check (j, 1))
     return false;
 
   return true;
@@ -1523,12 +1579,12 @@ gfc_check_chmod_sub (gfc_expr *name, gfc_expr *mode, g
 bool
 gfc_check_cmplx (gfc_expr *x, gfc_expr *y, gfc_expr *kind)
 {
-  if (!numeric_check (x, 0))
+  if (x->ts.type != BT_BOZ && !numeric_or_boz_check (x, 0))
     return false;
 
   if (y != NULL)
     {
-      if (!numeric_check (y, 1))
+      if (y->ts.type != BT_BOZ && !numeric_or_boz_check (y, 1))
 	return false;
 
       if (x->ts.type == BT_COMPLEX)
@@ -1859,13 +1915,27 @@ gfc_check_co_sum (gfc_expr *a, gfc_expr *result_image,
 bool
 gfc_check_complex (gfc_expr *x, gfc_expr *y)
 {
-  if (!int_or_real_check (x, 0))
-    return false;
+  if (x->ts.type != BT_BOZ && x->ts.type != BT_INTEGER && x->ts.type != BT_REAL)
+    {
+       gfc_error ("%qs argument of %qs intrinsic at %L must be INTEGER or "
+		  "REAL or boz-literal-constant",
+		  gfc_current_intrinsic_arg[0]->name, gfc_current_intrinsic,
+		  &x->where);
+       return false;
+    }
+
   if (!scalar_check (x, 0))
     return false;
 
-  if (!int_or_real_check (y, 1))
-    return false;
+  if (y->ts.type != BT_BOZ && y->ts.type != BT_INTEGER && y->ts.type != BT_REAL)
+    {
+       gfc_error ("%qs argument of %qs intrinsic at %L must be INTEGER or "
+		  "REAL or boz-literal-constant",
+		  gfc_current_intrinsic_arg[1]->name, gfc_current_intrinsic,
+		  &y->where);
+       return false;
+    }
+
   if (!scalar_check (y, 1))
     return false;
 
@@ -1980,12 +2050,12 @@ bool gfc_check_datan2 (gfc_expr *y, gfc_expr *x)
 bool
 gfc_check_dcmplx (gfc_expr *x, gfc_expr *y)
 {
-  if (!numeric_check (x, 0))
+  if (x->ts.type != BT_BOZ && !numeric_or_boz_check (x, 0))
     return false;
 
   if (y != NULL)
     {
-      if (!numeric_check (y, 1))
+      if (y->ts.type != BT_BOZ && !numeric_or_boz_check (y, 1))
 	return false;
 
       if (x->ts.type == BT_COMPLEX)
@@ -2014,6 +2084,9 @@ gfc_check_dcmplx (gfc_expr *x, gfc_expr *y)
 bool
 gfc_check_dble (gfc_expr *x)
 {
+  if (x->ts.type == BT_BOZ)
+    return true;
+
   if (!numeric_check (x, 0))
     return false;
 
@@ -2101,42 +2174,84 @@ gfc_check_dprod (gfc_expr *x, gfc_expr *y)
 }
 
 
+static bool
+boz_args_check(gfc_expr *i, gfc_expr *j)
+{
+  if (i->ts.type == BT_BOZ && j->ts.type == BT_BOZ)
+    {
+      gfc_error ("Arguments of %qs at %L and %L cannot both be BOZ "
+		 "literal constants", gfc_current_intrinsic, &i->where,
+		 &j->where);
+      return false;
+
+    }
+  return true;
+}
+
+/* Given a BT_BOZ in i, convert to an BT_INTEGER with kind of j.  */
+
+void
+gfc_boz2int (gfc_expr *i, gfc_expr *j)
+{
+  char *t;
+  int radix;
+
+  i->ts.type = BT_INTEGER;
+  i->ts.kind = j->ts.kind;
+
+  t = i->boz;
+  radix = 16;
+  if (*t == 'b') radix = 2;
+  if (*t++ == 'o') radix = 8;
+
+  mpz_init (i->value.integer);
+  mpz_set_str (i->value.integer, t, radix);
+}
+
+
 bool
 gfc_check_dshift (gfc_expr *i, gfc_expr *j, gfc_expr *shift)
 {
-  if (!type_check (i, 0, BT_INTEGER))
+  if (!int_or_boz_check (i, 0))
     return false;
 
-  if (!type_check (j, 1, BT_INTEGER))
+  if (!int_or_boz_check (j, 1))
     return false;
 
-  if (i->is_boz && j->is_boz)
-    {
-      gfc_error ("%<I%> at %L and %<J%>' at %L cannot both be BOZ literal "
-		   "constants", &i->where, &j->where);
-      return false;
-    }
+  if (!boz_args_check (i, j))
+    return false;
 
-  if (!i->is_boz && !j->is_boz && !same_type_check (i, 0, j, 1))
+  if (i->ts.type == BT_BOZ)
+    gfc_boz2int (i, j);
+
+  if (j->ts.type == BT_BOZ)
+    gfc_boz2int (j, i);
+
+  if (!same_type_check (i, 0, j, 1))
     return false;
 
-  if (!type_check (shift, 2, BT_INTEGER))
+  if (!int_or_boz_check (shift, 2))
     return false;
 
+  if (shift->ts.type == BT_BOZ)
+    gfc_boz2int (shift, i);
+
+  /* shift shall be nonnegative and less than or equal to BIT_SIZE(I)
+     if I is an integer; otherwise, it shall be less than or equal to
+     BIT_SIZE(J).  */
+
   if (!nonnegative_check ("SHIFT", shift))
     return false;
 
-  if (i->is_boz)
+  if (i->ts.type == BT_BOZ)
     {
       if (!less_than_bitsize1 ("J", j, "SHIFT", shift, true))
     	return false;
-      i->ts.kind = j->ts.kind;
     }
-  else
+  else 
     {
       if (!less_than_bitsize1 ("I", i, "SHIFT", shift, true))
     	return false;
-      j->ts.kind = i->ts.kind;
     }
 
   return true;
@@ -2361,18 +2476,27 @@ gfc_check_i (gfc_expr *i)
 
 
 bool
-gfc_check_iand (gfc_expr *i, gfc_expr *j)
+gfc_check_iand_ieor_ior (gfc_expr *i, gfc_expr *j)
 {
-  if (!type_check (i, 0, BT_INTEGER))
+  if (!int_or_boz_check (i, 0))
     return false;
 
-  if (!type_check (j, 1, BT_INTEGER))
+  if (!int_or_boz_check (j, 1))
     return false;
 
+  if (!boz_args_check (i, j))
+    return false;
+
+  if (i->ts.type == BT_BOZ)
+    gfc_boz2int (i, j);
+
+  if (j->ts.type == BT_BOZ)
+    gfc_boz2int (j, i);
+
   if (i->ts.kind != j->ts.kind)
     {
-      if (!gfc_notify_std (GFC_STD_GNU, "Different type kinds at %L",
-			   &i->where))
+      gfc_error ("Arguments of %qs have different kind type parameters "
+		 "at %L", gfc_current_intrinsic, &i->where);
 	return false;
     }
 
@@ -2487,26 +2611,6 @@ gfc_check_idnint (gfc_expr *a)
 
 
 bool
-gfc_check_ieor (gfc_expr *i, gfc_expr *j)
-{
-  if (!type_check (i, 0, BT_INTEGER))
-    return false;
-
-  if (!type_check (j, 1, BT_INTEGER))
-    return false;
-
-  if (i->ts.kind != j->ts.kind)
-    {
-      if (!gfc_notify_std (GFC_STD_GNU, "Different type kinds at %L",
-			   &i->where))
-	return false;
-    }
-
-  return true;
-}
-
-
-bool
 gfc_check_index (gfc_expr *string, gfc_expr *substring, gfc_expr *back,
 		 gfc_expr *kind)
 {
@@ -2540,7 +2644,7 @@ gfc_check_index (gfc_expr *string, gfc_expr *substring
 bool
 gfc_check_int (gfc_expr *x, gfc_expr *kind)
 {
-  if (!numeric_check (x, 0))
+  if (!numeric_or_boz_check (x, 0))
     return false;
 
   if (!kind_check (kind, 1, BT_INTEGER))
@@ -2559,28 +2663,7 @@ gfc_check_intconv (gfc_expr *x)
   return true;
 }
 
-
 bool
-gfc_check_ior (gfc_expr *i, gfc_expr *j)
-{
-  if (!type_check (i, 0, BT_INTEGER))
-    return false;
-
-  if (!type_check (j, 1, BT_INTEGER))
-    return false;
-
-  if (i->ts.kind != j->ts.kind)
-    {
-      if (!gfc_notify_std (GFC_STD_GNU, "Different type kinds at %L",
-			   &i->where))
-	return false;
-    }
-
-  return true;
-}
-
-
-bool
 gfc_check_ishft (gfc_expr *i, gfc_expr *shift)
 {
   if (!type_check (i, 0, BT_INTEGER)
@@ -3358,21 +3441,45 @@ gfc_check_merge (gfc_expr *tsource, gfc_expr *fsource,
 bool
 gfc_check_merge_bits (gfc_expr *i, gfc_expr *j, gfc_expr *mask)
 {
-  if (!type_check (i, 0, BT_INTEGER))
+  if (!int_or_boz_check (i, 0))
     return false;
 
-  if (!type_check (j, 1, BT_INTEGER))
+  if (!int_or_boz_check (j, 1))
     return false;
 
-  if (!type_check (mask, 2, BT_INTEGER))
+  if (!boz_args_check (i, j))
     return false;
 
-  if (!same_type_check (i, 0, j, 1))
+  if (!int_or_boz_check (mask, 2))
     return false;
 
-  if (!same_type_check (i, 0, mask, 2))
-    return false;
+  if (i->ts.type == BT_BOZ)
+    {
+      gfc_boz2int (i, j);
+      if (mask->ts.type == BT_BOZ)
+	gfc_boz2int (mask, j);
+      else if (!same_type_check (j, 0, mask, 2))
+    	return false;
+    }
+  else if (j->ts.type == BT_BOZ)
+    {
+      gfc_boz2int (j, i);
+      if (mask->ts.type == BT_BOZ)
+	gfc_boz2int (mask, i);
+      else if (!same_type_check (i, 0, mask, 2))
+    	return false;
+    }
+  else
+    {
+      if (!same_type_check (i, 0, j, 1))
+	return false;
 
+      if (mask->ts.type == BT_BOZ)
+        gfc_boz2int (mask, i);
+      else if (!same_type_check (i, 0, mask, 2))
+    	return false;
+    }
+
   return true;
 }
 
@@ -3774,7 +3881,10 @@ gfc_check_rank (gfc_expr *a)
 bool
 gfc_check_real (gfc_expr *a, gfc_expr *kind)
 {
-  if (!numeric_check (a, 0))
+  if (a->ts.type == BT_BOZ)
+    return true;
+
+  if (!numeric_or_boz_check (a, 0))
     return false;
 
   if (!kind_check (kind, 1, BT_REAL))
@@ -6430,21 +6540,34 @@ gfc_check_system_sub (gfc_expr *cmd, gfc_expr *status)
 bool
 gfc_check_and (gfc_expr *i, gfc_expr *j)
 {
-  if (i->ts.type != BT_INTEGER && i->ts.type != BT_LOGICAL)
+  if (i->ts.type != BT_INTEGER && i->ts.type != BT_LOGICAL
+      && i->ts.type != BT_BOZ)
     {
       gfc_error ("%qs argument of %qs intrinsic at %L must be INTEGER "
-		 "or LOGICAL", gfc_current_intrinsic_arg[0]->name,
+		 "or LOGICAL or a boz-literal-constant",
+		 gfc_current_intrinsic_arg[0]->name,
 		 gfc_current_intrinsic, &i->where);
       return false;
     }
 
-  if (j->ts.type != BT_INTEGER && j->ts.type != BT_LOGICAL)
+  if (j->ts.type != BT_INTEGER && j->ts.type != BT_LOGICAL
+      && j->ts.type != BT_BOZ)
     {
       gfc_error ("%qs argument of %qs intrinsic at %L must be INTEGER "
-		 "or LOGICAL", gfc_current_intrinsic_arg[1]->name,
+		 "or LOGICAL or a boz-literal-constant",
+		 gfc_current_intrinsic_arg[1]->name,
 		 gfc_current_intrinsic, &j->where);
       return false;
     }
+
+  if (!boz_args_check (i, j))
+    return false;
+
+  if (i->ts.type == BT_BOZ)
+    gfc_boz2int (i, j);
+
+  if (j->ts.type == BT_BOZ)
+      gfc_boz2int (j, i);
 
   if (i->ts.type != j->ts.type)
     {
Index: gcc/fortran/data.c
===================================================================
--- gcc/fortran/data.c	(revision 253236)
+++ gcc/fortran/data.c	(working copy)
@@ -508,9 +508,33 @@ gfc_assign_data_value (gfc_expr *lvalue, gfc_expr *rva
 	    return false;
 	}
 
-      expr = gfc_copy_expr (rvalue);
-      if (!gfc_compare_types (&lvalue->ts, &expr->ts))
-	gfc_convert_type (expr, &lvalue->ts, 0);
+      if (rvalue->ts.type == BT_BOZ)
+	{
+	  char *t;
+	  int radix;
+
+	  if (lvalue->ts.type != BT_INTEGER)
+	    {
+	      gfc_error ("data-stmt-object at %L must be of type INTEGER",
+			 &lvalue->where);
+	      return false;
+	    }
+
+	  t = rvalue->boz;
+  	  radix = 16;
+  	  if (*t == 'b') radix = 2;
+  	  if (*t++ == 'o') radix = 8;
+
+	  expr = gfc_get_constant_expr (BT_INTEGER, lvalue->ts.kind,
+		 &lvalue->where);
+  	  mpz_set_str (expr->value.integer, t, radix);
+	}
+      else
+	{
+	  expr = gfc_copy_expr (rvalue);
+	  if (!gfc_compare_types (&lvalue->ts, &expr->ts))
+	    gfc_convert_type (expr, &lvalue->ts, 0);
+	}
     }
 
   if (last_con == NULL)
Index: gcc/fortran/expr.c
===================================================================
--- gcc/fortran/expr.c	(revision 253236)
+++ gcc/fortran/expr.c	(working copy)
@@ -50,6 +50,7 @@ gfc_get_expr (void)
   e->shape = NULL;
   e->ref = NULL;
   e->symtree = NULL;
+  e->boz = NULL;
   return e;
 }
 
@@ -333,6 +334,7 @@ gfc_copy_expr (gfc_expr *p)
 	    }
 	  break;
 
+	case BT_BOZ:
 	case BT_HOLLERITH:
 	case BT_LOGICAL:
 	case_bt_struct:
@@ -453,6 +455,10 @@ free_expr0 (gfc_expr *e)
 	  mpc_clear (e->value.complex);
 	  break;
 
+	case BT_BOZ:
+	  free (e->boz);
+	  break;
+
 	default:
 	  break;
 	}
@@ -3282,45 +3288,55 @@ gfc_check_assign (gfc_expr *lvalue, gfc_expr *rvalue, 
       && !gfc_check_conformance (lvalue, rvalue, "array assignment"))
     return false;
 
-  if (rvalue->is_boz && lvalue->ts.type != BT_INTEGER
+  if (rvalue->ts.type == BT_BOZ && lvalue->ts.type != BT_INTEGER
       && lvalue->symtree->n.sym->attr.data
       && !gfc_notify_std (GFC_STD_GNU, "BOZ literal at %L used to "
 			  "initialize non-integer variable %qs",
 			  &rvalue->where, lvalue->symtree->n.sym->name))
     return false;
-  else if (rvalue->is_boz && !lvalue->symtree->n.sym->attr.data
+  else if (rvalue->ts.type == BT_BOZ && !lvalue->symtree->n.sym->attr.data
       && !gfc_notify_std (GFC_STD_GNU, "BOZ literal at %L outside "
 			  "a DATA statement and outside INT/REAL/DBLE/CMPLX",
 			  &rvalue->where))
     return false;
 
   /* Handle the case of a BOZ literal on the RHS.  */
-  if (rvalue->is_boz && lvalue->ts.type != BT_INTEGER)
+  if (rvalue->ts.type == BT_BOZ)
     {
-      int rc;
-      if (warn_surprising)
-	gfc_warning (OPT_Wsurprising,
-		     "BOZ literal at %L is bitwise transferred "
-		     "non-integer symbol %qs", &rvalue->where,
-		     lvalue->symtree->n.sym->name);
-      if (!gfc_convert_boz (rvalue, &lvalue->ts))
-	return false;
-      if ((rc = gfc_range_check (rvalue)) != ARITH_OK)
+      if (lvalue->ts.type != BT_INTEGER)
 	{
-	  if (rc == ARITH_UNDERFLOW)
-	    gfc_error ("Arithmetic underflow of bit-wise transferred BOZ at %L"
-		       ". This check can be disabled with the option "
-		       "%<-fno-range-check%>", &rvalue->where);
-	  else if (rc == ARITH_OVERFLOW)
-	    gfc_error ("Arithmetic overflow of bit-wise transferred BOZ at %L"
-		       ". This check can be disabled with the option "
-		       "%<-fno-range-check%>", &rvalue->where);
-	  else if (rc == ARITH_NAN)
-	    gfc_error ("Arithmetic NaN of bit-wise transferred BOZ at %L"
-		       ". This check can be disabled with the option "
-		       "%<-fno-range-check%>", &rvalue->where);
-	  return false;
+	  int rc;
+
+	  if (warn_surprising)
+	    gfc_warning (OPT_Wsurprising, "BOZ literal at %L is bitwise "
+			"transferred non-integer symbol %qs", &rvalue->where,
+			lvalue->symtree->n.sym->name);
+
+	  if (!gfc_convert_boz (rvalue, &lvalue->ts))
+	    return false;
+
+	  if ((rc = gfc_range_check (rvalue)) != ARITH_OK)
+	    {
+	      if (rc == ARITH_UNDERFLOW)
+		gfc_error ("Arithmetic underflow of bit-wise transferred BOZ "
+			   "at %L. This check can be disabled with the option "
+			   "%<-fno-range-check%>", &rvalue->where);
+	      else if (rc == ARITH_OVERFLOW)
+		gfc_error ("Arithmetic overflow of bit-wise transferred BOZ "
+			   "at %L. This check can be disabled with the option "
+			   "%<-fno-range-check%>", &rvalue->where);
+	      else if (rc == ARITH_NAN)
+		gfc_error ("Arithmetic NaN of bit-wise transferred BOZ at %L"
+			   ". This check can be disabled with the option "
+			   "%<-fno-range-check%>", &rvalue->where);
+	      return false;
+	    }
 	}
+      else
+	{
+	  gfc_boz2int(rvalue, lvalue);
+	  return true;
+	}
     }
 
   if (gfc_expr_attr (lvalue).pdt_kind || gfc_expr_attr (lvalue).pdt_len)
@@ -3344,6 +3360,9 @@ gfc_check_assign (gfc_expr *lvalue, gfc_expr *rvalue, 
 	return true;
 
       if (lvalue->ts.type == BT_LOGICAL && rvalue->ts.type == BT_LOGICAL)
+	return true;
+
+      if (lvalue->ts.type == BT_INTEGER && rvalue->ts.type == BT_BOZ)
 	return true;
 
       gfc_error ("Incompatible types in DATA statement at %L; attempted "
Index: gcc/fortran/gfortran.h
===================================================================
--- gcc/fortran/gfortran.h	(revision 253236)
+++ gcc/fortran/gfortran.h	(working copy)
@@ -2113,10 +2113,12 @@ typedef struct gfc_expr
      is not a variable.  */
   struct gfc_expr *base_expr;
 
-  /* is_boz is true if the integer is regarded as BOZ bit pattern and is_snan
-     denotes a signalling not-a-number.  */
-  unsigned int is_boz : 1, is_snan : 1;
+  /* is_snan denotes a signalling not-a-number.  */
+  unsigned int is_snan : 1;
 
+  /* The BOZ string with either a 'b', 'o', and 'z' prefix.  */
+  char *boz;
+
   /* Sometimes, when an error has been emitted, it is necessary to prevent
       it from recurring.  */
   unsigned int error : 1;
@@ -3360,6 +3362,7 @@ int gfc_dep_compare_expr (gfc_expr *, gfc_expr *);
 bool gfc_dep_difference (gfc_expr *, gfc_expr *, mpz_t *);
 
 /* check.c */
+void gfc_boz2int (gfc_expr *, gfc_expr *);
 bool gfc_check_same_strlen (const gfc_expr*, const gfc_expr*, const char*);
 bool gfc_calculate_transfer_sizes (gfc_expr*, gfc_expr*, gfc_expr*,
 				      size_t*, size_t*, size_t*);
Index: gcc/fortran/intrinsic.c
===================================================================
--- gcc/fortran/intrinsic.c	(revision 253236)
+++ gcc/fortran/intrinsic.c	(working copy)
@@ -1970,8 +1970,9 @@ add_functions (void)
 
   make_generic ("iachar", GFC_ISYM_IACHAR, GFC_STD_F95);
 
-  add_sym_2 ("iand", GFC_ISYM_IAND, CLASS_ELEMENTAL, ACTUAL_NO, BT_INTEGER, di, GFC_STD_F95,
-	     gfc_check_iand, gfc_simplify_iand, gfc_resolve_iand,
+  add_sym_2 ("iand", GFC_ISYM_IAND, CLASS_ELEMENTAL, ACTUAL_NO, BT_INTEGER, di,
+	     GFC_STD_F95,
+	     gfc_check_iand_ieor_ior, gfc_simplify_iand, gfc_resolve_iand,
 	     i, BT_INTEGER, di, REQUIRED, j, BT_INTEGER, di, REQUIRED);
 
   if (flag_dec_intrinsic_ints)
@@ -2059,8 +2060,9 @@ add_functions (void)
 
   make_generic ("ichar", GFC_ISYM_ICHAR, GFC_STD_F77);
 
-  add_sym_2 ("ieor", GFC_ISYM_IEOR, CLASS_ELEMENTAL, ACTUAL_NO, BT_INTEGER, di, GFC_STD_F95,
-	     gfc_check_ieor, gfc_simplify_ieor, gfc_resolve_ieor,
+  add_sym_2 ("ieor", GFC_ISYM_IEOR, CLASS_ELEMENTAL, ACTUAL_NO, BT_INTEGER, di,
+	     GFC_STD_F95,
+	     gfc_check_iand_ieor_ior, gfc_simplify_ieor, gfc_resolve_ieor,
 	     i, BT_INTEGER, di, REQUIRED, j, BT_INTEGER, di, REQUIRED);
 
   if (flag_dec_intrinsic_ints)
@@ -2137,8 +2139,9 @@ add_functions (void)
 
   make_generic ("long", GFC_ISYM_LONG, GFC_STD_GNU);
 
-  add_sym_2 ("ior", GFC_ISYM_IOR, CLASS_ELEMENTAL, ACTUAL_NO, BT_INTEGER, di, GFC_STD_F95,
-	     gfc_check_ior, gfc_simplify_ior, gfc_resolve_ior,
+  add_sym_2 ("ior", GFC_ISYM_IOR, CLASS_ELEMENTAL, ACTUAL_NO, BT_INTEGER, di,
+	     GFC_STD_F95,
+	     gfc_check_iand_ieor_ior, gfc_simplify_ior, gfc_resolve_ior,
 	     i, BT_INTEGER, di, REQUIRED, j, BT_INTEGER, di, REQUIRED);
 
   if (flag_dec_intrinsic_ints)
Index: gcc/fortran/intrinsic.h
===================================================================
--- gcc/fortran/intrinsic.h	(revision 253236)
+++ gcc/fortran/intrinsic.h	(working copy)
@@ -87,17 +87,15 @@ bool gfc_check_hostnm (gfc_expr *);
 bool gfc_check_huge (gfc_expr *);
 bool gfc_check_hypot (gfc_expr *, gfc_expr *);
 bool gfc_check_i (gfc_expr *);
-bool gfc_check_iand (gfc_expr *, gfc_expr *);
+bool gfc_check_iand_ieor_ior (gfc_expr *, gfc_expr *);
 bool gfc_check_and (gfc_expr *, gfc_expr *);
 bool gfc_check_ibits (gfc_expr *, gfc_expr *, gfc_expr *);
 bool gfc_check_ichar_iachar (gfc_expr *, gfc_expr *);
 bool gfc_check_idnint (gfc_expr *);
-bool gfc_check_ieor (gfc_expr *, gfc_expr *);
 bool gfc_check_image_status (gfc_expr *, gfc_expr *);
 bool gfc_check_index (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *);
 bool gfc_check_int (gfc_expr *, gfc_expr *);
 bool gfc_check_intconv (gfc_expr *);
-bool gfc_check_ior (gfc_expr *, gfc_expr *);
 bool gfc_check_irand (gfc_expr *);
 bool gfc_check_isatty (gfc_expr *);
 bool gfc_check_isnan (gfc_expr *);
Index: gcc/fortran/intrinsic.texi
===================================================================
--- gcc/fortran/intrinsic.texi	(revision 253236)
+++ gcc/fortran/intrinsic.texi	(working copy)
@@ -1142,15 +1142,20 @@ Function
 @item @emph{Arguments}:
 @multitable @columnfractions .15 .70
 @item @var{I} @tab The type shall be either a scalar @code{INTEGER}
-type or a scalar @code{LOGICAL} type.
-@item @var{J} @tab The type shall be the same as the type of @var{I}.
+type or a scalar @code{LOGICAL} type or a boz-literal-constant.
+@item @var{J} @tab The type shall be the same as the type of @var{I} or
+a boz-literal-constant. @var{I} and @var{J} shall not both be
+boz-literal-constants.  If either @var{I} or @var{J} is a
+boz-literal-constant, then the other argument must be a scalar @code{INTEGER}.
 @end multitable
 
 @item @emph{Return value}:
 The return type is either a scalar @code{INTEGER} or a scalar
 @code{LOGICAL}.  If the kind type parameters differ, then the
 smaller kind type is implicitly converted to larger kind, and the 
-return has the larger kind.
+return has the larger kind.  A boz-literal-constant is 
+converted to an @code{INTEGER} with the kind type parameter of
+the other argument as-if a call to @ref{INT} occurred.
 
 @item @emph{Example}:
 @smallexample
@@ -7461,16 +7466,17 @@ Elemental function
 
 @item @emph{Arguments}:
 @multitable @columnfractions .15 .70
-@item @var{I} @tab The type shall be @code{INTEGER}.
-@item @var{J} @tab The type shall be @code{INTEGER}, of the same
-kind as @var{I}.  (As a GNU extension, different kinds are also 
-permitted.)
+@item @var{I} @tab The type shall be @code{INTEGER} or a boz-literal-constant.
+@item @var{J} @tab The type shall be @code{INTEGER} with the same
+kind type parameter as @var{I} or a boz-literal-constant.
+@var{I} and @var{J} shall not both be boz-literal-constants.
 @end multitable
 
 @item @emph{Return value}:
-The return type is @code{INTEGER}, of the same kind as the
-arguments.  (If the argument kinds differ, it is of the same kind as
-the larger argument.)
+The return type is @code{INTEGER} with the kind type parameter of the
+arguments.
+A boz-literal-constant is converted to an @code{INTEGER} with the kind
+type parameter of the other argument as-if a call to @ref{INT} occurred.
 
 @item @emph{Example}:
 @smallexample
@@ -7911,16 +7917,17 @@ Elemental function
 
 @item @emph{Arguments}:
 @multitable @columnfractions .15 .70
-@item @var{I} @tab The type shall be @code{INTEGER}.
-@item @var{J} @tab The type shall be @code{INTEGER}, of the same
-kind as @var{I}.  (As a GNU extension, different kinds are also 
-permitted.)
+@item @var{I} @tab The type shall be @code{INTEGER} or a boz-literal-constant.
+@item @var{J} @tab The type shall be @code{INTEGER} with the same
+kind type parameter as @var{I} or a boz-literal-constant.
+@var{I} and @var{J} shall not both be boz-literal-constants.
 @end multitable
 
 @item @emph{Return value}:
-The return type is @code{INTEGER}, of the same kind as the
-arguments.  (If the argument kinds differ, it is of the same kind as
-the larger argument.)
+The return type is @code{INTEGER} with the kind type parameter of the
+arguments.
+A boz-literal-constant is converted to an @code{INTEGER} with the kind
+type parameter of the other argument as-if a call to @ref{INT} occurred.
 
 @item @emph{Specific names}:
 @multitable @columnfractions .20 .20 .20 .25
@@ -8229,16 +8236,17 @@ Elemental function
 
 @item @emph{Arguments}:
 @multitable @columnfractions .15 .70
-@item @var{I} @tab The type shall be @code{INTEGER}.
-@item @var{J} @tab The type shall be @code{INTEGER}, of the same
-kind as @var{I}.  (As a GNU extension, different kinds are also 
-permitted.)
+@item @var{I} @tab The type shall be @code{INTEGER} or a boz-literal-constant.
+@item @var{J} @tab The type shall be @code{INTEGER} with the same
+kind type parameter as @var{I} or a boz-literal-constant.
+@var{I} and @var{J} shall not both be boz-literal-constants.
 @end multitable
 
 @item @emph{Return value}:
-The return type is @code{INTEGER}, of the same kind as the
-arguments.  (If the argument kinds differ, it is of the same kind as
-the larger argument.)
+The return type is @code{INTEGER} with the kind type parameter of the
+arguments.
+A boz-literal-constant is converted to an @code{INTEGER} with the kind
+type parameter of the other argument as-if a call to @ref{INT} occurred.
 
 @item @emph{Specific names}:
 @multitable @columnfractions .20 .20 .20 .25
@@ -10225,11 +10233,12 @@ Elemental function
 
 @item @emph{Arguments}:
 @multitable @columnfractions .15 .70
-@item @var{I}    @tab Shall be of type @code{INTEGER}.
-@item @var{J}    @tab Shall be of type @code{INTEGER} and of the same
-kind as @var{I}.
-@item @var{MASK} @tab Shall be of type @code{INTEGER} and of the same
-kind as @var{I}.
+@item @var{I} @tab Shall be of type @code{INTEGER} or a boz-literal-constant.
+@item @var{J} @tab Shall be of type @code{INTEGER} with the same
+kind type parameter as @var{I} or a boz-literal-constant.
+@var{I} and @var{J} shall not both be boz-literal-constants.
+@item @var{MASK} @tab Shall be of type @code{INTEGER} or a boz-literal-constant
+and of the same kind as @var{I}.
 @end multitable
 
 @item @emph{Return value}:
@@ -11046,15 +11055,20 @@ Function
 @item @emph{Arguments}:
 @multitable @columnfractions .15 .70
 @item @var{I} @tab The type shall be either a scalar @code{INTEGER}
-type or a scalar @code{LOGICAL} type.
-@item @var{J} @tab The type shall be the same as the type of @var{J}.
+type or a scalar @code{LOGICAL} type or a boz-literal-constant.
+@item @var{J} @tab The type shall be the same as the type of @var{I} or
+a boz-literal-constant. @var{I} and @var{J} shall not both be
+boz-literal-constants.  If either @var{I} and @var{J} is a
+boz-literal-constant, then the other argument must be a scalar @code{INTEGER}.
 @end multitable
 
 @item @emph{Return value}:
 The return type is either a scalar @code{INTEGER} or a scalar
 @code{LOGICAL}.  If the kind type parameters differ, then the
 smaller kind type is implicitly converted to larger kind, and the 
-return has the larger kind.
+return has the larger kind.  A boz-literal-constant is 
+converted to an @code{INTEGER} with the kind type parameter of
+the other argument as-if a call to @ref{INT} occurred.
 
 @item @emph{Example}:
 @smallexample
@@ -14506,16 +14520,21 @@ Function
 
 @item @emph{Arguments}:
 @multitable @columnfractions .15 .70
-@item @var{I} @tab The type shall be either  a scalar @code{INTEGER}
-type or a scalar @code{LOGICAL} type.
-@item @var{J} @tab The type shall be the same as the type of @var{I}.
+@item @var{I} @tab The type shall be either a scalar @code{INTEGER}
+type or a scalar @code{LOGICAL} type or a boz-literal-constant.
+@item @var{J} @tab The type shall be the same as the type of @var{I} or
+a boz-literal-constant. @var{I} and @var{J} shall not both be
+boz-literal-constants.  If either @var{I} and @var{J} is a
+boz-literal-constant, then the other argument must be a scalar @code{INTEGER}.
 @end multitable
 
 @item @emph{Return value}:
 The return type is either a scalar @code{INTEGER} or a scalar
 @code{LOGICAL}.  If the kind type parameters differ, then the
 smaller kind type is implicitly converted to larger kind, and the 
-return has the larger kind.
+return has the larger kind.  A boz-literal-constant is 
+converted to an @code{INTEGER} with the kind type parameter of
+the other argument as-if a call to @ref{INT} occurred.
 
 @item @emph{Example}:
 @smallexample
Index: gcc/fortran/iresolve.c
===================================================================
--- gcc/fortran/iresolve.c	(revision 253236)
+++ gcc/fortran/iresolve.c	(working copy)
@@ -1222,19 +1222,8 @@ gfc_resolve_iall (gfc_expr *f, gfc_expr *array, gfc_ex
 
 
 void
-gfc_resolve_iand (gfc_expr *f, gfc_expr *i, gfc_expr *j)
+gfc_resolve_iand (gfc_expr *f, gfc_expr *i, gfc_expr *j ATTRIBUTE_UNUSED)
 {
-  /* If the kind of i and j are different, then g77 cross-promoted the
-     kinds to the largest value.  The Fortran 95 standard requires the 
-     kinds to match.  */
-  if (i->ts.kind != j->ts.kind)
-    {
-      if (i->ts.kind == gfc_kind_max (i, j))
-	gfc_convert_type (j, &i->ts, 2);
-      else
-	gfc_convert_type (i, &j->ts, 2);
-    }
-
   f->ts = i->ts;
   f->value.function.name = gfc_get_string ("__iand_%d", i->ts.kind);
 }
@@ -1313,38 +1302,16 @@ gfc_resolve_ierrno (gfc_expr *f)
 
 
 void
-gfc_resolve_ieor (gfc_expr *f, gfc_expr *i, gfc_expr *j)
+gfc_resolve_ieor (gfc_expr *f, gfc_expr *i, gfc_expr *j ATTRIBUTE_UNUSED)
 {
-  /* If the kind of i and j are different, then g77 cross-promoted the
-     kinds to the largest value.  The Fortran 95 standard requires the 
-     kinds to match.  */
-  if (i->ts.kind != j->ts.kind)
-    {
-      if (i->ts.kind == gfc_kind_max (i, j))
-	gfc_convert_type (j, &i->ts, 2);
-      else
-	gfc_convert_type (i, &j->ts, 2);
-    }
-
   f->ts = i->ts;
   f->value.function.name = gfc_get_string ("__ieor_%d", i->ts.kind);
 }
 
 
 void
-gfc_resolve_ior (gfc_expr *f, gfc_expr *i, gfc_expr *j)
+gfc_resolve_ior (gfc_expr *f, gfc_expr *i, gfc_expr *j ATTRIBUTE_UNUSED)
 {
-  /* If the kind of i and j are different, then g77 cross-promoted the
-     kinds to the largest value.  The Fortran 95 standard requires the 
-     kinds to match.  */
-  if (i->ts.kind != j->ts.kind)
-    {
-      if (i->ts.kind == gfc_kind_max (i, j))
-	gfc_convert_type (j, &i->ts, 2);
-      else
-	gfc_convert_type (i, &j->ts, 2);
-    }
-
   f->ts = i->ts;
   f->value.function.name = gfc_get_string ("__ior_%d", i->ts.kind);
 }
Index: gcc/fortran/libgfortran.h
===================================================================
--- gcc/fortran/libgfortran.h	(revision 253236)
+++ gcc/fortran/libgfortran.h	(working copy)
@@ -159,12 +159,12 @@ typedef enum
 #define GFC_DTYPE_TYPE_MASK 0x38
 #define GFC_DTYPE_SIZE_SHIFT 6
 
-/* Basic types.  BT_VOID is used by ISO C Binding so funcs like c_f_pointer
+/* Basic types.  BT_VOID is used by ISO C Binding so functions like c_f_pointer
    can take any arg with the pointer attribute as a param.  These are also
    used in the run-time library for IO.  */
 typedef enum
 { BT_UNKNOWN = 0, BT_INTEGER, BT_LOGICAL, BT_REAL, BT_COMPLEX,
   BT_DERIVED, BT_CHARACTER, BT_CLASS, BT_PROCEDURE, BT_HOLLERITH, BT_VOID,
-  BT_ASSUMED, BT_UNION
+  BT_ASSUMED, BT_UNION, BT_BOZ
 }
 bt;
Index: gcc/fortran/primary.c
===================================================================
--- gcc/fortran/primary.c	(revision 253236)
+++ gcc/fortran/primary.c	(working copy)
@@ -328,16 +328,16 @@ cleanup:
 }
 
 
-/* Match a binary, octal or hexadecimal constant that can be found in
-   a DATA statement.  The standard permits b'010...', o'73...', and
-   z'a1...' where b, o, and z can be capital letters.  This function
-   also accepts postfixed forms of the constants: '01...'b, '73...'o,
-   and 'a1...'z.  An additional extension is the use of x for z.  */
+/* Match a binary, octal or hexadecimal constant.  The standard permits
+   b'010...', o'73...', and z'a1...' where b, o, and z can be capital
+   letters.  This function also accepts postfixed forms of the constants:
+   '01...'b, '73...'o, and 'a1...'z.  An additional extension is the use
+   of x for z.  */
 
 static match
 match_boz_constant (gfc_expr **result)
 {
-  int radix, length, x_hex, kind;
+  int radix, length, x_hex;
   locus old_loc, start_loc;
   char *buffer, post, delim;
   gfc_expr *e;
@@ -443,18 +443,16 @@ match_boz_constant (gfc_expr **result)
      the representation method with the largest decimal exponent range
      supported by the processor."  */
 
-  kind = gfc_max_integer_kind;
-  e = gfc_convert_integer (buffer, kind, radix, &gfc_current_locus);
-
-  /* Mark as boz variable.  */
-  e->is_boz = 1;
-
-  if (gfc_range_check (e) != ARITH_OK)
-    {
-      gfc_error ("Integer too big for integer kind %i at %C", kind);
-      gfc_free_expr (e);
-      return MATCH_ERROR;
-    }
+  /* Save the BOZ with an appropriate prefix, e.g., b1001011.  */
+  e = gfc_get_constant_expr (BT_BOZ, -1, &gfc_current_locus);
+  e->boz = XCNEWVEC (char, length + 2);
+  if (radix == 2)
+      strcpy (e->boz, "b");
+  else if (radix == 8)
+      strcpy (e->boz, "o");
+  else
+      strcpy (e->boz, "z");
+  strcat (e->boz, buffer);
 
   if (!gfc_in_match_data ()
       && (!gfc_notify_std(GFC_STD_F2003, "BOZ used outside a DATA "
Index: gcc/fortran/resolve.c
===================================================================
--- gcc/fortran/resolve.c	(revision 253236)
+++ gcc/fortran/resolve.c	(working copy)
@@ -3776,6 +3776,31 @@ resolve_operator (gfc_expr *e)
     case INTRINSIC_TIMES:
     case INTRINSIC_DIVIDE:
     case INTRINSIC_POWER:
+
+      if (op1->ts.type == BT_BOZ && op2->ts.type == BT_BOZ)
+	{
+	  gfc_error ("Operands at %L and %L of intrinsic operator %qs cannot "
+		     "both be boz-literal-constants", &op1->where, &op2->where,
+		     gfc_op2string (e->value.op.op));
+	  return false;
+	}
+
+      if (op1->ts.type == BT_BOZ)
+        {
+	  if (op2->ts.type == BT_INTEGER)
+	    gfc_boz2int (op1, op2);
+	  else 
+	    gfc_convert_boz (op1, &op2->ts);
+        }
+
+      if (op2->ts.type == BT_BOZ)
+        {
+	  if (op1->ts.type == BT_INTEGER)
+	    gfc_boz2int (op2, op1);
+	  else 
+	    gfc_convert_boz (op2, &op1->ts);
+        }
+
       if (gfc_numeric_ts (&op1->ts) && gfc_numeric_ts (&op2->ts))
 	{
 	  gfc_type_convert_binary (e, 1);
@@ -3886,6 +3911,30 @@ resolve_operator (gfc_expr *e)
 	  break;
 	}
 
+      if (op1->ts.type == BT_BOZ && op2->ts.type == BT_BOZ)
+	{
+	  gfc_error ("Operands of comparison operator %qs at %L cannot both be "
+		     "boz-literal-constants", gfc_op2string (e->value.op.op), 
+		     &op2->where);
+	  return false;
+	}
+
+      if (op1->ts.type == BT_BOZ)
+        {
+	  if (op2->ts.type == BT_INTEGER)
+	    gfc_boz2int (op1, op2);
+	  else 
+	    gfc_convert_boz (op1, &op2->ts);
+        }
+
+      if (op2->ts.type == BT_BOZ)
+        {
+	  if (op1->ts.type == BT_INTEGER)
+	    gfc_boz2int (op2, op1);
+	  else 
+	    gfc_convert_boz (op2, &op1->ts);
+        }
+
       if (gfc_numeric_ts (&op1->ts) && gfc_numeric_ts (&op2->ts))
 	{
 	  gfc_type_convert_binary (e, 1);
@@ -7387,8 +7436,14 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code, bo
   if (code->ext.alloc.ts.type == BT_CHARACTER && !e->ts.deferred
       && !UNLIMITED_POLY (e))
     {
-      int cmp = gfc_dep_compare_expr (e->ts.u.cl->length,
-				      code->ext.alloc.ts.u.cl->length);
+      int cmp;
+
+      if (!e->ts.u.cl->length)
+	goto failure;
+
+      cmp = gfc_dep_compare_expr (e->ts.u.cl->length,
+				  code->ext.alloc.ts.u.cl->length);
+
       if (cmp == 1 || cmp == -1 || cmp == -3)
 	{
 	  gfc_error ("Allocating %s at %L with type-spec requires the same "
@@ -10059,14 +10114,14 @@ resolve_ordinary_assign (gfc_code *code, gfc_namespace
   lhs = code->expr1;
   rhs = code->expr2;
 
-  if (rhs->is_boz
+  if (rhs->ts.type == BT_BOZ
       && !gfc_notify_std (GFC_STD_GNU, "BOZ literal at %L outside "
 			  "a DATA statement and outside INT/REAL/DBLE/CMPLX",
 			  &code->loc))
     return false;
 
   /* Handle the case of a BOZ literal on the RHS.  */
-  if (rhs->is_boz && lhs->ts.type != BT_INTEGER)
+  if (rhs->ts.type == BT_BOZ && lhs->ts.type != BT_INTEGER)
     {
       int rc;
       if (warn_surprising)
Index: gcc/fortran/simplify.c
===================================================================
--- gcc/fortran/simplify.c	(revision 253236)
+++ gcc/fortran/simplify.c	(working copy)
@@ -212,7 +212,7 @@ gfc_convert_mpz_to_signed (mpz_t x, int bitsize)
 static gfc_expr *
 convert_boz (gfc_expr *x, int kind)
 {
-  if (x && x->ts.type == BT_INTEGER && x->is_boz)
+  if (x && x->ts.type == BT_BOZ)
     {
       gfc_typespec ts;
       gfc_clear_ts (&ts);
@@ -1614,14 +1614,21 @@ simplify_cmplx (const char *name, gfc_expr *x, gfc_exp
 {
   gfc_expr *result;
 
-  if (convert_boz (x, kind) == &gfc_bad_expr)
-    return &gfc_bad_expr;
+  /* If x is a BOZ at this point, then convert it.  */
+  if (x->expr_type == EXPR_CONSTANT)
+    {
+      if (convert_boz (x, kind) == &gfc_bad_expr)
+	return &gfc_bad_expr;
+    }
 
-  if (convert_boz (y, kind) == &gfc_bad_expr)
-    return &gfc_bad_expr;
+  /* If y is a BOZ at this point, then convert it. */
+  if (y && y->expr_type == EXPR_CONSTANT)
+    {
+      if (convert_boz (y, kind) == &gfc_bad_expr)
+	return &gfc_bad_expr;
+    }
 
-  if (x->expr_type != EXPR_CONSTANT
-      || (y != NULL && y->expr_type != EXPR_CONSTANT))
+  if (x->expr_type != EXPR_CONSTANT || (y && y->expr_type != EXPR_CONSTANT))
     return NULL;
 
   result = gfc_get_constant_expr (BT_COMPLEX, kind, &x->where);
@@ -1685,7 +1692,21 @@ gfc_simplify_complex (gfc_expr *x, gfc_expr *y)
 {
   int kind;
 
-  if (x->ts.type == BT_INTEGER && y->ts.type == BT_INTEGER)
+  if (x->ts.type == BT_BOZ)
+    {
+      if (y->ts.type == BT_BOZ || y->ts.type == BT_INTEGER)
+	kind = gfc_default_complex_kind;
+      else
+	kind = y->ts.kind;
+    }
+  else if (y->ts.type == BT_BOZ)
+    {
+      if (x->ts.type == BT_BOZ || x->ts.type == BT_INTEGER)
+	kind = gfc_default_complex_kind;
+      else
+	kind = x->ts.kind;
+    }
+  else if (x->ts.type == BT_INTEGER && y->ts.type == BT_INTEGER)
     kind = gfc_default_complex_kind;
   else if (x->ts.type == BT_REAL || y->ts.type == BT_INTEGER)
     kind = x->ts.kind;
@@ -2504,7 +2525,7 @@ gfc_simplify_float (gfc_expr *a)
   if (a->expr_type != EXPR_CONSTANT)
     return NULL;
 
-  if (a->is_boz)
+  if (a->ts.type == BT_BOZ)
     {
       if (convert_boz (a, gfc_default_real_kind) == &gfc_bad_expr)
 	return &gfc_bad_expr;
@@ -3151,6 +3172,19 @@ simplify_intconv (gfc_expr *e, int kind, const char *n
 
   if (e->expr_type != EXPR_CONSTANT)
     return NULL;
+
+  if (e->ts.type == BT_BOZ)
+    {
+      char *t;
+      int radix;
+      t = e->boz;
+      radix = 16;
+      if (*t == 'b') radix = 2;
+      if (*t++ == 'o') radix = 8;
+      e->ts.type = BT_INTEGER;
+      mpz_init (e->value.integer);
+      mpz_set_str (e->value.integer, t, radix);
+    }
 
   result = gfc_convert_constant (e, BT_INTEGER, kind);
   if (result == &gfc_bad_expr)
Index: gcc/fortran/target-memory.c
===================================================================
--- gcc/fortran/target-memory.c	(revision 253236)
+++ gcc/fortran/target-memory.c	(working copy)
@@ -735,7 +735,27 @@ gfc_merge_initializers (gfc_typespec ts, gfc_expr *e, 
   return len;
 }
 
+/* boz2int implements the old semantics of converting a boz to an 
+   integer with the largest kind value.  This is a kludge until one
+   determines if gfc_convert_boz can use e->boz directly.  */
 
+static void
+boz2int (gfc_expr *i)
+{
+  char *t;
+  int radix;
+
+  t = i->boz;
+  radix = 16;
+  if (*t == 'b') radix = 2;
+  if (*t++ == 'o') radix = 8;
+
+  i->ts.kind = gfc_max_integer_kind;
+  mpz_init (i->value.integer);
+  mpz_set_str (i->value.integer, t, radix);
+}
+
+
 /* Transfer the bitpattern of a (integer) BOZ to real or complex variables.
    When successful, no BOZ or nothing to do, true is returned.  */
 
@@ -746,12 +766,11 @@ gfc_convert_boz (gfc_expr *expr, gfc_typespec *ts)
   int index;
   unsigned char *buffer;
 
-  if (!expr->is_boz)
+  gcc_assert (expr->expr_type == EXPR_CONSTANT);
+
+  if (expr->ts.type != BT_BOZ)
     return true;
 
-  gcc_assert (expr->expr_type == EXPR_CONSTANT
-	      && expr->ts.type == BT_INTEGER);
-
   /* Don't convert BOZ to logical, character, derived etc.  */
   if (ts->type == BT_REAL)
     {
@@ -766,7 +785,9 @@ gfc_convert_boz (gfc_expr *expr, gfc_typespec *ts)
   else
     return true;
 
+
   /* Convert BOZ to the smallest possible integer kind.  */
+  boz2int (expr);
   boz_bit_size = mpz_sizeinbase (expr->value.integer, 2);
 
   if (boz_bit_size > ts_bit_size)
@@ -798,7 +819,6 @@ gfc_convert_boz (gfc_expr *expr, gfc_typespec *ts)
       gfc_interpret_complex (ts->kind, buffer, buffer_size,
 			     expr->value.complex);
     }
-  expr->is_boz = 0;
   expr->ts.type = ts->type;
   expr->ts.kind = ts->kind;
 
Index: gcc/testsuite/gfortran.dg/achar_5.f90
===================================================================
--- gcc/testsuite/gfortran.dg/achar_5.f90	(revision 253236)
+++ gcc/testsuite/gfortran.dg/achar_5.f90	(working copy)
@@ -37,9 +37,4 @@ program test
   print *, char(huge(0_8),kind=4) ! { dg-error "too large for the collating sequence" }
   print *, achar(huge(0_8),kind=4) ! { dg-error "too large for the collating sequence" }
 
-  print *, char(z'FFFFFFFF', kind=4)
-  print *, achar(z'FFFFFFFF', kind=4)
-  print *, char(z'100000000', kind=4) ! { dg-error "too large for the collating sequence" }
-  print *, achar(z'100000000', kind=4) ! { dg-error "too large for the collating sequence" }
-
 end program test
Index: gcc/testsuite/gfortran.dg/boz_4.f90
===================================================================
--- gcc/testsuite/gfortran.dg/boz_4.f90	(revision 253236)
+++ gcc/testsuite/gfortran.dg/boz_4.f90	(nonexistent)
@@ -1,29 +0,0 @@
-! { dg-do compile }
-! Test that the conversion of a BOZ constant that is too large for the
-! integer variable is caught by the compiler.
-program boz
-
-   implicit none
-
-   integer(1), parameter :: &
-   &  b1 = b'0101010110101010'  ! { dg-error "overflow converting" }
-   integer(2), parameter :: &
-   &  b2 = b'01110000111100001111000011110000'  ! { dg-error "overflow converting" }
-   integer(4), parameter :: &
-   &  b4 = b'0111000011110000111100001111000011110000111100001111000011110000'  ! { dg-error "overflow converting" }
-
-   integer(1), parameter :: &
-   &  o1 = o'1234567076543210'  ! { dg-error "overflow converting" }
-   integer(2), parameter :: &
-   &  o2 = o'1234567076543210'  ! { dg-error "overflow converting" }
-   integer(4), parameter :: &
-   &  o4 = o'1234567076543210'  ! { dg-error "overflow converting" }
-
-   integer(1), parameter :: &
-   &  z1 = z'deadbeef'  ! { dg-error "overflow converting" }
-   integer(2), parameter :: &
-   &  z2 = z'deadbeef'  ! { dg-error "overflow converting" }
-   integer(4), parameter :: &
-   &  z4 = z'deadbeeffeed'  ! { dg-error "overflow converting" }
-
-end program boz
Index: gcc/testsuite/gfortran.dg/graphite/id-26.f03
===================================================================
--- gcc/testsuite/gfortran.dg/graphite/id-26.f03	(revision 253236)
+++ gcc/testsuite/gfortran.dg/graphite/id-26.f03	(working copy)
@@ -51,11 +51,11 @@
   ! Attempt to create 64-byte aligned allocatable
   do i = 1, 64
     allocate (c(1023 + i))
-    if (iand (loc (c(1)), 63) == 0) exit
+    if (iand(int(loc(c(1)), 8), 63_8) == 0) exit
     deallocate (c)
     allocate (b(i)%a(1023 + i))
     allocate (c(1023 + i))
-    if (iand (loc (c(1)), 63) == 0) exit
+    if (iand(int(loc(c(1)), 8), 63_8) == 0) exit
     deallocate (c)
   end do
   if (allocated (c)) then
Index: gcc/testsuite/gfortran.dg/pr81509_1.f90
===================================================================
--- gcc/testsuite/gfortran.dg/pr81509_1.f90	(nonexistent)
+++ gcc/testsuite/gfortran.dg/pr81509_1.f90	(working copy)
@@ -0,0 +1,12 @@
+! { dg-do run }
+! https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81509
+program foo
+logical :: a = .false.
+integer :: i = 42
+integer(8) :: k = 42
+if (kind(ieor(z'ade',i)) /= 4) call abort
+if (kind(ior(i,z'1111')) /= 4) call abort
+if (kind(ior(1_8,k)) /= 8) call abort
+if (kind(iand(k,b'1111')) /= 8) call abort
+end program foo
+
Index: gcc/testsuite/gfortran.dg/pr81509_2.f90
===================================================================
--- gcc/testsuite/gfortran.dg/pr81509_2.f90	(nonexistent)
+++ gcc/testsuite/gfortran.dg/pr81509_2.f90	(working copy)
@@ -0,0 +1,18 @@
+! { dg-do compile }
+! https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81509
+!
+program foo
+logical :: a = .false.
+integer :: i = 42
+integer(8) :: k
+k = iand(z'aaaa', z'1234')    ! { dg-error "cannot both be BOZ literal" }
+k = and(z'aaaa', z'1234')     ! { dg-error "cannot both be BOZ literal" }
+k = and(1, z'1234')
+k = and(i, z'1234')
+k = ieor(z'ade',i)
+k = ior(i,z'1111')
+k = ior(i,k)                  ! { dg-error "different kind type parameters" }
+k = and(i,k)
+k = and(a,z'1234')            ! { dg-error "must have the same type" }
+end program foo
+
Index: gcc/testsuite/gfortran.dg/unf_io_convert_2.f90
===================================================================
--- gcc/testsuite/gfortran.dg/unf_io_convert_2.f90	(revision 253236)
+++ gcc/testsuite/gfortran.dg/unf_io_convert_2.f90	(working copy)
@@ -6,6 +6,11 @@ program main
   integer(kind=1) :: b(8)
   integer(kind=8) :: j
 
+  integer(1), parameter :: b1 = z'11', b2 = z'22', b3 = z'33', b4 = z'44', b5 = z'55', &
+  &   b6 = z'66', b7 = z'77', b8 = z'00'  ! { dg-warning "BOZ literal" }
+
+  integer(4), parameter :: i1 = z'11223344', i2 = z'55667700' ! { dg-warning "BOZ literal" }
+
   c = (3.14, 2.71)
   open (10, form="unformatted",convert="swap") ! { dg-warning "Extension: CONVERT" }
   write (10) c
@@ -15,11 +20,11 @@ program main
   close(10,status="delete")
 
   open (10, form="unformatted",convert="big_endian") ! { dg-warning "Extension: CONVERT" }
-  i = (/ Z'11223344', Z'55667700' /)
+  i = (/ i1, i2 /)
   write (10) i
   rewind (10)
   read (10) b
-  if (any(b /= (/ Z'11', Z'22', Z'33', Z'44', Z'55', Z'66', Z'77', Z'00' /))) &
+  if (any(b /= (/ b1, b2, b3, b4, b5, b6, b7, b8 /))) &
     call abort
   backspace 10
   read (10) j
@@ -30,7 +35,7 @@ program main
   write (10) i
   rewind (10)
   read (10) b
-  if (any(b /= (/ Z'44', Z'33', Z'22', Z'11', Z'00', Z'77', Z'66', Z'55' /))) &
+  if (any(b /= (/ b4, b3, b2, b1, b8, b7, b6, b5 /))) &
     call abort
   backspace 10
   read (10) j

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