* [PATCH v2] New mechanism for declaring const-covariant string functions.
@ 2016-11-21 17:46 Zack Weinberg
2016-11-22 6:07 ` Paul Eggert
2016-11-22 9:05 ` Florian Weimer
0 siblings, 2 replies; 7+ messages in thread
From: Zack Weinberg @ 2016-11-21 17:46 UTC (permalink / raw)
To: GNU C Library
Several functions in string.h, strings.h, and wchar.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 the C++ standard (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 files 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.
Tested on x86-64-linux-gnu. OK?
(The only change from the previous iteration of this patch is to give
wchar.h the same treatment, as suggested by Joseph.)
zw
* string/bits/const-covariance.h: New file.
* string/Makefile (headers): Add it.
* 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.
* wcsmbs/wchar.h: Likewise for wcschr, wcsrchr, wcschrnul,
wcspbrk, wcsstr, wcswcs, and wmemchr.
* include/bits/const-covariance.h: New wrapper.
---
include/bits/const-covariance.h | 1 +
string/Makefile | 3 +-
string/bits/const-covariance.h | 130 ++++++++++++++++++++
string/string.h | 266
+++++++++++-----------------------------
string/strings.h | 71 +++--------
wcsmbs/wchar.h | 131 +++++++++-----------
6 files changed, 281 insertions(+), 321 deletions(-)
create mode 100644 include/bits/const-covariance.h
create mode 100644 string/bits/const-covariance.h
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/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..6378438
--- /dev/null
+++ b/string/bits/const-covariance.h
@@ -0,0 +1,130 @@
+/* Copyright (C) 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 && !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
+ 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)
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)
--
2.10.2
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2] New mechanism for declaring const-covariant string functions.
2016-11-21 17:46 [PATCH v2] New mechanism for declaring const-covariant string functions Zack Weinberg
@ 2016-11-22 6:07 ` Paul Eggert
2016-11-23 12:56 ` Zack Weinberg
2016-11-22 9:05 ` Florian Weimer
1 sibling, 1 reply; 7+ messages in thread
From: Paul Eggert @ 2016-11-22 6:07 UTC (permalink / raw)
To: Zack Weinberg, GNU C Library
Zack Weinberg wrote:
> 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 files much nicer
> to read, too.
That is a impressive use of the C preprocessor.
Question: if I get the types wrong with a C or C++ program, what do the
resulting diagnostics look like? For this invalid program:
#include <string.h>
char *
foo (int *x, int p)
{
return strchr (x, p);
}
I currently get a diagnostic that ends like this:
/usr/include/string.h:231:14: note: expected ‘const char *’ but argument is
of type ‘int *’
extern char *strchr (const char *__s, int __c)
^
and this is is reasonably easy to follow in isolation. Would it be as easy to
follow with the proposed patch? (Similarly for C++.)
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2] New mechanism for declaring const-covariant string functions.
2016-11-21 17:46 [PATCH v2] New mechanism for declaring const-covariant string functions Zack Weinberg
2016-11-22 6:07 ` Paul Eggert
@ 2016-11-22 9:05 ` Florian Weimer
2016-11-23 13:06 ` Zack Weinberg
1 sibling, 1 reply; 7+ messages in thread
From: Florian Weimer @ 2016-11-22 9:05 UTC (permalink / raw)
To: Zack Weinberg, GNU C Library
On 11/21/2016 06:46 PM, Zack Weinberg wrote:
> diff --git a/string/bits/const-covariance.h b/string/bits/const-covariance.h
> +#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
It's not clear to me what ensures that variadic macros are available at
this point. <bits/const-covariance.h> seems to be included
unconditionally, not just for GNU or C++11. I don't think you can use
variadic macros for this.
Florian
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2] New mechanism for declaring const-covariant string functions.
2016-11-22 6:07 ` Paul Eggert
@ 2016-11-23 12:56 ` Zack Weinberg
0 siblings, 0 replies; 7+ messages in thread
From: Zack Weinberg @ 2016-11-23 12:56 UTC (permalink / raw)
To: Paul Eggert; +Cc: GNU C Library
On Tue, Nov 22, 2016 at 1:06 AM, Paul Eggert <eggert@cs.ucla.edu> wrote:
> Zack Weinberg wrote:
>>
>> 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 files much nicer
>> to read, too.
>
> Question: if I get the types wrong with a C or C++ program, what do the
> resulting diagnostics look like?
The diagnostics are unfortunately not as easy to read. For the same
program you posted, I get this with gcc 6:
strchr-wrong-types.c: In function ‘foo’:
strchr-wrong-types.c:5:17: error: passing argument 1 of ‘strchr’ from
incompatible pointer type [-Werror=incompatible-pointer-types]
return strchr (x, p);
^
In file included from ../include/bits/const-covariance.h:1:0,
from ../string/string.h:39,
from ../include/string.h:56,
from strchr-wrong-types.c:1:
../string/string.h:181:22: note: expected ‘const char *’ but argument
is of type ‘int *’
__CONST_COV_BUILTIN (strchr, __attribute_pure__ __nonnull ((1)),
^
../string/bits/const-covariance.h:90:17: note: in definition of macro
‘__CONST_COV_PROTO’
extern rtype name __CC_XPROTO(const rtype, __VA_ARGS__) __THROW attrs
^~~~
../string/string.h:181:1: note: in expansion of macro ‘__CONST_COV_BUILTIN’
__CONST_COV_BUILTIN (strchr, __attribute_pure__ __nonnull ((1)),
^~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
... and this with g++ 6 ...
strchr-wrong-types.c: In function ‘char* foo(int*, int)’:
strchr-wrong-types.c:5:21: error: no matching function for call to
‘strchr(int*&, int&)’
return strchr (x, p);
^
In file included from ../include/bits/const-covariance.h:1:0,
from ../string/string.h:39,
from ../include/string.h:56,
from strchr-wrong-types.c:1:
../string/string.h:181:22: note: candidate: char* strchr(char*, int)
__CONST_COV_BUILTIN (strchr, __attribute_pure__ __nonnull ((1)),
^
../string/bits/const-covariance.h:119:5: note: in definition of macro
‘__CONST_COV_BUILTIN’
name __CC_XPROTO (rtype, __VA_ARGS__) __THROW \
^~~~
../string/string.h:181:22: note: no known conversion for argument 1
from ‘int*’ to ‘char*’
__CONST_COV_BUILTIN (strchr, __attribute_pure__ __nonnull ((1)),
^
../string/bits/const-covariance.h:119:5: note: in definition of macro
‘__CONST_COV_BUILTIN’
name __CC_XPROTO (rtype, __VA_ARGS__) __THROW \
^~~~
../string/string.h:181:22: note: candidate: const char* strchr(const char*, int)
__CONST_COV_BUILTIN (strchr, __attribute_pure__ __nonnull ((1)),
^
../string/bits/const-covariance.h:122:5: note: in definition of macro
‘__CONST_COV_BUILTIN’
name __CC_XPROTO (const rtype, __VA_ARGS__) __THROW \
^~~~
../string/string.h:181:22: note: no known conversion for argument 1
from ‘int*’ to ‘const char*’
__CONST_COV_BUILTIN (strchr, __attribute_pure__ __nonnull ((1)),
^
../string/bits/const-covariance.h:122:5: note: in definition of macro
‘__CONST_COV_BUILTIN’
name __CC_XPROTO (const rtype, __VA_ARGS__) __THROW \
^~~~
cc1plus: all warnings being treated as errors
clang 3.9 doesn't flood the screen with a bunch of macro expansions,
but what you do get is still a bit confusing:
strchr-wrong-types.c:5:17: error: incompatible pointer types passing 'int *' to
parameter of type 'const char *' [-Werror,-Wincompatible-pointer-types]
return strchr (x, p);
^
../string/string.h:182:28: note: passing argument to parameter '__s' here
char *, __s, int, __c);
^
or in C++ mode
strchr-wrong-types.c:5:9: error: no matching function for call to 'strchr'
return strchr (x, p);
^~~~~~
../string/string.h:181:22: note: candidate function not viable: no known
conversion from 'int *' to 'const char *' for 1st argument
__CONST_COV_BUILTIN (strchr, __attribute_pure__ __nonnull ((1)),
^
../string/bits/const-covariance.h:92:54: note: expanded from macro
'__CONST_COV_BUILTIN'
# define __CONST_COV_BUILTIN(...) __CONST_COV_PROTO (__VA_ARGS__)
^
../string/bits/const-covariance.h:90:17: note: expanded from macro
'__CONST_COV_PROTO'
extern rtype name __CC_XPROTO(const rtype, __VA_ARGS__) __THROW attrs
^
(Note: if testing against an uninstalled build tree you will need to
pass both -D_ISOMAC and -D__NO_STRING_INLINES to reproduce these
errors.)
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2] New mechanism for declaring const-covariant string functions.
2016-11-22 9:05 ` Florian Weimer
@ 2016-11-23 13:06 ` Zack Weinberg
2016-11-23 13:29 ` Florian Weimer
0 siblings, 1 reply; 7+ messages in thread
From: Zack Weinberg @ 2016-11-23 13:06 UTC (permalink / raw)
To: Florian Weimer; +Cc: GNU C Library
On Tue, Nov 22, 2016 at 4:05 AM, Florian Weimer <fweimer@redhat.com> wrote:
> On 11/21/2016 06:46 PM, Zack Weinberg wrote:
>> diff --git a/string/bits/const-covariance.h
>> b/string/bits/const-covariance.h
>> +#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
>
> It's not clear to me what ensures that variadic macros are available at this
> point. <bits/const-covariance.h> seems to be included unconditionally, not
> just for GNU or C++11. I don't think you can use variadic macros for this.
This is a good point. I had been blithely assuming that all supported
compilers provide variadic macros as an extension even in C89 mode,
but maybe I shouldn't do that.
To avoid variadic macros we would need to encode the number of
arguments in the macro name, e.g.
__CONST_COV_PROTO_2 (strchr, char *, __s, int, __c);
__CONST_COV_PROTO_3 (memchr, void *, __s, int, __c, size_t, __n);
Do you think we could live with that? I won't have time to rework the
patch till the weekend.
zw
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2] New mechanism for declaring const-covariant string functions.
2016-11-23 13:06 ` Zack Weinberg
@ 2016-11-23 13:29 ` Florian Weimer
2016-11-28 12:33 ` Zack Weinberg
0 siblings, 1 reply; 7+ messages in thread
From: Florian Weimer @ 2016-11-23 13:29 UTC (permalink / raw)
To: Zack Weinberg; +Cc: GNU C Library
On 11/23/2016 02:06 PM, Zack Weinberg wrote:
> On Tue, Nov 22, 2016 at 4:05 AM, Florian Weimer <fweimer@redhat.com> wrote:
>> On 11/21/2016 06:46 PM, Zack Weinberg wrote:
>>> diff --git a/string/bits/const-covariance.h
>>> b/string/bits/const-covariance.h
>>> +#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
>>
>> It's not clear to me what ensures that variadic macros are available at this
>> point. <bits/const-covariance.h> seems to be included unconditionally, not
>> just for GNU or C++11. I don't think you can use variadic macros for this.
>
> This is a good point. I had been blithely assuming that all supported
> compilers provide variadic macros as an extension even in C89 mode,
> but maybe I shouldn't do that.
>
> To avoid variadic macros we would need to encode the number of
> arguments in the macro name, e.g.
>
> __CONST_COV_PROTO_2 (strchr, char *, __s, int, __c);
> __CONST_COV_PROTO_3 (memchr, void *, __s, int, __c, size_t, __n);
>
> Do you think we could live with that? I won't have time to rework the
> patch till the weekend.
I think the diagnostics issue is the show-stopper here. This looks
increasingly like an application of Joseph's idea of generated installed
headers.
Thanks,
Florian
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2] New mechanism for declaring const-covariant string functions.
2016-11-23 13:29 ` Florian Weimer
@ 2016-11-28 12:33 ` Zack Weinberg
0 siblings, 0 replies; 7+ messages in thread
From: Zack Weinberg @ 2016-11-28 12:33 UTC (permalink / raw)
To: Florian Weimer; +Cc: GNU C Library
On Wed, Nov 23, 2016 at 8:29 AM, Florian Weimer <fweimer@redhat.com> wrote:
>
> I think the diagnostics issue is the show-stopper here. This looks
> increasingly like an application of Joseph's idea of generated installed
> headers.
Yeah. I'm withdrawing this patch for the time being.
zw
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2016-11-28 12:33 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-11-21 17:46 [PATCH v2] New mechanism for declaring const-covariant string functions Zack Weinberg
2016-11-22 6:07 ` Paul Eggert
2016-11-23 12:56 ` Zack Weinberg
2016-11-22 9:05 ` Florian Weimer
2016-11-23 13:06 ` Zack Weinberg
2016-11-23 13:29 ` Florian Weimer
2016-11-28 12:33 ` 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).