1 | // RUN: %check_clang_tidy %s google-explicit-constructor %t |
2 | |
3 | namespace std { |
4 | typedef decltype(sizeof(int)) size_t; |
5 | |
6 | // libc++'s implementation |
7 | template <class _E> |
8 | class initializer_list |
9 | { |
10 | const _E* __begin_; |
11 | size_t __size_; |
12 | |
13 | initializer_list(const _E* __b, size_t __s) |
14 | : __begin_(__b), |
15 | __size_(__s) |
16 | {} |
17 | |
18 | public: |
19 | typedef _E value_type; |
20 | typedef const _E& reference; |
21 | typedef const _E& const_reference; |
22 | typedef size_t size_type; |
23 | |
24 | typedef const _E* iterator; |
25 | typedef const _E* const_iterator; |
26 | |
27 | initializer_list() : __begin_(nullptr), __size_(0) {} |
28 | |
29 | size_t size() const {return __size_;} |
30 | const _E* begin() const {return __begin_;} |
31 | const _E* end() const {return __begin_ + __size_;} |
32 | }; |
33 | } |
34 | |
35 | struct A { |
36 | A() {} |
37 | A(int x, int y) {} |
38 | |
39 | explicit A(void *x) {} |
40 | explicit A(void *x, void *y) {} |
41 | explicit operator bool() const { return true; } |
42 | |
43 | operator double() const = delete; |
44 | |
45 | explicit A(const A& a) {} |
46 | // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: copy constructor should not be declared explicit [google-explicit-constructor] |
47 | // CHECK-FIXES: {{^ }}A(const A& a) {} |
48 | |
49 | A(int x1); |
50 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: single-argument constructors must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] |
51 | // CHECK-FIXES: {{^ }}explicit A(int x1); |
52 | |
53 | A(double x2, double y = 3.14) {} |
54 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructors that are callable with a single argument must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] |
55 | // CHECK-FIXES: {{^ }}explicit A(double x2, double y = 3.14) {} |
56 | |
57 | template <typename... T> |
58 | A(T&&... args); |
59 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructors that are callable with a single argument |
60 | // CHECK-FIXES: {{^ }}explicit A(T&&... args); |
61 | }; |
62 | |
63 | inline A::A(int x1) {} |
64 | |
65 | struct B { |
66 | B(std::initializer_list<int> list1) {} |
67 | B(const std::initializer_list<unsigned> &list2) {} |
68 | B(std::initializer_list<unsigned> &&list3) {} |
69 | |
70 | operator bool() const { return true; } |
71 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'operator bool' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] |
72 | // CHECK-FIXES: {{^ }}explicit operator bool() const { return true; } |
73 | |
74 | operator double() const; |
75 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'operator double' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] |
76 | // CHECK-FIXES: {{^ }}explicit operator double() const; |
77 | |
78 | explicit B(::std::initializer_list<double> list4) {} |
79 | // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: initializer-list constructor should not be declared explicit [google-explicit-constructor] |
80 | // CHECK-FIXES: {{^ }}B(::std::initializer_list<double> list4) {} |
81 | |
82 | explicit B(const ::std::initializer_list<char> &list5) {} |
83 | // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: initializer-list constructor |
84 | // CHECK-FIXES: {{^ }}B(const ::std::initializer_list<char> &list5) {} |
85 | |
86 | explicit B(::std::initializer_list<char> &&list6) {} |
87 | // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: initializer-list constructor |
88 | // CHECK-FIXES: {{^ }}B(::std::initializer_list<char> &&list6) {} |
89 | }; |
90 | |
91 | inline B::operator double() const { return 0.0; } |
92 | |
93 | struct StructWithFnPointer { |
94 | void (*f)(); |
95 | } struct_with_fn_pointer = {.f: [] {}}; |
96 | |
97 | using namespace std; |
98 | |
99 | struct C { |
100 | C(initializer_list<int> list1) {} |
101 | C(const initializer_list<unsigned> &list2) {} |
102 | C(initializer_list<unsigned> &&list3) {} |
103 | }; |
104 | |
105 | template <typename T> |
106 | struct C2 { |
107 | C2(initializer_list<int> list1) {} |
108 | C2(const initializer_list<unsigned> &list2) {} |
109 | C2(initializer_list<unsigned> &&list3) {} |
110 | |
111 | explicit C2(initializer_list<double> list4) {} |
112 | // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: initializer-list constructor |
113 | // CHECK-FIXES: {{^ }}C2(initializer_list<double> list4) {} |
114 | }; |
115 | |
116 | template <typename T> |
117 | struct C3 { |
118 | C3(initializer_list<T> list1) {} |
119 | C3(const std::initializer_list<T*> &list2) {} |
120 | C3(::std::initializer_list<T**> &&list3) {} |
121 | |
122 | template <typename U> |
123 | C3(initializer_list<U> list3) {} |
124 | }; |
125 | |
126 | struct D { |
127 | template <typename T> |
128 | explicit D(T t) {} |
129 | }; |
130 | |
131 | template <typename T> |
132 | struct E { |
133 | E(T *pt) {} |
134 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: single-argument constructors |
135 | // CHECK-FIXES: {{^ }}explicit E(T *pt) {} |
136 | template <typename U> |
137 | E(U *pu) {} |
138 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: single-argument constructors |
139 | // CHECK-FIXES: {{^ }}explicit E(U *pu) {} |
140 | |
141 | explicit E(T t) {} |
142 | template <typename U> |
143 | explicit E(U u) {} |
144 | }; |
145 | |
146 | void f(std::initializer_list<int> list) { |
147 | D d(list); |
148 | E<decltype(list)> e(list); |
149 | E<int> e2(list); |
150 | } |
151 | |
152 | template <typename T> |
153 | struct F {}; |
154 | |
155 | template<typename T> |
156 | struct G { |
157 | operator bool() const; |
158 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'operator bool' must be marked |
159 | // CHECK-FIXES: {{^}} explicit operator bool() const; |
160 | operator F<T>() const; |
161 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'operator F<type-parameter-0-0>' must be marked |
162 | // CHECK-FIXES: {{^}} explicit operator F<T>() const; |
163 | template<typename U> |
164 | operator F<U>*() const; |
165 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'operator F<type-parameter-1-0> *' must be marked |
166 | // CHECK-FIXES: {{^}} explicit operator F<U>*() const; |
167 | }; |
168 | |
169 | void f2() { |
170 | G<int> a; |
171 | (void)(F<int>)a; |
172 | if (a) {} |
173 | (void)(F<int>*)a; |
174 | (void)(F<int*>*)a; |
175 | |
176 | G<double> b; |
177 | (void)(F<double>)b; |
178 | if (b) {} |
179 | (void)(F<double>*)b; |
180 | (void)(F<double*>*)b; |
181 | } |
182 | |
183 | #define DEFINE_STRUCT_WITH_OPERATOR_BOOL(name) \ |
184 | struct name { \ |
185 | operator bool() const; \ |
186 | } |
187 | |
188 | DEFINE_STRUCT_WITH_OPERATOR_BOOL(H); |
189 | |