[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / clang-tools-extra / docs / clang-tidy / checks / bugprone / signed-char-misuse.rst
blob72860e8cf2a1d440521f5186bfc6f01798f30320
1 .. title:: clang-tidy - bugprone-signed-char-misuse
3 bugprone-signed-char-misuse
4 ===========================
6 `cert-str34-c` redirects here as an alias for this check. For the CERT alias,
7 the `DiagnoseSignedUnsignedCharComparisons` option is set to `false`.
9 Finds those ``signed char`` -> integer conversions which might indicate a
10 programming error. The basic problem with the ``signed char``, that it might
11 store the non-ASCII characters as negative values. This behavior can cause a
12 misunderstanding of the written code both when an explicit and when an
13 implicit conversion happens.
15 When the code contains an explicit ``signed char`` -> integer conversion, the
16 human programmer probably expects that the converted value matches with the
17 character code (a value from [0..255]), however, the actual value is in
18 [-128..127] interval. To avoid this kind of misinterpretation, the desired way
19 of converting from a ``signed char`` to an integer value is converting to
20 ``unsigned char`` first, which stores all the characters in the positive [0..255]
21 interval which matches the known character codes.
23 In case of implicit conversion, the programmer might not actually be aware
24 that a conversion happened and char value is used as an integer. There are
25 some use cases when this unawareness might lead to a functionally imperfect code.
26 For example, checking the equality of a ``signed char`` and an ``unsigned char``
27 variable is something we should avoid in C++ code. During this comparison,
28 the two variables are converted to integers which have different value ranges.
29 For ``signed char``, the non-ASCII characters are stored as a value in [-128..-1]
30 interval, while the same characters are stored in the [128..255] interval for
31 an ``unsigned char``.
33 It depends on the actual platform whether plain ``char`` is handled as ``signed char``
34 by default and so it is caught by this check or not. To change the default behavior
35 you can use ``-funsigned-char`` and ``-fsigned-char`` compilation options.
37 Currently, this check warns in the following cases:
38 - ``signed char`` is assigned to an integer variable
39 - ``signed char`` and ``unsigned char`` are compared with equality/inequality operator
40 - ``signed char`` is converted to an integer in the array subscript
42 See also:
43 `STR34-C. Cast characters to unsigned char before converting to larger integer sizes
44 <https://wiki.sei.cmu.edu/confluence/display/c/STR34-C.+Cast+characters+to+unsigned+char+before+converting+to+larger+integer+sizes>`_
46 A good example from the CERT description when a ``char`` variable is used to
47 read from a file that might contain non-ASCII characters. The problem comes
48 up when the code uses the ``-1`` integer value as EOF, while the 255 character
49 code is also stored as ``-1`` in two's complement form of char type.
50 See a simple example of this below. This code stops not only when it reaches
51 the end of the file, but also when it gets a character with the 255 code.
53 .. code-block:: c++
55   #define EOF (-1)
57   int read(void) {
58     char CChar;
59     int IChar = EOF;
61     if (readChar(CChar)) {
62       IChar = CChar;
63     }
64     return IChar;
65   }
67 A proper way to fix the code above is converting the ``char`` variable to
68 an ``unsigned char`` value first.
70 .. code-block:: c++
72   #define EOF (-1)
74   int read(void) {
75     char CChar;
76     int IChar = EOF;
78     if (readChar(CChar)) {
79       IChar = static_cast<unsigned char>(CChar);
80     }
81     return IChar;
82   }
84 Another use case is checking the equality of two ``char`` variables with
85 different signedness. Inside the non-ASCII value range this comparison between
86 a ``signed char`` and an ``unsigned char`` always returns ``false``.
88 .. code-block:: c++
90   bool compare(signed char SChar, unsigned char USChar) {
91     if (SChar == USChar)
92       return true;
93     return false;
94   }
96 The easiest way to fix this kind of comparison is casting one of the arguments,
97 so both arguments will have the same type.
99 .. code-block:: c++
101   bool compare(signed char SChar, unsigned char USChar) {
102     if (static_cast<unsigned char>(SChar) == USChar)
103       return true;
104     return false;
105   }
107 .. option:: CharTypdefsToIgnore
109   A semicolon-separated list of typedef names. In this list, we can list
110   typedefs for ``char`` or ``signed char``, which will be ignored by the
111   check. This is useful when a typedef introduces an integer alias like
112   ``sal_Int8`` or ``int8_t``. In this case, human misinterpretation is not
113   an issue.
115 .. option:: DiagnoseSignedUnsignedCharComparisons
117   When `true`, the check will warn on ``signed char``/``unsigned char`` comparisons,
118   otherwise these comparisons are ignored. By default, this option is set to `true`.