Ejemplo n.º 1
0
        private static void CheckForRedundantConditions(ExplodedGraph explodedGraph, SyntaxNodeAnalysisContext context)
        {
            var conditionTrue  = new HashSet <SyntaxNode>();
            var conditionFalse = new HashSet <SyntaxNode>();

            EventHandler <ConditionEvaluatedEventArgs> collectConditions =
                (sender, args) => CollectConditions(args, conditionTrue, conditionFalse);

            EventHandler explorationEnded =
                (sender, args) => Enumerable.Empty <Diagnostic>()
                .Union(conditionTrue
                       .Except(conditionFalse)
                       .Where(c => !IsConditionOfLoopWithBreak((ExpressionSyntax)c))
                       .Select(node => GetDiagnostics(node, true)))
                .Union(conditionFalse
                       .Except(conditionTrue)
                       .Select(node => GetDiagnostics(node, false)))
                .ToList()
                .ForEach(context.ReportDiagnostic);

            explodedGraph.ExplorationEnded   += explorationEnded;
            explodedGraph.ConditionEvaluated += collectConditions;

            try
            {
                explodedGraph.Walk();
            }
            finally
            {
                explodedGraph.ExplorationEnded   -= explorationEnded;
                explodedGraph.ConditionEvaluated -= collectConditions;
            }
        }
        public void ExplodedGraph_LoopExploration()
        {
            string        testInput = "var i = 0; while (i < 1) { i = i + 1; }";
            SemanticModel semanticModel;
            var           method       = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out semanticModel);
            var           methodSymbol = semanticModel.GetDeclaredSymbol(method);

            var cfg = ControlFlowGraph.Create(method.Body, semanticModel);
            var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel);

            var explodedGraph    = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva);
            var explorationEnded = false;

            explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; };

            var exceeded = 0;

            explodedGraph.ProgramPointVisitCountExceedLimit += (sender, args) =>
            {
                exceeded++;
                args.ProgramPoint.Block.Instructions.Where(i => i.ToString() == "i < 1").Should().NotBeEmpty();
            };

            explodedGraph.Walk();

            Assert.IsTrue(explorationEnded);
            Assert.AreEqual(1, exceeded);
        }
        public void ExplodedGraph_BothBranchesVisited_NonCondition()
        {
            string        testInput = "var str = this?.ToString();";
            SemanticModel semanticModel;
            var           method       = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out semanticModel);
            var           methodSymbol = semanticModel.GetDeclaredSymbol(method);

            var cfg = ControlFlowGraph.Create(method.Body, semanticModel);
            var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel);

            var explodedGraph    = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva);
            var explorationEnded = false;

            explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; };

            var countConditionEvaluated = 0;

            explodedGraph.ConditionEvaluated += (sender, args) => { countConditionEvaluated++; };

            var visitedBlocks = new HashSet <Block>();

            explodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                visitedBlocks.Add(args.ProgramPoint.Block);
            };

            explodedGraph.Walk();

            Assert.IsTrue(explorationEnded);
            Assert.AreEqual(cfg.Blocks.Count() - 1 /* Exit block */, visitedBlocks.Count);
            Assert.AreEqual(0, countConditionEvaluated);
        }
        public void ExplodedGraph_SequentialInput_Max()
        {
            var inputBuilder = new StringBuilder();

            for (int i = 0; i < ExplodedGraph.MaxStepCount / 2 + 1; i++)
            {
                inputBuilder.AppendLine($"var x{i} = true;");
            }
            string        testInput = inputBuilder.ToString();
            SemanticModel semanticModel;
            var           method       = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out semanticModel);
            var           methodSymbol = semanticModel.GetDeclaredSymbol(method);

            var cfg = ControlFlowGraph.Create(method.Body, semanticModel);
            var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel);

            var explodedGraph    = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva);
            var explorationEnded = false;

            explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; };
            var maxStepCountReached = false;

            explodedGraph.MaxStepCountReached += (sender, args) => { maxStepCountReached = true; };

            var numberOfExitBlockReached = 0;

            explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; };

            explodedGraph.Walk();

            Assert.IsFalse(explorationEnded);
            Assert.IsTrue(maxStepCountReached);
            Assert.AreEqual(0, numberOfExitBlockReached);
        }
        public void ExplodedGraph_SingleBranchVisited_If()
        {
            string        testInput = "var a = false; bool b; if (a) { b = true; } else { b = false; } a = b;";
            SemanticModel semanticModel;
            var           method         = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out semanticModel);
            var           methodSymbol   = semanticModel.GetDeclaredSymbol(method);
            var           varDeclarators = method.DescendantNodes().OfType <VariableDeclaratorSyntax>();
            var           aSymbol        = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "a"));
            var           bSymbol        = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "b"));

            var cfg = ControlFlowGraph.Create(method.Body, semanticModel);
            var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel);

            var explodedGraph    = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva);
            var explorationEnded = false;

            explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; };

            var numberOfExitBlockReached = 0;

            explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; };

            var numberOfLastInstructionVisits = 0;
            var numberOfProcessedInstructions = 0;

            explodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                numberOfProcessedInstructions++;
                if (args.Instruction.ToString() == "a = false")
                {
                    Assert.IsTrue(args.ProgramState.GetSymbolValue(aSymbol) == SymbolicValue.False);
                }
                if (args.Instruction.ToString() == "b = true")
                {
                    Assert.Fail("We should never get into this branch");
                }
                if (args.Instruction.ToString() == "b = false")
                {
                    Assert.IsTrue(args.ProgramState.GetSymbolValue(bSymbol) == SymbolicValue.False);
                    Assert.IsNull(args.ProgramState.GetSymbolValue(aSymbol),
                                  "a is dead, so there should be no associated value to it.");
                }
                if (args.Instruction.ToString() == "a = b")
                {
                    numberOfLastInstructionVisits++;
                }
            };

            explodedGraph.Walk();

            Assert.IsTrue(explorationEnded);
            Assert.AreEqual(8, numberOfProcessedInstructions);
            Assert.AreEqual(1, numberOfExitBlockReached);
            Assert.AreEqual(1, numberOfLastInstructionVisits);
        }
        public void ExplodedGraph_SequentialInput()
        {
            string        testInput = "var a = true; var b = false; b = !b; a = (b);";
            SemanticModel semanticModel;
            var           method         = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out semanticModel);
            var           methodSymbol   = semanticModel.GetDeclaredSymbol(method);
            var           varDeclarators = method.DescendantNodes().OfType <VariableDeclaratorSyntax>();
            var           aSymbol        = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "a"));
            var           bSymbol        = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "b"));

            var cfg = ControlFlowGraph.Create(method.Body, semanticModel);
            var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel);

            var explodedGraph    = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva);
            var explorationEnded = false;

            explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; };

            var numberOfExitBlockReached = 0;

            explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; };

            var numberOfProcessedInstructions = 0;

            explodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                numberOfProcessedInstructions++;
                if (args.Instruction.ToString() == "a = true")
                {
                    Assert.IsTrue(args.ProgramState.GetSymbolValue(aSymbol) == SymbolicValue.True);
                }
                if (args.Instruction.ToString() == "b = false")
                {
                    Assert.IsTrue(args.ProgramState.GetSymbolValue(bSymbol) == SymbolicValue.False);
                }
                if (args.Instruction.ToString() == "b = !b")
                {
                    Assert.IsFalse(args.ProgramState.GetSymbolValue(bSymbol) == SymbolicValue.False);
                    Assert.IsFalse(args.ProgramState.GetSymbolValue(bSymbol) == SymbolicValue.True);
                }
                if (args.Instruction.ToString() == "a = (b)")
                {
                    Assert.AreEqual(
                        args.ProgramState.GetSymbolValue(bSymbol),
                        args.ProgramState.GetSymbolValue(aSymbol));
                }
            };

            explodedGraph.Walk();

            Assert.IsTrue(explorationEnded);
            Assert.AreEqual(9, numberOfProcessedInstructions);
            Assert.AreEqual(1, numberOfExitBlockReached);
        }
        public void ExplodedGraph_AllBranchesVisited()
        {
            string        testInput = "int i = 1; switch (i) { case 1: default: cw1(); break; case 2: cw2(); break; }";
            SemanticModel semanticModel;
            var           method       = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out semanticModel);
            var           methodSymbol = semanticModel.GetDeclaredSymbol(method);

            var cfg = ControlFlowGraph.Create(method.Body, semanticModel);
            var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel);

            var explodedGraph    = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva);
            var explorationEnded = false;

            explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; };

            var numberOfExitBlockReached = 0;

            explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; };

            var numberOfCw1InstructionVisits  = 0;
            var numberOfCw2InstructionVisits  = 0;
            var numberOfProcessedInstructions = 0;

            explodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                numberOfProcessedInstructions++;
                if (args.Instruction.ToString() == "cw1()")
                {
                    numberOfCw1InstructionVisits++;
                }
                if (args.Instruction.ToString() == "cw2()")
                {
                    numberOfCw2InstructionVisits++;
                }
            };

            explodedGraph.Walk();

            Assert.IsTrue(explorationEnded);
            Assert.AreEqual(1, numberOfExitBlockReached);
            Assert.AreEqual(1, numberOfCw1InstructionVisits);
            Assert.AreEqual(1, numberOfCw2InstructionVisits);
        }
        public void ExplodedGraph_SingleBranchVisited_And()
        {
            string        testInput = "var a = false; if (a && !a) { a = true; }";
            SemanticModel semanticModel;
            var           method         = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out semanticModel);
            var           methodSymbol   = semanticModel.GetDeclaredSymbol(method);
            var           varDeclarators = method.DescendantNodes().OfType <VariableDeclaratorSyntax>();
            var           aSymbol        = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "a"));

            var cfg = ControlFlowGraph.Create(method.Body, semanticModel);
            var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel);

            var explodedGraph    = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva);
            var explorationEnded = false;

            explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; };

            var numberOfExitBlockReached = 0;

            explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; };

            var numberOfProcessedInstructions = 0;

            explodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                numberOfProcessedInstructions++;
                if (args.Instruction.ToString() == "a = !true")
                {
                    Assert.IsTrue(args.ProgramState.GetSymbolValue(aSymbol) == SymbolicValue.False);     // Roslyn is clever !true has const value.
                }
                if (args.Instruction.ToString() == "!a")
                {
                    Assert.Fail("We should never get into this branch");
                }
            };

            explodedGraph.Walk();

            Assert.IsTrue(explorationEnded);
            Assert.AreEqual(1, numberOfExitBlockReached);
        }
