public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [patch] Don't duplicate declarations between string.h and strings.h
@ 2016-11-16 20:55 Zack Weinberg
  2016-11-17  0:36 ` Zack Weinberg
  2016-11-21 17:17 ` Zack Weinberg
  0 siblings, 2 replies; 5+ messages in thread
From: Zack Weinberg @ 2016-11-16 20:55 UTC (permalink / raw)
  To: GNU C Library, Joseph Myers

I was looking into something else and noticed that all of the
declarations in strings.h are duplicated in string.h, but not quite
consistently.  This patch cleans that all up; strings.h is given
consistent declarations of everything, and then string.h just does

#ifdef __USE_MISC
# include <strings.h>
#endif

The prototype of __bzero is moved to include/string.h instead of
strings.h, since it is an internal name.

Tested on x86-64/linux. OK?

zw

	* string/string.h [__USE_MISC]: Include strings.h.
	(__bzero, bcmp, bcopy, bzero, index, rindex)
	(strcasecmp, strncasecmp, strcasecmp_l, strncasecmp_l)
	(ffs, ffsl, ffsll): Don't declare.

	* string/strings.h: Do not suppress the file if string.h has
	already been included.
	(bcmp, bcopy, bzero, strcasecmp, strncasecmp): Add __nonnull
	annotations.
	(index, rindex): Define inline forwarders even if
	__CORRECT_ISO_CPP_STRING_H_PROTO is defined.
	(ffs): Use __attribute_const__.
	(ffsl, ffsll): Declare here.
	(strcasecmp_l, strncasecmp_l): Correct comments; these functions
	have now been standardized.

	* include/string.h (__bzero): Declare here.

diff --git a/include/string.h b/include/string.h
index e145bfd..749e691 100644
--- a/include/string.h
+++ b/include/string.h
@@ -41,6 +41,8 @@ extern void *__memrchr (const void *__s, int __c,
size_t __n)
 extern void *__memchr (const void *__s, int __c, size_t __n)
      __attribute_pure__;

+extern void __bzero (void *__s, size_t __n) __THROW __nonnull ((1));
+
 extern int __ffs (int __i) __attribute__ ((const));

 extern char *__strerror_r (int __errnum, char *__buf, size_t __buflen);
diff --git a/string/string.h b/string/string.h
index b103e64..ca22cd0 100644
--- a/string/string.h
+++ b/string/string.h
@@ -440,110 +440,8 @@ extern char *strerror_r (int __errnum, char
*__buf, size_t __buflen)
 extern char *strerror_l (int __errnum, __locale_t __l) __THROW;
 #endif

-
-/* We define this function always since `bzero' is sometimes needed when
-   the namespace rules does not allow this.  */
-extern void __bzero (void *__s, size_t __n) __THROW __nonnull ((1));
-
 #ifdef __USE_MISC
-/* Copy N bytes of SRC to DEST (like memmove, but args reversed).  */
-extern void bcopy (const void *__src, void *__dest, size_t __n)
-     __THROW __nonnull ((1, 2));
-
-/* Set N bytes of S to 0.  */
-extern void bzero (void *__s, size_t __n) __THROW __nonnull ((1));
-
-/* Compare N bytes of S1 and S2 (same as memcmp).  */
-extern int bcmp (const void *__s1, const void *__s2, size_t __n)
-     __THROW __attribute_pure__ __nonnull ((1, 2));
-
-/* Find the first occurrence of C in S (same as strchr).  */
-# ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
-extern "C++"
-{
-extern char *index (char *__s, int __c)
-     __THROW __asm ("index") __attribute_pure__ __nonnull ((1));
-extern const char *index (const char *__s, int __c)
-     __THROW __asm ("index") __attribute_pure__ __nonnull ((1));
-
-#  if defined __OPTIMIZE__ && !defined __CORRECT_ISO_CPP_STRINGS_H_PROTO
-__extern_always_inline char *
-index (char *__s, int __c) __THROW
-{
-  return __builtin_index (__s, __c);
-}
-
-__extern_always_inline const char *
-index (const char *__s, int __c) __THROW
-{
-  return __builtin_index (__s, __c);
-}
-#  endif
-}
-# else
-extern char *index (const char *__s, int __c)
-     __THROW __attribute_pure__ __nonnull ((1));
-# endif
-
-/* Find the last occurrence of C in S (same as strrchr).  */
-# ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
-extern "C++"
-{
-extern char *rindex (char *__s, int __c)
-     __THROW __asm ("rindex") __attribute_pure__ __nonnull ((1));
-extern const char *rindex (const char *__s, int __c)
-     __THROW __asm ("rindex") __attribute_pure__ __nonnull ((1));
-
-#  if defined __OPTIMIZE__ && !defined __CORRECT_ISO_CPP_STRINGS_H_PROTO
-__extern_always_inline char *
-rindex (char *__s, int __c) __THROW
-{
-  return __builtin_rindex (__s, __c);
-}
-
-__extern_always_inline const char *
-rindex (const char *__s, int __c) __THROW
-{
-  return __builtin_rindex (__s, __c);
-}
-#endif
-}
-# else
-extern char *rindex (const char *__s, int __c)
-     __THROW __attribute_pure__ __nonnull ((1));
-# endif
-
-/* Return the position of the first bit set in I, or 0 if none are set.
-   The least-significant bit is position 1, the most-significant 32.  */
-extern int ffs (int __i) __THROW __attribute__ ((__const__));
-
-/* The following two functions are non-standard but necessary for
non-32 bit
-   platforms.  */
-# ifdef	__USE_GNU
-extern int ffsl (long int __l) __THROW __attribute__ ((__const__));
-__extension__ extern int ffsll (long long int __ll)
-     __THROW __attribute__ ((__const__));
-# endif
-
-/* Compare S1 and S2, ignoring case.  */
-extern int strcasecmp (const char *__s1, const char *__s2)
-     __THROW __attribute_pure__ __nonnull ((1, 2));
-
-/* Compare no more than N chars of S1 and S2, ignoring case.  */
-extern int strncasecmp (const char *__s1, const char *__s2, size_t __n)
-     __THROW __attribute_pure__ __nonnull ((1, 2));
-#endif /* Use misc.  */
-
-#ifdef	__USE_GNU
-/* Again versions of a few functions which use the given locale instead
-   of the global one.  */
-extern int strcasecmp_l (const char *__s1, const char *__s2,
-			 __locale_t __loc)
-     __THROW __attribute_pure__ __nonnull ((1, 2, 3));
-
-extern int strncasecmp_l (const char *__s1, const char *__s2,
-			  size_t __n, __locale_t __loc)
-     __THROW __attribute_pure__ __nonnull ((1, 2, 4));
+# include <strings.h>
 #endif

 #ifdef	__USE_MISC
diff --git a/string/strings.h b/string/strings.h
index e372a33..f78eca5 100644
--- a/string/strings.h
+++ b/string/strings.h
@@ -18,35 +18,31 @@
 #ifndef	_STRINGS_H
 #define	_STRINGS_H	1

-/* We don't need and should not read this file if <string.h> was already
-   read. The one exception being that if __USE_MISC isn't defined, then
-   these aren't defined in string.h, so we need to define them here.  */
-#if !defined _STRING_H || !defined __USE_MISC
-
-# include <features.h>
-# define __need_size_t
-# include <stddef.h>
+#include <features.h>
+#define __need_size_t
+#include <stddef.h>

 /* Tell the caller that we provide correct C++ prototypes.  */
