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 | |
6 | namespace 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 | |
32 | namespace 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 | |
42 | namespace 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 | |
52 | template<typename T> |
53 | struct CustomOptional { |
54 | CustomOptional(); |
55 | CustomOptional(const T&); |
56 | const T& Read() const; |
57 | T& operator*(); |
58 | T& Ooo(); |
59 | }; |
60 | |
61 | void takeOptionalValue(std::optional<int>); |
62 | void takeOptionalRef(const std::optional<int>&); |
63 | void takeOptionalRRef(std::optional<int>&&); |
64 | void takeOtherOptional(std::optional<long>); |
65 | void takeBOptionalValue(boost::optional<int>); |
66 | void takeAOptionalValue(absl::optional<int>); |
67 | |
68 | void incorrect(std::optional<int> param) |
69 | { |
70 | std::optional<int>* ptr = ¶m; |
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 | |
179 | void takeCustom(const CustomOptional<int>&); |
180 | |
181 | void 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 | |
193 | void 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 = ¶m; |
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 | |