Macro definition removed with #undef
ID |
objectivec.maintainability.avoid_undef |
Severity |
info |
Remediation Complexity |
medium |
Remediation Risk |
low |
Remediation Effort |
medium |
Resource |
Preprocessor |
Language |
Objective-C |
Description
Reports a #undef directive, wherever it appears. A #undef written inside a method or function body is reported here too, so that every removal of a macro is listed in one place; the companion rule for directives inside a block covers #define only.
Rationale
#undef makes a macro name mean one thing above the directive and something else - or nothing - below it, and the boundary is invisible at the point of use. Code that reads correctly in isolation then compiles differently depending on which headers were included first, and a later #define of the same name is silently accepted rather than reported as a redefinition, so a name can quietly change value in the middle of a translation unit.
The following code illustrates the pattern detected by this rule:
// FLAGGED: Macro definition removed with #undef
#undef TRACE_ENABLED
Remediation
Give the two meanings two names rather than reusing one, so nothing has to be undefined. Where the macro is a compile-time switch, test it with #if instead of undefining it; where it is a constant or a small function, replace it with a static const or a static inline function, which obeys scope and needs no directive to end.