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 
initializer_list(const _E * __b,size_t __s)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 
initializer_list()27     initializer_list() : __begin_(nullptr), __size_(0) {}
28 
size() const29     size_t    size()  const {return __size_;}
begin() const30     const _E* begin() const {return __begin_;}
end() const31     const _E* end()   const {return __begin_ + __size_;}
32   };
33 }
34 
35 struct A {
AA36   A() {}
AA37   A(int x, int y) {}
38 
AA39   explicit A(void *x) {}
AA40   explicit A(void *x, void *y) {}
operator boolA41   explicit operator bool() const { return true; }
42 
43   operator double() const = delete;
44 
AA45   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 
AA53   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 
A(int x1)63 inline A::A(int x1) {}
64 
65 struct B {
BB66   B(std::initializer_list<int> list1) {}
BB67   B(const std::initializer_list<unsigned> &list2) {}
BB68   B(std::initializer_list<unsigned> &&list3) {}
69 
operator boolB70   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 
BB78   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 
BB82   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 
BB86   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 
operator double() const91 inline B::operator double() const { return 0.0; }
92 
93 struct StructWithFnPointer {
94   void (*f)();
__anona62eef5c0102null95 } struct_with_fn_pointer = {[] {}};
96 
97 using namespace std;
98 
99 struct C {
CC100   C(initializer_list<int> list1) {}
CC101   C(const initializer_list<unsigned> &list2) {}
CC102   C(initializer_list<unsigned> &&list3) {}
103 };
104 
105 template <typename T>
106 struct C2 {
C2C2107   C2(initializer_list<int> list1) {}
C2C2108   C2(const initializer_list<unsigned> &list2) {}
C2C2109   C2(initializer_list<unsigned> &&list3) {}
110 
C2C2111   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 {
C3C3118   C3(initializer_list<T> list1) {}
C3C3119   C3(const std::initializer_list<T*> &list2) {}
C3C3120   C3(::std::initializer_list<T**> &&list3) {}
121 
122   template <typename U>
C3C3123   C3(initializer_list<U> list3) {}
124 };
125 
126 struct D {
127   template <typename T>
DD128   explicit D(T t) {}
129 };
130 
131 template <typename T>
132 struct E {
EE133   E(T *pt) {}
134   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: single-argument constructors
135   // CHECK-FIXES: {{^  }}explicit E(T *pt) {}
136   template <typename U>
EE137   E(U *pu) {}
138   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: single-argument constructors
139   // CHECK-FIXES: {{^  }}explicit E(U *pu) {}
140 
EE141   explicit E(T t) {}
142   template <typename U>
EE143   explicit E(U u) {}
144 };
145 
f(std::initializer_list<int> list)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 
f2()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