189a1d03eSRichard // RUN: %check_clang_tidy %s bugprone-unchecked-optional-access %t -- -- -I %S/Inputs/unchecked-optional-access 289a1d03eSRichard 389a1d03eSRichard #include "absl/types/optional.h" 42f0630f8SAnton Dukeman #include "folly/types/Optional.h" 5*11c423f9SChris Cotter #include "bde/types/bsl_optional.h" 6*11c423f9SChris Cotter #include "bde/types/bdlb_nullablevalue.h" 789a1d03eSRichard 889a1d03eSRichard void unchecked_value_access(const absl::optional<int> &opt) { 989a1d03eSRichard opt.value(); 1089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: unchecked access to optional value [bugprone-unchecked-optional-access] 1189a1d03eSRichard } 1289a1d03eSRichard 1389a1d03eSRichard void unchecked_deref_operator_access(const absl::optional<int> &opt) { 1489a1d03eSRichard *opt; 1589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:4: warning: unchecked access to optional value 1689a1d03eSRichard } 1789a1d03eSRichard 1889a1d03eSRichard struct Foo { 1989a1d03eSRichard void foo() const {} 2089a1d03eSRichard }; 2189a1d03eSRichard 2289a1d03eSRichard void unchecked_arrow_operator_access(const absl::optional<Foo> &opt) { 2389a1d03eSRichard opt->foo(); 2489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: unchecked access to optional value 2589a1d03eSRichard } 2689a1d03eSRichard 272f0630f8SAnton Dukeman void folly_check_value_then_reset(folly::Optional<int> opt) { 282f0630f8SAnton Dukeman if (opt) { 292f0630f8SAnton Dukeman opt.reset(); 302f0630f8SAnton Dukeman opt.value(); 312f0630f8SAnton Dukeman // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: unchecked access to optional value 322f0630f8SAnton Dukeman } 332f0630f8SAnton Dukeman } 342f0630f8SAnton Dukeman 352f0630f8SAnton Dukeman void folly_value_after_swap(folly::Optional<int> opt1, folly::Optional<int> opt2) { 362f0630f8SAnton Dukeman if (opt1) { 372f0630f8SAnton Dukeman opt1.swap(opt2); 382f0630f8SAnton Dukeman opt1.value(); 392f0630f8SAnton Dukeman // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: unchecked access to optional value 402f0630f8SAnton Dukeman } 412f0630f8SAnton Dukeman } 422f0630f8SAnton Dukeman 4389a1d03eSRichard void checked_access(const absl::optional<int> &opt) { 4489a1d03eSRichard if (opt.has_value()) { 4589a1d03eSRichard opt.value(); 4689a1d03eSRichard } 4789a1d03eSRichard } 4889a1d03eSRichard 492f0630f8SAnton Dukeman void folly_checked_access(const folly::Optional<int> &opt) { 502f0630f8SAnton Dukeman if (opt.hasValue()) { 512f0630f8SAnton Dukeman opt.value(); 522f0630f8SAnton Dukeman } 532f0630f8SAnton Dukeman } 542f0630f8SAnton Dukeman 55*11c423f9SChris Cotter void bsl_optional_unchecked_value_access(const bsl::optional<int> &opt) { 56*11c423f9SChris Cotter opt.value(); 57*11c423f9SChris Cotter // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: unchecked access to optional value [bugprone-unchecked-optional-access] 58*11c423f9SChris Cotter 59*11c423f9SChris Cotter int x = *opt; 60*11c423f9SChris Cotter // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: unchecked access to optional value [bugprone-unchecked-optional-access] 61*11c423f9SChris Cotter 62*11c423f9SChris Cotter if (!opt) { 63*11c423f9SChris Cotter return; 64*11c423f9SChris Cotter } 65*11c423f9SChris Cotter 66*11c423f9SChris Cotter opt.value(); 67*11c423f9SChris Cotter x = *opt; 68*11c423f9SChris Cotter } 69*11c423f9SChris Cotter 70*11c423f9SChris Cotter void bsl_optional_checked_access(const bsl::optional<int> &opt) { 71*11c423f9SChris Cotter if (opt.has_value()) { 72*11c423f9SChris Cotter opt.value(); 73*11c423f9SChris Cotter } 74*11c423f9SChris Cotter if (opt) { 75*11c423f9SChris Cotter opt.value(); 76*11c423f9SChris Cotter } 77*11c423f9SChris Cotter } 78*11c423f9SChris Cotter 79*11c423f9SChris Cotter void bsl_optional_value_after_swap(bsl::optional<int> &opt1, bsl::optional<int> &opt2) { 80*11c423f9SChris Cotter if (opt1) { 81*11c423f9SChris Cotter opt1.swap(opt2); 82*11c423f9SChris Cotter opt1.value(); 83*11c423f9SChris Cotter // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: unchecked access to optional value 84*11c423f9SChris Cotter } 85*11c423f9SChris Cotter } 86*11c423f9SChris Cotter 87*11c423f9SChris Cotter void nullable_value_unchecked_value_access(const BloombergLP::bdlb::NullableValue<int> &opt) { 88*11c423f9SChris Cotter opt.value(); 89*11c423f9SChris Cotter // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: unchecked access to optional value [bugprone-unchecked-optional-access] 90*11c423f9SChris Cotter 91*11c423f9SChris Cotter int x = *opt; 92*11c423f9SChris Cotter // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: unchecked access to optional value [bugprone-unchecked-optional-access] 93*11c423f9SChris Cotter 94*11c423f9SChris Cotter if (opt.isNull()) { 95*11c423f9SChris Cotter opt.value(); 96*11c423f9SChris Cotter } 97*11c423f9SChris Cotter // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: unchecked access to optional value [bugprone-unchecked-optional-access] 98*11c423f9SChris Cotter 99*11c423f9SChris Cotter if (!opt) { 100*11c423f9SChris Cotter opt.value(); 101*11c423f9SChris Cotter } 102*11c423f9SChris Cotter // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: unchecked access to optional value [bugprone-unchecked-optional-access] 103*11c423f9SChris Cotter 104*11c423f9SChris Cotter if (!opt) { 105*11c423f9SChris Cotter return; 106*11c423f9SChris Cotter } 107*11c423f9SChris Cotter 108*11c423f9SChris Cotter opt.value(); 109*11c423f9SChris Cotter x = *opt; 110*11c423f9SChris Cotter } 111*11c423f9SChris Cotter 112*11c423f9SChris Cotter void nullable_value_optional_checked_access(const BloombergLP::bdlb::NullableValue<int> &opt) { 113*11c423f9SChris Cotter if (opt.has_value()) { 114*11c423f9SChris Cotter opt.value(); 115*11c423f9SChris Cotter } 116*11c423f9SChris Cotter if (opt) { 117*11c423f9SChris Cotter opt.value(); 118*11c423f9SChris Cotter } 119*11c423f9SChris Cotter if (!opt.isNull()) { 120*11c423f9SChris Cotter opt.value(); 121*11c423f9SChris Cotter } 122*11c423f9SChris Cotter } 123*11c423f9SChris Cotter 124*11c423f9SChris Cotter void nullable_value_emplaced(BloombergLP::bdlb::NullableValue<int> &opt) { 125*11c423f9SChris Cotter opt.value(); 126*11c423f9SChris Cotter // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: unchecked access to optional value [bugprone-unchecked-optional-access] 127*11c423f9SChris Cotter 128*11c423f9SChris Cotter opt.emplace(1); 129*11c423f9SChris Cotter opt.value(); 130*11c423f9SChris Cotter 131*11c423f9SChris Cotter opt.reset(); 132*11c423f9SChris Cotter opt.value(); 133*11c423f9SChris Cotter // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: unchecked access to optional value [bugprone-unchecked-optional-access] 134*11c423f9SChris Cotter } 135*11c423f9SChris Cotter 136*11c423f9SChris Cotter void nullable_value_after_swap(BloombergLP::bdlb::NullableValue<int> &opt1, BloombergLP::bdlb::NullableValue<int> &opt2) { 137*11c423f9SChris Cotter if (opt1) { 138*11c423f9SChris Cotter opt1.swap(opt2); 139*11c423f9SChris Cotter opt1.value(); 140*11c423f9SChris Cotter // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: unchecked access to optional value 141*11c423f9SChris Cotter } 142*11c423f9SChris Cotter } 143*11c423f9SChris Cotter 14489a1d03eSRichard template <typename T> 14589a1d03eSRichard void function_template_without_user(const absl::optional<T> &opt) { 14689a1d03eSRichard opt.value(); // no-warning 14789a1d03eSRichard } 14889a1d03eSRichard 14989a1d03eSRichard template <typename T> 15089a1d03eSRichard void function_template_with_user(const absl::optional<T> &opt) { 15189a1d03eSRichard opt.value(); 15289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: unchecked access to optional value 15389a1d03eSRichard } 15489a1d03eSRichard 15589a1d03eSRichard void function_template_user(const absl::optional<int> &opt) { 15689a1d03eSRichard // Instantiate the f3 function template so that it gets matched by the check. 15789a1d03eSRichard function_template_with_user(opt); 15889a1d03eSRichard } 15989a1d03eSRichard 16089a1d03eSRichard template <typename T> 16189a1d03eSRichard void function_template_with_specialization(const absl::optional<int> &opt) { 16289a1d03eSRichard opt.value(); // no-warning 16389a1d03eSRichard } 16489a1d03eSRichard 16589a1d03eSRichard template <> 16689a1d03eSRichard void function_template_with_specialization<int>( 16789a1d03eSRichard const absl::optional<int> &opt) { 16889a1d03eSRichard opt.value(); 16989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: unchecked access to optional value 17089a1d03eSRichard } 17189a1d03eSRichard 17289a1d03eSRichard template <typename T> 17389a1d03eSRichard class ClassTemplateWithSpecializations { 17489a1d03eSRichard void f(const absl::optional<int> &opt) { 17589a1d03eSRichard opt.value(); // no-warning 17689a1d03eSRichard } 17789a1d03eSRichard }; 17889a1d03eSRichard 17989a1d03eSRichard template <typename T> 18089a1d03eSRichard class ClassTemplateWithSpecializations<T *> { 18189a1d03eSRichard void f(const absl::optional<int> &opt) { 18289a1d03eSRichard opt.value(); // no-warning 18389a1d03eSRichard } 18489a1d03eSRichard }; 18589a1d03eSRichard 18689a1d03eSRichard template <> 18789a1d03eSRichard class ClassTemplateWithSpecializations<int> { 18889a1d03eSRichard void f(const absl::optional<int> &opt) { 18989a1d03eSRichard opt.value(); 19089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: unchecked access to optional 19189a1d03eSRichard } 19289a1d03eSRichard }; 19389a1d03eSRichard 19489a1d03eSRichard // The templates below are not instantiated and CFGs can not be properly built 19589a1d03eSRichard // for them. They are here to make sure that the checker does not crash, but 19689a1d03eSRichard // instead ignores non-instantiated templates. 19789a1d03eSRichard 19889a1d03eSRichard template <typename T> 19989a1d03eSRichard struct C1 {}; 20089a1d03eSRichard 20189a1d03eSRichard template <typename T> 20289a1d03eSRichard struct C2 : public C1<T> { 20389a1d03eSRichard ~C2() {} 20489a1d03eSRichard }; 20589a1d03eSRichard 20689a1d03eSRichard template <typename T, template <class> class B> 20789a1d03eSRichard struct C3 : public B<T> { 20889a1d03eSRichard ~C3() {} 20989a1d03eSRichard }; 21089a1d03eSRichard 21189a1d03eSRichard void multiple_unchecked_accesses(absl::optional<int> opt1, 21289a1d03eSRichard absl::optional<int> opt2) { 21389a1d03eSRichard for (int i = 0; i < 10; i++) { 21489a1d03eSRichard opt1.value(); 21589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: unchecked access to optional 21689a1d03eSRichard } 21789a1d03eSRichard opt2.value(); 21889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: unchecked access to optional value 21989a1d03eSRichard } 22089a1d03eSRichard 22189a1d03eSRichard class C4 { 22289a1d03eSRichard explicit C4(absl::optional<int> opt) : foo_(opt.value()) { 22389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:47: warning: unchecked access to optional 22489a1d03eSRichard } 22589a1d03eSRichard int foo_; 22689a1d03eSRichard }; 22725956d55SAMS21 22825956d55SAMS21 // llvm#59705 22925956d55SAMS21 namespace std 23025956d55SAMS21 { 23125956d55SAMS21 template <typename T> 23225956d55SAMS21 constexpr T&& forward(T& type) noexcept { 23325956d55SAMS21 return static_cast<T&&>(type); 23425956d55SAMS21 } 23525956d55SAMS21 23625956d55SAMS21 template <typename T> 23725956d55SAMS21 constexpr T&& forward(T&& type) noexcept { 23825956d55SAMS21 return static_cast<T&&>(type); 23925956d55SAMS21 } 24025956d55SAMS21 } 24125956d55SAMS21 24225956d55SAMS21 void std_forward_copy(absl::optional<int> opt) { 24325956d55SAMS21 std::forward<absl::optional<int>>(opt).value(); 24425956d55SAMS21 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: unchecked access to optional 24525956d55SAMS21 } 24625956d55SAMS21 24725956d55SAMS21 void std_forward_copy_safe(absl::optional<int> opt) { 24825956d55SAMS21 if (!opt) return; 24925956d55SAMS21 25025956d55SAMS21 std::forward<absl::optional<int>>(opt).value(); 25125956d55SAMS21 } 25225956d55SAMS21 25325956d55SAMS21 void std_forward_copy(absl::optional<int>& opt) { 25425956d55SAMS21 std::forward<absl::optional<int>>(opt).value(); 25525956d55SAMS21 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: unchecked access to optional 25625956d55SAMS21 } 25725956d55SAMS21 25825956d55SAMS21 void std_forward_lvalue_ref_safe(absl::optional<int>& opt) { 25925956d55SAMS21 if (!opt) return; 26025956d55SAMS21 26125956d55SAMS21 std::forward<absl::optional<int>>(opt).value(); 26225956d55SAMS21 } 26325956d55SAMS21 26425956d55SAMS21 void std_forward_copy(absl::optional<int>&& opt) { 26525956d55SAMS21 std::forward<absl::optional<int>>(opt).value(); 26625956d55SAMS21 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: unchecked access to optional 26725956d55SAMS21 } 26825956d55SAMS21 26925956d55SAMS21 void std_forward_rvalue_ref_safe(absl::optional<int>&& opt) { 27025956d55SAMS21 if (!opt) return; 27125956d55SAMS21 27225956d55SAMS21 std::forward<absl::optional<int>>(opt).value(); 27325956d55SAMS21 } 27414bc11a6SQizhi Hu 27514bc11a6SQizhi Hu namespace std { 27614bc11a6SQizhi Hu 27714bc11a6SQizhi Hu template <typename T> class vector { 27814bc11a6SQizhi Hu public: 27914bc11a6SQizhi Hu T &operator[](unsigned long index); 28014bc11a6SQizhi Hu bool empty(); 28114bc11a6SQizhi Hu }; 28214bc11a6SQizhi Hu 28314bc11a6SQizhi Hu } // namespace std 28414bc11a6SQizhi Hu 28514bc11a6SQizhi Hu struct S { 28614bc11a6SQizhi Hu absl::optional<float> x; 28714bc11a6SQizhi Hu }; 28814bc11a6SQizhi Hu std::vector<S> vec; 28914bc11a6SQizhi Hu 29014bc11a6SQizhi Hu void foo() { 29114bc11a6SQizhi Hu if (!vec.empty()) 29214bc11a6SQizhi Hu vec[0].x = 0; 29314bc11a6SQizhi Hu } 294