Ejemplo n.º 9
0
        public void ExplodedGraph_BothBranchesVisited_StateMerge()
        {
            string        testInput = "var a = !true; bool b; if (inParameter) { b = false; } else { b = false; } a = b;";
            SemanticModel semanticModel;
            var           method       = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out semanticModel);
            var           methodSymbol = semanticModel.GetDeclaredSymbol(method);

            var varDeclarators = method.DescendantNodes().OfType <VariableDeclaratorSyntax>();
            var aSymbol        = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "a"));

            var cfg = ControlFlowGraph.Create(method.Body, semanticModel);
            var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel);

            var explodedGraph    = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva);
            var explorationEnded = false;

            explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; };

            var numberOfExitBlockReached = 0;

            explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; };

            var numberOfLastInstructionVisits = 0;
            var numberOfProcessedInstructions = 0;

            explodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                numberOfProcessedInstructions++;
                if (args.Instruction.ToString() == "a = b")
                {
                    args.ProgramState.GetSymbolValue(aSymbol).Should().Be(SymbolicValue.False);
                    numberOfLastInstructionVisits++;
                }
            };

            explodedGraph.Walk();

            explorationEnded.Should().BeTrue();
            numberOfExitBlockReached.Should().Be(1);
            numberOfLastInstructionVisits.Should().Be(1);
        }