-# if defined __cplusplus && __GNUC_PREREQ (4, 4)
-#  define __CORRECT_ISO_CPP_STRINGS_H_PROTO
-# endif
+#if defined __cplusplus && __GNUC_PREREQ (4, 4)
+# define __CORRECT_ISO_CPP_STRINGS_H_PROTO
+#endif

 __BEGIN_DECLS

-# if defined __USE_MISC || !defined __USE_XOPEN2K8
+#if defined __USE_MISC || !defined __USE_XOPEN2K8
 /* Compare N bytes of S1 and S2 (same as memcmp).  */
 extern int bcmp (const void *__s1, const void *__s2, size_t __n)
-     __THROW __attribute_pure__;
+     __THROW __attribute_pure__ __nonnull ((1, 2));

 /* Copy N bytes of SRC to DEST (like memmove, but args reversed).  */
-extern void bcopy (const void *__src, void *__dest, size_t __n) __THROW;
+extern void bcopy (const void *__src, void *__dest, size_t __n)
+  __THROW __nonnull ((1, 2));

 /* Set N bytes of S to 0.  */
-extern void bzero (void *__s, size_t __n) __THROW;
+extern void bzero (void *__s, size_t __n) __THROW __nonnull ((1));

 /* Find the first occurrence of C in S (same as strchr).  */
