|
| 1 | +.. title:: clang-tidy - modernize-avoid-fundamental-integer-types |
| 2 | + |
| 3 | +modernize-avoid-fundamental-integer-types |
| 4 | +========================================== |
| 5 | + |
| 6 | +Finds fundamental integer types and recommends using typedefs or fixed-width types instead. |
| 7 | + |
| 8 | +This check detects fundamental integer types (``int``, ``short``, ``long``, ``long long``, and their |
| 9 | +``unsigned`` variants) and warns against their use due to non-standard platform-dependent behavior. |
| 10 | +For example, ``long`` is 64 bits on Linux but 32 bits on Windows. There is no standard rationale or |
| 11 | +intent for the sizes of these types. |
| 12 | + |
| 13 | +Instead of fundamental types, use fixed-width types such as ``int32_t`` or implementation-defined |
| 14 | +types with standard semantics, e.g. ``int_fast32_t`` for the fastest integer type greater than or |
| 15 | +equal to 32 bits. |
| 16 | + |
| 17 | +Examples |
| 18 | +-------- |
| 19 | + |
| 20 | +.. code-block:: c++ |
| 21 | + |
| 22 | + // Bad: platform-dependent fundamental types |
| 23 | + int global_int = 42; |
| 24 | + short global_short = 10; |
| 25 | + long global_long = 100L; |
| 26 | + unsigned long global_unsigned_long = 100UL; |
| 27 | + |
| 28 | + void function_with_int_param(int param) { |
| 29 | + // ... |
| 30 | + } |
| 31 | + |
| 32 | + int function_returning_int() { |
| 33 | + return 42; |
| 34 | + } |
| 35 | + |
| 36 | + struct MyStruct { |
| 37 | + int member_int; |
| 38 | + long member_long; |
| 39 | + }; |
| 40 | + |
| 41 | +.. code-block:: c++ |
| 42 | + |
| 43 | + // Good: use fixed-width types or typedefs |
| 44 | + #include <cstdint> |
| 45 | + |
| 46 | + int32_t global_int32 = 42; |
| 47 | + int16_t global_int16 = 10; |
| 48 | + int64_t global_int64 = 100L; |
| 49 | + uint64_t global_uint64 = 100UL; |
| 50 | + |
| 51 | + void function_with_int32_param(int32_t param) { |
| 52 | + // ... |
| 53 | + } |
| 54 | + |
| 55 | + int32_t function_returning_int32() { |
| 56 | + return 42; |
| 57 | + } |
| 58 | + |
| 59 | + struct MyStruct { |
| 60 | + int32_t member_int32; |
| 61 | + int64_t member_int64; |
| 62 | + }; |
| 63 | + |
| 64 | +The check will also warn about typedef declarations that use fundamental types as their underlying type: |
| 65 | + |
| 66 | +.. code-block:: c++ |
| 67 | + |
| 68 | + // Bad: typedef using fundamental type |
| 69 | + typedef long long MyLongType; |
| 70 | + using MyIntType = int; |
| 71 | + |
| 72 | +.. code-block:: c++ |
| 73 | + |
| 74 | + // Good: use descriptive names or fixed-width types |
| 75 | + typedef int64_t TimestampType; |
| 76 | + using CounterType = uint32_t; |
| 77 | + |
| 78 | +Rationale |
| 79 | +--------- |
| 80 | + |
| 81 | +Fundamental integer types have platform-dependent sizes and behavior: |
| 82 | + |
| 83 | +- ``int`` is typically 32 bits on modern platforms but is only guaranteed to be 16 bits by the spec |
| 84 | +- ``long int`` is 32 bits on Windows but 64 bits on most Unix systems |
| 85 | + |
| 86 | +The C++ specification does not define these types beyond their minimum sizes. That means they can |
| 87 | +communicate intent in non-standard ways and are often needlessly incompatible. For example, ``int`` |
| 88 | +was traditionally the word size of a given processor in 16-bit and 32-bit computing and was a |
| 89 | +reasonable default for performance. This is no longer true on modern 64-bit computers, but the size |
| 90 | +of ``int`` remains fixed at 32 bits for backwards compatibility with code that relied on a 32-bit |
| 91 | +implementation of ``int``. |
| 92 | + |
| 93 | +If code is explicitly relying on the size of an ``int`` being 32 bits, it is better to say so in |
| 94 | +the typename with ``int32_t``. Otherwise, use an appropriate implementation-defined type that |
| 95 | +communicates your intent. |
| 96 | + |
| 97 | +Types Not Flagged |
| 98 | +----------------- |
| 99 | + |
| 100 | +The following types are intentionally not flagged: |
| 101 | + |
| 102 | +- ``char``, ``signed char``, ``unsigned char`` (character types) |
| 103 | +- ``bool`` (boolean type) |
| 104 | +- Standard library typedefs like ``size_t``, ``ptrdiff_t``, or ``uint32_t``. |
| 105 | +- Already typedef'd types, though the check will flag the typedef itself |
| 106 | + |
| 107 | +``char`` is excluded because it is implementation-defined to always be 1 byte, regardless of the |
| 108 | +platform's definition of a byte. |
| 109 | + |
| 110 | +``bool`` is excluded because it can only be true or false, and is not vulnerable to overflow or |
| 111 | +narrowing issues that occur as a result of using implementation-defined types. |
0 commit comments