Ejemplo n.º 10
0
        public void ExplodedGraph_SequentialInput_OutParameter()
        {
            string        testInput = "outParameter = true;";
            SemanticModel semanticModel;
            var           method             = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out semanticModel);
            var           methodSymbol       = semanticModel.GetDeclaredSymbol(method);
            var           parameters         = method.DescendantNodes().OfType <ParameterSyntax>();
            var           outParameterSymbol = semanticModel.GetDeclaredSymbol(parameters.First(d => d.Identifier.ToString() == "outParameter"));

            var cfg = ControlFlowGraph.Create(method.Body, semanticModel);
            var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel);

            var explodedGraph    = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva);
            var explorationEnded = false;

            explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; };

            var numberOfExitBlockReached = 0;

            explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; };

            var numberOfProcessedInstructions = 0;

            explodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                numberOfProcessedInstructions++;
                if (args.Instruction.ToString() == "outParameter = true")
                {
                    args.ProgramState.GetSymbolValue(outParameterSymbol)
                    .Should().Be(SymbolicValue.True);
                }
            };

            explodedGraph.Walk();

            explorationEnded.Should().BeTrue();
            numberOfProcessedInstructions.Should().Be(2);
            numberOfExitBlockReached.Should().Be(1);
        }
Ejemplo n.º 11
0
        private static void CheckForNullDereference(ExplodedGraph explodedGraph, SyntaxNodeAnalysisContext context)
        {
            if (context.IsTest())
            {
                return;
            }

            var methodSymbol = context.SemanticModel.GetSymbolInfo(context.Node).Symbol
                               ?? context.SemanticModel.GetDeclaredSymbol(context.Node);

            if (!methodSymbol.IsPubliclyAccessible())
            {
                return;
            }

            var nullPointerCheck = new NullPointerDereference.NullPointerCheck(explodedGraph);

            explodedGraph.AddExplodedGraphCheck(nullPointerCheck);

            var identifiers = new HashSet <IdentifierNameSyntax>();

            EventHandler <MemberAccessingEventArgs> memberAccessingHandler =
                (sender, args) => CollectMemberAccesses(args, identifiers, context.SemanticModel);

            nullPointerCheck.MemberAccessing += memberAccessingHandler;

            try
            {
                explodedGraph.Walk();
            }
            finally
            {
                nullPointerCheck.MemberAccessing -= memberAccessingHandler;
            }

            foreach (var identifier in identifiers)
            {
                context.ReportDiagnostic(Diagnostic.Create(rule, identifier.GetLocation(), identifier.Identifier.ValueText));
            }
        }
        public void ExplodedGraph_NonLocalNorFieldSymbolBranching()
        {
            string        testInput = "if (Property) { cw(); }";
            SemanticModel semanticModel;
            var           method         = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out semanticModel);
            var           methodSymbol   = semanticModel.GetDeclaredSymbol(method);
            var           propertySymbol = semanticModel.GetSymbolInfo(
                method.DescendantNodes().OfType <IdentifierNameSyntax>().First(d => d.Identifier.ToString() == "Property")).Symbol;

            Assert.IsNotNull(propertySymbol);

            var cfg = ControlFlowGraph.Create(method.Body, semanticModel);
            var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel);

            var explodedGraph    = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva);
            var explorationEnded = false;

            explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; };

            var numberOfExitBlockReached = 0;

            explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; };

            var numberOfProcessedInstructions = 0;

            explodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                numberOfProcessedInstructions++;
                if (args.Instruction.ToString() == "Property")
                {
                    Assert.IsNull(args.ProgramState.GetSymbolValue(propertySymbol));
                }
            };

            explodedGraph.Walk();

            Assert.IsTrue(explorationEnded);
            Assert.AreEqual(1, numberOfExitBlockReached);
        }
