1// RUN: %check_clang_tidy -std=c++17-or-later %s bugprone-optional-value-conversion %t -- --fix-notes
2// RUN: %check_clang_tidy -check-suffix=CUSTOM -std=c++17-or-later %s bugprone-optional-value-conversion %t -- \
3// RUN: -config="{CheckOptions: {bugprone-optional-value-conversion.OptionalTypes: 'CustomOptional', \
4// RUN: bugprone-optional-value-conversion.ValueMethods: '::Read$;::Ooo$'}}" --fix-notes
5
6namespace std {
7 template<typename T>
8 struct optional
9 {
10 constexpr optional() noexcept;
11 constexpr optional(T&&) noexcept;
12 constexpr optional(const T&) noexcept;
13 template<typename U>
14 constexpr optional(U&&) noexcept;
15 const T& operator*() const;
16 T* operator->();
17 const T* operator->() const;
18 T& operator*();
19 const T& value() const;
20 T& value();
21 const T& get() const;
22 T& get();
23 T value_or(T) const;
24 };
25
26 template <class T>
27 T&& move(T &x) {
28 return static_cast<T&&>(x);
29 }
30}
31
32namespace boost {
33 template<typename T>
34 struct optional {
35 constexpr optional() noexcept;
36 constexpr optional(const T&) noexcept;
37 const T& operator*() const;
38 const T& get() const;
39 };
40}
41
42namespace absl {
43 template<typename T>
44 struct optional {
45 constexpr optional() noexcept;
46 constexpr optional(const T&) noexcept;
47 const T& operator*() const;
48 const T& value() const;
49 };
50}
51
52template<typename T>
53struct CustomOptional {
54 CustomOptional();
55 CustomOptional(const T&);
56 const T& Read() const;
57 T& operator*();
58 T& Ooo();
59};
60
61void takeOptionalValue(std::optional<int>);
62void takeOptionalRef(const std::optional<int>&);
63void takeOptionalRRef(std::optional<int>&&);
64void takeOtherOptional(std::optional<long>);
65void takeBOptionalValue(boost::optional<int>);
66void takeAOptionalValue(absl::optional<int>);
67
68void incorrect(std::optional<int> param)
69{
70 std::optional<int>* ptr = &param;
71 takeOptionalValue(**ptr);
72 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
73 // CHECK-FIXES: takeOptionalValue(*ptr);
74 takeOptionalValue(*param);
75 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
76 // CHECK-FIXES: takeOptionalValue(param);
77 takeOptionalValue(param.value());
78 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
79 // CHECK-FIXES: takeOptionalValue(param);
80 takeOptionalValue(ptr->value());
81 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
82 // CHECK-FIXES: takeOptionalValue(*ptr);
83 takeOptionalValue(param.operator*());
84 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
85 // CHECK-FIXES: takeOptionalValue(param);
86 takeOptionalValue(ptr->operator*());
87 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
88 // CHECK-FIXES: takeOptionalValue(*ptr);
89 takeOptionalRef(*param);
90 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
91 // CHECK-FIXES: takeOptionalRef(param);
92 takeOptionalRef(param.value());
93 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
94 // CHECK-FIXES: takeOptionalRef(param);
95 takeOptionalRef(ptr->value());
96 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
97 // CHECK-FIXES: takeOptionalRef(*ptr);
98 takeOptionalRef(param.operator*());
99 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
100 // CHECK-FIXES: takeOptionalRef(param);
101 takeOptionalRef(ptr->operator*());
102 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
103 // CHECK-FIXES: takeOptionalRef(*ptr);
104 std::optional<int> p = *param;
105 // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
106 // CHECK-FIXES: std::optional<int> p = param;
107
108 takeOptionalValue(std::move(**ptr));
109 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
110 // CHECK-FIXES: takeOptionalValue(std::move(*ptr));
111 takeOptionalValue(std::move(*param));
112 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
113 // CHECK-FIXES: takeOptionalValue(std::move(param));
114 takeOptionalValue(std::move(param.value()));
115 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
116 // CHECK-FIXES: takeOptionalValue(std::move(param));
117 takeOptionalValue(std::move(ptr->value()));
118 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
119 // CHECK-FIXES: takeOptionalValue(std::move(*ptr));
120 takeOptionalValue(std::move(param.operator*()));
121 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
122 // CHECK-FIXES: takeOptionalValue(std::move(param));
123 takeOptionalRef(std::move(*param));
124 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
125 // CHECK-FIXES: takeOptionalRef(std::move(param));
126 takeOptionalRef(std::move(param.value()));
127 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
128 // CHECK-FIXES: takeOptionalRef(std::move(param));
129 takeOptionalRef(std::move(ptr->value()));
130 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
131 // CHECK-FIXES: takeOptionalRef(std::move(*ptr));
132 takeOptionalRef(std::move(param.operator*()));
133 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
134 // CHECK-FIXES: takeOptionalRef(std::move(param));
135 takeOptionalRRef(std::move(*param));
136 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
137 // CHECK-FIXES: takeOptionalRRef(std::move(param));
138 takeOptionalRRef(std::move(param.value()));
139 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
140 // CHECK-FIXES: takeOptionalRRef(std::move(param));
141 takeOptionalRRef(std::move(ptr->value()));
142 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
143 // CHECK-FIXES: takeOptionalRRef(std::move(*ptr));
144 takeOptionalRRef(std::move(param.operator*()));
145 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
146 // CHECK-FIXES: takeOptionalRRef(std::move(param));
147 takeOptionalRRef(std::move(ptr->operator*()));
148 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
149 // CHECK-FIXES: takeOptionalRRef(std::move(*ptr));
150 std::optional<int> p2 = std::move(*param);
151 // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
152 // CHECK-FIXES: std::optional<int> p2 = std::move(param);
153
154 std::optional<std::optional<int>> opt;
155 takeOptionalValue(opt->value());
156 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
157 // CHECK-FIXES: takeOptionalValue(*opt);
158 takeOptionalValue(opt->operator*());
159 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
160 // CHECK-FIXES: takeOptionalValue(*opt);
161
162 boost::optional<int> bopt;
163 takeBOptionalValue(*bopt);
164 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: conversion from 'boost::optional<int>' into 'int' and back into 'boost::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
165 // CHECK-FIXES: takeBOptionalValue(bopt);
166 takeBOptionalValue(bopt.get());
167 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: conversion from 'boost::optional<int>' into 'int' and back into 'boost::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
168 // CHECK-FIXES: takeBOptionalValue(bopt);
169
170 absl::optional<int> aopt;
171 takeAOptionalValue(*aopt);
172 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: conversion from 'absl::optional<int>' into 'int' and back into 'absl::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
173 // CHECK-FIXES: takeAOptionalValue(aopt);
174 takeAOptionalValue(aopt.value());
175 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: conversion from 'absl::optional<int>' into 'int' and back into 'absl::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
176 // CHECK-FIXES: takeAOptionalValue(aopt);
177}
178
179void takeCustom(const CustomOptional<int>&);
180
181void testCustom(CustomOptional<int> param) {
182 takeCustom(*param);
183 // CHECK-MESSAGES-CUSTOM: :[[@LINE-1]]:14: warning: conversion from 'CustomOptional<int>' into 'int' and back into 'CustomOptional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
184 // CHECK-FIXES-CUSTOM: takeCustom(param);
185 takeCustom(param.Read());
186 // CHECK-MESSAGES-CUSTOM: :[[@LINE-1]]:14: warning: conversion from 'CustomOptional<int>' into 'int' and back into 'CustomOptional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
187 // CHECK-FIXES-CUSTOM: takeCustom(param);
188 takeCustom(param.Ooo());
189 // CHECK-MESSAGES-CUSTOM: :[[@LINE-1]]:14: warning: conversion from 'CustomOptional<int>' into 'int' and back into 'CustomOptional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
190 // CHECK-FIXES-CUSTOM: takeCustom(param);
191}
192
193void correct(std::optional<int> param)
194{
195 takeOtherOptional(*param);
196 takeOtherOptional(param.value());
197 takeOtherOptional(param.value_or(5U));
198 takeOtherOptional(param.operator*());
199
200 std::optional<long> p = *param;
201 takeOptionalValue(param.value_or(5U));
202 takeOptionalRef(param.value_or(5U));
203
204 std::optional<int>* ptr = &param;
205 takeOtherOptional(**ptr);
206 takeOtherOptional(ptr->value());
207 takeOtherOptional(ptr->value_or(5U));
208 takeOtherOptional(ptr->operator*());
209
210 std::optional<long>* p2 = &p;
211 takeOptionalValue(p2->value_or(5U));
212 takeOptionalRef(p2->value_or(5U));
213}
214

source code of clang-tools-extra/test/clang-tidy/checkers/bugprone/optional-value-conversion.cpp