-#  ifdef __CORRECT_ISO_CPP_STRINGS_H_PROTO
+# ifdef __CORRECT_ISO_CPP_STRINGS_H_PROTO
 extern "C++"
 {
 extern char *index (char *__s, int __c)
@@ -54,7 +50,7 @@ extern char *index (char *__s, int __c)
 extern const char *index (const char *__s, int __c)
      __THROW __asm ("index") __attribute_pure__ __nonnull ((1));

-#   if defined __OPTIMIZE__ && !defined __CORRECT_ISO_CPP_STRING_H_PROTO
+#  if defined __OPTIMIZE__
 __extern_always_inline char *
 index (char *__s, int __c) __THROW
 {
@@ -66,15 +62,15 @@ index (const char *__s, int __c) __THROW
 {
   return __builtin_index (__s, __c);
 }
-#   endif
+#  endif
 }
-#  else
+# else
 extern char *index (const char *__s, int __c)
      __THROW __attribute_pure__ __nonnull ((1));
-#  endif
+# endif

 /* Find the last occurrence of C in S (same as strrchr).  */
-#  ifdef __CORRECT_ISO_CPP_STRINGS_H_PROTO
+# ifdef __CORRECT_ISO_CPP_STRINGS_H_PROTO
 extern "C++"
 {
 extern char *rindex (char *__s, int __c)
@@ -82,7 +78,7 @@ extern char *rindex (char *__s, int __c)
 extern const char *rindex (const char *__s, int __c)
      __THROW __asm ("rindex") __attribute_pure__ __nonnull ((1));

-#   if defined __OPTIMIZE__ && !defined __CORRECT_ISO_CPP_STRING_H_PROTO
+#  if defined __OPTIMIZE__
 __extern_always_inline char *
 rindex (char *__s, int __c) __THROW
 {
@@ -94,39 +90,45 @@ rindex (const char *__s, int __c) __THROW
 {
   return __builtin_rindex (__s, __c);
 }
-#   endif
+#  endif
 }
-#  else
+# else
 extern char *rindex (const char *__s, int __c)
      __THROW __attribute_pure__ __nonnull ((1));
-#  endif
 # endif
+#endif

 #if defined __USE_MISC || !defined __USE_XOPEN2K8 || defined
__USE_XOPEN2K8XSI
 /* Return the position of the first bit set in I, or 0 if none are set.
    The least-significant bit is position 1, the most-significant 32.  */
-extern int ffs (int __i) __THROW __attribute__ ((const));
+extern int ffs (int __i) __THROW __attribute_const__;
 #endif

+/* The following two functions are non-standard but necessary for
non-32 bit
+   platforms.  */
+# ifdef	__USE_GNU
+extern int ffsl (long int __l) __THROW __attribute_const__;
+__extension__ extern int ffsll (long long int __ll)
+     __THROW __attribute_const__;
+# endif
+
 /* Compare S1 and S2, ignoring case.  */
 extern int strcasecmp (const char *__s1, const char *__s2)
-     __THROW __attribute_pure__;
+     __THROW __attribute_pure__ __nonnull ((1, 2));

 /* Compare no more than N chars of S1 and S2, ignoring case.  */
 extern int strncasecmp (const char *__s1, const char *__s2, size_t __n)
-     __THROW __attribute_pure__;
+     __THROW __attribute_pure__ __nonnull ((1, 2));

 #ifdef	__USE_XOPEN2K8
-/* The following functions are equivalent to the both above but they
-   take the locale they use for the collation as an extra argument.
-   This is not standardsized but something like will come.  */
 # include <xlocale.h>

-/* Again versions of a few functions which use the given locale instead
-   of the global one.  */
+/* Compare S1 and S2, ignoring case, using collation rules from LOC.  */
 extern int strcasecmp_l (const char *__s1, const char *__s2, __locale_t
__loc)
      __THROW __attribute_pure__ __nonnull ((1, 2, 3));

+/* Compare no more than N chars of S1 and S2, ignoring case, using
+   collation rules from LOC.  */
 extern int strncasecmp_l (const char *__s1, const char *__s2,
 			  size_t __n, __locale_t __loc)
      __THROW __attribute_pure__ __nonnull ((1, 2, 4));
@@ -134,6 +136,4 @@ extern int strncasecmp_l (const char *__s1, const
char *__s2,

 __END_DECLS

-#endif	/* string.h  */
-
 #endif	/* strings.h  */

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [patch] Don't duplicate declarations between string.h and strings.h
  2016-11-16 20:55 [patch] Don't duplicate declarations between string.h and strings.h Zack Weinberg
@ 2016-11-17  0:36 ` Zack Weinberg
  2016-11-17  1:03   ` Joseph Myers
  2016-11-21 17:17 ` Zack Weinberg
  1 sibling, 1 reply; 5+ messages in thread
From: Zack Weinberg @ 2016-11-17  0:36 UTC (permalink / raw)
  To: GNU C Library, Joseph Myers

On 11/16/2016 03:55 PM, Zack Weinberg wrote:
> I was looking into something else and noticed that all of the
> declarations in strings.h are duplicated in string.h, but not quite
> consistently.  This patch cleans that all up

And as a follow-on, here is a patch that makes declaring const-covariant
string functions much tidier.  The macros involved are messy, but I
think the reduced duplication in the public header file is worth it.

zw

commit d076c75978afa4b22f1827503c197f90c309586a
Author: Zack Weinberg <zackw@panix.com>
Date:   Wed Nov 16 18:34:27 2016 -0500

    New mechanism for declaring const-covariant string functions.

    Several functions in string.h and strings.h return a pointer into a
    buffer passed as their first argument.  That pointer logically ought
    to inherit the 'const'-ness of the original buffer.  There's no way to
    express that in C, so all these functions are specified with a
    prototype that, as a side-effect, strips the 'const', potentially
    leading to bugs:

        char *strfoo(const char *buf, ...);

    In C++, however, you can get it exactly right via function overloads:

        char *strfoo(char *buf, ...);
        const char *strfoo(const char *buf, ...);

    and C++11 (21.7 [c.strings]) requires the library to do just that.
    We were implementing this requirement via a repetitive and error-prone
    mess of #ifdefs for each and every one of the affected functions.

    This patch absorbs the entire mess into a pair of macros,
    __CONST_COV_PROTO and __CONST_COV_BUILTIN, which are far less
    error-prone to use, and which make the public header file much nicer
    to read, too.  They needed some black magic to _implement_, but it's
    hiding in a bits header and hopefully nobody need ever change that
    file again.

            * string/bits/const-covariance.h: New file.
            * string/string.h: Use __CONST_COV_PROTO and
__CONST_COV_BUILTIN to
            declare memchr, rawmemchr, memrchr, strchr, strrchr, strchrnul,
            strpbrk, strstr, strcasestr, memmem, and basename.
            * string/strings.h: Likewise for index and rindex.

            * include/bits/const-covariance.h: New wrapper.
            * include/string.h: Suppress internal definitions when
__cplusplus
            is defined, as well as when _ISOMAC is defined.

diff --git a/ChangeLog b/ChangeLog
index 4a5dc8a..18f8296 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
 2016-11-16  Zack Weinberg  <zackw@panix.com>

+	* string/bits/const-covariance.h: New file.
+	* string/string.h: Use __CONST_COV_PROTO and __CONST_COV_BUILTIN to
+	declare memchr, rawmemchr, memrchr, strchr, strrchr, strchrnul,
+	strpbrk, strstr, strcasestr, memmem, and basename.
+	* string/strings.h: Likewise for index and rindex.
+
+	* include/bits/const-covariance.h: New wrapper.
+	* include/string.h: Suppress internal definitions when __cplusplus
+	is defined, as well as when _ISOMAC is defined.
+
+2016-11-16  Zack Weinberg  <zackw@panix.com>
+
 	* string/string.h [__USE_MISC]: Include strings.h.
 	(__bzero, bcmp, bcopy, bzero, index, rindex)
 	(strcasecmp, strncasecmp, strcasecmp_l, strncasecmp_l)
diff --git a/include/bits/const-covariance.h
b/include/bits/const-covariance.h
new file mode 100644
index 0000000..564d730
--- /dev/null
+++ b/include/bits/const-covariance.h
@@ -0,0 +1 @@
+#include <string/bits/const-covariance.h>
diff --git a/include/string.h b/include/string.h
index 749e691..4c029cf 100644
--- a/include/string.h
+++ b/include/string.h
@@ -1,6 +1,6 @@
 #ifndef _STRING_H

-#ifndef _ISOMAC
+#if !defined _ISOMAC && !defined __cplusplus
 #include <sys/types.h>

 extern void *__memccpy (void *__dest, const void *__src,
@@ -46,16 +46,16 @@ extern void __bzero (void *__s, size_t __n) __THROW
__nonnull ((1));
 extern int __ffs (int __i) __attribute__ ((const));

 extern char *__strerror_r (int __errnum, char *__buf, size_t __buflen);
-#endif

 /* Get _STRING_ARCH_unaligned.  */
 #include <string_private.h>
+#endif /* !_ISOMAC && !__cplusplus */

 /* Now the real definitions.  We do this here since some of the functions
    above are defined as macros in the headers.  */
 #include <string/string.h>

-#ifndef _ISOMAC
+#if !defined _ISOMAC && !defined __cplusplus
 extern __typeof (strcoll_l) __strcoll_l;
 extern __typeof (strxfrm_l) __strxfrm_l;
 extern __typeof (strcasecmp_l) __strcasecmp_l;
@@ -151,13 +151,11 @@ extern __typeof (mempcpy) mempcpy __asm__
("__mempcpy");
 extern __typeof (stpcpy) stpcpy __asm__ ("__stpcpy");
 #endif

-# ifndef _ISOMAC
-#  ifndef index
-#   define index(s, c)	(strchr ((s), (c)))
-#  endif
-#  ifndef rindex
-#   define rindex(s, c)	(strrchr ((s), (c)))
-#  endif
+# ifndef index
+#  define index(s, c)	(strchr ((s), (c)))
+# endif
+# ifndef rindex
+#  define rindex(s, c)	(strrchr ((s), (c)))
 # endif

 extern void *__memcpy_chk (void *__restrict __dest,
@@ -185,6 +183,6 @@ extern char *__strcat_chk (char *__restrict __dest,
 extern char *__strncat_chk (char *__restrict __dest,
 			    const char *__restrict __src,
 			    size_t __len, size_t __destlen) __THROW;
-#endif
+#endif /* !_ISOMAC && !__cplusplus */

 #endif
diff --git a/string/Makefile b/string/Makefile
index 69d3f80..c009872 100644
--- a/string/Makefile
+++ b/string/Makefile
@@ -24,7 +24,8 @@ include ../Makeconfig

 headers	:= string.h strings.h memory.h endian.h bits/endian.h \
 	   argz.h envz.h byteswap.h bits/byteswap.h bits/byteswap-16.h \
-	   bits/string.h bits/string2.h bits/string3.h
+	   bits/string.h bits/string2.h bits/string3.h \
+	   bits/const-covariance.h

 routines	:= strcat strchr strcmp strcoll strcpy strcspn		\
 		   strverscmp strdup strndup				\
diff --git a/string/bits/const-covariance.h b/string/bits/const-covariance.h
new file mode 100644
index 0000000..19b3e31
--- /dev/null
+++ b/string/bits/const-covariance.h
@@ -0,0 +1,130 @@
+/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _BITS_CONST_COVARIANCE_H
+#define _BITS_CONST_COVARIANCE_H 1
+
+#if !defined _STRING_H && !defined _STRINGS_H
+# error "Never use <bits/const-covariance.h> directly; include
<string.h> or <strings.h> instead."
+#endif
+
+/* This header defines internal-use macros that expand a C prototype
+   declaration like
+
+       extern void *memchr (const void *, int, size_t) attrs;
+
+   to a pair of C++ overloaded function declarations with improved
+   const-correctness:
+
+       extern void *memchr (void *, int, size_t) attrs;
+       extern const void *memchr (const void *, int, size_t) attrs;
+
+   You use them like this:
+
+       __CONST_COV_PROTO (memchr, attrs,
+                          void *, __s, int, __c, size_t, __n);
+
+    where the arguments after 'attrs' are the function's arguments,
+    alternating with argument names.  The first of these will be used
+    as the const-covariant return type.  It should be written without
+    a 'const' qualifier.
+
+    If the compiler has intrinsic knowledge of the function, use
+    __CONST_COV_BUILTIN instead of __CONST_COV_PROTO.  In C++ mode,
+    this will also generate inline functions of the form
+
+        __extern_always_inline [const] void *
+        memchr (void *__s, int __c, size_t __n) attrs
+        {
+          return __builtin_memchr (__s, __c, __n);
+        }
+
+    Due to limitations in the preprocessor, these macros support no
+    more than four arguments to any function.  This is all that
+    string.h/strings.h currently require.
+
+    Because g++ only accepts throw(), __asm("..."), and
+    __attribute__((whatever)) annotations in a specific order, all
+    functions declared with __CONST_COV_PROTO or defined with
+    __CONST_COV_BUILTIN are automatically marked __THROW.  Do not put
+    __THROW in 'attrs'.  */
+
+#define __CC_VA_NARGS(...)  __CC_VA_NARGS_(__VA_ARGS__, __CC_RSEQ)
+#define __CC_VA_NARGS_(...) __CC_VA_NARGS__(__VA_ARGS__)
+#define __CC_VA_NARGS__(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N
+#define __CC_RSEQ 8, 7, 6, 5, 4, 3, 2, 1
+
+#define __CC_2FOR2(op, a, b)	  op (a, b)
+#define __CC_2FOR4(op, a, b, ...) op (a, b), __CC_2FOR2 (op, __VA_ARGS__)
+#define __CC_2FOR6(op, a, b, ...) op (a, b), __CC_2FOR4 (op, __VA_ARGS__)
+#define __CC_2FOR8(op, a, b, ...) op (a, b), __CC_2FOR6 (op, __VA_ARGS__)
+
+#define __CC_2FOR(op, ...) \
+ __CC_2FOR_ (__CC_VA_NARGS (__VA_ARGS__)) (op, __VA_ARGS__)
+#define __CC_2FOR_(n) __CC_2FOR__ (n)
+#define __CC_2FOR__(n) __CC_2FOR##n
+
+#define __CC_XPROTO(...) (__CC_2FOR (__CC_XPROTO_, __VA_ARGS__))
+#define __CC_XPROTO_(type, name) type name
+
+#define __CC_XCALL(...) (__CC_2FOR (__CC_XCALL_, __VA_ARGS__))
+#define __CC_XCALL_(type, name) name
+
+#if !defined __cplusplus || !__GNUC_PREREQ (4, 4)
+
+# define __CONST_COV_PROTO(name, attrs, rtype, ...)			\
+   extern rtype name __CC_XPROTO(const rtype, __VA_ARGS__) __THROW attrs
+
+# define __CONST_COV_BUILTIN(...) __CONST_COV_PROTO (__VA_ARGS__)
+
+#else
+
+# define __CONST_COV_PROTO_BODY(name, attrs, rtype, ...)		\
+  extern rtype name __CC_XPROTO(rtype, __VA_ARGS__)			\
+    __THROW __asm (#name) attrs;					\
+  extern const rtype name __CC_XPROTO(const rtype, __VA_ARGS__)		\
+    __THROW __asm (#name) attrs;
+
+# define __CONST_COV_PROTO(...)						\
+   extern "C++"								\
+   {									\
+     __CONST_COV_PROTO_BODY(__VA_ARGS__)				\
+   }									\
+   struct __require_semicolon
+
+# ifndef __OPTIMIZE__
+#  define __CONST_COV_BUILTIN(...) __CONST_COV_PROTO (__VA_ARGS__)
+
+# else
+
+#  define __CONST_COV_BUILTIN(name, attrs, rtype, ...)			\
+  extern "C++"								\
+  {									\
+    __CONST_COV_PROTO_BODY (name, attrs, rtype, __VA_ARGS__)		\
+    __extern_always_inline rtype					\
+    name __CC_XPROTO (rtype, __VA_ARGS__) __THROW			\
+    { return __builtin_##name __CC_XCALL (rtype, __VA_ARGS__); }	\
+    __extern_always_inline const rtype					\
+    name __CC_XPROTO (const rtype, __VA_ARGS__) __THROW			\
+    { return __builtin_##name __CC_XCALL (rtype, __VA_ARGS__); }	\
+  }									\
+  struct __require_semicolon
+
+# endif /* __OPTIMIZE__ */
+#endif /* C++ and GCC >=4.4 */
+
+#endif /* const-covariance.h */
diff --git a/string/string.h b/string/string.h
index ca22cd0..601025b 100644
--- a/string/string.h
+++ b/string/string.h
@@ -36,7 +36,7 @@ __BEGIN_DECLS
 #if defined __cplusplus && __GNUC_PREREQ (4, 4)
 # define __CORRECT_ISO_CPP_STRING_H_PROTO
 #endif
-
+#include <bits/const-covariance.h>

 __BEGIN_NAMESPACE_STD
 /* Copy N bytes of SRC to DEST.  */
@@ -66,61 +66,31 @@ extern void *memset (void *__s, int __c, size_t __n)
__THROW __nonnull ((1));
 extern int memcmp (const void *__s1, const void *__s2, size_t __n)
      __THROW __attribute_pure__ __nonnull ((1, 2));

-/* Search N bytes of S for C.  */
-#ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
-extern "C++"
-{
-extern void *memchr (void *__s, int __c, size_t __n)
-      __THROW __asm ("memchr") __attribute_pure__ __nonnull ((1));
-extern const void *memchr (const void *__s, int __c, size_t __n)
-      __THROW __asm ("memchr") __attribute_pure__ __nonnull ((1));
-
-# ifdef __OPTIMIZE__
-__extern_always_inline void *
-memchr (void *__s, int __c, size_t __n) __THROW
-{
-  return __builtin_memchr (__s, __c, __n);
-}
-
-__extern_always_inline const void *
-memchr (const void *__s, int __c, size_t __n) __THROW
-{
-  return __builtin_memchr (__s, __c, __n);
-}
-# endif
-}
-#else
-extern void *memchr (const void *__s, int __c, size_t __n)
-      __THROW __attribute_pure__ __nonnull ((1));
-#endif
+/* Search N bytes of S for C.
+   [C]    extern void *memchr (const void *s, int c, size_t n);
+   [C++]  extern void *memchr (void *s, int c, size_t n);
+          extern const void *memchr (const void *s, int c, size_t n);  */
+__CONST_COV_BUILTIN (memchr, __attribute_pure__ __nonnull ((1)),
+                     void *, __s, int, __c, size_t, __n);
 __END_NAMESPACE_STD

 #ifdef __USE_GNU
-/* Search in S for C.  This is similar to `memchr' but there is no
-   length limit.  */
-# ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
-extern "C++" void *rawmemchr (void *__s, int __c)
-     __THROW __asm ("rawmemchr") __attribute_pure__ __nonnull ((1));
-extern "C++" const void *rawmemchr (const void *__s, int __c)
-     __THROW __asm ("rawmemchr") __attribute_pure__ __nonnull ((1));
-# else
-extern void *rawmemchr (const void *__s, int __c)
-     __THROW __attribute_pure__ __nonnull ((1));
-# endif
+/* Search in S for C.  This is similar to 'memchr' but there is no
+   length limit.
+   [C]    extern void *rawmemchr (const void *s, int c);
+   [C++]  extern void *rawmemchr (void *s, int c);
+          extern const void *rawmemchr (const void *s, int c);  */
+__CONST_COV_PROTO (rawmemchr, __attribute_pure__ __nonnull ((1)),
+                   void *, __s, int, __c);

-/* Search N bytes of S for the final occurrence of C.  */
-# ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
-extern "C++" void *memrchr (void *__s, int __c, size_t __n)
-      __THROW __asm ("memrchr") __attribute_pure__ __nonnull ((1));
-extern "C++" const void *memrchr (const void *__s, int __c, size_t __n)
-      __THROW __asm ("memrchr") __attribute_pure__ __nonnull ((1));
-# else
-extern void *memrchr (const void *__s, int __c, size_t __n)
-      __THROW __attribute_pure__ __nonnull ((1));
-# endif
+/* Search N bytes of S for the final occurrence of C.
+   [C]    extern void *memrchr (const void *s, int c, size_t n);
+   [C++]  extern void *memrchr (void *s, int c, size_t n);
+          extern const void *memrchr (const void *s, int c, size_t n);  */
+__CONST_COV_PROTO (memrchr, __attribute_pure__ __nonnull ((1)),
+                   void *, __s, int, __c, size_t, __n);
 #endif

-
 __BEGIN_NAMESPACE_STD
 /* Copy SRC to DEST.  */
 extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
@@ -204,74 +174,30 @@ extern char *strndup (const char *__string, size_t
__n)
 #endif

 __BEGIN_NAMESPACE_STD
-/* Find the first occurrence of C in S.  */
-#ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
-extern "C++"
-{
-extern char *strchr (char *__s, int __c)
-     __THROW __asm ("strchr") __attribute_pure__ __nonnull ((1));
-extern const char *strchr (const char *__s, int __c)
-     __THROW __asm ("strchr") __attribute_pure__ __nonnull ((1));
+/* Find the first occurrence of C in S.
+   [C]    extern char *strchr (const char *s, int c);
+   [C++]  extern char *strchr (char *s, int c);
+          extern const char *strchr (const char *s, int c);  */
+__CONST_COV_BUILTIN (strchr, __attribute_pure__ __nonnull ((1)),
+                   char *, __s, int, __c);

-# ifdef __OPTIMIZE__
-__extern_always_inline char *
-strchr (char *__s, int __c) __THROW
-{
-  return __builtin_strchr (__s, __c);
-}
+/* Find the last occurrence of C in S.
+   [C]    extern char *strrchr (const char *s, int c);
+   [C++]  extern char *strrchr (char *s, int c);
+          extern const char *strrchr (const char *s, int c);  */
+__CONST_COV_BUILTIN (strrchr, __attribute_pure__ __nonnull ((1)),
+                     char *, __s, int, __c);

-__extern_always_inline const char *
-strchr (const char *__s, int __c) __THROW
-{
-  return __builtin_strchr (__s, __c);
-}
-# endif
-}
-#else
-extern char *strchr (const char *__s, int __c)
-     __THROW __attribute_pure__ __nonnull ((1));
-#endif
-/* Find the last occurrence of C in S.  */
-#ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
-extern "C++"
-{
-extern char *strrchr (char *__s, int __c)
-     __THROW __asm ("strrchr") __attribute_pure__ __nonnull ((1));
-extern const char *strrchr (const char *__s, int __c)
-     __THROW __asm ("strrchr") __attribute_pure__ __nonnull ((1));
-
-# ifdef __OPTIMIZE__
-__extern_always_inline char *
-strrchr (char *__s, int __c) __THROW
-{
-  return __builtin_strrchr (__s, __c);
-}
-
-__extern_always_inline const char *
-strrchr (const char *__s, int __c) __THROW
-{
-  return __builtin_strrchr (__s, __c);
-}
-# endif
-}
-#else
-extern char *strrchr (const char *__s, int __c)
-     __THROW __attribute_pure__ __nonnull ((1));
-#endif
 __END_NAMESPACE_STD

 #ifdef __USE_GNU
 /* This function is similar to `strchr'.  But it returns a pointer to
-   the closing NUL byte in case C is not found in S.  */
-# ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
-extern "C++" char *strchrnul (char *__s, int __c)
-     __THROW __asm ("strchrnul") __attribute_pure__ __nonnull ((1));
-extern "C++" const char *strchrnul (const char *__s, int __c)
-     __THROW __asm ("strchrnul") __attribute_pure__ __nonnull ((1));
-# else
-extern char *strchrnul (const char *__s, int __c)
-     __THROW __attribute_pure__ __nonnull ((1));
-# endif
+   the closing NUL byte in case C is not found in S.
+   [C]    extern char *strchrnul (const char *s, int c);
+   [C++]  extern char *strchrnul (char *s, int c);
+          extern const char *strchrnul (const char *s, int c);  */
+__CONST_COV_PROTO (strchrnul, __attribute_pure__ __nonnull ((1)),
+                   char *, __s, int, __c);
 #endif

 __BEGIN_NAMESPACE_STD
@@ -279,65 +205,26 @@ __BEGIN_NAMESPACE_STD
    consists entirely of characters not in REJECT.  */
 extern size_t strcspn (const char *__s, const char *__reject)
      __THROW __attribute_pure__ __nonnull ((1, 2));
+
 /* Return the length of the initial segment of S which
    consists entirely of characters in ACCEPT.  */
 extern size_t strspn (const char *__s, const char *__accept)
      __THROW __attribute_pure__ __nonnull ((1, 2));
-/* Find the first occurrence in S of any character in ACCEPT.  */
-#ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
-extern "C++"
-{
-extern char *strpbrk (char *__s, const char *__accept)
-     __THROW __asm ("strpbrk") __attribute_pure__ __nonnull ((1, 2));
-extern const char *strpbrk (const char *__s, const char *__accept)
-     __THROW __asm ("strpbrk") __attribute_pure__ __nonnull ((1, 2));

-# ifdef __OPTIMIZE__
-__extern_always_inline char *
-strpbrk (char *__s, const char *__accept) __THROW
-{
-  return __builtin_strpbrk (__s, __accept);
-}
-
-__extern_always_inline const char *
-strpbrk (const char *__s, const char *__accept) __THROW
-{
-  return __builtin_strpbrk (__s, __accept);
-}
-# endif
-}
-#else
-extern char *strpbrk (const char *__s, const char *__accept)
-     __THROW __attribute_pure__ __nonnull ((1, 2));
-#endif
-/* Find the first occurrence of NEEDLE in HAYSTACK.  */
-#ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
-extern "C++"
-{
-extern char *strstr (char *__haystack, const char *__needle)
-     __THROW __asm ("strstr") __attribute_pure__ __nonnull ((1, 2));
-extern const char *strstr (const char *__haystack, const char *__needle)
-     __THROW __asm ("strstr") __attribute_pure__ __nonnull ((1, 2));
-
-# ifdef __OPTIMIZE__
-__extern_always_inline char *
-strstr (char *__haystack, const char *__needle) __THROW
-{
-  return __builtin_strstr (__haystack, __needle);
-}
-
-__extern_always_inline const char *
-strstr (const char *__haystack, const char *__needle) __THROW
-{
-  return __builtin_strstr (__haystack, __needle);
-}
-# endif
-}
-#else
-extern char *strstr (const char *__haystack, const char *__needle)
-     __THROW __attribute_pure__ __nonnull ((1, 2));
-#endif
+/* Find the first occurrence in S of any character in ACCEPT.
+   [C]   extern char *strpbrk (const char *s, const char *accept);
+   [C++] extern char *strpbrk (char *s, const char *accept);
+         extern const char *strpbrk (const char *s, const char *accept); */
+__CONST_COV_BUILTIN (strpbrk, __attribute_pure__ __nonnull ((1, 2)),
+                     char *, __s, const char *, __accept);

+/* Find the first occurrence of NEEDLE in HAYSTACK.
+   [C]   extern char *strstr (const char *haystack, const char *needle);
+   [C++] extern char *strstr (char *haystack, const char *needle);
+         extern const char *strstr (const char *haystack, const char
*needle);
+ */
+__CONST_COV_BUILTIN (strstr, __attribute_pure__ __nonnull ((1, 2)),
+                     char *, __haystack, const char *, __needle);

 /* Divide S into tokens separated by characters in DELIM.  */
 extern char *strtok (char *__restrict __s, const char *__restrict __delim)
@@ -357,26 +244,26 @@ extern char *strtok_r (char *__restrict __s, const
char *__restrict __delim,
 #endif

 #ifdef __USE_GNU
-/* Similar to `strstr' but this function ignores the case of both
strings.  */
-# ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
-extern "C++" char *strcasestr (char *__haystack, const char *__needle)
-     __THROW __asm ("strcasestr") __attribute_pure__ __nonnull ((1, 2));
-extern "C++" const char *strcasestr (const char *__haystack,
-				     const char *__needle)
-     __THROW __asm ("strcasestr") __attribute_pure__ __nonnull ((1, 2));
-# else
-extern char *strcasestr (const char *__haystack, const char *__needle)
-     __THROW __attribute_pure__ __nonnull ((1, 2));
-# endif
-#endif
+/* Similar to 'strstr', but ignores the case of both strings.
+   [C]   extern char *strcasestr (const char *haystack, const char
*needle);
+   [C++] extern char *strcasestr (char *haystack, const char *needle);
+         extern const char *strcasestr (const char *haystack,
+                                        const char *needle);  */
+__CONST_COV_PROTO (strcasestr, __attribute_pure__ __nonnull ((1, 2)),
+                   char *, __haystack, const char *, __needle);

-#ifdef __USE_GNU
 /* Find the first occurrence of NEEDLE in HAYSTACK.
    NEEDLE is NEEDLELEN bytes long;
-   HAYSTACK is HAYSTACKLEN bytes long.  */
-extern void *memmem (const void *__haystack, size_t __haystacklen,
-		     const void *__needle, size_t __needlelen)
-     __THROW __attribute_pure__ __nonnull ((1, 3));
+   HAYSTACK is HAYSTACKLEN bytes long.
+   [C]   extern void *memmem (const void *haystack, size_t haystacklen,
+                              const void *needle, size_t needlelen);
+   [C++] extern void *memmem (void *haystack, size_t haystacklen,
+                              const void *needle, size_t needlelen);
+         extern const void *memmem (const void *haystack, size_t
haystacklen,
+                                    const void *needle, size_t
needlelen);  */
+__CONST_COV_PROTO (memmem, __attribute_pure__ __nonnull ((1, 3)),
+                   void *, __haystack, size_t, __haystacklen,
+                   const void *, __needle, size_t, __needlelen);

 /* Copy N bytes of SRC to DEST, return pointer to bytes after the
    last written byte.  */
@@ -487,15 +374,12 @@ extern void *memfrob (void *__s, size_t __n)
__THROW __nonnull ((1));
 /* Return the file name within directory of FILENAME.  We don't
    declare the function if the `basename' macro is available (defined
    in <libgen.h>) which makes the XPG version of this function
-   available.  */
-#  ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
-extern "C++" char *basename (char *__filename)
-     __THROW __asm ("basename") __nonnull ((1));
-extern "C++" const char *basename (const char *__filename)
-     __THROW __asm ("basename") __nonnull ((1));
-#  else
-extern char *basename (const char *__filename) __THROW __nonnull ((1));
-#  endif
+   available.
+   [C]   char *basename (const char *filename);
+   [C++] char *basename (char *filename);
+         const char *basename (const char *filename);  */
+__CONST_COV_PROTO (basename, __nonnull ((1)),
+                   char *, __filename);
 # endif
 #endif

diff --git a/string/strings.h b/string/strings.h
index f78eca5..a72530a 100644
--- a/string/strings.h
+++ b/string/strings.h
@@ -26,6 +26,7 @@
 #if defined __cplusplus && __GNUC_PREREQ (4, 4)
 # define __CORRECT_ISO_CPP_STRINGS_H_PROTO
 #endif
+#include <bits/const-covariance.h>

 __BEGIN_DECLS

@@ -41,61 +42,19 @@ extern void bcopy (const void *__src, void *__dest,
size_t __n)
 /* Set N bytes of S to 0.  */
 extern void bzero (void *__s, size_t __n) __THROW __nonnull ((1));

-/* Find the first occurrence of C in S (same as strchr).  */
-# ifdef __CORRECT_ISO_CPP_STRINGS_H_PROTO
-extern "C++"
-{
-extern char *index (char *__s, int __c)
-     __THROW __asm ("index") __attribute_pure__ __nonnull ((1));
-extern const char *index (const char *__s, int __c)
-     __THROW __asm ("index") __attribute_pure__ __nonnull ((1));
+/* Find the first occurrence of C in S (same as strchr).
+   [C]    extern char *index (const char *s, int c);
+   [C++]  extern char *index (char *s, int c);
+          extern const char *index (const char *s, int c);  */
+__CONST_COV_BUILTIN (index, __attribute_pure__ __nonnull ((1)),
+                     char *, __s, int, __c);

-#  if defined __OPTIMIZE__
-__extern_always_inline char *
-index (char *__s, int __c) __THROW
-{
-  return __builtin_index (__s, __c);
-}
-
-__extern_always_inline const char *
-index (const char *__s, int __c) __THROW
-{
-  return __builtin_index (__s, __c);
-}
-#  endif
-}
-# else
-extern char *index (const char *__s, int __c)
-     __THROW __attribute_pure__ __nonnull ((1));
-# endif
-
-/* Find the last occurrence of C in S (same as strrchr).  */
-# ifdef __CORRECT_ISO_CPP_STRINGS_H_PROTO
-extern "C++"
-{
-extern char *rindex (char *__s, int __c)
-     __THROW __asm ("rindex") __attribute_pure__ __nonnull ((1));
-extern const char *rindex (const char *__s, int __c)
-     __THROW __asm ("rindex") __attribute_pure__ __nonnull ((1));
-
-#  if defined __OPTIMIZE__
-__extern_always_inline char *
-rindex (char *__s, int __c) __THROW
-{
-  return __builtin_rindex (__s, __c);
-}
-
-__extern_always_inline const char *
-rindex (const char *__s, int __c) __THROW
-{
-  return __builtin_rindex (__s, __c);
-}
-#  endif
-}
-# else
-extern char *rindex (const char *__s, int __c)
-     __THROW __attribute_pure__ __nonnull ((1));
-# endif
+/* Find the last occurrence of C in S (same as strrchr).
+   [C]    extern char *rindex (const char *s, int c);
+   [C++]  extern char *rindex (char *s, int c);
+          extern const char *rindex (const char *s, int c);  */
+__CONST_COV_BUILTIN (rindex, __attribute_pure__ __nonnull ((1)),
+                     char *, __s, int, __c);
 #endif

 #if defined __USE_MISC || !defined __USE_XOPEN2K8 || defined
__USE_XOPEN2K8XSI
@@ -106,11 +65,11 @@ extern int ffs (int __i) __THROW __attribute_const__;

 /* The following two functions are non-standard but necessary for
non-32 bit
    platforms.  */
-# ifdef	__USE_GNU
+#ifdef	__USE_GNU
 extern int ffsl (long int __l) __THROW __attribute_const__;
 __extension__ extern int ffsll (long long int __ll)
      __THROW __attribute_const__;
-# endif
+#endif

 /* Compare S1 and S2, ignoring case.  */
 extern int strcasecmp (const char *__s1, const char *__s2)


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [patch] Don't duplicate declarations between string.h and strings.h
  2016-11-17  0:36 ` Zack Weinberg
@ 2016-11-17  1:03   ` Joseph Myers
  2016-11-17  3:18     ` Zack Weinberg
  0 siblings, 1 reply; 5+ messages in thread
From: Joseph Myers @ 2016-11-17  1:03 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: GNU C Library

On Wed, 16 Nov 2016, Zack Weinberg wrote:

> On 11/16/2016 03:55 PM, Zack Weinberg wrote:
> > I was looking into something else and noticed that all of the
> > declarations in strings.h are duplicated in string.h, but not quite
> > consistently.  This patch cleans that all up
> 
> And as a follow-on, here is a patch that makes declaring const-covariant
> string functions much tidier.  The macros involved are messy, but I
> think the reduced duplication in the public header file is worth it.

const-covariance applies equally to wchar.h.  Have you designed the macros 
to be usable there as well?

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [patch] Don't duplicate declarations between string.h and strings.h
  2016-11-17  1:03   ` Joseph Myers
@ 2016-11-17  3:18     ` Zack Weinberg
  0 siblings, 0 replies; 5+ messages in thread
From: Zack Weinberg @ 2016-11-17  3:18 UTC (permalink / raw)
  To: Joseph Myers; +Cc: GNU C Library

On 11/16/2016 08:02 PM, Joseph Myers wrote:
> On Wed, 16 Nov 2016, Zack Weinberg wrote:
> 
>> On 11/16/2016 03:55 PM, Zack Weinberg wrote:
>>> I was looking into something else and noticed that all of the
>>> declarations in strings.h are duplicated in string.h, but not quite
>>> consistently.  This patch cleans that all up
>>
>> And as a follow-on, here is a patch that makes declaring const-covariant
>> string functions much tidier.  The macros involved are messy, but I
>> think the reduced duplication in the public header file is worth it.
> 
> const-covariance applies equally to wchar.h.  Have you designed the macros 
> to be usable there as well?

I should have thought to check for other headders needing the same
treatment.  They don't save quite as much typing since none of those
functions have __builtin versions, but they work; see for yourself.  I
think the comments are needed for the sake of end-users reading the header.

(If this is approved I would squash it together with the earlier patch.)

zw

        * wcsmbs/wchar.h: Use __CONST_COV_PROTO to declare wcschr,
        wcsrchr, wcschrnul, wcspbrk, wcsstr, wcswcs, and wmemchr.

diff --git a/string/bits/const-covariance.h b/string/bits/const-covariance.h
index bec187b..6378438 100644
--- a/string/bits/const-covariance.h
+++ b/string/bits/const-covariance.h
@@ -18,8 +18,8 @@
 #ifndef _BITS_CONST_COVARIANCE_H
 #define _BITS_CONST_COVARIANCE_H 1

-#if !defined _STRING_H && !defined _STRINGS_H
-# error "Never use <bits/const-covariance.h> directly; include
<string.h> or <strings.h> instead."
+#if !defined _STRING_H && !defined _STRINGS_H && !defined _WCHAR_H
+# error "Never use <bits/const-covariance.h> directly; include
<string.h>, <strings.h>, or <wchar.h> instead."
 #endif

 /* This header defines internal-use macros that expand a C prototype
diff --git a/wcsmbs/wchar.h b/wcsmbs/wchar.h
index 9686fcd..9d4d373 100644
--- a/wcsmbs/wchar.h
+++ b/wcsmbs/wchar.h
@@ -70,11 +70,6 @@ typedef __WINT_TYPE__ wint_t;
 __END_NAMESPACE_STD
 #  endif
 # endif
-
-/* Tell the caller that we provide correct C++ prototypes.  */
-# if defined __cplusplus && __GNUC_PREREQ (4, 4)
-#  define __CORRECT_ISO_CPP_WCHAR_H_PROTO
-# endif
 #endif

 #if (defined _WCHAR_H || defined __need_mbstate_t) && !defined
____mbstate_t_defined
@@ -101,6 +96,12 @@ typedef struct
    defined.  */
 #ifdef _WCHAR_H

+/* Tell the caller that we provide correct C++ prototypes.  */
+# if defined __cplusplus && __GNUC_PREREQ (4, 4)
+#  define __CORRECT_ISO_CPP_WCHAR_H_PROTO
+# endif
+# include <bits/const-covariance.h>
+
 # ifndef __mbstate_t_defined
 __BEGIN_NAMESPACE_C99
 /* Public type.  */
@@ -221,33 +222,29 @@ extern wchar_t *wcsdup (const wchar_t *__s)
__THROW __attribute_malloc__;
 #endif

 __BEGIN_NAMESPACE_STD
-/* Find the first occurrence of WC in WCS.  */
-#ifdef __CORRECT_ISO_CPP_WCHAR_H_PROTO
-extern "C++" wchar_t *wcschr (wchar_t *__wcs, wchar_t __wc)
-     __THROW __asm ("wcschr") __attribute_pure__;
-extern "C++" const wchar_t *wcschr (const wchar_t *__wcs, wchar_t __wc)
-     __THROW __asm ("wcschr") __attribute_pure__;
-#else
-extern wchar_t *wcschr (const wchar_t *__wcs, wchar_t __wc)
-     __THROW __attribute_pure__;
-#endif
-/* Find the last occurrence of WC in WCS.  */
-#ifdef __CORRECT_ISO_CPP_WCHAR_H_PROTO
-extern "C++" wchar_t *wcsrchr (wchar_t *__wcs, wchar_t __wc)
-     __THROW __asm ("wcsrchr") __attribute_pure__;
-extern "C++" const wchar_t *wcsrchr (const wchar_t *__wcs, wchar_t __wc)
-     __THROW __asm ("wcsrchr") __attribute_pure__;
-#else
-extern wchar_t *wcsrchr (const wchar_t *__wcs, wchar_t __wc)
-     __THROW __attribute_pure__;
-#endif
+/* Find the first occurrence of WC in WCS.
+   [C]   extern wchar_t *wcschr (const wchar_t *wcs, wchar_t wc);
+   [C++] extern wchar_t *wcschr (wchar_t *wcs, wchar_t wc);
+         extern const wchar_t *wcschr (const wchar_t *wcs, wchar_t wc); */
+__CONST_COV_PROTO (wcschr, __attribute_pure__,
+                   wchar_t *, __wcs, wchar_t, __wc);
+
+/* Find the last occurrence of WC in WCS.
+   [C]   extern wchar_t *wcsrchr (const wchar_t *wcs, wchar_t wc);
+   [C++] extern wchar_t *wcsrchr (wchar_t *wcs, wchar_t wc);
+         extern const wchar_t *wcsrchr (const wchar_t *wcs, wchar_t wc); */
+__CONST_COV_PROTO (wcsrchr, __attribute_pure__,
+                   wchar_t *, __wcs, wchar_t, __wc);
 __END_NAMESPACE_STD

 #ifdef __USE_GNU
 /* This function is similar to `wcschr'.  But it returns a pointer to
-   the closing NUL wide character in case C is not found in S.  */
-extern wchar_t *wcschrnul (const wchar_t *__s, wchar_t __wc)
-     __THROW __attribute_pure__;
+   the closing NUL wide character in case C is not found in S.
+   [C]   extern wchar_t *wcschrnul (const wchar_t *wcs, wchar_t wc);
+   [C++] extern wchar_t *wcschrnul (wchar_t *wcs, wchar_t wc);
+         extern const wchar_t *wcschrnul (const wchar_t *wcs, wchar_t
wc); */
+__CONST_COV_PROTO (wcschrnul, __attribute_pure__,
+                   wchar_t *, __wcs, wchar_t, __wc);
 #endif

 __BEGIN_NAMESPACE_STD
@@ -259,28 +256,23 @@ extern size_t wcscspn (const wchar_t *__wcs, const
wchar_t *__reject)
    consists entirely of wide characters in  ACCEPT.  */
 extern size_t wcsspn (const wchar_t *__wcs, const wchar_t *__accept)
      __THROW __attribute_pure__;
-/* Find the first occurrence in WCS of any character in ACCEPT.  */
-#ifdef __CORRECT_ISO_CPP_WCHAR_H_PROTO
-extern "C++" wchar_t *wcspbrk (wchar_t *__wcs, const wchar_t *__accept)
-     __THROW __asm ("wcspbrk") __attribute_pure__;
-extern "C++" const wchar_t *wcspbrk (const wchar_t *__wcs,
-                                    const wchar_t *__accept)
-     __THROW __asm ("wcspbrk") __attribute_pure__;
-#else
-extern wchar_t *wcspbrk (const wchar_t *__wcs, const wchar_t *__accept)
-     __THROW __attribute_pure__;
-#endif
-/* Find the first occurrence of NEEDLE in HAYSTACK.  */
-#ifdef __CORRECT_ISO_CPP_WCHAR_H_PROTO
-extern "C++" wchar_t *wcsstr (wchar_t *__haystack, const wchar_t *__needle)
-     __THROW __asm ("wcsstr") __attribute_pure__;
-extern "C++" const wchar_t *wcsstr (const wchar_t *__haystack,
-                                   const wchar_t *__needle)
-     __THROW __asm ("wcsstr") __attribute_pure__;
-#else
-extern wchar_t *wcsstr (const wchar_t *__haystack, const wchar_t *__needle)
-     __THROW __attribute_pure__;
-#endif
+/* Find the first occurrence in WCS of any character in ACCEPT.
+   [C]   extern wchar_t *wcspbrk (const wchar_t *wcs, const wchar_t
*accept);
+   [C++] extern wchar_t *wcspbrk (wchar_t *wcs, const wchar_t *accept);
+         extern const wchar_t *wcspbrk (const wchar_t *wcs,
+                                        const wchar_t *accept); */
+__CONST_COV_PROTO (wcspbrk, __attribute_pure__,
+                   wchar_t *, __wcs, const wchar_t *, __accept);
+
+/* Find the first occurrence of NEEDLE in HAYSTACK.
+   [C]   extern wchar_t *wcsstr (const wchar_t *haystack,
+                                 const wchar_t *needle);
+   [C++] extern wchar_t *wcsstr (wchar_t *haystack,
+                                 const wchar_t *needle);
+         extern const wchar_t *wcsstr (const wchar_t *haystack,
+                                       const wchar_t *needle); */
+__CONST_COV_PROTO (wcsstr, __attribute_pure__,
+                   wchar_t *, __haystack, const wchar_t *, __needle);

 /* Divide WCS into tokens separated by characters in DELIM.  */
 extern wchar_t *wcstok (wchar_t *__restrict __s,
@@ -292,17 +284,15 @@ extern size_t wcslen (const wchar_t *__s) __THROW
__attribute_pure__;
 __END_NAMESPACE_STD

 #ifdef __USE_XOPEN
-/* Another name for `wcsstr' from XPG4.  */
-# ifdef __CORRECT_ISO_CPP_WCHAR_H_PROTO
-extern "C++" wchar_t *wcswcs (wchar_t *__haystack, const wchar_t *__needle)
-     __THROW __asm ("wcswcs") __attribute_pure__;
-extern "C++" const wchar_t *wcswcs (const wchar_t *__haystack,
-                                   const wchar_t *__needle)
-     __THROW __asm ("wcswcs") __attribute_pure__;
-# else
-extern wchar_t *wcswcs (const wchar_t *__haystack, const wchar_t *__needle)
-     __THROW __attribute_pure__;
-# endif
+/* Another name for `wcsstr' from XPG4.
+   [C]   extern wchar_t *wcswcs (const wchar_t *haystack,
+                                 const wchar_t *needle);
+   [C++] extern wchar_t *wcswcs (wchar_t *haystack,
+                                 const wchar_t *needle);
+         extern const wchar_t *wcswcs (const wchar_t *haystack,
+                                       const wchar_t *needle); */
+__CONST_COV_PROTO (wcswcs, __attribute_pure__,
+                   wchar_t *, __haystack, const wchar_t *, __needle);
 #endif

 #ifdef __USE_XOPEN2K8
@@ -311,19 +301,14 @@ extern size_t wcsnlen (const wchar_t *__s, size_t
__maxlen)
      __THROW __attribute_pure__;
 #endif

-
 __BEGIN_NAMESPACE_STD
-/* Search N wide characters of S for C.  */
-#ifdef __CORRECT_ISO_CPP_WCHAR_H_PROTO
-extern "C++" wchar_t *wmemchr (wchar_t *__s, wchar_t __c, size_t __n)
-     __THROW __asm ("wmemchr") __attribute_pure__;
-extern "C++" const wchar_t *wmemchr (const wchar_t *__s, wchar_t __c,
-                                    size_t __n)
-     __THROW __asm ("wmemchr") __attribute_pure__;
-#else
-extern wchar_t *wmemchr (const wchar_t *__s, wchar_t __c, size_t __n)
-     __THROW __attribute_pure__;
-#endif
+/* Search N wide characters of S for C.
+   [C]   extern wchar_t *wmemchr (const wchar_t *s, wchar_t wc, size_t n);
+   [C++] extern wchar_t *wmemchr (wchar_t *s, wchar_t wc, size_t n);
+         extern const wchar_t *wmemchr (const wchar_t *s, wchar_t wc,
+                                        size_t n); */
+__CONST_COV_PROTO (wmemchr, __attribute_pure__,
+                   wchar_t *, __s, wchar_t, __c, size_t, __n);

 /* Compare N wide characters of S1 and S2.  */
 extern int wmemcmp (const wchar_t *__s1, const wchar_t *__s2, size_t __n)


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [patch] Don't duplicate declarations between string.h and strings.h
  2016-11-16 20:55 [patch] Don't duplicate declarations between string.h and strings.h Zack Weinberg
  2016-11-17  0:36 ` Zack Weinberg
@ 2016-11-21 17:17 ` Zack Weinberg
  1 sibling, 0 replies; 5+ messages in thread
From: Zack Weinberg @ 2016-11-21 17:17 UTC (permalink / raw)
  To: GNU C Library

On Wed, Nov 16, 2016 at 3:55 PM, Zack Weinberg <zackw@panix.com> wrote:
> I was looking into something else and noticed that all of the
> declarations in strings.h are duplicated in string.h, but not quite
> consistently.  This patch cleans that all up; strings.h is given
> consistent declarations of everything, and then string.h just does
>
> #ifdef __USE_MISC
> # include <strings.h>
> #endif
>
> The prototype of __bzero is moved to include/string.h instead of
> strings.h, since it is an internal name.
>
> Tested on x86-64/linux. OK?

Ping?

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2016-11-21 17:17 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-11-16 20:55 [patch] Don't duplicate declarations between string.h and strings.h Zack Weinberg
2016-11-17  0:36 ` Zack Weinberg
2016-11-17  1:03   ` Joseph Myers
2016-11-17  3:18     ` Zack Weinberg
2016-11-21 17:17 ` Zack Weinberg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).