1// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t \
2// RUN: -std=c++17 -- -target x86_64-unknown-linux
3
4#define CHAR_BITS 8
5static_assert(sizeof(unsigned int) == 32 / CHAR_BITS);
6
7template <typename T, typename U>
8struct is_same {
9 static constexpr bool value = false;
10};
11template <typename T>
12struct is_same<T, T> {
13 static constexpr bool value = true;
14};
15
16template <typename T, typename U>
17static constexpr bool is_same_v = is_same<T, U>::value;
18
19struct NoBitfield {
20 unsigned int id;
21};
22struct SmallBitfield {
23 unsigned int id : 4;
24};
25
26struct BigBitfield {
27 unsigned int id : 31;
28};
29struct CompleteBitfield {
30 unsigned int id : 32;
31};
32
33int example_warning(unsigned x) {
34 // CHECK-MESSAGES: :[[@LINE+1]]:10: warning: narrowing conversion from 'unsigned int' to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
35 return x;
36}
37
38void test_binary_and(SmallBitfield x) {
39 static_assert(is_same_v<decltype(x.id & 1), int>);
40 static_assert(is_same_v<decltype(x.id & 1u), unsigned>);
41
42 x.id & 1;
43 x.id & 1u;
44
45 1 & x.id;
46 1u & x.id;
47}
48
49void test_binary_or(SmallBitfield x) {
50 static_assert(is_same_v<decltype(x.id | 1), int>);
51 static_assert(is_same_v<decltype(x.id | 1u), unsigned>);
52
53 x.id | 1;
54 x.id | 1u;
55
56 1 | x.id;
57 1u | x.id;
58}
59
60template <typename T>
61void take(T);
62
63void test_parameter_passing(NoBitfield x) {
64 take<char>(x.id);
65 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: narrowing conversion from 'unsigned int' to signed type 'char' is implementation-defined
66 take<short>(x.id);
67 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: narrowing conversion from 'unsigned int' to signed type 'short' is implementation-defined
68 take<unsigned>(x.id);
69 take<int>(x.id);
70 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: narrowing conversion from 'unsigned int' to signed type 'int' is implementation-defined
71 take<long>(x.id);
72 take<long long>(x.id);
73}
74
75void test_parameter_passing(SmallBitfield x) {
76 take<char>(x.id);
77 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: narrowing conversion from 'unsigned int' to signed type 'char' is implementation-defined
78 take<short>(x.id);
79 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: narrowing conversion from 'unsigned int' to signed type 'short' is implementation-defined
80 take<unsigned>(x.id);
81 take<int>(x.id); // no-warning
82 take<long>(x.id);
83 take<long long>(x.id);
84}
85
86void test_parameter_passing(BigBitfield x) {
87 take<char>(x.id);
88 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: narrowing conversion from 'unsigned int' to signed type 'char' is implementation-defined
89 take<short>(x.id);
90 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: narrowing conversion from 'unsigned int' to signed type 'short' is implementation-defined
91 take<unsigned>(x.id);
92 take<int>(x.id); // no-warning
93 take<long>(x.id);
94 take<long long>(x.id);
95}
96
97void test_parameter_passing(CompleteBitfield x) {
98 take<char>(x.id);
99 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: narrowing conversion from 'unsigned int' to signed type 'char' is implementation-defined
100 take<short>(x.id);
101 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: narrowing conversion from 'unsigned int' to signed type 'short' is implementation-defined
102 take<unsigned>(x.id);
103 take<int>(x.id);
104 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: narrowing conversion from 'unsigned int' to signed type 'int' is implementation-defined
105 take<long>(x.id);
106 take<long long>(x.id);
107}
108
109void test(NoBitfield x) {
110 static_assert(is_same_v<decltype(x.id << 1), unsigned>);
111 static_assert(is_same_v<decltype(x.id << 1u), unsigned>);
112 static_assert(is_same_v<decltype(x.id + 1), unsigned>);
113 static_assert(is_same_v<decltype(x.id + 1u), unsigned>);
114
115 x.id << 1;
116 x.id << 1u;
117 x.id >> 1;
118 x.id >> 1u;
119 x.id + 1;
120 x.id + 1u;
121
122 1 << x.id;
123 1u << x.id;
124 1 >> x.id;
125 1u >> x.id;
126 1 + x.id;
127 1u + x.id;
128}
129
130void test(SmallBitfield x) {
131 static_assert(is_same_v<decltype(x.id << 1), int>);
132 static_assert(is_same_v<decltype(x.id << 1u), int>);
133
134 x.id << 1;
135 x.id << 1u;
136 x.id >> 1;
137 x.id >> 1u;
138
139 x.id + 1;
140 x.id + 1u;
141
142 1 << x.id;
143 1u << x.id;
144 1 >> x.id;
145 1u >> x.id;
146
147 1 + x.id;
148 1u + x.id;
149}
150
151void test(BigBitfield x) {
152 static_assert(is_same_v<decltype(x.id << 1), int>);
153 static_assert(is_same_v<decltype(x.id << 1u), int>);
154
155 x.id << 1;
156 x.id << 1u;
157 x.id >> 1;
158 x.id >> 1u;
159
160 x.id + 1;
161 x.id + 1u;
162
163 1 << x.id;
164 1u << x.id;
165 1 >> x.id;
166 1u >> x.id;
167
168 1 + x.id;
169 1u + x.id;
170}
171
172void test(CompleteBitfield x) {
173 static_assert(is_same_v<decltype(x.id << 1), unsigned>);
174 static_assert(is_same_v<decltype(x.id << 1u), unsigned>);
175
176 x.id << 1;
177 x.id << 1u;
178 x.id >> 1;
179 x.id >> 1u;
180
181 x.id + 1;
182 x.id + 1u;
183
184 1 << x.id;
185 1u << x.id;
186 1 >> x.id;
187 1u >> x.id;
188
189 1 + x.id;
190 1u + x.id;
191}
192
193void test_parens(SmallBitfield x) {
194 static_assert(is_same_v<decltype(x.id << (2)), int>);
195 static_assert(is_same_v<decltype(((x.id)) << (2)), int>);
196 x.id << (2);
197 ((x.id)) << (2);
198
199 static_assert(is_same_v<decltype((2) << x.id), int>);
200 static_assert(is_same_v<decltype((2) << ((x.id))), int>);
201 (2) << x.id;
202 (2) << ((x.id));
203}
204

source code of clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-bitfields.cpp