Ejemplo n.º 13
0
        private static void Analyze(CSharpSyntaxNode declarationBody, ISymbol symbol,
                                    Action <ExplodedGraph, SyntaxNodeAnalysisContext> analyze, SyntaxNodeAnalysisContext context)
        {
            if (declarationBody == null ||
                declarationBody.ContainsDiagnostics)
            {
                return;
            }

            IControlFlowGraph cfg;

            if (!ControlFlowGraph.TryGet(declarationBody, context.SemanticModel, out cfg))
            {
                return;
            }

            var lva = LiveVariableAnalysis.Analyze(cfg, symbol, context.SemanticModel);

            var explodedGraph = new ExplodedGraph(cfg, symbol, context.SemanticModel, lva);

            analyze(explodedGraph, context);
        }
        private static void CheckForMultipleDispose(ExplodedGraph explodedGraph, SyntaxNodeAnalysisContext context)
        {
            var objectDisposedCheck = new ObjectDisposedPointerCheck(explodedGraph);

            explodedGraph.AddExplodedGraphCheck(objectDisposedCheck);

            EventHandler <ObjectDisposedEventArgs> memberAccessedHandler =
                (sender, args) =>
            {
                context.ReportDiagnostic(
                    Diagnostic.Create(rule, args.Location, args.Name));
            };

            objectDisposedCheck.ObjectDisposed += memberAccessedHandler;

            try
            {
                explodedGraph.Walk();
            }
            finally
            {
                objectDisposedCheck.ObjectDisposed -= memberAccessedHandler;
            }
        }
 public ObjectDisposedPointerCheck(ExplodedGraph explodedGraph)
     : base(explodedGraph)
 {
 }
        public void ExplodedGraph_InternalStateCount_MaxReached()
        {
            var           testInput = @"
using System;

namespace TesteAnalyzer
{
    class Program
    {
        static bool GetBool() { return bool.Parse(""True""); }

        static void Main(string[] args)
        {
            bool corrupted = false;
            corrupted |= !GetBool();
            corrupted |= !GetBool();
            corrupted |= !GetBool();
            corrupted |= !GetBool();
            corrupted |= !GetBool();
            corrupted |= !GetBool();
            corrupted |= !GetBool();
            corrupted |= !GetBool();
            corrupted |= !GetBool();
            corrupted |= !GetBool();
            corrupted |= !GetBool();
            corrupted |= !GetBool();
            corrupted |= !GetBool();
            corrupted |= !GetBool();
            corrupted |= !GetBool();
            corrupted |= !GetBool();
            corrupted |= !GetBool();

            if (!corrupted)
            {
                Console.Out.WriteLine();
            }
        }
    }
}
";
            SemanticModel semanticModel;
            var           tree         = ControlFlowGraphTest.Compile(testInput, out semanticModel);
            var           method       = tree.GetRoot().DescendantNodes().OfType <MethodDeclarationSyntax>().First(m => m.Identifier.ValueText == "Main");
            var           methodSymbol = semanticModel.GetDeclaredSymbol(method);

            var cfg = ControlFlowGraph.Create(method.Body, semanticModel);
            var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel);

            var explodedGraph    = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva);
            var explorationEnded = false;

            explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; };
            var maxStepCountReached = false;

            explodedGraph.MaxStepCountReached += (sender, args) => { maxStepCountReached = true; };
            var maxInternalStateCountReached = false;

            explodedGraph.MaxInternalStateCountReached += (sender, args) => { maxInternalStateCountReached = true; };

            explodedGraph.Walk();

            Assert.IsFalse(explorationEnded);
            Assert.IsFalse(maxStepCountReached);
            Assert.IsTrue(maxInternalStateCountReached);
        }
        public void ExplodedGraph_BothBranchesVisited()
        {
            string        testInput = "var a = false; bool b; if (inParameter) { b = inParameter; } else { b = !inParameter; } a = b;";
            SemanticModel semanticModel;
            var           method       = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out semanticModel);
            var           methodSymbol = semanticModel.GetDeclaredSymbol(method);

            var varDeclarators = method.DescendantNodes().OfType <VariableDeclaratorSyntax>();
            var aSymbol        = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "a"));
            var bSymbol        = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "b"));

            var parameters        = method.DescendantNodes().OfType <ParameterSyntax>();
            var inParameterSymbol = semanticModel.GetDeclaredSymbol(parameters.First(d => d.Identifier.ToString() == "inParameter"));

            var cfg = ControlFlowGraph.Create(method.Body, semanticModel);
            var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel);

            var explodedGraph    = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva);
            var explorationEnded = false;

            explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; };

            var numberOfExitBlockReached = 0;

            explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; };

            var numberOfLastInstructionVisits = 0;
            var numberOfProcessedInstructions = 0;

            var visitedBlocks   = new HashSet <Block>();
            var branchesVisited = 0;

            explodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                visitedBlocks.Add(args.ProgramPoint.Block);

                numberOfProcessedInstructions++;
                if (args.Instruction.ToString() == "a = false")
                {
                    branchesVisited++;

                    Assert.IsTrue(args.ProgramState.GetSymbolValue(aSymbol) == SymbolicValue.False);     // Roslyn is clever !true has const value.
                }
                if (args.Instruction.ToString() == "b = inParameter")
                {
                    branchesVisited++;

                    Assert.IsTrue(bSymbol.HasConstraint(BoolConstraint.True, args.ProgramState));
                    Assert.IsTrue(inParameterSymbol.HasConstraint(BoolConstraint.True, args.ProgramState));
                }
                if (args.Instruction.ToString() == "b = !inParameter")
                {
                    branchesVisited++;

                    // b has value, but not true or false
                    Assert.IsNotNull(args.ProgramState.GetSymbolValue(bSymbol));
                    Assert.IsFalse(bSymbol.HasConstraint(BoolConstraint.False, args.ProgramState));
                    Assert.IsFalse(bSymbol.HasConstraint(BoolConstraint.True, args.ProgramState));

                    Assert.IsTrue(inParameterSymbol.HasConstraint(BoolConstraint.False, args.ProgramState));
                }
                if (args.Instruction.ToString() == "a = b")
                {
                    branchesVisited++;

                    Assert.IsNull(args.ProgramState.GetSymbolValue(inParameterSymbol));     // not out/ref parameter and LVA says dead
                    numberOfLastInstructionVisits++;
                }
            };

            explodedGraph.Walk();

            Assert.IsTrue(explorationEnded);
            Assert.AreEqual(4 + 1, branchesVisited);
            Assert.AreEqual(1, numberOfExitBlockReached,
                            "All variables are dead at the ExitBlock, so whenever we get there, the ExplodedGraph nodes should be the same, " +
                            "and thus should be processed only once.");
            Assert.AreEqual(2, numberOfLastInstructionVisits);

            Assert.AreEqual(cfg.Blocks.Count() - 1 /* Exit block */, visitedBlocks.Count);
        }
        public void ExplodedGraph_NonDecisionMakingAssignments()
        {
            string        testInput = "var a = true; a |= false; var b = 42; b++; ++b;";
            SemanticModel semanticModel;
            var           method         = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out semanticModel);
            var           methodSymbol   = semanticModel.GetDeclaredSymbol(method);
            var           varDeclarators = method.DescendantNodes().OfType <VariableDeclaratorSyntax>();
            var           aSymbol        = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "a"));
            var           bSymbol        = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "b"));

            var cfg = ControlFlowGraph.Create(method.Body, semanticModel);
            var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel);

            var explodedGraph = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva);

            SymbolicValue sv = null;
            var           numberOfProcessedInstructions = 0;
            var           branchesVisited = 0;

            explodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                numberOfProcessedInstructions++;
                if (args.Instruction.ToString() == "a = true")
                {
                    branchesVisited++;
                    Assert.IsTrue(args.ProgramState.GetSymbolValue(aSymbol) == SymbolicValue.True);
                }
                if (args.Instruction.ToString() == "a |= false")
                {
                    branchesVisited++;
                    Assert.IsNotNull(args.ProgramState.GetSymbolValue(aSymbol));
                    Assert.IsFalse(args.ProgramState.GetSymbolValue(aSymbol) == SymbolicValue.False);
                    Assert.IsFalse(args.ProgramState.GetSymbolValue(aSymbol) == SymbolicValue.True);
                }
                if (args.Instruction.ToString() == "b = 42")
                {
                    branchesVisited++;
                    sv = args.ProgramState.GetSymbolValue(bSymbol);
                    Assert.IsNotNull(sv);
                }
                if (args.Instruction.ToString() == "b++")
                {
                    branchesVisited++;
                    var svNew = args.ProgramState.GetSymbolValue(bSymbol);
                    Assert.IsNotNull(svNew);
                    Assert.AreNotEqual(sv, svNew);
                }
                if (args.Instruction.ToString() == "++b")
                {
                    branchesVisited++;
                    var svNew = args.ProgramState.GetSymbolValue(bSymbol);
                    Assert.IsNotNull(svNew);
                    Assert.AreNotEqual(sv, svNew);
                }
            };

            explodedGraph.Walk();

            Assert.AreEqual(11, numberOfProcessedInstructions);
            Assert.AreEqual(5, branchesVisited);
        }