defined operator placed in a macro replacement list
ID |
objectivec.maintainability.defined_operator_misuse |
Severity |
low |
Remediation Complexity |
medium |
Remediation Risk |
medium |
Remediation Effort |
medium |
Resource |
Preprocessor |
Language |
Objective-C |
Description
Reports a defined operator inside the replacement list of a #define, so that it reaches a controlling expression only by being macro-expanded into one. This rule is about where the operator is placed; a defined written directly in an #if or #elif with a non-standard operand is reported by defined-operator-nonstandard.
Rationale
The standard says that if the defined token comes out of a macro expansion during the evaluation of an #if, the behavior is undefined. Toolchains split on it: some evaluate the operator anyway, some treat the expanded defined as an ordinary identifier and replace it with 0, which turns the condition false and quietly drops the guarded code from the build. Both outcomes compile without a diagnostic, so a project that works on one compiler can lose whole features on another.
The following code illustrates the pattern detected by this rule:
// FLAGGED: defined operator placed in a macro replacement list
#define XY_HAS_DEBUG defined(DEBUG)
Remediation
Write the defined directly in the #if or #elif that needs it. Where the condition is shared, express the flag as a plain 0/1 macro chosen inside #if defined(…) - for example #if defined(DEBUG) then #define XY_HAS_DEBUG 1, #else then #define XY_HAS_DEBUG 0 - and test that macro with #if XY_HAS_DEBUG.