Menu

Misra; essential types

2021-07-18
2021-10-13
  • Daniel Marjamäki

    I wonder if you have a better understanding of essential type than I?

    For instance, I want to implement misra rule 10.3. I have seen some example code here:

    https://gitlab.com/MISRA/MISRA-C/MISRA-C-2012/Example-Suite/-/blob/master/R_10_03.c

    I feel I need to understand these examples better.

    for instance:

    u8a = (uint16_t)2U + (uint16_t)3U; /* Compliant */
    u8a = (uint16_t)(2U + 3U); /* Non-compliant */
    

    Do you understand why the first expression is compliant (does that RHS have the essential type "unsigned char"?) and the second is not?

     
  • vix

    vix - 2021-07-19

    I try to give my point of view, besed on what I understood.

    In the first case, every constant value is first casted to uint16_t, and so the sum is the constant expression 5U. This expression fits into uint8_t type and so can be assigned to u8a (UTLR - the unsigned type having the lowest rank required to represent the value of a particular integer constant expression or the maximum value of a bit-field).

    In the second case, there is a constant expression (2U + 3U) which could be assigned directly to u8a, but then there is an explicit C-cast of this expression to uint16_t.
    This cast promotes the expression to the C standard type uint16_t, and this can't be assigned to u8a.

     
  • Daniel Marjamäki

    In the first case, every constant value is first casted to uint16_t, and so the sum is the constant expression 5U.

    Thanks for the explanation.. So the sum has a more narrow essential type than its operands. That is a bit weird imho. But it is a logic I can implement.

     
  • Daniel Marjamäki

    I have a doubt about our test code.
    https://github.com/danmar/cppcheck/blob/2.5/addons/test/misra/misra-test.c#L574

    The expression is c1 & c2. c1 and c2 are variables with type char. The essential types for c1 and c2 should be signed char shouldn't it? So 10.1 should not be reported for that?

     
    • Georgiy Komarov

      Georgiy Komarov - 2021-07-19

      Well, according to git blame, this was my fix for the false negative in rule 10.1: https://trac.cppcheck.net/ticket/9489 .

      This ticket contains a link to the following line in the example suite: https://gitlab.com/MISRA/MISRA-C/MISRA-C-2012/Example-Suite/blob/master/R_10_01.c#L77 . So, the test clearly implements this case.

       
      • Daniel Marjamäki

        Thanks! This is really tricky :-(

         

        Last edit: Daniel Marjamäki 2021-07-19
  • vix

    vix - 2021-07-19

    I'm not 100% sure, but I think that when bitwise operations are applied to signed narrow types, they're promoted to int.
    And so the misra violation comes.

     
  • Daniel Marjamäki

    I'm not 100% sure, but I think that when bitwise operations are applied to signed narrow types, they're promoted to int.

    Well according to the C standard.. both signed char and unsigned char will be promoted to int. So yes technically it will be int no matter what sign there is. I just rewrite the test for now..

    I have the feeling we need to review the handling of essential types in misra.py. Somebody should run through the examples here:
    https://gitlab.com/MISRA/MISRA-C/MISRA-C-2012/Example-Suite/-/blob/master/

     
  • Georgiy Komarov

    Georgiy Komarov - 2021-07-19

    I'm not sure about the question in the OP post. But here is my understanding of the example in the test suite.

    The first example has a rvalue with 5U value, without explicit specification of the type. The MISRA document introduces a definition of Unsigned Type of Lowest Rank (UTLR) in Appendix D3. This roughly means the minimal possible unsigned type that can hold the given value. uint8_t can store 5U value, so there is no error.

    The second example provides the explicit cast of the result to the uint16_t type. So the result value needs at least 2 bytes in memory and can't be stored in uint8_t.

     
  • Peeter Vois

    Peeter Vois - 2021-10-13

    I'm struggling with the misra checks on a very similar issue and found following that I would say is a bug:

    #include <stdint.h>
    #define COMPOSITE (((30U<<1U)-3U)&(~1U))
    static uint32_t val32 = COMPOSITE;
    static uint8_t val8 = COMPOSITE;
    

    the misra check (d62242da27e0) with --std=c99 and --platform=arm32-wchar_t2 does output the misra-c2012-10.6 for the line 3. It does not output the misra-c2012-10.3 for the line 4. You would see the 10.3 be reported when instead of the number 30 above you write 300. Both are bugs:

    The C standard states that the signed integer is smallest container that the literal value is to be fitted in, in this platform int32_t. But with U it is uint32_t. but clearly misra check takes it as unsigned char.

    Hi all, please confirm if my understanding is correct !

     

    Last edit: Peeter Vois 2021-10-13

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.