public ControlFlowEdge(ControlFlowNode from, ControlFlowNode to, ControlFlowEdgeType type)
 {
     if (from == null)
         throw new ArgumentNullException("from");
     if (to == null)
         throw new ArgumentNullException("to");
     this.From = from;
     this.To = to;
     this.Type = type;
 }
 public override void VisitYieldStatement(YieldStatementSyntax node)
 {
     if (node.IsKind(SyntaxKind.YieldBreakStatement))
     {
         // end not connected with data
         curNode = builder.CreateEndNode(node);
     }
     else {
         CreateConnectedEndNode(node);
     }
 }
 public override void VisitTryStatement(TryStatementSyntax node)
 {
     ControlFlowNode end = builder.CreateEndNode(node, addToNodeList: false);
     HandleEmbeddedStatement(node.Block, curNode);
     var edge = Connect(curNode, end);
     if (node.Finally?.Block != null)
         edge.AddJumpOutOfTryFinally(node);
     var tryEndPoint = curNode;
     foreach (var cc in node.Catches) {
         HandleEmbeddedStatement(cc.Block, tryEndPoint);
         edge = Connect(tryEndPoint, end);
         if (node.Finally?.Block != null)
             edge.AddJumpOutOfTryFinally(node);
     }
     if (node.Finally?.Block != null) {
         // Don't connect the end of the try-finally block to anything.
         // Consumers of the CFG will have to special-case try-finally.
         HandleEmbeddedStatement(node.Finally.Block, curNode);
     }
     builder.nodes.Add(end);
     curNode = end;
 }
 public override void VisitThrowStatement(ThrowStatementSyntax node)
 {
     // end not connected with data
     curNode = builder.CreateEndNode(node);
 }
 public override void VisitGotoStatement(GotoStatementSyntax node)
 {
     if (node.IsKind(SyntaxKind.GotoDefaultStatement) || node.IsKind(SyntaxKind.GotoCaseStatement)) {
         gotoCaseOrDefault.Add(curNode);
     } else {
         builder.gotoStatements.Add(node);
     }
     curNode = builder.CreateEndNode(node);
 }
 internal ControlFlowEdge Connect(ControlFlowNode from, ControlFlowNode to, ControlFlowEdgeType type = ControlFlowEdgeType.Normal)
 {
     if (from == null || to == null)
         return null;
     ControlFlowEdge edge = builder.CreateEdge(from, to, type);
     from.Outgoing.Add(edge);
     to.Incoming.Add(edge);
     return edge;
 }
