Macro parameter used as an operand without its own parentheses

ID

objectivec.correctness.macro_parentheses

Severity

low

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Preprocessor

Language

Objective-C

Description

Reports a function-like #define in which a parameter is written next to an arithmetic, bitwise, relational or equality operator without parentheses of its own. A parameter that is always written (param) is not reported, and neither is a parameter used only as a call argument, an array subscript, a member access, a stringify or paste operand, or a value macro with no parameter list. Only single-line definitions are examined.

Rationale

A macro is expanded by text substitution before the compiler sees any grouping, so the argument arrives as raw tokens and re-associates with whatever surrounds it. #define SQUARE(x) x * x turns SQUARE(a + b) into a + b * a + b, which is a + (b * a) + b - the wrong value, computed without any warning at either the definition or the call. Wrapping the whole body helps but is not enough: (x * x) still expands to (a + b * a + b). The bug only appears for arguments that are themselves expressions, so it survives every test that passes a plain variable and surfaces later, far from the macro.

The following code illustrates the pattern detected by this rule:

// FLAGGED: Macro parameter used as an operand without its own parentheses
#define XY_SQUARE(x) x * x

Remediation

Parenthesise each parameter at every point of use, and the body as a whole - #define SQUARE(x) x) * (x. Where the macro evaluates a parameter more than once, prefer a static inline function instead: it groups its arguments by construction, evaluates them once, and is type-checked.

Configuration

This detector does not need any configuration.

© 2026 Xygeni. All rights reserved