@@ -144,11 +144,12 @@ value truncation, the ``-Wconstant-conversion`` warning behavior depends on
144
144
the **destination type **:
145
145
146
146
* **Destination is wrapping type **
147
- (``__attribute__((overflow_behavior(wrap))) ``): No warning is issued because
148
- truncation with wrapping behavior is expected and well-defined.
147
+ (``__attribute__((overflow_behavior(wrap))) ``): No warning is issued
148
+ regardless of compiler flags because truncation with wrapping behavior is
149
+ expected and well-defined.
149
150
150
- * **Destination is non-wrapping or standard type **: Warning is issued if the
151
- constant value would be truncated .
151
+ * **Destination is non-wrapping or standard type **: Warnings are issued based
152
+ on compiler flags .
152
153
153
154
.. code-block :: c++
154
155
@@ -165,6 +166,38 @@ This rule ensures that explicit use of wrapping types suppresses warnings
165
166
only when the destination is intended to wrap, while preserving warnings
166
167
for potentially unintended truncation to standard or non-wrapping types.
167
168
169
+ See below for more details specifically regarding implicit conversions due to
170
+ assignment.
171
+
172
+ Implicit Conversions Due to Assignment
173
+ --------------------------------------
174
+
175
+ Like with the basic integral types in C and C++, types on the right-hand side
176
+ of an assignment may be implicitly converted to match the left-hand side.
177
+
178
+ All built-in integral types can be implicitly converted to an overflow behavior
179
+ version.
180
+
181
+ .. code-block :: c++
182
+
183
+ char x = 1;
184
+ int __attribute__((overflow_behavior(wrap))) a = x; // x converted to int __attribute__((overflow_behavior(wrap)))
185
+
186
+ When assigning one overflow behavior type to another, the left-hand side's type
187
+ is always used - just like with traditional integer types.
188
+
189
+ .. code-block :: c++
190
+
191
+ long __attribute__((overflow_behavior(wrap))) x = __LONG_MAX__;
192
+ int __attribute__((overflow_behavior(no_wrap))) a = x; // x converted to int __attribute__((overflow_behavior(no_wrap)))
193
+
194
+ For the purposes of truncation warnings from UBSAN or ``-Wconversion ``, the
195
+ left-hand side's overflow behavior determines the instrumentation and
196
+ reporting. For example, the code above would cause a ``-Wshorten-64-to-32 ``
197
+ warning. Swapping the overflow behavior kinds in the above example would not
198
+ result in a warning diagnostic as the left-hand side would be ``wraps `` which
199
+ silences any truncation warnings.
200
+
168
201
C++ Narrowing Conversions
169
202
-------------------------
170
203
@@ -207,8 +240,8 @@ The destination type also determines UBSan's
207
240
``__attribute__((overflow_behavior(wrap))) `` destinations suppress these UBSan
208
241
checks since truncation is expected and well-defined for wrapping types.
209
242
210
- C++ Template and Overload Resolution
211
- -------------------------------------
243
+ C++ Overload Resolution
244
+ -----------------------
212
245
213
246
For the purposes of C++ overload set formation, promotions or conversions to
214
247
and from overflow behavior types are of the same rank as normal integer
@@ -256,6 +289,62 @@ certain contexts.
256
289
Overflow behavior types may also be used as template parameters and used within
257
290
C ``_Generic `` expressions.
258
291
292
+ C _Generic Expressions
293
+ ----------------------
294
+
295
+ Overflow behavior types may be used within C ``_Generic `` expressions.
296
+
297
+ Overflow behavior types do not match against their underlying types within C
298
+ ``_Generic `` expressions. This means that an OBT will not be considered
299
+ equivalent to its base type for generic selection purposes. OBTs will match
300
+ against exact types considering bitwidth, signedness and overflow
301
+ behavior kind.
302
+
303
+ .. code-block :: c++
304
+
305
+ typedef int __attribute__((overflow_behavior(wrap))) wrap_int;
306
+
307
+ int foo(wrap_int x) {
308
+ return _Generic(x, int: 1, char: 2, default: 3); // returns 3
309
+ }
310
+
311
+ int bar(wrap_int x) {
312
+ return _Generic(x, wrap_int: 1, int: 2, default: 3); // returns 1
313
+ }
314
+
315
+
316
+ C++ Template Specializations
317
+ -----------------------------
318
+
319
+ Like with ``_Generic ``, each OBT is treated as a distinct type for template
320
+ specialization purposes, enabling precise type-based template selection.
321
+
322
+ .. code-block :: c++
323
+
324
+ template<typename T>
325
+ struct TypeProcessor {
326
+ static constexpr int value = 0; // default case
327
+ };
328
+
329
+ template<>
330
+ struct TypeProcessor<int> {
331
+ static constexpr int value = 1; // int specialization
332
+ };
333
+
334
+ template<>
335
+ struct TypeProcessor<int __attribute__((overflow_behavior(wrap)))> {
336
+ static constexpr int value = 2; // __wrap int specialization
337
+ };
338
+
339
+ template<>
340
+ struct TypeProcessor<int __attribute__((overflow_behavior(no_wrap)))> {
341
+ static constexpr int value = 3; // __no_wrap int specialization
342
+ };
343
+
344
+ When no exact template specialization exists for an OBT, it falls back to the
345
+ default template rather than matching the underlying type specialization,
346
+ maintaining type safety and avoiding unexpected behavior.
347
+
259
348
Interaction with Command-Line Flags and Sanitizer Special Case Lists
260
349
====================================================================
261
350
0 commit comments