ContainsTarget() private method

private ContainsTarget ( LabelTarget target ) : bool
target LabelTarget
return bool
Beispiel #1
0
        // Returns true if the label was successfully defined
        // or false if the label is now ambiguous
        internal void Define(LabelScopeInfo block)
        {
            // Prevent the label from being shadowed, which enforces cleaner
            // trees. Also we depend on this for simplicity (keeping only one
            // active IL Label per LabelInfo)
            for (LabelScopeInfo j = block; j != null; j = j.Parent)
            {
                if (j.ContainsTarget(_node))
                {
                    throw Error.LabelTargetAlreadyDefined(_node.Name);
                }
            }

            _definitions.Add(block);
            block.AddLabelInfo(_node, this);

            // Once defined, validate all jumps
            if (_definitions.Count == 1)
            {
                foreach (var r in _references)
                {
                    ValidateJump(r);
                }
            }
            else
            {
                // Was just redefined, if we had any across block jumps, they're
                // now invalid
                if (_acrossBlockJump)
                {
                    throw Error.AmbiguousJump(_node.Name);
                }
                // For local jumps, we need a new IL label
                // This is okay because:
                //   1. no across block jumps have been made or will be made
                //   2. we don't allow the label to be shadowed
                _labelDefined = false;
            }
        }
Beispiel #2
0
        private static (LabelScopeInfo parent, LabelScopeKind kind, IList <Expression>?nodes)? GetLabelScopeChangeInfo(bool emitStart, LabelScopeInfo labelBlock, Expression node)
        {
            if (!emitStart)
            {
                return(null);
            }

            // Anything that is "statement-like" -- e.g. has no associated
            // stack state can be jumped into, with the exception of try-blocks
            // We indicate this by a "Block"
            //
            // Otherwise, we push an "Expression" to indicate that it can't be
            // jumped into
            switch (node.NodeType)
            {
            default:
                if (labelBlock.Kind == LabelScopeKind.Expression)
                {
                    return(null);
                }

                return(labelBlock, LabelScopeKind.Expression, null);

            case ExpressionType.Label:
                // LabelExpression is a bit special, if it's directly in a
                // block it becomes associate with the block's scope. Same
                // thing if it's in a switch case body.
                if (labelBlock.Kind != LabelScopeKind.Block)
                {
                    return(labelBlock, LabelScopeKind.Statement, null);
                }

                var label = ((LabelExpression)node).Target;
                if (labelBlock.ContainsTarget(label))
                {
                    return(null);
                }

                if (labelBlock.Parent?.Kind == LabelScopeKind.Switch && labelBlock.Parent.ContainsTarget(label))
                {
                    return(null);
                }

                return(labelBlock, LabelScopeKind.Statement, null);

            case ExpressionType.Block:
                if (node is SpilledExpressionBlock)
                {
                    // treat it as an expression
                    goto default;
                }

                return(labelBlock.Parent?.Kind != LabelScopeKind.Switch
                        ? (labelBlock, LabelScopeKind.Block, new[] { node })
                        : (labelBlock, LabelScopeKind.Block, null));

            case ExpressionType.Switch:
                var nodes   = new List <Expression>();
                var @switch = (SwitchExpression)node;
                foreach (var c in @switch.Cases)
                {
                    nodes.Add(c.Body);
                }

                if (@switch.DefaultBody != null)
                {
                    nodes.Add(@switch.DefaultBody);
                }

                return(labelBlock, LabelScopeKind.Switch, nodes);

            // Remove this when Convert(Void) goes away.
            case ExpressionType.Convert:
                if (node.Type != typeof(void))
                {
                    // treat it as an expression
                    goto default;
                }

                return(labelBlock, LabelScopeKind.Statement, null);

            case ExpressionType.Conditional:
            case ExpressionType.Loop:
            case ExpressionType.Goto:
                return(labelBlock, LabelScopeKind.Statement, null);
            }
        }