Skip to content

Commit

Permalink
Prevent type and constant value on a constant pattern
Browse files Browse the repository at this point in the history
See also dotnet#31150
  • Loading branch information
gafter committed Nov 13, 2018
1 parent 9b5780c commit c9da431
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1964,10 +1964,8 @@ private IConstantPatternOperation CreateBoundConstantPatternOperation(BoundConst
{
Lazy<IOperation> value = new Lazy<IOperation>(() => Create(boundConstantPattern.Value));
SyntaxNode syntax = boundConstantPattern.Syntax;
ITypeSymbol type = null;
Optional<object> constantValue = default(Optional<object>);
bool isImplicit = boundConstantPattern.WasCompilerGenerated;
return new LazyConstantPattern(value, _semanticModel, syntax, type, constantValue, isImplicit);
return new LazyConstantPattern(value, _semanticModel, syntax, isImplicit);
}

private IDeclarationPatternOperation CreateBoundDeclarationPatternOperation(BoundDeclarationPattern boundDeclarationPattern)
Expand Down Expand Up @@ -2005,8 +2003,7 @@ private ISwitchOperation CreateBoundPatternSwitchStatementOperation(BoundSwitchS
ITypeSymbol type = null;
Optional<object> constantValue = default(Optional<object>);
bool isImplicit = boundPatternSwitchStatement.WasCompilerGenerated;
bool wasPatternSwitch = boundPatternSwitchStatement.Expression.Type?.IsValidV6SwitchGoverningType() == false;
return new LazySwitchStatement(locals, value, cases, exitLabel, wasPatternSwitch, _semanticModel, syntax, type, constantValue, isImplicit);
return new LazySwitchStatement(locals, value, cases, exitLabel, _semanticModel, syntax, type, constantValue, isImplicit);
}

private ICaseClauseOperation CreateBoundPatternSwitchLabelOperation(BoundPatternSwitchLabel boundPatternSwitchLabel)
Expand All @@ -2025,7 +2022,7 @@ private ICaseClauseOperation CreateBoundPatternSwitchLabelOperation(BoundPattern
else if (boundPatternSwitchLabel.WhenClause == null &&
boundPatternSwitchLabel.Pattern.Kind == BoundKind.ConstantPattern &&
boundPatternSwitchLabel.Pattern is BoundConstantPattern cp &&
cp.Value.Type.IsValidV6SwitchGoverningType())
cp.InputType.IsValidV6SwitchGoverningType())
{
Lazy<IOperation> value = new Lazy<IOperation>(() => Create(cp.Value));
return new LazySingleValueCaseClause(label, value, _semanticModel, syntax, type, constantValue, isImplicit);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1972,11 +1972,11 @@ void M(bool result, dynamic input)
IParameterReferenceOperation: input (OperationKind.ParameterReference, Type: dynamic) (Syntax: 'input')
Jump if False (Regular) to Block[B3]
IIsPatternOperation (OperationKind.IsPattern, Type: System.Boolean, IsImplicit) (Syntax: '1')
IIsPatternOperation (OperationKind.IsPattern, Type: System.Boolean, IsImplicit) (Syntax: 'case 1:')
Expression:
IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: dynamic, IsImplicit) (Syntax: 'input')
Pattern:
IConstantPatternOperation (OperationKind.ConstantPattern, Type: System.Int32, Constant: 1, IsImplicit) (Syntax: '1')
IConstantPatternOperation (OperationKind.ConstantPattern, Type: null, IsImplicit) (Syntax: 'case 1:')
Value:
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
Leaving: {R1}
Expand Down Expand Up @@ -2424,11 +2424,11 @@ void M(bool result, object input)
IParameterReferenceOperation: input (OperationKind.ParameterReference, Type: System.Object) (Syntax: 'input')
Jump if False (Regular) to Block[B3]
IIsPatternOperation (OperationKind.IsPattern, Type: System.Boolean, IsImplicit) (Syntax: '1')
IIsPatternOperation (OperationKind.IsPattern, Type: System.Boolean, IsImplicit) (Syntax: 'case 1:')
Expression:
IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Object, IsImplicit) (Syntax: 'input')
Pattern:
IConstantPatternOperation (OperationKind.ConstantPattern, Type: System.Int32, Constant: 1, IsImplicit) (Syntax: '1')
IConstantPatternOperation (OperationKind.ConstantPattern, Type: null, IsImplicit) (Syntax: 'case 1:')
Value:
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
Leaving: {R1}
Expand Down Expand Up @@ -2801,11 +2801,11 @@ void M(bool result, object input)
IParameterReferenceOperation: input (OperationKind.ParameterReference, Type: System.Object) (Syntax: 'input')
Jump if False (Regular) to Block[B3]
IIsPatternOperation (OperationKind.IsPattern, Type: System.Boolean, IsImplicit) (Syntax: '1')
IIsPatternOperation (OperationKind.IsPattern, Type: System.Boolean, IsImplicit) (Syntax: 'case 1:')
Expression:
IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Object, IsImplicit) (Syntax: 'input')
Pattern:
IConstantPatternOperation (OperationKind.ConstantPattern, Type: System.Int32, Constant: 1, IsImplicit) (Syntax: '1')
IConstantPatternOperation (OperationKind.ConstantPattern, Type: null, IsImplicit) (Syntax: 'case 1:')
Value:
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
Expand All @@ -2827,11 +2827,11 @@ void M(bool result, object input)
Predecessors: [B1]
Statements (0)
Jump if False (Regular) to Block[B5]
IIsPatternOperation (OperationKind.IsPattern, Type: System.Boolean, IsImplicit) (Syntax: '2')
IIsPatternOperation (OperationKind.IsPattern, Type: System.Boolean, IsImplicit) (Syntax: 'case 2:')
Expression:
IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Object, IsImplicit) (Syntax: 'input')
Pattern:
IConstantPatternOperation (OperationKind.ConstantPattern, Type: System.Int32, Constant: 2, IsImplicit) (Syntax: '2')
IConstantPatternOperation (OperationKind.ConstantPattern, Type: null, IsImplicit) (Syntax: 'case 2:')
Value:
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2) (Syntax: '2')
Leaving: {R1}
Expand Down
68 changes: 28 additions & 40 deletions src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4881,8 +4881,6 @@ public override IOperation VisitSwitch(ISwitchOperation operation, int? captureI

INamedTypeSymbol booleanType = _compilation.GetSpecialType(SpecialType.System_Boolean);
IOperation switchValue = VisitAndCapture(operation.Value);
bool patternMatchingOnly = ((BaseSwitchStatement)operation).PatternMatchingOnly;

ImmutableArray<ILocalSymbol> locals = getLocals();
var switchRegion = new RegionBuilder(ControlFlowRegionKind.LocalLifetime, locals: locals);
EnterRegion(switchRegion);
Expand Down Expand Up @@ -4962,59 +4960,49 @@ void handleCase(ICaseClauseOperation caseClause, BasicBlockBuilder body, BasicBl
switch (caseClause.CaseKind)
{
case CaseKind.SingleValue:
handleEqualityCheck(((ISingleValueCaseClauseOperation)caseClause).Value);
handleEqualityCheck(((ISingleValueCaseClauseOperation)caseClause).Value);
break;

void handleEqualityCheck(IOperation compareWith)
{
bool leftIsNullable = ITypeSymbolHelpers.IsNullableType(operation.Value.Type);
bool rightIsNullable = ITypeSymbolHelpers.IsNullableType(compareWith.Type);
bool isLifted = leftIsNullable || rightIsNullable;

EvalStackFrame frame = PushStackFrame();
PushOperand(OperationCloner.CloneOperation(switchValue));
IOperation rightOperand = Visit(compareWith);
IOperation leftOperand = PopOperand();

if (patternMatchingOnly)
if (isLifted)
{
var pattern = (IPatternOperation)new ConstantPattern(rightOperand, semanticModel: null,
compareWith.Syntax, compareWith.Type, compareWith.ConstantValue, isImplicit: true);
condition = new IsPatternExpression(leftOperand, pattern, semanticModel: null,
compareWith.Syntax, booleanType, constantValue: default, isImplicit: true);
}
else
{
bool leftIsNullable = ITypeSymbolHelpers.IsNullableType(operation.Value.Type);
bool rightIsNullable = ITypeSymbolHelpers.IsNullableType(compareWith.Type);
bool isLifted = leftIsNullable || rightIsNullable;

if (isLifted)
if (!leftIsNullable)
{
if (!leftIsNullable)
if (leftOperand.Type != null)
{
if (leftOperand.Type != null)
{
leftOperand = MakeNullable(leftOperand, compareWith.Type);
}
}
else if (!rightIsNullable && rightOperand.Type != null)
{
rightOperand = MakeNullable(rightOperand, operation.Value.Type);
leftOperand = MakeNullable(leftOperand, compareWith.Type);
}
}

condition = new BinaryOperatorExpression(BinaryOperatorKind.Equals,
leftOperand,
rightOperand,
isLifted,
isChecked: false,
isCompareText: false,
operatorMethod: null,
unaryOperatorMethod: null,
semanticModel: null,
compareWith.Syntax,
booleanType,
constantValue: default,
isImplicit: true);
else if (!rightIsNullable && rightOperand.Type != null)
{
rightOperand = MakeNullable(rightOperand, operation.Value.Type);
}
}

condition = new BinaryOperatorExpression(BinaryOperatorKind.Equals,
leftOperand,
rightOperand,
isLifted,
isChecked: false,
isCompareText: false,
operatorMethod: null,
unaryOperatorMethod: null,
semanticModel: null,
compareWith.Syntax,
booleanType,
constantValue: default,
isImplicit: true);

condition = Operation.SetParentOperation(condition, null);
LinkBlocks(CurrentBasicBlock, condition, jumpIfTrue: false, RegularBranch(nextCase));

Expand Down Expand Up @@ -6558,7 +6546,7 @@ public override IOperation VisitTranslatedQuery(ITranslatedQueryOperation operat
public override IOperation VisitConstantPattern(IConstantPatternOperation operation, int? captureIdForResult)
{
return new ConstantPattern(Visit(operation.Value), semanticModel: null,
operation.Syntax, operation.Type, operation.ConstantValue, IsImplicit(operation));
syntax: operation.Syntax, isImplicit: IsImplicit(operation));
}

public override IOperation VisitDeclarationPattern(IDeclarationPatternOperation operation, int? captureIdForResult)
Expand Down
4 changes: 2 additions & 2 deletions src/Compilers/Core/Portable/Operations/OperationCloner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public override IOperation VisitConversion(IConversionOperation operation, objec

public override IOperation VisitSwitch(ISwitchOperation operation, object argument)
{
return new SwitchStatement(operation.Locals, Visit(operation.Value), VisitArray(operation.Cases), operation.ExitLabel, ((BaseSwitchStatement)operation).PatternMatchingOnly, ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit);
return new SwitchStatement(operation.Locals, Visit(operation.Value), VisitArray(operation.Cases), operation.ExitLabel, ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit);
}

public override IOperation VisitSwitchCase(ISwitchCaseOperation operation, object argument)
Expand Down Expand Up @@ -519,7 +519,7 @@ public override IOperation VisitIsPattern(IIsPatternOperation operation, object

public override IOperation VisitConstantPattern(IConstantPatternOperation operation, object argument)
{
return new ConstantPattern(Visit(operation.Value), ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit);
return new ConstantPattern(Visit(operation.Value), ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.IsImplicit);
}

public override IOperation VisitDeclarationPattern(IDeclarationPatternOperation operation, object argument)
Expand Down
Loading

0 comments on commit c9da431

Please sign in to comment.