Dear all,

we need to check the POS (and LEN) arguments of bit intrinsics
when simplifying, e.g. when used in array constructors.
Otherwise we ICE.  Found by Gerhard.

The fix is straightforward, see attached.

Regtested on x86_64-pc-linux-gnu.  OK for mainline?

Thanks,
Harald

From 32c95012378ada5ce555a819dbc640e1dd2b88d5 Mon Sep 17 00:00:00 2001
From: Harald Anlauf <anl...@gmx.de>
Date: Wed, 15 Jun 2022 22:20:09 +0200
Subject: [PATCH] Fortran: check POS and LEN arguments simplifying bit
 intrinsics [PR105986]

gcc/fortran/ChangeLog:

	PR fortran/105986
	* simplify.cc (gfc_simplify_btest): Add check for POS argument.
	(gfc_simplify_ibclr): Add check for POS argument.
	(gfc_simplify_ibits): Add check for POS and LEN arguments.
	(gfc_simplify_ibset): Add check for POS argument.

gcc/testsuite/ChangeLog:

	PR fortran/105986
	* gfortran.dg/check_bits_3.f90: New test.
---
 gcc/fortran/simplify.cc                    | 12 ++++++++++++
 gcc/testsuite/gfortran.dg/check_bits_3.f90 | 16 ++++++++++++++++
 2 files changed, 28 insertions(+)
 create mode 100644 gcc/testsuite/gfortran.dg/check_bits_3.f90

diff --git a/gcc/fortran/simplify.cc b/gcc/fortran/simplify.cc
index 233cc42137f..c8f2ef9fbf4 100644
--- a/gcc/fortran/simplify.cc
+++ b/gcc/fortran/simplify.cc
@@ -1644,6 +1644,9 @@ gfc_simplify_btest (gfc_expr *e, gfc_expr *bit)
   if (e->expr_type != EXPR_CONSTANT || bit->expr_type != EXPR_CONSTANT)
     return NULL;

+  if (!gfc_check_bitfcn (e, bit))
+    return &gfc_bad_expr;
+
   if (gfc_extract_int (bit, &b) || b < 0)
     return gfc_get_logical_expr (gfc_default_logical_kind, &e->where, false);

@@ -3353,6 +3356,9 @@ gfc_simplify_ibclr (gfc_expr *x, gfc_expr *y)
   if (x->expr_type != EXPR_CONSTANT || y->expr_type != EXPR_CONSTANT)
     return NULL;

+  if (!gfc_check_bitfcn (x, y))
+    return &gfc_bad_expr;
+
   gfc_extract_int (y, &pos);

   k = gfc_validate_kind (x->ts.type, x->ts.kind, false);
@@ -3384,6 +3390,9 @@ gfc_simplify_ibits (gfc_expr *x, gfc_expr *y, gfc_expr *z)
       || z->expr_type != EXPR_CONSTANT)
     return NULL;

+  if (!gfc_check_ibits (x, y, z))
+    return &gfc_bad_expr;
+
   gfc_extract_int (y, &pos);
   gfc_extract_int (z, &len);

@@ -3438,6 +3447,9 @@ gfc_simplify_ibset (gfc_expr *x, gfc_expr *y)
   if (x->expr_type != EXPR_CONSTANT || y->expr_type != EXPR_CONSTANT)
     return NULL;

+  if (!gfc_check_bitfcn (x, y))
+    return &gfc_bad_expr;
+
   gfc_extract_int (y, &pos);

   k = gfc_validate_kind (x->ts.type, x->ts.kind, false);
diff --git a/gcc/testsuite/gfortran.dg/check_bits_3.f90 b/gcc/testsuite/gfortran.dg/check_bits_3.f90
new file mode 100644
index 00000000000..3018e6977ef
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/check_bits_3.f90
@@ -0,0 +1,16 @@
+! { dg-do compile }
+! PR fortran/105986
+! Contributed by G.Steinmetz
+
+program p
+  integer :: i
+  logical, parameter :: a(*) = [(btest(8_4,i), i=-1,-1)] ! { dg-error "nonnegative" }
+  integer, parameter :: b(*) = [(ibclr(8_4,i), i=-1,-1)] ! { dg-error "nonnegative" }
+  integer, parameter :: c(*) = [(ibset(8_4,i), i=-1,-1)] ! { dg-error "nonnegative" }
+  logical, parameter :: d(*) = [(btest(8_1,i), i= 8, 8)] ! { dg-error "must be less" }
+  integer, parameter :: e(*) = [(ibclr(8_2,i), i=16,16)] ! { dg-error "must be less" }
+  integer, parameter :: f(*) = [(ibset(8_4,i), i=32,32)] ! { dg-error "must be less" }
+  integer, parameter :: g(*) = [(ibits(8_4,i,1),i=-1,-1)] ! { dg-error "nonnegative" }
+  integer, parameter :: h(*) = [(ibits(8_4,1,i),i=-1,-1)] ! { dg-error "nonnegative" }
+  integer, parameter :: j(*) = [(ibits(8_4,i,i),i=32,32)] ! { dg-error "must be less" }
+end
--
2.35.3

Reply via email to