-1

I want to use the following MACRO in my file

#define DO_WAKEUP_SYNCHRONISIEREN proc.id = process_WAKEUP;proc.priority.level = PRIO_AKTIV_1;proc.priority.param=0u;(void)prio_mapF_put_in_matrix(proc)

I know that it is a violation of MISRA-C:2004 Rule 19.4 - but I need to use this and to solve the violation.

Is there any way I can use the MACRO and also solve the MISRA-C violation?

MISRA-C:2004 Rule 19.4 is

C macros shall only expand to a braced initialiser, a constant, a string literal, a parenthesised expression, a type qualifier, a storage class specifier, or a do-while-zero construct.

Andrew
  • 2,046
  • 1
  • 24
  • 37
Ankit Shah
  • 97
  • 1
  • 11
  • better to wrap your macro code in `do {} while(0)` for starters so it's considered as one sole "instruction" in conditions. – Jean-François Fabre Jul 17 '18 at 12:21
  • @Jean-FrançoisFabre I get the following message "Violates MISRA 2004 Required Rule 19.4, Disallowed definition for macro 'DO_WAKEUP_SYNCHRONISIEREN'" – Ankit Shah Jul 17 '18 at 14:29

1 Answers1

5

it looks like the rule is:

#define B A

The above is not a permitted form of macro definition under this rule because A is not a constant, braced initializer, parenthesized expression, type qualifier, storage class specifier or do-while-zero construct

#define B (A)

The above is permitted. The replacement list is a parenthesised expression.

an extension of this would be (even without MISRA constraints I'd do this, but I just noticed that the rule states it: "do-while-zero construct", IMHO it's not obvious at first glance what "do-while-zero construct" means when you're not aware of that...):

#define DO_WAKEUP_SYNCHRONISIEREN do {proc.id = process_WAKEUP;proc.priority.level = PRIO_AKTIV_1;proc.priority.param=0u;(void)prio_mapF_put_in_matrix(proc);} while(0)

so the instruction block cannot be "partially called" by constructs like this:

if (flag) DO_WAKEUP_SYNCHRONISIEREN;

which would give headaches to anyone trying to understand the bug.

And at the same time it forces to add a ; as opposed to a simple {} block. So the macro looks very much like a function call (also read Why use do { } while (0) in macro definition?).

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
  • As an (perhaps interesting) aside, MISRA C:2012 has relaxed this requirement - although personally, I would still advise using braces or parentheses to bound the macro unless otherwise required – Andrew Jul 19 '18 at 07:47
  • maybe they did so so it was possible to define `case x: do_##x()` stuff... Dunno. This rule sounded like a good idea to me, and every rule has exceptions. – Jean-François Fabre Jul 19 '18 at 08:09
  • do while(0) was removed from MISRA-C with version 2012. Earlier MISRA-C recommended using this practice, but it was criticized since do while(0) allows you to write control/loop statements that are not compound statements, which is in turn required by a different MISRA rule. The whole purpose of the do while(0) trick is to allow code such as `if(x) macro(); else`. But MISRA-C compatible code would have to be `if(x) { macro(); } else`. And so the do-while(0) trick is harmful, as it blocks the compiler from detecting MISRA-C violations. – Lundin Aug 07 '18 at 09:55
  • Thanks for the clarification. The whole purpose of the `do while(0)` trick (that's heavily covered here on SO) is to allow block and still force a `;` in the end, which you cannot ensure with `if(x) { macro(); } else`. As you said, there's no perfect world, and sometimes rules contradict each other like you mentionned. Rules are there to be violated with some justification when you know what you're doing. – Jean-François Fabre Aug 07 '18 at 12:28