Ejemplo n.º 1
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);
        }
Ejemplo n.º 2
0
        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++;

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

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

                    // b has value, but not true or false
                    args.ProgramState.GetSymbolValue(bSymbol).Should().NotBeNull();
                    bSymbol.HasConstraint(BoolConstraint.False, args.ProgramState).Should().BeFalse();
                    bSymbol.HasConstraint(BoolConstraint.True, args.ProgramState).Should().BeFalse();

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

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

            explodedGraph.Walk();

            explorationEnded.Should().BeTrue();
            branchesVisited.Should().Be(4 + 1);
            numberOfExitBlockReached.Should().Be(1,
                                                 "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.");
            numberOfLastInstructionVisits.Should().Be(2);

            visitedBlocks.Count.Should().Be(cfg.Blocks.Count() - 1 /* Exit block*/);
        }
        public void ExplodedGraph_NonDecisionMakingAssignments()
        {
            string        testInput = "var a = true; a |= false; var b = 42; b++; ++b;";
            SemanticModel semanticModel;
            var           method         = ControlFlowGraphTest.Compile(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);
        }