This is the mail archive of the
mailing list for the glibc project.
[PATCH][BZ 17979][BZ 17721] Fix issues with sys/cdefs.h and uchar.h when using non-gcc compiler.
- From: "Dwight Guth" <dwight dot guth at runtimeverification dot com>
- To: libc-alpha at sourceware dot org
- Date: Thu, 28 Jan 2016 14:20:10 -0600
- Subject: [PATCH][BZ 17979][BZ 17721] Fix issues with sys/cdefs.h and uchar.h when using non-gcc compiler.
- Authentication-results: sourceware.org; auth=none
If linking against Glibc with a compiler for which the __GNUC__ macro is not
defined, problems arise when including header files that use the __restrict
or __inline keyword and when including uchar.h.
Glibc strips __restrict from the prototypes of C library functions in this
case. This is incorrect if the compiler is a C99-compliant compiler, because
C99 includes the restrict keyword and uses it in the declaration of a number
of functions in the C library. This leads to undefined behavior because
the definitions of those functions were defined with the restrict keyword,
which makes their type signatures incompatible with their declaration,
a violation of C99 sec. 6.2.7 paragraph 2. The same thing occurs with the
__inline keyword, which, while not undefined behavior per-se, seems
in cases where the compiler is C99-compliant and therefore includes the
inline keyword. Here we except the case where the compiler declares itself
to be C99-compliant from these checks in order to allow better C99 compliance
for compilers other than gcc which link against Glibc.
Glibc defines char16_t and char32_t in uchar.h as __CHAR16_TYPE__ and
__CHAR32_TYPE__ when the __GNUC__ macro is defined, but when linking against
Glibc with a different compiler, these types are not defined at all,
which is a violation of C11 sec. 7.28 paragraph 2, as well as a syntax
error because these types are used in the prototypes of functions declared
later in the file. According to this section of the standard, these types
must be defined in this header file and must be the same type as
uint_least16_t and uint_least32_t, which are defined in stdint.h as
"unsigned short int" and "unsigned int" respectively. Here we modify the
header so that if __GNUC__ is not defined, we still provide these typedefs,
but we default them manually to the same type as uint_least16_t and
uint_least32_t if __CHAR16_TYPE__ and __CHAR32_TYPE__ are not defined by
I had trouble testing this patch because I ran into unrelated errors in the
test suite. If someone could help me figure out how to set up a test
environment that is likely to pass all the tests, I can try again, but I
have the resources to struggle with all the errors that arise without knowing
their solutions. The patch should not affect any version of GCC, however.
2016-01-28 Dwight Guth <firstname.lastname@example.org>
* wcsmbs/uchar.h (char16_t, char32_t): Define types if __GNUC__,
__CHAR16_TYPE__, or __CHAR32_TYPE__ are not defined.
* misc/sys/cdefs.h (__restrict, __inline): Define as keywords if
__GNUC__ is not defined but __STDC_VERSION__ is at least C99.
diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h
index 7fd4154..af23ff7 100644
@@ -69,8 +69,11 @@
#else /* Not GCC. */
-# define __inline /* No inline functions. */
+# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
+# define __inline inline
+# define __inline /* No inline functions. */
# define __THROW
# define __THROWNL
# define __NTH(fct) fct
@@ -360,7 +363,11 @@
/* __restrict is known in EGCS 1.2 and above. */
#if !__GNUC_PREREQ (2,92)
-# define __restrict /* Ignore */
+# if !defined __GNUC__ && defined __STDC_VERSION__ && __STDC_VERSION__ >=
+# define __restrict restrict
+# define __restrict /* Ignore */
/* ISO C99 also allows to declare arrays as non-overlapping. The syntax is
diff --git a/wcsmbs/uchar.h b/wcsmbs/uchar.h
index ce92b25..1484e56 100644
@@ -39,14 +39,16 @@ __END_NAMESPACE_C99
-#if defined __GNUC__ && !defined __USE_ISOCXX11
+#if !defined __USE_ISOCXX11
/* Define the 16-bit and 32-bit character types. Use the information
provided by the compiler. */
# if !defined __CHAR16_TYPE__ || !defined __CHAR32_TYPE__
# if defined __STDC_VERSION__ && __STDC_VERSION__ < 201000L
# error "<uchar.h> requires ISO C11 mode"
-# error "definitions of __CHAR16_TYPE__ and/or __CHAR32_TYPE__ missing"
+/* Same as uint_least16_t and uint_least32_t in stdint.h. */
+typedef unsigned short int __CHAR16_TYPE__;
+typedef unsigned int __CHAR32_TYPE__;
typedef __CHAR16_TYPE__ char16_t;