[PATCH] ctype.h (another try)

Ian Wienand ianw@gelato.unsw.edu.au
Tue Mar 25 23:49:00 GMT 2003


Hello,

A previous patch
(http://sources.redhat.com/ml/libc-alpha/2003-03/msg00379.html) to
stop the type punning errors in this file with gcc 3.3 was shown to be
incorrect, but it is still annoying me.  As I understand it, gcc warns
when you do

something i;
void *ptr = &i;
void **ptr2ptr = &ptr;

somthing **ptr2 = (somthing **)ptr2ptr <- warning

because if you dereference ptr2ptr it's really void *, but gcc (and
probably the developer) would assume it's a something * and hence you
are in danger of accessing the same memory as two different types,
which breaks the type based aliasing rules.

i think by using a union you are explictly specifying your punning, so
gcc can know what you are up to and take account accordingly.

-i
ianw@gelato.unsw.edu.au
http://www.gelato.unsw.edu.au
-------------- next part --------------
Index: include/ctype.h
===================================================================
RCS file: /cvs/glibc/libc/include/ctype.h,v
retrieving revision 1.7
diff -u -r1.7 ctype.h
--- include/ctype.h	18 Mar 2003 00:37:46 -0000	1.7
+++ include/ctype.h	23 Mar 2003 23:29:36 -0000
@@ -25,31 +25,46 @@
 CTYPE_EXTERN_INLINE const uint16_t ** __attribute__ ((const))
 __ctype_b_loc (void)
 {
-  const uint16_t **tablep =
-    (const uint16_t **) __libc_tsd_address (CTYPE_B);
-  if (__builtin_expect (*tablep == NULL, 0))
-    *tablep = (const uint16_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_CLASS) + 128;
-  return tablep;
+  /* __libc_tsd_address returns a void **, therefore dereferencing it
+     gives a void *.  Thus if we just cast this return to a const
+     unit16_t **, upon dereferecing the compiler would think it was a
+     unit16_t *, when it was declared as a void *.  Thus type based
+     aliasing will be broken.  Use a union.
+  */
+  union {
+    const uint16_t **t;
+    void **p;
+  } tablep;
+  tablep.p = __libc_tsd_address (CTYPE_B);
+  if (__builtin_expect (*tablep.p == NULL, 0))
+    *tablep.t = (const uint16_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_CLASS) + 128;
+  return tablep.t;
 }
 
 CTYPE_EXTERN_INLINE const int32_t ** __attribute__ ((const))
 __ctype_toupper_loc (void)
 {
-  const int32_t **tablep =
-    (const int32_t **) __libc_tsd_address (CTYPE_TOUPPER);
-  if (__builtin_expect (*tablep == NULL, 0))
-    *tablep = ((int32_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_TOUPPER) + 128);
-  return tablep;
+  union {
+    const int32_t **t;
+    void **p;
+  } tablep;
+  tablep.p = __libc_tsd_address (CTYPE_TOUPPER);
+  if (__builtin_expect (*tablep.p == NULL, 0))
+    *tablep.t = ((int32_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_TOUPPER) + 128);
+  return tablep.t;
 }
 
 CTYPE_EXTERN_INLINE const int32_t ** __attribute__ ((const))
 __ctype_tolower_loc (void)
 {
-  const int32_t **tablep =
-    (const int32_t **) __libc_tsd_address (CTYPE_TOLOWER);
-  if (__builtin_expect (*tablep == NULL, 0))
-    *tablep = ((int32_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_TOLOWER) + 128);
-  return tablep;
+  union {
+    const int32_t **t;
+    void **p;
+  } tablep;
+  tablep.p = __libc_tsd_address (CTYPE_TOLOWER);
+  if (__builtin_expect (*tablep.p == NULL, 0))
+    *tablep.t = ((int32_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_TOLOWER) + 128);
+  return tablep.t;
 }
 
 # endif	/* Not NOT_IN_libc.  */


More information about the Libc-alpha mailing list