protected override void VisitPatternSwitchSection(BoundPatternSwitchSection node, BoundExpression switchExpression, bool isLastSection) { foreach (var label in node.SwitchLabels) { NoteDeclaredPatternVariables(label.Pattern); } base.VisitPatternSwitchSection(node, switchExpression, isLastSection); }
protected virtual void VisitPatternSwitchSection(BoundPatternSwitchSection node, BoundExpression switchExpression, bool isLastSection) { SetState(UnreachableState()); foreach (var label in node.SwitchLabels) { VisitLabel(label.Label, node); } VisitStatementList(node); }
protected override void VisitPatternSwitchSection(BoundPatternSwitchSection node, BoundExpression switchExpression, bool isLastSection) { base.VisitPatternSwitchSection(node, switchExpression, isLastSection); // Check for switch section fall through error if (this.State.Alive) { var syntax = node.SwitchLabels.Last().Pattern.Syntax; Diagnostics.Add(isLastSection ? ErrorCode.ERR_SwitchFallOut : ErrorCode.ERR_SwitchFallThrough, new SourceLocation(syntax), syntax.ToString()); } }
public Guarded( BoundExpression expression, TypeSymbol type, ImmutableArray <KeyValuePair <BoundExpression, BoundExpression> > bindings, BoundPatternSwitchSection section, BoundExpression guard, BoundPatternSwitchLabel label) : base(expression, type, null) { this.Guard = guard; this.Label = label; this.Bindings = bindings; this.Section = section; Debug.Assert(guard?.ConstantValue != ConstantValue.False); base.MatchIsComplete = (guard == null) || (guard.ConstantValue == ConstantValue.True); }
protected virtual void VisitPatternSwitchSection(BoundPatternSwitchSection node, BoundExpression switchExpression, bool isLastSection) { // visit switch section labels var initialState = this.State; var afterGuardState = UnreachableState(); foreach (var label in node.PatternSwitchLabels) { SetState(initialState.Clone()); VisitPattern(switchExpression, label.Pattern); SetState(StateWhenTrue); if (label.Guard != null) { VisitCondition(label.Guard); SetState(StateWhenTrue); } IntersectWith(ref afterGuardState, ref this.State); } // visit switch section body SetState(afterGuardState); VisitStatementList(node); }
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); }