Example #7
0
            public override void VisitSwitchStatement(SwitchStatementSyntax node)
            {
                // First, figure out which switch section will get called (if the expression is constant):
                var constant = builder.EvaluateConstant(node.Expression);
                SwitchSectionSyntax defaultSection           = null;
                SwitchSectionSyntax sectionMatchedByConstant = null;

                foreach (var section in node.Sections)
                {
                    foreach (var label in section.Labels)
                    {
                        if (label.IsKind(SyntaxKind.DefaultSwitchLabel))
                        {
                            defaultSection = section;
                        }
                        else if (constant.HasValue /*&& constant.IsCompileTimeConstant*/)
                        {
                            var scl           = label as CaseSwitchLabelSyntax;
                            var labelConstant = builder.EvaluateConstant(scl.Value);
                            if (builder.AreEqualConstants(constant, labelConstant))
                            {
                                sectionMatchedByConstant = section;
                            }
                        }
                    }
                }
                if (constant.HasValue && sectionMatchedByConstant == null)
                {
                    sectionMatchedByConstant = defaultSection;
                }

                int gotoCaseOrDefaultInOuterScope        = gotoCaseOrDefault.Count;
                List <ControlFlowNode> sectionStartNodes = new List <ControlFlowNode>();

                ControlFlowNode end = builder.CreateEndNode(node, addToNodeList: false);

                breakTargets.Push(end);
                var myEntryPoint = curNode;

                foreach (var section in node.Sections)
                {
                    int sectionStartNodeID = builder.nodes.Count;
                    if (!constant.HasValue || section == sectionMatchedByConstant)
                    {
                        curNode = myEntryPoint;
                        HandleStatementList(section.Statements, myEntryPoint);
                    }
                    else
                    {
                        // This section is unreachable: pass null to HandleStatementList.
                        curNode = null;
                        HandleStatementList(section.Statements, null);
                    }
                    // Don't bother connecting the ends of the sections: the 'break' statement takes care of that.

                    // Store the section start node for 'goto case' statements.
                    sectionStartNodes.Add(sectionStartNodeID < builder.nodes.Count ? builder.nodes[sectionStartNodeID] : null);
                }
                breakTargets.Pop();
                if (defaultSection == null && sectionMatchedByConstant == null)
                {
                    Connect(myEntryPoint, end);
                }

                if (gotoCaseOrDefault.Count > gotoCaseOrDefaultInOuterScope)
                {
                    // Resolve 'goto case' statements:
                    for (int i = gotoCaseOrDefaultInOuterScope; i < gotoCaseOrDefault.Count; i++)
                    {
                        ControlFlowNode   gotoCaseNode      = gotoCaseOrDefault[i];
                        var               gotoCaseStatement = gotoCaseNode.NextStatement as GotoStatementSyntax;
                        Optional <object> gotoCaseConstant  = null;
                        if (gotoCaseStatement != null)
                        {
                            gotoCaseConstant = builder.EvaluateConstant(gotoCaseStatement.Expression);
                        }
                        int targetSectionIndex  = -1;
                        int currentSectionIndex = 0;
                        foreach (var section in node.Sections)
                        {
                            foreach (var label in section.Labels)
                            {
                                if (label is CaseSwitchLabelSyntax)
                                {
                                    var scl = label as CaseSwitchLabelSyntax;

                                    // goto case
                                    if (scl.Value != null)
                                    {
                                        var labelConstant = builder.EvaluateConstant(scl.Value);
                                        if (builder.AreEqualConstants(gotoCaseConstant, labelConstant))
                                        {
                                            targetSectionIndex = currentSectionIndex;
                                        }
                                    }
                                }
                                else
                                {
                                    // goto default
                                    if (label.IsKind(SyntaxKind.DefaultSwitchLabel))
                                    {
                                        targetSectionIndex = currentSectionIndex;
                                    }
                                }
                            }
                            currentSectionIndex++;
                        }
                        if (targetSectionIndex >= 0 && sectionStartNodes[targetSectionIndex] != null)
                        {
                            Connect(gotoCaseNode, sectionStartNodes[targetSectionIndex], ControlFlowEdgeType.Jump);
                        }
                        else
                        {
                            Connect(gotoCaseNode, end, ControlFlowEdgeType.Jump);
                        }
                    }
                    gotoCaseOrDefault.RemoveRange(gotoCaseOrDefaultInOuterScope, gotoCaseOrDefault.Count - gotoCaseOrDefaultInOuterScope);
                }

                builder.nodes.Add(end);
                curNode = end;
            }
