Hello world, the attached patch fixes the PR by doing comparisions for wide characters as unsigned 4-byte ints.
I have put the comparison function into libgfortran.h because I will need it for MINLOC and friends for characters. OK for trunk? Which branches should this be backported to? Thomas 2011-08-26 Thomas Koenig <tkoe...@gcc.gnu.org> PR libfortran/50192 * intrinsics/string_intrinsics.c (memcmp_char4): New function. * intrinsics/string_intrinsics_inc.c: New macro MEMCMP, either set to memcmp or memcmp_char4. (compare_string): Use MEMCMP, with correct size for it. * libgfortran.h: Add prototype for memcmp_char4. 2011-08-26 Thomas Koenig <tkoe...@gcc.gnu.org> PR libfortran/50192 * gfortran.dg/widechar_compare_1.f90: New test.
Index: intrinsics/string_intrinsics_inc.c =================================================================== --- intrinsics/string_intrinsics_inc.c (Revision 178067) +++ intrinsics/string_intrinsics_inc.c (Arbeitskopie) @@ -90,7 +90,7 @@ compare_string (gfc_charlen_type len1, const CHART gfc_charlen_type len; int res; - res = memcmp (s1, s2, ((len1 < len2) ? len1 : len2) * sizeof (CHARTYPE)); + res = MEMCMP (s1, s2, ((len1 < len2) ? len1 : len2)); if (res != 0) return res; Index: intrinsics/string_intrinsics.c =================================================================== --- intrinsics/string_intrinsics.c (Revision 178067) +++ intrinsics/string_intrinsics.c (Arbeitskopie) @@ -51,7 +51,24 @@ memset_char4 (gfc_char4_t *b, gfc_char4_t c, size_ return b; } +/* Compare wide character types, which are handled internally as + unsigned 4-byte integers. */ +int +memcmp_char4 (const void *a, const void *b, size_t len) +{ + const GFC_UINTEGER_4 *pa = a; + const GFC_UINTEGER_4 *pb = b; + while (len-- > 0) + { + if (*pa != *pb) + return *pa < *pb ? -1 : 1; + pa ++; + pb ++; + } + return 0; +} + /* All other functions are defined using a few generic macros in string_intrinsics_inc.c, so we avoid code duplication between the various character type kinds. */ @@ -64,6 +81,8 @@ memset_char4 (gfc_char4_t *b, gfc_char4_t c, size_ #define SUFFIX(x) x #undef MEMSET #define MEMSET memset +#undef MEMCMP +#define MEMCMP memcmp #include "string_intrinsics_inc.c" @@ -76,6 +95,8 @@ memset_char4 (gfc_char4_t *b, gfc_char4_t c, size_ #define SUFFIX(x) x ## _char4 #undef MEMSET #define MEMSET memset_char4 +#undef MEMCMP +#define MEMCMP memcmp_char4 #include "string_intrinsics_inc.c" Index: libgfortran.h =================================================================== --- libgfortran.h (Revision 178067) +++ libgfortran.h (Arbeitskopie) @@ -1266,6 +1266,10 @@ extern int compare_string_char4 (gfc_charlen_type, gfc_charlen_type, const gfc_char4_t *); iexport_proto(compare_string_char4); +extern int memcmp_char4 (const void *, const void *, size_t); +internal_proto(memcmp_char4); + + /* random.c */ extern void random_seed_i4 (GFC_INTEGER_4 * size, gfc_array_i4 * put,
! { dg-do run } ! PR 50192 - on little-endian systems, this used to fail. program main character(kind=4,len=2) :: c1, c2 c1 = 4_' ' c2 = 4_' ' c1(1:1) = transfer(257, mold=c1(1:1)) c2(1:1) = transfer(64, mold=c2(1:1)) if (c1 < c2) call abort end program main