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 cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits