]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Add merge_bits. devel/fortran_unsigned
authorThomas Koenig <tkoenig@gcc.gnu.org>
Thu, 8 Aug 2024 18:10:33 +0000 (20:10 +0200)
committerThomas Koenig <tkoenig@gcc.gnu.org>
Thu, 8 Aug 2024 18:10:33 +0000 (20:10 +0200)
gcc/fortran/check.cc
gcc/fortran/iresolve.cc
gcc/fortran/simplify.cc
gcc/testsuite/gfortran.dg/unsigned_14.f90 [new file with mode: 0644]

index 108e05dbe74ebec42ca08492ccb1f39787cb1f3d..ae1ca6e11162e93f3d616d4a7a19eb18d9dd4db2 100644 (file)
@@ -4443,20 +4443,54 @@ gfc_check_merge_bits (gfc_expr *i, gfc_expr *j, gfc_expr *mask)
       && !gfc_boz2int (j, i->ts.kind))
     return false;
 
-  if (!type_check (i, 0, BT_INTEGER))
-    return false;
+  if (flag_unsigned)
+    {
+      /* If i is BOZ and j is unsigned, convert i to type of j.  */
+      if (i->ts.type == BT_BOZ && j->ts.type == BT_UNSIGNED
+         && !gfc_boz2uint (i, j->ts.kind))
+       return false;
 
-  if (!type_check (j, 1, BT_INTEGER))
-    return false;
+      /* If j is BOZ and i is unsigned, convert j to type of i.  */
+      if (j->ts.type == BT_BOZ && i->ts.type == BT_UNSIGNED
+         && !gfc_boz2int (j, i->ts.kind))
+       return false;
+
+      if (!type_check2 (i, 0, BT_INTEGER, BT_UNSIGNED))
+       return false;
+
+      if (!type_check2 (j, 1, BT_INTEGER, BT_UNSIGNED))
+       return false;
+    }
+  else
+    {
+      if (!type_check (i, 0, BT_INTEGER))
+       return false;
+
+      if (!type_check (j, 1, BT_INTEGER))
+       return false;
+    }
 
   if (!same_type_check (i, 0, j, 1))
     return false;
 
-  if (mask->ts.type == BT_BOZ && !gfc_boz2int(mask, i->ts.kind))
-    return false;
+  if (mask->ts.type == BT_BOZ)
+    {
+      if (i->ts.type == BT_INTEGER && !gfc_boz2int (mask, i->ts.kind))
+       return false;
+      if (i->ts.type == BT_UNSIGNED && !gfc_boz2uint (mask, i->ts.kind))
+       return false;
+    }
 
-  if (!type_check (mask, 2, BT_INTEGER))
-    return false;
+  if (flag_unsigned)
+    {
+      if (!type_check2 (mask, 2, BT_INTEGER, BT_UNSIGNED))
+       return false;
+    }
+  else
+    {
+      if (!type_check (mask, 2, BT_INTEGER))
+       return false;
+    }
 
   if (!same_type_check (i, 0, mask, 2))
     return false;
index 8e2ad8780f8c5e5ba1218f898c57d302144c691d..a43c07c91aa05d6650f1e431ee5e9c92b05dcfaf 100644 (file)
@@ -2000,7 +2000,9 @@ gfc_resolve_merge_bits (gfc_expr *f, gfc_expr *i,
                        gfc_expr *mask ATTRIBUTE_UNUSED)
 {
   f->ts = i->ts;
-  f->value.function.name = gfc_get_string ("__merge_bits_i%d", i->ts.kind);
+  const char *name = i->ts.kind == BT_UNSIGNED ? "__merge_bits_u%d" :
+    "__merge_bits_i%d";
+  f->value.function.name = gfc_get_string (name, i->ts.kind);
 }
 
 
index 05396035b58e51bd5e5be1fd822264b60bd21c8d..da3c3cfe3e9249d25f3cba44aa5ee5a1bfcfdaee 100644 (file)
@@ -5221,7 +5221,7 @@ gfc_simplify_merge_bits (gfc_expr *i, gfc_expr *j, gfc_expr *mask_expr)
       || mask_expr->expr_type != EXPR_CONSTANT)
     return NULL;
 
-  result = gfc_get_constant_expr (BT_INTEGER, i->ts.kind, &i->where);
+  result = gfc_get_constant_expr (i->ts.type, i->ts.kind, &i->where);
 
   /* Convert all argument to unsigned.  */
   mpz_init_set (arg1, i->value.integer);
diff --git a/gcc/testsuite/gfortran.dg/unsigned_14.f90 b/gcc/testsuite/gfortran.dg/unsigned_14.f90
new file mode 100644 (file)
index 0000000..3ccce68
--- /dev/null
@@ -0,0 +1,18 @@
+! { dg-do run }
+! { dg-options "-funsigned" }
+! Test basic functionality of merge_bits.
+program main
+  unsigned(kind=4) :: a, b, c
+  if (merge_bits(15u,51u,85u) /= 39u) stop 1
+  a = 15u
+  b = 51u
+  c = 85u
+  if (merge_bits(a,b,c) /= 39u) stop 2
+
+  if  (merge_bits(4026531840u,3422552064u,2852126720u) /= 3825205248u) stop 3
+
+  a = 4026531840u_4
+  b = 3422552064u_4
+  c = 2852126720u_4
+  if (merge_bits(a,b,c) /= 3825205248u) stop 4
+end program