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)63inline 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() const91inline B::operator double() const { return 0.0; } 92 93 struct StructWithFnPointer { 94 void (*f)(); __anon06d70b7a0102null95} 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)146void 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()169void 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