This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Compiler: MISRA as supported in TI ARM compiler 20.x and stdints and C99

Expert 1965 points

Tool/software: TI C/C++ Compiler

The compiler comes with MISRA C 2004 checks support.  That MISRA revision doesn't support C99, for example.

Yet it seems if I include <stdint.h>  then I do not get any warnings.  Or is that header as provided , is fully MISRA compliant? I also do not seem to get any warnings if I set strict ANSI C89  (just to check)  on this module, it still builds fine.

I see these in the stdint.h header:

#include <_ti_config.h>

_TI_PROPRIETARY_PRAGMA("diag_push")
_TI_PROPRIETARY_PRAGMA("CHECK_MISRA(\"-19.1\")") /* no code before #include */
_TI_PROPRIETARY_PRAGMA("CHECK_MISRA(\"-19.7\")") /* prefer functions to macros */

.....

Don't know what those proprietary macros mean, but  is the provided stdint.h (and what it includes) fully MISRA compliant?

  • v01d said:
    is that header as provided , is fully MISRA compliant?

    Yes

    v01d said:
    Don't know what those proprietary macros mean

    Those macros suppress some MISRA diagnostics that otherwise would be emitted.  Each of those was examined, and are judged to not be violations.

    Thanks and regards,

    -George

  • It seems, that header is not fully compliant with that MISRA.

    #include <stdint.h>
    
    uint8_t tmp;
    
    tmp = UINT8_MAX;
    
    

    And the MISRA warning/error I get : 

    Description Resource Path Location Type
    #1393-D (MISRA-C:2004 10.1/R) The value of an expression of integer type shall not be implicitly converted to a different underlying type if it is not a conversion to a wider integer type of the same signedness .....  C/C++ Problem

    This however , doesnt :

    tmp =  0xffu;

    Thus probably that header is not fully on with your MISRA checker.

    Does TI have any plans to support MISRA  >= 2012 soon?

  • Thank you for notifying us of this problem, and providing a concise test case.  I can reproduce the same behavior.  I filed the entry EXT_EP-9939 to have this investigated.  You are welcome to follow it with the link below in my signature.

    v01d said:
    Does TI have any plans to support MISRA  >= 2012 soon?

    Unfortunately, there are no plans to add support for MISRA 2012 to TI compilers.  We suggest you look to other static code analysis tools for a solution.

    Thanks and regards,

    -George  

  • Somewhat confusingly, the type of UINT8_MAX is not uint8_t.

    C99 7.18. "Limits of specified-width integer types" says: "this expression shall have the same type as would an expression that is an object of the corresponding type converted according to the integer promotions." Therefore this macro has a value of type "signed int," and you get a MISRA-2004 warning for trying to assign it directly to a variable of type uint8_t.

    On the other hand, MISRA-2004 has a special case for constants. MISRA-2004 specifically allows your second case "tmp = 0xffu", because it is a literal constant with a value that fits into x without changing the value.  MISRA-2004 does not make an exception for macros that have a value that fits, nor does it recognize UINT8_MAX as a special case, as it is a C99 feature.

  • Archaeologist said:

    Somewhat confusingly, the type of UINT8_MAX is not uint8_t.

    It was clear from that stdint.h header supplied with TI's compiler, it's a define and is a literal int  (don't have it in my head now, but is it even defined as unsigned, or just int ..)

    Archaeologist said:
    nor does it recognize UINT8_MAX as a special case, as it is a C99 feature.

    I understand, but I thought the supplied header with the compiler allows using it as is to be compliant with the MISRA 2004 checker it comes with.

    I wouldn't want to be stuck with 2004 MISRA for long, but atm this is a free checker available with the compiler. I also see/saw that setting strict ANSI mode, does not preclude me or flags this as error to include stdint.h into the code , even with std c89. I thought that this means this compiler and this MISRA checker accept that header as fully compliant & usable, in 89 or 99.

  • For ARM, UINT8_MAX is required by the C99 standard to be a signed int, because uint8_t is smaller than "int" and would be integer-promoted to "int."  For ARM 20.x, UINT8_MAX is defined as the token 0xff, which is an unsuffixed hexadecimal constant, so the type is not specified in the source code.  This means that the compiler needs to deduce the type according to the rules in the standard (C99 6.4.4.1 "Integer constants"), and for ARM, this turns out to be a signed int, as required.

    MISRA-C:2004 expects the input to be compiled in "strict ANSI" mode, and one of the things the implementation checks for is that you've used the "strict ANSI" compiler option.  It's not really meant to be used without the option, although it usually works fine without it.

    The TI compiler's "strict ANSI" mode does not mean that it will only accept standard code; it means that the compiler will disable extensions that would interfere with the interpretation of a strictly-conforming program.  This requires a bit of explanation.  The C standard defines a "strictly conforming" program as a program which uses only those features defined in the C standard, and does not rely on any implementation(compiler)-defined behavior.  The C standard defines a "conforming implementation" as one which accepts all strictly-conforming programs.  It's OK if the compiler doesn't accept all strictly-conforming programs in its default mode, it only needs a mode where it will accept all such programs.   "Strict ANSI" mode is that mode.  For example, the keyword "inline" is a perfectly valid identifier in a C89 program, but if you try to use it as a variable name in the default mode, you'll get a syntax error.  By using "strict ANSI" mode, you disable "inline" as a keyword and now you can compiler a strictly conforming program that uses "inline" as a variable name.

    Now, stdbool.h is not a C89 feature, so a program which uses it is not a strictly-conforming C89 program.  That program might be a strictly-conforming C99 program, but that doesn't matter to MISRA-C:2004; it expects the compiler to be in a "conforming" (aka "strict ANSI") C89 mode.  Thus, a program which uses stdbool.h is outside of the scope of MISRA-C:2004.  Now, just including stdbool.h is pretty harmless, so we've added pragmas to stdbool.h to disable a couple of MISRA-C:2004 checks inside the file itself so that you can at least include the file.  However, these pragmas do not extend to code which uses the definitions from stdbool.h.  The existence of these pragmas should not be taken as endorsing the use of stdbool.h in a program meant to be checked with MISRA-C:2004; they are just a convenience for programs that want to relax the MISRA-C:2004 rules a bit.  Including stdbool.h will make your program non-portable to C89-only implementations, and portability is one of the primary concerns for MISRA-C:2004.

    In summary, you can include stdbool.h without getting any warning from MISRA-C:2004, but it makes your program slightly less portable, and you may still get MISRA-C:2004 warnings when you try to use the definitions from the header file.

  • Archaeologist said:
    Now, stdbool.h is not a C89 feature, so a program which uses it is not a strictly-conforming C89 program.  That program might be a strictly-conforming C99 program, but that doesn't matter to MISRA-C:2004; it e

    I think that was for my other thread.

    Understand all about integer promotion rules with std C, and ARM - thank you.

  • I will be honest and say I found this not straight forward to understand:

    Archaeologist said:
    The TI compiler's "strict ANSI" mode does not mean that it will only accept standard code; it means that the compiler will disable extensions that would interfere with the interpretation of a strictly-conforming program.  This requires a bit of explanation.  The C standard defines a "strictly conforming" program as a program which uses only those features defined in the C standard, and does not rely on any implementation(compiler)-defined behavior.  The C standard defines a "conforming implementation" as one which accepts all strictly-conforming programs.  It's OK if the compiler doesn't accept all strictly-conforming programs in its default mode, it only needs a mode where it will accept all such programs.   "Strict ANSI" mode is that mode.  For example, the keyword "inline" is a perfectly valid identifier in a C89 program, but if you try to use it as a variable name in the default mode, you'll get a syntax error.  By using "strict ANSI" mode, you disable "inline" as a keyword and now you can compiler a strictly conforming program that uses "inline" as a variable name.

    Especially I want to ask about this :

    Archaeologist said:
    It's OK if the compiler doesn't accept all strictly-conforming programs in its default mode, it only needs a mode where it will accept all such programs.   "Strict ANSI" mode is that mode. 

    Do I understand it wrong, but does this say that the 'default 'mode' (for this compiler)  is a more strict / limited mode where it does not even accept all standard conforming ones?  While the "Strict ANSI" mode is more accepting?    I.e. , here "Strict ANSI" >  "default" mode ? I would have expected it reversed  - the fully conforming ANSI mode is stricter <  'default'  compiler mode with possible provider extensions.

    And here : 

    Archaeologist said:
    The TI compiler's "strict ANSI" mode does not mean that it will only accept standard code; it means that the compiler will disable extensions that would interfere with the interpretation of a strictly-conforming program.

    &&

    .

    Archaeologist said:
    For example, the keyword "inline" is a perfectly valid identifier in a C89 program, but if you try to use it as a variable name in the default mode, you'll get a syntax error.  By using "strict ANSI" mode, you disable "inline" as a keyword and now you can compiler a strictly conforming program that uses "inline" as a variable name.

    Do I understand it wrong too:  does "ANSI" here mean the old  C89(or C90), and  does not correspond to the second option/flag of specific revision of the standard , e.g. C99 ?   ( I thought this & later standards were also adopted by ANSI)

    So with the inline keyword example :   I would hope, that setting  options  standard = C99 && strict ANSI  would allow me to use keyword 'inline' (part of C99, i think..)   , but  if standard  < C99  &&  strict ANSI  then get inline disabled per your example.

    But, what I seems to get from your explanation, TI's ANSI only knows about the first version of the standard ?

  • Please search the TI ARM compiler manual for the sub-chapter titled Strict ANSI Mode and Relaxed ANSI Mode.  Do you understand that explanation better?

    Thanks and regards,

    -George

  •  :

    5.16.3, p 132

    " ... 

    Under relaxed ANSI/ISO mode (the default), the compiler accepts language extensions that could
    potentially conflict with a strictly conforming ANSI/ISO C/C++ program. Under strict ANSI mode, these
    language extensions are suppressed so that the compiler will accept all strictly conforming programs.
    Use the --strict_ansi option when you know your program is a conforming program and it will not compile
    in relaxed mode. In this mode, language extensions that conflict with ANSI/ISO C/C++ are disabled and
    the compiler will emit error messages where the standard requires it to do so. Violations that are
    considered discretionary by the standard may be emitted as warnings instead. "

    This seems  - at least in my reading - to say exactly as I would expect / understand it to work.  Which I couldn't marry with explanation given above.

  • Let me try again.  First of all, the "strict ANSI" mode and option is a poor name for what the mode is; unfortunately, we're stuck with it at this point.  This mode should really be called "conforming mode."  This is the mode that is guaranteed to accept all strictly conforming programs.  A strictly conforming program is a narrow category; it is carefully written so that it doesn't use any features that aren't in the C standard, and also doesn't rely on implementation-defined behavior, such as the size of "int."  There is a different "strict ANSI" mode for each language version, so there's a "strict ANSI C89," "strict ANSI C99," and "strict ANSI C++98," and so on.

    Most programs will be accepted just fine in either default "relaxed" mode or "strict ANSI" mode.  There are only a small number of programs that will be rejected by one or the other.  A good example of such a program is one that uses the identifier "inline" as a variable name.  This is perfectly legal as far as the C standard is concerned, so a strictly conforming C program could use "inline" as a variable or function name.  However, as a language extension, the TI compiler implements "inline" as a keyword in the default mode, so that you can use it to inline functions.  This means that the default mode won't accept that strictly conforming program that uses "inline" as a variable name.  To resolve this, you would use "strict ANSI" mode, which turns off extensions that would conflict with accepting strictly conforming programs.

    It is uncommon for real programs to require "strict ANSI" mode.  Usually it's more useful to allow all possible language extensions; that is, in the default mode, we are more likely to accept any particular random program.  That's why it's the default.

    Note that our hypothetical program that uses inline as a keyword to inline a function would be rejected in "strict ANSI C89" mode, but would be accepted in "strict ANSI C99" mode.

    So now we ask, which mode is more "limiting?"  Well, neither, really.  Each will accept a small number of programs that the other won't.  "Strict ANSI" mode will accept a strictly-conforming C89 program that uses inline as a variable name.  The default (relaxed) mode will accept a non-strictly-conforming C89 program that uses inline as a keyword to inline a function.  In practice, I'd say more "real world" programs will be accepted in default mode just because people do use the language extensions.  Strictly-conforming programs are less common unless a high degree of portability is a big concern.

  • @,

    Thank you again, for the detailed explanation.  I think this explained better what you have explained in previous post, esp. the default mode vs strict. ( Also made me think again about what standard conforming is ..)

    Note for 'inline' example :   with 'strict ANSI C99'  mode or default/relaxed mode both will accept it and mean it as directive   So on this one keyword example we're conforming and have "read world" useful keyword.  :)