Пример #1
0
 internal SubsumptionDiagnosticBuilder(Symbol enclosingSymbol,
                                       Conversions conversions,
                                       BoundExpression expression)
     : base(enclosingSymbol, conversions)
 {
     _subsumptionTree = DecisionTree.Create(expression, expression.Type, enclosingSymbol);
 }
Пример #2
0
            private DecisionTree LowerToDecisionTree(
                BoundExpression loweredExpression,
                BoundPatternSwitchStatement node)
            {
                var loweredDecisionTree = DecisionTree.Create(loweredExpression, loweredExpression.Type, _enclosingSymbol);
                BoundPatternSwitchLabel defaultLabel = null;
                SyntaxNode defaultSection            = null;

                foreach (var section in node.SwitchSections)
                {
                    var sectionSyntax = (SyntaxNode)section.Syntax;
                    foreach (var label in section.SwitchLabels)
                    {
                        var loweredLabel = LowerSwitchLabel(label);
                        if (loweredLabel.Syntax.Kind() == SyntaxKind.DefaultSwitchLabel)
                        {
                            if (defaultLabel != null)
                            {
                                // duplicate switch label will have been reported during initial binding.
                            }
                            else
                            {
                                defaultLabel   = loweredLabel;
                                defaultSection = sectionSyntax;
                            }
                        }
                        else
                        {
                            Syntax = label.Syntax;
                            AddToDecisionTree(loweredDecisionTree, sectionSyntax, loweredLabel);
                        }
                    }
                }

                if (defaultLabel != null)
                {
                    Add(loweredDecisionTree, (e, t) => new DecisionTree.Guarded(loweredExpression, loweredExpression.Type, default(ImmutableArray <KeyValuePair <BoundExpression, BoundExpression> >), defaultSection, null, defaultLabel));
                }

                // We discard use-site diagnostics, as they have been reported during initial binding.
                _useSiteDiagnostics.Clear();
                return(loweredDecisionTree);
            }
Пример #3
0
        internal DecisionTree ComputeDecisionTree()
        {
            Debug.Assert(_section == null);
            var expression = _switchStatement.Expression;

            if (expression.ConstantValue == null && expression.Kind != BoundKind.Local)
            {
                // unless the expression is simple enough, copy it into a local
                var localSymbol = new SynthesizedLocal(_enclosingSymbol as MethodSymbol, expression.Type, SynthesizedLocalKind.PatternMatchingTemp, _switchStatement.Syntax, false, RefKind.None);
                expression = new BoundLocal(expression.Syntax, localSymbol, null, expression.Type);
            }

            var result          = DecisionTree.Create(_switchStatement.Expression, _switchStatement.Expression.Type, _enclosingSymbol);
            var subsumptionTree = DecisionTree.Create(_switchStatement.Expression, _switchStatement.Expression.Type, _enclosingSymbol);
            BoundPatternSwitchLabel   defaultLabel   = null;
            BoundPatternSwitchSection defaultSection = null;

            foreach (var section in _switchStatement.SwitchSections)
            {
                this._section = section;
                foreach (var label in section.SwitchLabels)
                {
                    if (label.Syntax.Kind() == SyntaxKind.DefaultSwitchLabel)
                    {
                        if (defaultLabel != null)
                        {
                            // duplicate switch label will have been reported during initial binding.
                        }
                        else
                        {
                            defaultLabel   = label;
                            defaultSection = section;
                        }
                    }
                    else
                    {
                        this._syntax = label.Syntax;
                        // For purposes of subsumption, we do not take into consideration the value
                        // of the input expression. Therefore we consider null possible if the type permits.
                        var subsumedErrorCode = CheckSubsumed(label.Pattern, subsumptionTree, inputCouldBeNull: true);
                        if (subsumedErrorCode != 0 && subsumedErrorCode != ErrorCode.ERR_NoImplicitConvCast)
                        {
                            if (!label.HasErrors)
                            {
                                _diagnostics.Add(subsumedErrorCode, label.Pattern.Syntax.Location);
                            }
                        }
                        else
                        {
                            AddToDecisionTree(result, label);
                            if (label.Guard == null || label.Guard.ConstantValue == ConstantValue.True)
                            {
                                // Only unconditional switch labels contribute to subsumption
                                AddToDecisionTree(subsumptionTree, label);
                            }
                        }
                    }
                }
            }

            if (defaultLabel != null)
            {
                Add(result, (e, t) => new DecisionTree.Guarded(_switchStatement.Expression, _switchStatement.Expression.Type, default(ImmutableArray <KeyValuePair <BoundExpression, BoundExpression> >), defaultSection, null, defaultLabel));
            }

            return(result);
        }