nil check written as an assignment or with misplaced negation

ID

objectivec.correctness.broken_nil_check

Severity

low

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Suspicious Code

Language

Objective-C

Description

Reports two ways a nil check is written wrongly in the condition of an if or a while: assigning nil instead of comparing to it (if (x = nil)), and negating the operand before the comparison runs (if (!x == nil)). The deliberate assign-and-then-compare idiom if ((x = [self lookup]) == nil) is not reported, and neither is a correct == nil, != nil or !x. This is about how the check is written; a check written correctly but placed after the pointer has already been used is reported by misplaced-nil-check.

Rationale

if (x = nil) stores nil into the variable and then tests that value, so the branch never runs and the object the caller passed in is destroyed on the way past. The compiler warning for it is easy to lose in a noisy build, and the line reads like a comparison to everyone who reviews it afterwards. if (!x == nil) is worse, because it compiles cleanly and the precedence is not what it looks like: ! binds tighter than ==, so the test is (!x) == nil, which asks whether the boolean 0 or 1 equals nil — it is true exactly when x is non-nil, the opposite of the intent, and the guard lets nil straight through.

The following code illustrates the pattern detected by this rule:

@implementation Loader
- (void)loadNamed:(NSString *)name {
    // FLAGGED: nil check written as an assignment or with misplaced negation
    if (name = nil) {
        return;
    }
    [self load:name];
}

- (NSString *)lookup {
    return nil;
}

- (void)load:(NSString *)name {
    NSLog(@"%@", name);
}
@end

Remediation

Write if (x == nil) or the idiomatic if (!x) for the nil case, and if (x != nil) for the non-nil case. Where the assignment is deliberate, make it explicit by parenthesising it and comparing the result — if ((x = [self lookup]) == nil) — or better, split it into an assignment statement followed by the check on its own line.

Configuration

This detector does not need any configuration.

© 2026 Xygeni. All rights reserved