Skip to content

Commit b5348e7

Browse files
authored
[libc++] Diagnose passing null pointers to a bunch of APIs (#148585)
1 parent baf2953 commit b5348e7

File tree

11 files changed

+219
-45
lines changed

11 files changed

+219
-45
lines changed

libcxx/.clang-format

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ AttributeMacros: [
3333
'_LIBCPP_DEPRECATED_IN_CXX20',
3434
'_LIBCPP_DEPRECATED_IN_CXX23',
3535
'_LIBCPP_DEPRECATED',
36+
'_LIBCPP_DIAGNOSE_NULLPTR_IF',
3637
'_LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION',
3738
'_LIBCPP_EXPORTED_FROM_ABI',
3839
'_LIBCPP_EXTERN_TEMPLATE_TYPE_VIS',

libcxx/include/__config

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,6 +1081,20 @@ typedef __char32_t char32_t;
10811081
# define _LIBCPP_DIAGNOSE_WARNING(...)
10821082
# endif
10831083

1084+
# if __has_attribute(__diagnose_if__) && !defined(_LIBCPP_APPLE_CLANG_VER) && \
1085+
(!defined(_LIBCPP_CLANG_VER) || _LIBCPP_CLANG_VER >= 2001)
1086+
# define _LIBCPP_DIAGNOSE_IF(...) __attribute__((__diagnose_if__(__VA_ARGS__)))
1087+
# else
1088+
# define _LIBCPP_DIAGNOSE_IF(...)
1089+
# endif
1090+
1091+
# define _LIBCPP_DIAGNOSE_NULLPTR_IF(condition, condition_description) \
1092+
_LIBCPP_DIAGNOSE_IF( \
1093+
condition, \
1094+
"null passed to callee that requires a non-null argument" condition_description, \
1095+
"warning", \
1096+
"nonnull")
1097+
10841098
# if __has_cpp_attribute(_Clang::__lifetimebound__)
10851099
# define _LIBCPP_LIFETIMEBOUND [[_Clang::__lifetimebound__]]
10861100
# else

libcxx/include/__memory/construct_at.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
3333
#if _LIBCPP_STD_VER >= 20
3434

3535
template <class _Tp, class... _Args, class = decltype(::new(std::declval<void*>()) _Tp(std::declval<_Args>()...))>
36-
_LIBCPP_HIDE_FROM_ABI constexpr _Tp* construct_at(_Tp* __location, _Args&&... __args) {
36+
_LIBCPP_HIDE_FROM_ABI constexpr _Tp* construct_at(_Tp* _LIBCPP_DIAGNOSE_NULLPTR __location, _Args&&... __args) {
3737
_LIBCPP_ASSERT_NON_NULL(__location != nullptr, "null pointer given to construct_at");
3838
return ::new (static_cast<void*>(__location)) _Tp(std::forward<_Args>(__args)...);
3939
}
@@ -73,13 +73,13 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __destroy_at(_Tp* __loc) {
7373
#if _LIBCPP_STD_VER >= 17
7474

7575
template <class _Tp, enable_if_t<!is_array_v<_Tp>, int> = 0>
76-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void destroy_at(_Tp* __loc) {
76+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void destroy_at(_Tp* _LIBCPP_DIAGNOSE_NULLPTR __loc) {
7777
std::__destroy_at(__loc);
7878
}
7979

8080
# if _LIBCPP_STD_VER >= 20
8181
template <class _Tp, enable_if_t<is_array_v<_Tp>, int> = 0>
82-
_LIBCPP_HIDE_FROM_ABI constexpr void destroy_at(_Tp* __loc) {
82+
_LIBCPP_HIDE_FROM_ABI constexpr void destroy_at(_Tp* _LIBCPP_DIAGNOSE_NULLPTR __loc) {
8383
std::__destroy_at(__loc);
8484
}
8585
# endif

libcxx/include/print

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,8 @@ __vprint_unicode([[maybe_unused]] FILE* __stream,
329329
} // namespace __print
330330

331331
template <class... _Args>
332-
_LIBCPP_HIDE_FROM_ABI void print(FILE* __stream, format_string<_Args...> __fmt, _Args&&... __args) {
332+
_LIBCPP_HIDE_FROM_ABI void
333+
print(FILE* _LIBCPP_DIAGNOSE_NULLPTR __stream, format_string<_Args...> __fmt, _Args&&... __args) {
333334
# if _LIBCPP_HAS_UNICODE
334335
if constexpr (__print::__use_unicode_execution_charset)
335336
__print::__vprint_unicode(__stream, __fmt.get(), std::make_format_args(__args...), false);
@@ -346,7 +347,8 @@ _LIBCPP_HIDE_FROM_ABI void print(format_string<_Args...> __fmt, _Args&&... __arg
346347
}
347348

348349
template <class... _Args>
349-
_LIBCPP_HIDE_FROM_ABI void println(FILE* __stream, format_string<_Args...> __fmt, _Args&&... __args) {
350+
_LIBCPP_HIDE_FROM_ABI void
351+
println(FILE* _LIBCPP_DIAGNOSE_NULLPTR __stream, format_string<_Args...> __fmt, _Args&&... __args) {
350352
# if _LIBCPP_HAS_UNICODE
351353
// Note the wording in the Standard is inefficient. The output of
352354
// std::format is a std::string which is then copied. This solution
@@ -361,7 +363,7 @@ _LIBCPP_HIDE_FROM_ABI void println(FILE* __stream, format_string<_Args...> __fmt
361363
}
362364

363365
template <class = void> // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563).
364-
_LIBCPP_HIDE_FROM_ABI inline void println(FILE* __stream) {
366+
_LIBCPP_HIDE_FROM_ABI inline void println(FILE* _LIBCPP_DIAGNOSE_NULLPTR __stream) {
365367
std::print(__stream, "\n");
366368
}
367369

@@ -377,7 +379,8 @@ _LIBCPP_HIDE_FROM_ABI void println(format_string<_Args...> __fmt, _Args&&... __a
377379

378380
# if _LIBCPP_HAS_UNICODE
379381
template <class = void> // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563).
380-
_LIBCPP_HIDE_FROM_ABI inline void vprint_unicode(FILE* __stream, string_view __fmt, format_args __args) {
382+
_LIBCPP_HIDE_FROM_ABI inline void
383+
vprint_unicode(FILE* _LIBCPP_DIAGNOSE_NULLPTR __stream, string_view __fmt, format_args __args) {
381384
__print::__vprint_unicode(__stream, __fmt, __args, false);
382385
}
383386

@@ -389,7 +392,8 @@ _LIBCPP_HIDE_FROM_ABI inline void vprint_unicode(string_view __fmt, format_args
389392
# endif // _LIBCPP_HAS_UNICODE
390393

391394
template <class = void> // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563).
392-
_LIBCPP_HIDE_FROM_ABI inline void vprint_nonunicode(FILE* __stream, string_view __fmt, format_args __args) {
395+
_LIBCPP_HIDE_FROM_ABI inline void
396+
vprint_nonunicode(FILE* _LIBCPP_DIAGNOSE_NULLPTR __stream, string_view __fmt, format_args __args) {
393397
__print::__vprint_nonunicode(__stream, __fmt, __args, false);
394398
}
395399

libcxx/include/string

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,13 +1065,15 @@ public:
10651065
basic_string(nullptr_t) = delete;
10661066
# endif
10671067

1068-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const _CharT* __s, size_type __n) {
1068+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const _CharT* __s, size_type __n)
1069+
_LIBCPP_DIAGNOSE_NULLPTR_IF(__n != 0 && __s == nullptr, " if n is not zero") {
10691070
_LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "basic_string(const char*, n) detected nullptr");
10701071
__init(__s, __n);
10711072
}
10721073

10731074
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
10741075
basic_string(const _CharT* __s, size_type __n, const _Allocator& __a)
1076+
_LIBCPP_DIAGNOSE_NULLPTR_IF(__n != 0 && __s == nullptr, " if n is not zero")
10751077
: __alloc_(__a) {
10761078
_LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "basic_string(const char*, n, allocator) detected nullptr");
10771079
__init(__s, __n);
@@ -1394,7 +1396,8 @@ public:
13941396
return append(__sv.data() + __pos, std::min(__n, __sz - __pos));
13951397
}
13961398

1397-
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const value_type* __s, size_type __n);
1399+
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const value_type* __s, size_type __n)
1400+
_LIBCPP_DIAGNOSE_NULLPTR_IF(__n != 0 && __s == nullptr, " if n is not zero");
13981401
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const value_type* _LIBCPP_DIAGNOSE_NULLPTR __s);
13991402
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(size_type __n, value_type __c);
14001403

@@ -1521,8 +1524,9 @@ public:
15211524
return assign(__sv.data() + __pos, std::min(__n, __sz - __pos));
15221525
}
15231526

1524-
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const value_type* __s, size_type __n);
1525-
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const value_type* __s);
1527+
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const value_type* __s, size_type __n)
1528+
_LIBCPP_DIAGNOSE_NULLPTR_IF(__n != 0 && __s == nullptr, " if n is not zero");
1529+
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const value_type* _LIBCPP_DIAGNOSE_NULLPTR __s);
15261530
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(size_type __n, value_type __c);
15271531

15281532
template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0>
@@ -1593,7 +1597,8 @@ public:
15931597

15941598
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
15951599
insert(size_type __pos1, const basic_string& __str, size_type __pos2, size_type __n = npos);
1596-
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos, const value_type* __s, size_type __n);
1600+
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos, const value_type* __s, size_type __n)
1601+
_LIBCPP_DIAGNOSE_NULLPTR_IF(__n != 0 && __s == nullptr, " if n is not zero");
15971602
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos, const value_type* _LIBCPP_DIAGNOSE_NULLPTR __s);
15981603
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos, size_type __n, value_type __c);
15991604
_LIBCPP_CONSTEXPR_SINCE_CXX20 iterator insert(const_iterator __pos, value_type __c);
@@ -1673,8 +1678,10 @@ public:
16731678
}
16741679

