8

I am in the early stages of framing stuff out on a new project.

I defined a function with a return type of "bool"

I got this output from PC-Lint

    Including file sockets.h (hdr)
bool sock_close(uint8_t socket_id);
^
"LINT: sockets.h (52, 1) Note 970: Use of modifier or type '_Bool' outside of a typedef [MISRA 2012 Directive 4.6, advisory]"

I went ahead and defined this in another header to shut lint up:

typedef bool bool_t;

Then I started wondering why I had to do that and why it changed anything. I turned to MISRA 2012 Dir 4.6. It is concerned mostly about the width of primitive types like short, int, and long, their width, and how they are signed.

The standard does not give any amplification, rational, exception, or example for bool.

bool is explicitly defined as _Bool in stdbool.h in C99. So does this criteria really apply bool?

I thought _Bool was explicitly always the "smallest standard unsigned integer type large enough to store the values 0 and 1" according to section 6.2.5 of C99. So we know bool is unsigned. Is it then just a matter of the fact that _Bool is not fixed width and subject being promoted somehow that's the issue? Because the rational would seem to contradict that notion.

Adherence to this guideline does not guarantee portability because the size of the int type may determine whether or not an expression is subject to integer promotion.

How does just putting typedef bool bool_t; change anything - because I do nothing to indicate the width or the signdedness in doing so? The width of bool_t will just be platform dependent too. Is there a better way to redefine bool?

A type must not be defined with a specific length unless the implemented type is actually of that length

so typedef bool bool8_t; should be totally illegal.

Is Gimpel wrong in their interpretation of Directive 4.6 or are they spot on?

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
Nick
  • 1,361
  • 1
  • 14
  • 42
  • _Bool is a native type in C99 and for Misra you can not use native type directly. This is normally for code portability. Sometimes int is (signed) 32 bits and sometimes it is (signed) 16 bits for example on 8 bits platforms. So your code should typedef s32 or s16 instead to definitively clarify your needs – NGI Jun 02 '15 at 22:25
  • MISRA does not say "do not use native types". Directive 4.6 says "typedefs that indicate size and signedness should be used in place of the basic numerical types". My question here is does _Bool fit that definition of a basic numerical type. I am looking at pages 28-30 of MISRA C 2012 and they do not explicitly say anything about bool - they talk about the typedefs in stdint at length though. – Nick Jun 02 '15 at 22:28
  • One data point: `bool` (defined in `` is a macro that expands to `_Bool`, not a typedef. The width and signedness of `bool` / `_Bool` should be irrelevant as long as you use it correctly; if MISRA really does recommend against using it (while allowing your typedef), that seems silly. – Keith Thompson Jun 02 '15 at 22:37
  • @KeithThompson Agreed, _Bool is special and should be preferred over `typedef uint8_t bool_t;` – Nick Jun 02 '15 at 22:41
  • 1
    It sounds like omitting `` and adding `typedef _Bool bool;` would work. – Keith Thompson Jun 02 '15 at 23:19
  • @KeithThompson Lint doesn't generate any output for that. But that has some code smell to it. I'd think that should violate some other rule about redefining a reserved symbol. I'd like to know what's wrong with the definition in stdbool. Is it just because it is a macro definition and not a typedef that's the issue? `#define bool _Bool` Once this is all said and done I'll be perfectly happy using `typedef bool bool_t;`, I'd just like to know why it's necessary. – Nick Jun 02 '15 at 23:36
  • @Nick: I think PC-lint is operating on the preprocessed source (which is why the error message refers to `_Bool` rather than to the `bool` that appears in the source). C99's choice of making `bool` a macro rather than a typedef is IMHO questionable. Personally I wouldn't want to invent the name `bool_t` rather than using the standard `bool` -- even if I have to define `bool` myself. I might do something like `typedef _Bool bool; enum { false, true};`, which avoids all use of macros. – Keith Thompson Jun 02 '15 at 23:48
  • There is nothing in MISRA C:2012 that prohibits the use of bool - the too is wrong! As an aside, that the ISO C standard implementation of bool sucks is a separate issue. – Andrew Jun 20 '15 at 19:26

2 Answers2

10

Use of modifier or type '_Bool' outside of a typedef [MISRA 2012 Directive 4.6, advisory]

That's nonsense, directive 4.6 is only concerned about using the types in stdint.h rather than int, short etc. The directive is about the basic numerical types. bool has nothing to do with that directive whatsoever, as it is not a numerical type.

For reasons unknown, MISRA-C:2012 examples use a weird type called bool_t, which isn't standard. But MISRA does by no means enforce this type to be used anywhere, particularly they do not enforce it in directive 4.6, which doesn't even mention booleans. MISRA does not discourage the use of bool or _Bool anywhere.

Is Gimpel wrong in their interpretation of Directive 4.6

Yes, their tool is giving incorrect diagnostics.

In addition, you may have to configure the tool (if possible) to tell it which bool type that is used. 5.3.2 mentions that you might have to do so if not using _Bool, implying that all static analysers must understand _Bool. But even if the bool type is correctly configured, dir 4.6 has nothing to do with it.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • I looked through MISRA C 2012 for references to bool_t and they often seem to be used as an example for some effectively bool value that is not necessarily explicitly _Bool. I guess that's relevant for C90, and perhaps MISRA tried to make their examples work for both C99 and C90 since it covers both. – Nick Jun 04 '15 at 00:42
  • 3
    Gimpel's support also agreed that this was a false positive. So I am just going to suppress note 970 about bool using -esym(970,_Bool) in my project's lnt file. – Nick Jun 05 '15 at 01:54
  • Agreed - bool is fine to use. – Andrew Jun 20 '15 at 19:23
4

A potential concern with Boolean types is that a lot of code prior to C99 used a single-byte type to hold true/false values, and a fair amount of it may have used the name "bool". Attempting to store any multiple of 256 into most such types would be regarded as storing zero, while storing a non-zero multiple of 256 into a c99 "bool" would yield 1. If a piece of code which uses a C99 "bool" is ported into a piece of code that uses a typedef'ed byte, the resulting code could very easily malfunction (it's somewhat less likely that code written for a typedef'ed byte would rely upon any particular behavior when storing a value other than 0 or 1).

supercat
  • 77,689
  • 9
  • 166
  • 211
  • Obvious problem once I have been made aware of it... but not before. Interestingly it would not be fixed by typedefing a byte (but lint would be happy, I guess). – Peter - Reinstate Monica Nov 10 '21 at 09:36
  • @Peter-ReinstateMonica: I dislike the way bool is defined in C99. If C99 had specified that a bool written with any odd number will read an Unspecified odd number, a bool written as zero will read as zero, and reading any other bool will yield an Unspecified Value (even, odd, or zero), that would have allowed implementations to process code that uses `bool` more efficiently. If e.g. a function returns a flag in an `int` and code needs to store it to a `bool`, letting the programmer write `!!function(whatever)` if non-zero even numbers need to be treated as 1, but letting the programmer... – supercat Nov 10 '21 at 19:18
  • ...omit the `!!` if that wouldn't be necessary, would have allowed more efficient code generation in many cases than would requiring that a compiler always behave as though the `!!` was present. – supercat Nov 10 '21 at 19:18