brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.6 KiB · 4b98c36 Raw
126 lines · plain
1.. title:: clang-tidy - bugprone-signed-char-misuse2 3bugprone-signed-char-misuse4===========================5 6`cert-str34-c` redirects here as an alias for this check. For the CERT alias,7the `DiagnoseSignedUnsignedCharComparisons` option is set to `false`.8 9Finds those ``signed char`` -> integer conversions which might indicate a10programming error. The basic problem with the ``signed char``, that it might11store the non-ASCII characters as negative values. This behavior can cause a12misunderstanding of the written code both when an explicit and when an13implicit conversion happens.14 15When the code contains an explicit ``signed char`` -> integer conversion, the16human programmer probably expects that the converted value matches with the17character code (a value from [0..255]), however, the actual value is in18[-128..127] interval. To avoid this kind of misinterpretation, the desired way19of converting from a ``signed char`` to an integer value is converting to20``unsigned char`` first, which stores all the characters in the positive21[0..255] interval which matches the known character codes.22 23In case of implicit conversion, the programmer might not actually be aware24that a conversion happened and char value is used as an integer. There are25some use cases when this unawareness might lead to a functionally imperfect26code. For example, checking the equality of a ``signed char`` and an27``unsigned char`` variable is something we should avoid in C++ code. During28this comparison, the two variables are converted to integers which have29different value ranges. For ``signed char``, the non-ASCII characters are30stored as a value in [-128..-1] interval, while the same characters are31stored in the [128..255] interval for an ``unsigned char``.32 33It depends on the actual platform whether plain ``char`` is handled as34``signed char`` by default and so it is caught by this check or not.35To change the default behavior you can use ``-funsigned-char`` and36``-fsigned-char`` compilation options.37 38Currently, this check warns in the following cases:39 40- ``signed char`` is assigned to an integer variable41- ``signed char`` and ``unsigned char`` are compared with42  equality/inequality operator43- ``signed char`` is converted to an integer in the array subscript44 45See also:46`STR34-C. Cast characters to unsigned char before converting to larger47integer sizes48<https://wiki.sei.cmu.edu/confluence/display/c/STR34-C.+Cast+characters+to+unsigned+char+before+converting+to+larger+integer+sizes>`_49 50A good example from the CERT description when a ``char`` variable is used to51read from a file that might contain non-ASCII characters. The problem comes52up when the code uses the ``-1`` integer value as EOF, while the 255 character53code is also stored as ``-1`` in two's complement form of char type.54See a simple example of this below. This code stops not only when it reaches55the end of the file, but also when it gets a character with the 255 code.56 57.. code-block:: c++58 59  #define EOF (-1)60 61  int read(void) {62    char CChar;63    int IChar = EOF;64 65    if (readChar(CChar)) {66      IChar = CChar;67    }68    return IChar;69  }70 71A proper way to fix the code above is converting the ``char`` variable to72an ``unsigned char`` value first.73 74.. code-block:: c++75 76  #define EOF (-1)77 78  int read(void) {79    char CChar;80    int IChar = EOF;81 82    if (readChar(CChar)) {83      IChar = static_cast<unsigned char>(CChar);84    }85    return IChar;86  }87 88Another use case is checking the equality of two ``char`` variables with89different signedness. Inside the non-ASCII value range this comparison between90a ``signed char`` and an ``unsigned char`` always returns ``false``.91 92.. code-block:: c++93 94  bool compare(signed char SChar, unsigned char USChar) {95    if (SChar == USChar)96      return true;97    return false;98  }99 100The easiest way to fix this kind of comparison is casting one of the arguments,101so both arguments will have the same type.102 103.. code-block:: c++104 105  bool compare(signed char SChar, unsigned char USChar) {106    if (static_cast<unsigned char>(SChar) == USChar)107      return true;108    return false;109  }110 111Options112-------113 114.. option:: CharTypedefsToIgnore115 116  A semicolon-separated list of typedef names. In this list, we can list117  typedefs for ``char`` or ``signed char``, which will be ignored by the118  check. This is useful when a typedef introduces an integer alias like119  ``sal_Int8`` or ``int8_t``. In this case, human misinterpretation is not120  an issue. Default is an empty string.121 122.. option:: DiagnoseSignedUnsignedCharComparisons123 124  When `true`, the check will warn on ``signed char``/``unsigned char`` comparisons,125  otherwise these comparisons are ignored. By default, this option is set to `true`.126