16751680
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
1676-
replace(size_type __pos, size_type __n1, const value_type* __s, size_type __n2);
1677-
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(size_type __pos, size_type __n1, const value_type* __s);
1681+
replace(size_type __pos, size_type __n1, const value_type* __s, size_type __n2)
1682+
_LIBCPP_DIAGNOSE_NULLPTR_IF(__n2 != 0 && __s == nullptr, " if n2 is not zero");
1683+
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
1684+
replace(size_type __pos, size_type __n1, const value_type* _LIBCPP_DIAGNOSE_NULLPTR __s);
16781685
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(size_type __pos, size_type __n1, size_type __n2, value_type __c);
16791686

16801687
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
@@ -1783,7 +1790,8 @@ public:
17831790
return std::__str_find<value_type, size_type, traits_type, npos>(data(), size(), __sv.data(), __pos, __sv.size());
17841791
}
17851792

1786-
_LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT {
1793+
_LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT
1794+
_LIBCPP_DIAGNOSE_NULLPTR_IF(__n != 0 && __s == nullptr, " if n is not zero") {
17871795
_LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::find(): received nullptr");
17881796
return std::__str_find<value_type, size_type, traits_type, npos>(data(), size(), __s, __pos, __n);
17891797
}
@@ -1814,7 +1822,8 @@ public:
18141822
return std::__str_rfind<value_type, size_type, traits_type, npos>(data(), size(), __sv.data(), __pos, __sv.size());
18151823
}
18161824

