diff options
author | Anton Dukeman <antondukeman@fb.com> | 2023-07-24 19:14:35 +0000 |
---|---|---|
committer | Piotr Zegar <me@piotrzegar.pl> | 2023-07-24 19:42:19 +0000 |
commit | 2f0630f8bc91e81fd5948e82164cf82ae595caf2 (patch) | |
tree | d1927b9a4a91c3a10d5f9094f05e52490edb631c /clang-tools-extra | |
parent | a6cd1f623dcf6fc443a1b1726d77b36c6b0caa83 (diff) | |
download | llvm-2f0630f8bc91e81fd5948e82164cf82ae595caf2.zip llvm-2f0630f8bc91e81fd5948e82164cf82ae595caf2.tar.gz llvm-2f0630f8bc91e81fd5948e82164cf82ae595caf2.tar.bz2 |
[clang-tidy] Add folly::Optional to unchecked-optional-access
The unchecked-optional-access check identifies attempted value
unwrapping without checking if the value exists. These changes extend
that support to checking folly::Optional.
Reviewed By: gribozavr2
Differential Revision: https://reviews.llvm.org/D155890
Diffstat (limited to 'clang-tools-extra')
4 files changed, 83 insertions, 3 deletions
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index d7a525b..7c4d06b 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -319,7 +319,7 @@ Changes in existing checks - Improved :doc:`bugprone-unchecked-optional-access <clang-tidy/checks/bugprone/unchecked-optional-access>` check to properly handle calls - to ``std::forward``. + to ``std::forward`` and support for ``folly::Optional`` were added. - Extend :doc:`bugprone-unused-return-value <clang-tidy/checks/bugprone/unused-return-value>` check to check for all functions diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unchecked-optional-access.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unchecked-optional-access.rst index 4736518..5a6aaa0 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unchecked-optional-access.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unchecked-optional-access.rst @@ -8,8 +8,9 @@ results. Therefore, it may be more resource intensive (RAM, CPU) than the average clang-tidy check. This check identifies unsafe accesses to values contained in -``std::optional<T>``, ``absl::optional<T>``, or ``base::Optional<T>`` -objects. Below we will refer to all these types collectively as ``optional<T>``. +``std::optional<T>``, ``absl::optional<T>``, ``base::Optional<T>``, or +``folly::Optional<T>`` objects. Below we will refer to all these types +collectively as ``optional<T>``. An access to the value of an ``optional<T>`` occurs when one of its ``value``, ``operator*``, or ``operator->`` member functions is invoked. To align with diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/Inputs/unchecked-optional-access/folly/types/Optional.h b/clang-tools-extra/test/clang-tidy/checkers/bugprone/Inputs/unchecked-optional-access/folly/types/Optional.h new file mode 100644 index 0000000..818b066 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/Inputs/unchecked-optional-access/folly/types/Optional.h @@ -0,0 +1,56 @@ +#ifndef LLVM_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_CHECKERS_BUGPRONE_INPUTS_UNCHECKED_OPTIONAL_ACCESS_FOLLY_TYPES_OPTIONAL_H_ +#define LLVM_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_CHECKERS_BUGPRONE_INPUTS_UNCHECKED_OPTIONAL_ACCESS_FOLLY_TYPES_OPTIONAL_H_ + +/// Mock of `folly::Optional`. +namespace folly { + +struct None { + constexpr explicit None() {} +}; + +constexpr None none; + +template <typename T> +class Optional { +public: + constexpr Optional() noexcept; + + constexpr Optional(None) noexcept; + + Optional(const Optional &) = default; + + Optional(Optional &&) = default; + + const T &operator*() const &; + T &operator*() &; + const T &&operator*() const &&; + T &&operator*() &&; + + const T *operator->() const; + T *operator->(); + + const T &value() const &; + T &value() &; + const T &&value() const &&; + T &&value() &&; + + constexpr explicit operator bool() const noexcept; + constexpr bool has_value() const noexcept; + constexpr bool hasValue() const noexcept; + + template <typename U> + constexpr T value_or(U &&v) const &; + template <typename U> + T value_or(U &&v) &&; + + template <typename... Args> + T &emplace(Args &&...args); + + void reset() noexcept; + + void swap(Optional &rhs) noexcept; +}; + +} // namespace folly + +#endif // LLVM_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_CHECKERS_BUGPRONE_INPUTS_UNCHECKED_OPTIONAL_ACCESS_FOLLY_TYPES_OPTIONAL_H_ diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unchecked-optional-access.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unchecked-optional-access.cpp index c1e731f..1921291 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unchecked-optional-access.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unchecked-optional-access.cpp @@ -1,6 +1,7 @@ // RUN: %check_clang_tidy %s bugprone-unchecked-optional-access %t -- -- -I %S/Inputs/unchecked-optional-access #include "absl/types/optional.h" +#include "folly/types/Optional.h" void unchecked_value_access(const absl::optional<int> &opt) { opt.value(); @@ -21,12 +22,34 @@ void unchecked_arrow_operator_access(const absl::optional<Foo> &opt) { // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: unchecked access to optional value } +void folly_check_value_then_reset(folly::Optional<int> opt) { + if (opt) { + opt.reset(); + opt.value(); + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: unchecked access to optional value + } +} + +void folly_value_after_swap(folly::Optional<int> opt1, folly::Optional<int> opt2) { + if (opt1) { + opt1.swap(opt2); + opt1.value(); + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: unchecked access to optional value + } +} + void checked_access(const absl::optional<int> &opt) { if (opt.has_value()) { opt.value(); } } +void folly_checked_access(const folly::Optional<int> &opt) { + if (opt.hasValue()) { + opt.value(); + } +} + template <typename T> void function_template_without_user(const absl::optional<T> &opt) { opt.value(); // no-warning |