Example #8
0
 public override void VisitBlock(BlockSyntax node)
 {
     // C# 4.0 spec: §8.2 Blocks
     curNode = HandleStatementList(node.Statements, curNode);
     CreateConnectedEndNode(node);
 }
            public override void VisitForStatement(ForStatementSyntax forStatement)
            {
                // Initializers/Iterators ?  -> difference between NR5/Roslyn -> they're not statements anymore.
                // HandleStatementList(forStatement.Initializers, curNode);

                // for (initializers <data>; <condition>cond; <iteratorStart>iterators<iteratorEnd>) { <bodyStart> embeddedStmt; <bodyEnd> } <end>
                ControlFlowNode end = builder.CreateEndNode(forStatement, addToNodeList: false);
                ControlFlowNode conditionNode = builder.CreateSpecialNode(forStatement, ControlFlowNodeType.LoopCondition);
                Connect(curNode, conditionNode);

                int iteratorStartNodeID = builder.nodes.Count;
                ControlFlowNode iteratorEnd = null; // HandleStatementList(forStatement.Incrementors, null);
                ControlFlowNode iteratorStart;
                if (iteratorEnd != null) {
                    iteratorStart = builder.nodes[iteratorStartNodeID];
                    Connect(iteratorEnd, conditionNode);
                } else {
                    iteratorStart = conditionNode;
                }

                breakTargets.Push(end);
                continueTargets.Push(iteratorStart);

                ControlFlowNode bodyStart = builder.CreateStartNode(forStatement.Statement);
                Visit (forStatement.Statement);
                Connect(curNode, iteratorStart);

                breakTargets.Pop();
                continueTargets.Pop();

                bool? cond = forStatement.Condition == null ? true : builder.EvaluateCondition(forStatement.Condition);
                if (cond != false)
                    Connect(conditionNode, bodyStart, ControlFlowEdgeType.ConditionTrue);
                if (cond != true)
                    Connect(conditionNode, end, ControlFlowEdgeType.ConditionFalse);

                builder.nodes.Add(end);
                curNode = end;
            }
            public override void VisitDoStatement(DoStatementSyntax node)
            {
                // <data> do { <bodyStart> embeddedStmt; <bodyEnd>} <condition> while(cond); <end>
                ControlFlowNode end = builder.CreateEndNode(node, addToNodeList: false);
                ControlFlowNode conditionNode = builder.CreateSpecialNode(node, ControlFlowNodeType.LoopCondition, addToNodeList: false);
                breakTargets.Push(end);
                continueTargets.Push(conditionNode);

                ControlFlowNode bodyStart = builder.CreateStartNode(node.Statement);
                Connect(curNode, bodyStart);
                Visit(node.Statement);
                Connect(curNode, conditionNode);

                bool? cond = builder.EvaluateCondition(node.Condition);
                if (cond != false)
                    Connect(conditionNode, bodyStart, ControlFlowEdgeType.ConditionTrue);
                if (cond != true)
                    Connect(conditionNode, end, ControlFlowEdgeType.ConditionFalse);

                breakTargets.Pop();
                continueTargets.Pop();
                builder.nodes.Add(conditionNode);
                builder.nodes.Add(end);
                curNode = end;
            }
            public override void VisitSwitchStatement(SwitchStatementSyntax node)
            {
                // First, figure out which switch section will get called (if the expression is constant):
                var constant = builder.EvaluateConstant(node.Expression);
                SwitchSectionSyntax defaultSection = null;
                SwitchSectionSyntax sectionMatchedByConstant = null;
                foreach (var section in node.Sections) {
                    foreach (var label in section.Labels) {
                        
                        if (label.IsKind(SyntaxKind.DefaultSwitchLabel)) {
                            defaultSection = section;
                        } else if (constant.HasValue /*&& constant.IsCompileTimeConstant*/) {
                            var scl = label as CaseSwitchLabelSyntax;
                            var labelConstant = builder.EvaluateConstant(scl.Value);
                            if (builder.AreEqualConstants(constant, labelConstant))
                                sectionMatchedByConstant = section;
                        }
                    }
                }
                if (constant.HasValue && sectionMatchedByConstant == null)
                    sectionMatchedByConstant = defaultSection;

                int gotoCaseOrDefaultInOuterScope = gotoCaseOrDefault.Count;
                List<ControlFlowNode> sectionStartNodes = new List<ControlFlowNode>();

                ControlFlowNode end = builder.CreateEndNode(node, addToNodeList: false);
                breakTargets.Push(end);
                var myEntryPoint = curNode;
                foreach (var section in node.Sections) {
                    int sectionStartNodeID = builder.nodes.Count;
                    if (!constant.HasValue || section == sectionMatchedByConstant) {
                        curNode = myEntryPoint;
                        HandleStatementList(section.Statements, myEntryPoint);
                    } else {
                        // This section is unreachable: pass null to HandleStatementList.
                        curNode = null;
                        HandleStatementList(section.Statements, null);
                    }
                    // Don't bother connecting the ends of the sections: the 'break' statement takes care of that.

                    // Store the section start node for 'goto case' statements.
                    sectionStartNodes.Add(sectionStartNodeID < builder.nodes.Count ? builder.nodes[sectionStartNodeID] : null);
                }
                breakTargets.Pop();
                if (defaultSection == null && sectionMatchedByConstant == null) {
                    Connect(myEntryPoint, end);
                }

                if (gotoCaseOrDefault.Count > gotoCaseOrDefaultInOuterScope) {
                    // Resolve 'goto case' statements:
                    for (int i = gotoCaseOrDefaultInOuterScope; i < gotoCaseOrDefault.Count; i++) {
                        ControlFlowNode gotoCaseNode = gotoCaseOrDefault[i];
                        var gotoCaseStatement = gotoCaseNode.NextStatement as GotoStatementSyntax;
                        Optional<object> gotoCaseConstant = null;
                        if (gotoCaseStatement != null) {
                            gotoCaseConstant = builder.EvaluateConstant(gotoCaseStatement.Expression);
                        }
                        int targetSectionIndex = -1;
                        int currentSectionIndex = 0;
                        foreach (var section in node.Sections) {
                            foreach (var label in section.Labels) {
                                if (label is CaseSwitchLabelSyntax) {
                                    var scl = label as CaseSwitchLabelSyntax;

                                    // goto case
                                    if (scl.Value != null) {
                                        var labelConstant = builder.EvaluateConstant(scl.Value);
                                        if (builder.AreEqualConstants(gotoCaseConstant, labelConstant))
                                            targetSectionIndex = currentSectionIndex;
                                    }
                                } else {
                                    // goto default
                                    if (label.IsKind(SyntaxKind.DefaultSwitchLabel))
                                        targetSectionIndex = currentSectionIndex;
                                }
                            }
                            currentSectionIndex++;
                        }
                        if (targetSectionIndex >= 0 && sectionStartNodes[targetSectionIndex] != null)
                            Connect(gotoCaseNode, sectionStartNodes[targetSectionIndex], ControlFlowEdgeType.Jump);
                        else
                            Connect(gotoCaseNode, end, ControlFlowEdgeType.Jump);
                    }
                    gotoCaseOrDefault.RemoveRange(gotoCaseOrDefaultInOuterScope, gotoCaseOrDefault.Count - gotoCaseOrDefaultInOuterScope);
                }

                builder.nodes.Add(end);
                curNode = end;
            }
            public override void VisitIfStatement(IfStatementSyntax node)
            {
                bool? cond = builder.EvaluateCondition(node.Condition);

                var startNode = curNode;
                ControlFlowNode trueBegin = builder.CreateStartNode(node.Statement);
                if (cond != false)
                    Connect(startNode, trueBegin, ControlFlowEdgeType.ConditionTrue);

                curNode = trueBegin;
                Visit(node.Statement);
                ControlFlowNode trueEnd = curNode;

                ControlFlowNode falseEnd = null;

                if (node.Else?.Statement != null)
                {
                    ControlFlowNode falseBegin = builder.CreateStartNode(node.Else?.Statement);
                    if (cond != true)
                        Connect(startNode, falseBegin, ControlFlowEdgeType.ConditionFalse);

                    curNode = trueBegin;
                    Visit(node.Else?.Statement);

                    falseEnd = curNode;
                }
                // (if no else statement exists, both falseBegin and falseEnd will be null)

                ControlFlowNode end = builder.CreateEndNode(node);
                Connect(trueEnd, end);
                if (falseEnd != null) {
                    Connect(falseEnd, end);
                } else if (cond != true) {
                    Connect(startNode, end, ControlFlowEdgeType.ConditionFalse);
                }
                curNode = end;
            }
 ControlFlowNode HandleStatementList(IEnumerable<StatementSyntax> statements, ControlFlowNode source)
 {
     var oldCurNode = curNode;
     ControlFlowNode childNode = null;
     foreach (var stmt in statements) {
         if (childNode == null) {
             curNode = childNode = builder.CreateStartNode(stmt);
             if (source != null)
                 Connect(source, childNode);
         }
         // Debug.Assert(childNode.NextStatement == stmt);
         Visit(stmt);
         childNode = curNode;
         // Debug.Assert(childNode.PreviousStatement == stmt);
     }
     curNode = oldCurNode;
     return childNode ?? source;
 }
 public override void VisitBlock(BlockSyntax node)
 {
     // C# 4.0 spec: §8.2 Blocks
     curNode = HandleStatementList(node.Statements, curNode);
     CreateConnectedEndNode(node);
 }
 /// <summary>
 /// Creates an end node for <c>stmt</c> and connects <c>from</c> with the new node.
 /// </summary>
 void CreateConnectedEndNode(StatementSyntax stmt)
 {
     ControlFlowNode newNode = builder.CreateEndNode(stmt);
     Connect(curNode, newNode);
     curNode = newNode;
 }
 void HandleEmbeddedStatement(StatementSyntax embeddedStatement, ControlFlowNode source)
 {
     if (embeddedStatement == null)
     {
         curNode = source;
     }
     ControlFlowNode bodyStart = builder.CreateStartNode(embeddedStatement);
     if (source != null)
         Connect(source, bodyStart);
     Visit(embeddedStatement); 
 }
