protected override void WalkNonNull(IAbstractSyntax syntax, bool isLValue)
        {
            // TODO this doesn't handle loops correctly
            switch (syntax)
            {
            case IReachabilityAnnotationSyntax _:
                // Ignore for now
                return;

            case IConcreteInvocableDeclaration exp:
                checker      = strategy.BeginAnalysis(exp, symbolTree, diagnostics);
                currentState = checker.StartState();
                break;

            case IAssignmentExpression exp:
                WalkNonNull(exp.RightOperand, false);
                WalkNonNull(exp.LeftOperand, true);
                currentState = checker !.Assignment(exp, currentState !);
                return;

            case INameExpression exp:
                if (isLValue)
                {
                    return;               // ignore
                }
                currentState = checker !.IdentifierName(exp, currentState !);
                return;

            case IVariableDeclarationStatement exp:
                currentState = checker !.VariableDeclaration(exp, currentState !);
                WalkChildrenInReverse(exp, false);
                return;

            case IForeachExpression exp:
                WalkNonNull(exp.Block, isLValue);
                currentState = checker !.VariableDeclaration(exp, currentState !);
                WalkNonNull(exp.InExpression, isLValue);
                return;

            case IFieldAccessExpression exp:
                WalkNonNull(exp.Context, isLValue);
                // Don't walk the field name, it shouldn't be treated as a variable
                return;

            case ITypeSyntax _:
                return;

            case IDeclarationSyntax _:
                throw new InvalidOperationException($"Analyze data flow of declaration of type {syntax.GetType().Name}");
            }
            WalkChildrenInReverse(syntax, isLValue);
        }