mclow.lists created this revision.
mclow.lists added reviewers: chandlerc, rsmith, EricWF.
mclow.lists added a subscriber: cfe-commits.
Herald added subscribers: danalbert, tberghammer.
The C standard says that calling `memcpy`, etc with null parameters is
undefined behavior.
GCC (and clang) have attributes that allow us to mark the parameters of
functions as "must not be null".
Define a mechanism to do this, and use it (for the first time) to mark the
parameters of `memcpy`, `memmove`, `memcmp` and `strncmp` as "must not be null".
This gives us compile time checking for constant pointers, and hints to the
code generator.
Note: This will not be a big win on systems that use glibc, because it marks
the global functions `::memcpy`, etc the same way. On Mac OS X, iOS, Android,
FreeBSD, etc, this will make a bigger difference.
I will be adding tests as well; this post is to gather consensus that this is
the right way to go.
http://reviews.llvm.org/D11948
Files:
include/__config
include/cstring
Index: include/cstring
===================================================================
--- include/cstring
+++ include/cstring
@@ -67,15 +67,34 @@
_LIBCPP_BEGIN_NAMESPACE_STD
using ::size_t;
-using ::memcpy;
-using ::memmove;
+
+// using ::memcpy;
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_NON_NULL2(1, 2)
+void* memcpy(void* __s1, const void* __s2, size_t __n)
+{ return ::memcpy(__s1, __s2, __n); }
+
+// using ::memmove;
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_NON_NULL2(1, 2)
+void* memmove(void* __s1, const void* __s2, size_t __n)
+{ return ::memmove(__s1, __s2, __n); }
+
using ::strcpy;
using ::strncpy;
using ::strcat;
using ::strncat;
-using ::memcmp;
+
+// using ::memcmp;
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_NON_NULL2(1, 2)
+int memcmp(const void* __s1, const void* __s2, size_t __n)
+{ return ::memcmp(__s1, __s2, __n); }
+
using ::strcmp;
-using ::strncmp;
+
+// using ::strncmp;
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_NON_NULL2(1, 2)
+int strncmp(const char* __s1, const char* __s2, size_t __n)
+{ return ::memcmp(__s1, __s2, __n); }
+
using ::strcoll;
using ::strxfrm;
Index: include/__config
===================================================================
--- include/__config
+++ include/__config
@@ -273,6 +273,11 @@
#define _LIBCPP_UNUSED __attribute__((__unused__))
+#define _LIBCPP_NON_NULL
__attribute__((__nonnull__))
+#define _LIBCPP_NON_NULL1(x) __attribute__((__nonnull__(x)))
+#define _LIBCPP_NON_NULL2(x,y)
__attribute__((__nonnull__(x,y)))
+#define _LIBCPP_NON_NULL3(x,y,z)
__attribute__((__nonnull__(x,y,z)))
+
#if !(__has_feature(cxx_defaulted_functions))
#define _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS
#endif // !(__has_feature(cxx_defaulted_functions))
@@ -405,6 +410,11 @@
#define _LIBCPP_UNUSED __attribute__((__unused__))
+#define _LIBCPP_NON_NULL
__attribute__((__nonnull__))
+#define _LIBCPP_NON_NULL1(x) __attribute__((__nonnull__(x)))
+#define _LIBCPP_NON_NULL2(x,y)
__attribute__((__nonnull__(x,y)))
+#define _LIBCPP_NON_NULL3(x,y,z)
__attribute__((__nonnull__(x,y,z)))
+
#if _GNUC_VER >= 407
#define _LIBCPP_UNDERLYING_TYPE(T) __underlying_type(T)
#define _LIBCPP_IS_LITERAL(T) __is_literal_type(T)
Index: include/cstring
===================================================================
--- include/cstring
+++ include/cstring
@@ -67,15 +67,34 @@
_LIBCPP_BEGIN_NAMESPACE_STD
using ::size_t;
-using ::memcpy;
-using ::memmove;
+
+// using ::memcpy;
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_NON_NULL2(1, 2)
+void* memcpy(void* __s1, const void* __s2, size_t __n)
+{ return ::memcpy(__s1, __s2, __n); }
+
+// using ::memmove;
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_NON_NULL2(1, 2)
+void* memmove(void* __s1, const void* __s2, size_t __n)
+{ return ::memmove(__s1, __s2, __n); }
+
using ::strcpy;
using ::strncpy;
using ::strcat;
using ::strncat;
-using ::memcmp;
+
+// using ::memcmp;
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_NON_NULL2(1, 2)
+int memcmp(const void* __s1, const void* __s2, size_t __n)
+{ return ::memcmp(__s1, __s2, __n); }
+
using ::strcmp;
-using ::strncmp;
+
+// using ::strncmp;
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_NON_NULL2(1, 2)
+int strncmp(const char* __s1, const char* __s2, size_t __n)
+{ return ::memcmp(__s1, __s2, __n); }
+
using ::strcoll;
using ::strxfrm;
Index: include/__config
===================================================================
--- include/__config
+++ include/__config
@@ -273,6 +273,11 @@
#define _LIBCPP_UNUSED __attribute__((__unused__))
+#define _LIBCPP_NON_NULL __attribute__((__nonnull__))
+#define _LIBCPP_NON_NULL1(x) __attribute__((__nonnull__(x)))
+#define _LIBCPP_NON_NULL2(x,y) __attribute__((__nonnull__(x,y)))
+#define _LIBCPP_NON_NULL3(x,y,z) __attribute__((__nonnull__(x,y,z)))
+
#if !(__has_feature(cxx_defaulted_functions))
#define _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS
#endif // !(__has_feature(cxx_defaulted_functions))
@@ -405,6 +410,11 @@
#define _LIBCPP_UNUSED __attribute__((__unused__))
+#define _LIBCPP_NON_NULL __attribute__((__nonnull__))
+#define _LIBCPP_NON_NULL1(x) __attribute__((__nonnull__(x)))
+#define _LIBCPP_NON_NULL2(x,y) __attribute__((__nonnull__(x,y)))
+#define _LIBCPP_NON_NULL3(x,y,z) __attribute__((__nonnull__(x,y,z)))
+
#if _GNUC_VER >= 407
#define _LIBCPP_UNDERLYING_TYPE(T) __underlying_type(T)
#define _LIBCPP_IS_LITERAL(T) __is_literal_type(T)
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits