Conditional-compilation directive inside a call argument list

ID

objectivec.correctness.macro_arg_preprocessing_directive

Severity

low

Remediation Complexity

medium

Remediation Risk

medium

Remediation Effort

medium

Resource

Preprocessor

Language

Objective-C

Description

Reports a #if, #ifdef or #ifndef that opens inside the parenthesized argument list of a call, that is, on the line after one ending in ( or ,. A directive between statements, in an enum or array initializer, in an if/while condition, or in an Objective-C message send is not reported.

Rationale

If the call turns out to be a macro invocation, a directive among its arguments is undefined behavior: the standard does not say whether the preprocessor evaluates the directive or treats its tokens as part of an argument, and toolchains genuinely differ. What makes it worth avoiding even when the callee is a plain function today is that turning that function into a macro later - or including a header that already defines one with the same name - silently changes which arguments the call receives, with no diagnostic.

The following code illustrates the pattern detected by this rule:

@implementation XYArguments
- (void)conditionalArgument {
    // FLAGGED: Conditional-compilation directive inside a call argument list
    XYLog(@"%@",
#ifdef DEBUG
          self.debugDescription
#else
          self.description
#endif
          );
}
@end

Remediation

Hoist the conditional out of the argument list. Select the value into a local variable inside #if/#else first, then pass that variable, or write the whole call twice, once in each branch of the conditional.

Configuration

This detector does not need any configuration.

© 2026 Xygeni. All rights reserved