Loop advances a different variable from the one it initialises

ID

objectivec.correctness.jumbled_incrementer

Severity

low

Remediation Complexity

medium

Remediation Risk

medium

Remediation Effort

low

Resource

Control Flow

Language

Objective-C

Description

Reports a for header whose initialiser sets one variable and whose update clause advances a different one - for (column = 0; column < n; row++). Only headers with a single initialiser and a single update are reported, so a loop advancing two cursors together and a loop that deliberately initialises one variable and advances another alongside it are left alone, as are fast enumeration and a copy of the shape inside a comment.

Rationale

The variable the loop sets up is never advanced, so whatever the condition tests keeps the value it started with unless something in the body happens to change it. In the nested form this rule most often finds - an inner loop whose update advances the outer index because the header was copied from the loop above and only half renamed - the inner loop either never terminates or terminates on the wrong bound, and the outer loop skips iterations because its index was advanced from inside. Neither symptom points back at the header, so the loop is usually rewritten several times before anyone reads the update clause.

The following code illustrates the pattern detected by this rule:

@implementation Grid
- (void)fillRows:(NSInteger)rows columns:(NSInteger)columns {
    for (NSInteger row = 0; row < rows; row++) {
        // FLAGGED: Loop advances a different variable from the one it initialises
        for (NSInteger column = 0; column < columns; row++) {
            [self fillRow:row column:column];
        }
    }
}

- (void)fillRow:(NSInteger)row column:(NSInteger)column { }
- (void)visit:(NSInteger)index { }
- (void)visitItem:(id)item { }
@end

Remediation

Advance the variable the condition tests. In a nested loop, check every clause of the copied header against the index the inner loop owns, not just the declaration. Where two variables genuinely have to move together, update both in the header - for (i = 0, j = n; i < j; i++, j--) - so the intent is stated rather than left to the body.

Configuration

This detector does not need any configuration.

© 2026 Xygeni. All rights reserved