diff options
author | Thomas Koenig <tkoenig@gcc.gnu.org> | 2024-08-08 20:10:33 +0200 |
---|---|---|
committer | Thomas Koenig <tkoenig@gcc.gnu.org> | 2024-08-08 20:10:33 +0200 |
commit | 8366ec0e2fbf52cdf209272826b64d4e049743de (patch) | |
tree | 7cb3dd3d648af470e0e398c0e213d20d4d543f64 | |
parent | d5c05281bacf79bca1c10c34135aa61e14be8acb (diff) | |
download | gcc-devel/fortran_unsigned.zip gcc-devel/fortran_unsigned.tar.gz gcc-devel/fortran_unsigned.tar.bz2 |
Add merge_bits.devel/fortran_unsigned
-rw-r--r-- | gcc/fortran/check.cc | 50 | ||||
-rw-r--r-- | gcc/fortran/iresolve.cc | 4 | ||||
-rw-r--r-- | gcc/fortran/simplify.cc | 2 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/unsigned_14.f90 | 18 |
4 files changed, 64 insertions, 10 deletions
diff --git a/gcc/fortran/check.cc b/gcc/fortran/check.cc index 108e05d..ae1ca6e 100644 --- a/gcc/fortran/check.cc +++ b/gcc/fortran/check.cc @@ -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; diff --git a/gcc/fortran/iresolve.cc b/gcc/fortran/iresolve.cc index 8e2ad87..a43c07c 100644 --- a/gcc/fortran/iresolve.cc +++ b/gcc/fortran/iresolve.cc @@ -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); } diff --git a/gcc/fortran/simplify.cc b/gcc/fortran/simplify.cc index 0539603..da3c3cf 100644 --- a/gcc/fortran/simplify.cc +++ b/gcc/fortran/simplify.cc @@ -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 index 0000000..3ccce68 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/unsigned_14.f90 @@ -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 |