Patchwork [libfortran] Fix PR 50192 - fix wide-char comparison

login
register
mail settings
Submitter Thomas Koenig
Date Aug. 26, 2011, 12:40 p.m.
Message ID <4E579423.8010308@netcologne.de>
Download mbox | patch
Permalink /patch/111763/
State New
Headers show

Comments

Thomas Koenig - Aug. 26, 2011, 12:40 p.m.
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  <tkoenig@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  <tkoenig@gcc.gnu.org>

         PR libfortran/50192
         * gfortran.dg/widechar_compare_1.f90:  New test.
! { 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
Thomas Koenig - Aug. 26, 2011, 12:41 p.m.
Am 26.08.2011 14:40, schrieb Thomas Koenig:
>
> OK for trunk?  Which branches should this be backported to?

I forgot - also regression-tested.

	Thomas
jerry DeLisle - Aug. 28, 2011, 7:31 p.m.
On 08/26/2011 05:40 AM, Thomas Koenig wrote:
> 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

OK, suggest if this problem produces wrong code, backport to at least 4.5, and 
4.6, if applicable 4.4

Patch

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,