319 lines · cpp
1// RUN: %check_clang_tidy %s bugprone-unchecked-optional-access %t -- -- -I %S/Inputs/unchecked-optional-access2 3#include "absl/types/optional.h"4#include "folly/types/Optional.h"5#include "bde/types/bsl_optional.h"6#include "bde/types/bdlb_nullablevalue.h"7 8void unchecked_value_access(const absl::optional<int> &opt) {9 opt.value();10 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: unchecked access to optional value [bugprone-unchecked-optional-access]11}12 13void unchecked_deref_operator_access(const absl::optional<int> &opt) {14 *opt;15 // CHECK-MESSAGES: :[[@LINE-1]]:4: warning: unchecked access to optional value16}17 18struct Foo {19 void foo() const {}20};21 22void unchecked_arrow_operator_access(const absl::optional<Foo> &opt) {23 opt->foo();24 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: unchecked access to optional value25}26 27void folly_check_value_then_reset(folly::Optional<int> opt) {28 if (opt) {29 opt.reset();30 opt.value();31 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: unchecked access to optional value32 }33}34 35void folly_value_after_swap(folly::Optional<int> opt1, folly::Optional<int> opt2) {36 if (opt1) {37 opt1.swap(opt2);38 opt1.value();39 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: unchecked access to optional value40 }41}42 43void checked_access(const absl::optional<int> &opt) {44 if (opt.has_value()) {45 opt.value();46 }47}48 49void folly_checked_access(const folly::Optional<int> &opt) {50 if (opt.hasValue()) {51 opt.value();52 }53}54 55void bsl_optional_unchecked_value_access(const bsl::optional<int> &opt) {56 opt.value();57 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: unchecked access to optional value [bugprone-unchecked-optional-access]58 59 int x = *opt;60 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: unchecked access to optional value [bugprone-unchecked-optional-access]61 62 if (!opt) {63 return;64 }65 66 opt.value();67 x = *opt;68}69 70void bsl_optional_checked_access(const bsl::optional<int> &opt) {71 if (opt.has_value()) {72 opt.value();73 }74 if (opt) {75 opt.value();76 }77}78 79void bsl_optional_value_after_swap(bsl::optional<int> &opt1, bsl::optional<int> &opt2) {80 if (opt1) {81 opt1.swap(opt2);82 opt1.value();83 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: unchecked access to optional value84 }85}86 87void nullable_value_unchecked_value_access(const BloombergLP::bdlb::NullableValue<int> &opt) {88 opt.value();89 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: unchecked access to optional value [bugprone-unchecked-optional-access]90 91 int x = *opt;92 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: unchecked access to optional value [bugprone-unchecked-optional-access]93 94 if (opt.isNull()) {95 opt.value();96 }97 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: unchecked access to optional value [bugprone-unchecked-optional-access]98 99 if (!opt) {100 opt.value();101 }102 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: unchecked access to optional value [bugprone-unchecked-optional-access]103 104 if (!opt) {105 return;106 }107 108 opt.value();109 x = *opt;110}111 112void nullable_value_optional_checked_access(const BloombergLP::bdlb::NullableValue<int> &opt) {113 if (opt.has_value()) {114 opt.value();115 }116 if (opt) {117 opt.value();118 }119 if (!opt.isNull()) {120 opt.value();121 }122}123 124void nullable_value_emplaced(BloombergLP::bdlb::NullableValue<int> &opt) {125 opt.value();126 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: unchecked access to optional value [bugprone-unchecked-optional-access]127 128 opt.emplace(1);129 opt.value();130 131 opt.reset();132 opt.value();133 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: unchecked access to optional value [bugprone-unchecked-optional-access]134}135 136void nullable_value_after_swap(BloombergLP::bdlb::NullableValue<int> &opt1, BloombergLP::bdlb::NullableValue<int> &opt2) {137 if (opt1) {138 opt1.swap(opt2);139 opt1.value();140 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: unchecked access to optional value141 }142}143 144void nullable_value_make_value(BloombergLP::bdlb::NullableValue<int> &opt1, BloombergLP::bdlb::NullableValue<int> &opt2) {145 if (opt1.isNull()) {146 opt1.makeValue(42);147 }148 149 opt1.value();150 151 if (opt2.isNull()) {152 opt2.makeValueInplace(42);153 }154 155 opt2.value();156}157 158void assertion_handler() __attribute__((analyzer_noreturn));159 160void function_calling_analyzer_noreturn(const bsl::optional<int>& opt)161{162 if (!opt) {163 assertion_handler();164 }165 166 *opt; // no-warning: The previous condition guards this dereference.167}168 169template <typename T>170void function_template_without_user(const absl::optional<T> &opt) {171 opt.value(); // no-warning172}173 174template <typename T>175void function_template_with_user(const absl::optional<T> &opt) {176 opt.value();177 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: unchecked access to optional value178}179 180void function_template_user(const absl::optional<int> &opt) {181 // Instantiate the f3 function template so that it gets matched by the check.182 function_template_with_user(opt);183}184 185template <typename T>186void function_template_with_specialization(const absl::optional<int> &opt) {187 opt.value(); // no-warning188}189 190template <>191void function_template_with_specialization<int>(192 const absl::optional<int> &opt) {193 opt.value();194 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: unchecked access to optional value195}196 197template <typename T>198class ClassTemplateWithSpecializations {199 void f(const absl::optional<int> &opt) {200 opt.value(); // no-warning201 }202};203 204template <typename T>205class ClassTemplateWithSpecializations<T *> {206 void f(const absl::optional<int> &opt) {207 opt.value(); // no-warning208 }209};210 211template <>212class ClassTemplateWithSpecializations<int> {213 void f(const absl::optional<int> &opt) {214 opt.value();215 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: unchecked access to optional216 }217};218 219// The templates below are not instantiated and CFGs can not be properly built220// for them. They are here to make sure that the checker does not crash, but221// instead ignores non-instantiated templates.222 223template <typename T>224struct C1 {};225 226template <typename T>227struct C2 : public C1<T> {228 ~C2() {}229};230 231template <typename T, template <class> class B>232struct C3 : public B<T> {233 ~C3() {}234};235 236void multiple_unchecked_accesses(absl::optional<int> opt1,237 absl::optional<int> opt2) {238 for (int i = 0; i < 10; i++) {239 opt1.value();240 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: unchecked access to optional241 }242 opt2.value();243 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: unchecked access to optional value244}245 246class C4 {247 explicit C4(absl::optional<int> opt) : foo_(opt.value()) {248 // CHECK-MESSAGES: :[[@LINE-1]]:47: warning: unchecked access to optional249 }250 int foo_;251};252 253// llvm#59705254namespace std255{256 template <typename T>257 constexpr T&& forward(T& type) noexcept {258 return static_cast<T&&>(type);259 }260 261 template <typename T>262 constexpr T&& forward(T&& type) noexcept {263 return static_cast<T&&>(type);264 }265}266 267void std_forward_copy(absl::optional<int> opt) {268 std::forward<absl::optional<int>>(opt).value();269 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: unchecked access to optional270}271 272void std_forward_copy_safe(absl::optional<int> opt) {273 if (!opt) return;274 275 std::forward<absl::optional<int>>(opt).value();276}277 278void std_forward_copy(absl::optional<int>& opt) {279 std::forward<absl::optional<int>>(opt).value();280 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: unchecked access to optional281}282 283void std_forward_lvalue_ref_safe(absl::optional<int>& opt) {284 if (!opt) return;285 286 std::forward<absl::optional<int>>(opt).value();287}288 289void std_forward_copy(absl::optional<int>&& opt) {290 std::forward<absl::optional<int>>(opt).value();291 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: unchecked access to optional292}293 294void std_forward_rvalue_ref_safe(absl::optional<int>&& opt) {295 if (!opt) return;296 297 std::forward<absl::optional<int>>(opt).value();298}299 300namespace std {301 302template <typename T> class vector {303public:304 T &operator[](unsigned long index);305 bool empty();306};307 308} // namespace std309 310struct S {311 absl::optional<float> x;312};313std::vector<S> vec;314 315void foo() {316 if (!vec.empty())317 vec[0].x = 0;318}319