1817-
_LIBCPP_CONSTEXPR_SINCE_CXX20 size_type rfind(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT {
1825+
_LIBCPP_CONSTEXPR_SINCE_CXX20 size_type rfind(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT
1826+
_LIBCPP_DIAGNOSE_NULLPTR_IF(__n != 0 && __s == nullptr, " if n is not zero") {
18181827
_LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::rfind(): received nullptr");
18191828
return std::__str_rfind<value_type, size_type, traits_type, npos>(data(), size(), __s, __pos, __n);
18201829
}
@@ -1847,7 +1856,8 @@ public:
18471856
}
18481857

18491858
_LIBCPP_CONSTEXPR_SINCE_CXX20 size_type
1850-
find_first_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT {
1859+
find_first_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT
1860+
_LIBCPP_DIAGNOSE_NULLPTR_IF(__n != 0 && __s == nullptr, " if n is not zero") {
18511861
_LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::find_first_of(): received nullptr");
18521862
return std::__str_find_first_of<value_type, size_type, traits_type, npos>(data(), size(), __s, __pos, __n);
18531863
}
@@ -1881,7 +1891,8 @@ public:
18811891
}
18821892

18831893
_LIBCPP_CONSTEXPR_SINCE_CXX20 size_type
1884-
find_last_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT {
1894+
find_last_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT
1895+
_LIBCPP_DIAGNOSE_NULLPTR_IF(__n != 0 && __s == nullptr, " if n is not zero") {
18851896
_LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::find_last_of(): received nullptr");
18861897
return std::__str_find_last_of<value_type, size_type, traits_type, npos>(data(), size(), __s, __pos, __n);
18871898
}
@@ -1915,7 +1926,8 @@ public:
19151926
}
19161927

19171928
_LIBCPP_CONSTEXPR_SINCE_CXX20 size_type
1918-
find_first_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT {
1929+
find_first_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT
1930+
_LIBCPP_DIAGNOSE_NULLPTR_IF(__n != 0 && __s == nullptr, " if n is not zero") {
19191931
_LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::find_first_not_of(): received nullptr");
19201932
return std::__str_find_first_not_of<value_type, size_type, traits_type, npos>(data(), size(), __s, __pos, __n);
19211933
}
@@ -1949,7 +1961,8 @@ public:
19491961
}
19501962

19511963
_LIBCPP_CONSTEXPR_SINCE_CXX20 size_type
1952-
find_last_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT {
1964+
find_last_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT
1965+
_LIBCPP_DIAGNOSE_NULLPTR_IF(__n != 0 && __s == nullptr, " if n is not zero") {
19531966
_LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::find_last_not_of(): received nullptr");
19541967
return std::__str_find_last_not_of<value_type, size_type, traits_type, npos>(data(), size(), __s, __pos, __n);
19551968
}
@@ -2026,7 +2039,8 @@ public:
20262039
}
20272040

20282041
_LIBCPP_CONSTEXPR_SINCE_CXX20 int
2029-
compare(size_type __pos1, size_type __n1, const value_type* __s, size_type __n2) const;
2042+
compare(size_type __pos1, size_type __n1, const value_type* __s, size_type __n2) const
2043+
_LIBCPP_DIAGNOSE_NULLPTR_IF(__n2 != 0 && __s == nullptr, " if n2 is not zero");
20302044

20312045
// starts_with
20322046

@@ -3564,7 +3578,8 @@ operator==(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
35643578

35653579
template <class _CharT, class _Traits, class _Allocator>
35663580
inline _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool
3567-
operator==(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) _NOEXCEPT {
3581+
operator==(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
3582+
const _CharT* _LIBCPP_DIAGNOSE_NULLPTR __rhs) _NOEXCEPT {
35683583
_LIBCPP_ASSERT_NON_NULL(__rhs != nullptr, "operator==(basic_string, char*): received nullptr");
35693584

35703585
using _String = basic_string<_CharT, _Traits, _Allocator>;

0 commit comments

Comments
 (0)