Example #17
0
 protected virtual ControlFlowEdge CreateEdge(ControlFlowNode from, ControlFlowNode to, ControlFlowEdgeType type)
 {
     cancellationToken.ThrowIfCancellationRequested();
     return(new ControlFlowEdge(from, to, type));
 }
            public override void VisitForEachStatement(ForEachStatementSyntax node)
            {
                // <data> foreach (<condition>...) { <bodyStart>embeddedStmt<bodyEnd> } <end>
                ControlFlowNode end = builder.CreateEndNode(node, addToNodeList: false);
                ControlFlowNode conditionNode = builder.CreateSpecialNode(node, ControlFlowNodeType.LoopCondition);
                Connect(curNode, conditionNode);

                breakTargets.Push(end);
                continueTargets.Push(conditionNode);

                HandleEmbeddedStatement(node.Statement, conditionNode);
                Connect(curNode, conditionNode);

                breakTargets.Pop();
                continueTargets.Pop();

                Connect(conditionNode, end);
                builder.nodes.Add(end);
                curNode = end;
            }
Example #19
0
            ControlFlowNode HandleStatementList(IEnumerable <StatementSyntax> statements, ControlFlowNode source)
            {
                var             oldCurNode = curNode;
                ControlFlowNode childNode  = null;

                foreach (var stmt in statements)
                {
                    if (childNode == null)
                    {
                        curNode = childNode = builder.CreateStartNode(stmt);
                        if (source != null)
                        {
                            Connect(source, childNode);
                        }
                    }
                    // Debug.Assert(childNode.NextStatement == stmt);
                    Visit(stmt);
                    childNode = curNode;
                    // Debug.Assert(childNode.PreviousStatement == stmt);
                }
                curNode = oldCurNode;
                return(childNode ?? source);
            }
 public override void VisitContinueStatement(ContinueStatementSyntax node)
 {
     if (continueTargets.Count > 0)
     {
         var target = continueTargets.Peek();
         Connect(curNode, target, ControlFlowEdgeType.Jump);
         curNode = target;
     }
     curNode = builder.CreateEndNode(node);
 }
Example #21
0
 public override void VisitThrowStatement(ThrowStatementSyntax node)
 {
     // end not connected with data
     curNode = builder.CreateEndNode(node);
 }
 protected virtual ControlFlowEdge CreateEdge(ControlFlowNode from, ControlFlowNode to, ControlFlowEdgeType type)
 {
     cancellationToken.ThrowIfCancellationRequested();
     return new ControlFlowEdge(from, to, type);
 }