|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable disable
using System;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Operations;
using Microsoft.CodeAnalysis.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
public class IOperationTests_ICompoundAssignmentOperation : SemanticModelTestBase
{
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void ICompoundAssignment_NullArgumentToGetConversionThrows()
{
ICompoundAssignmentOperation nullAssignment = null;
Assert.Throws<ArgumentNullException>("compoundAssignment", () => nullAssignment.GetInConversion());
Assert.Throws<ArgumentNullException>("compoundAssignment", () => nullAssignment.GetOutConversion());
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void ICompoundAssignment_GetConversionOnValidNode_IdentityConversion()
{
string source = @"
class C
{
static void M()
{
int x = 1, y = 1;
/*<bind>*/x += y/*</bind>*/;
}
}
";
var syntaxTree = Parse(source);
var compilation = CreateCompilationWithMscorlib461(new[] { syntaxTree });
(IOperation operation, _) = GetOperationAndSyntaxForTest<AssignmentExpressionSyntax>(compilation);
var compoundAssignment = (ICompoundAssignmentOperation)operation;
Assert.Equal(Conversion.Identity, compoundAssignment.GetInConversion());
Assert.Equal(Conversion.Identity, compoundAssignment.GetOutConversion());
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void ICompoundAssignment_GetConversionOnValidNode_InOutConversion()
{
string source = @"
class C
{
static void M()
{
var c = new C();
var x = 1;
/*<bind>*/c += x/*</bind>*/;
}
public static implicit operator C(int i)
{
return null;
}
public static implicit operator int(C c)
{
return 0;
}
}
";
var syntaxTree = Parse(source);
var compilation = CreateCompilationWithMscorlib461(new[] { syntaxTree });
(IOperation operation, SyntaxNode node) = GetOperationAndSyntaxForTest<AssignmentExpressionSyntax>(compilation);
var compoundAssignment = (ICompoundAssignmentOperation)operation;
var typeSymbol = compilation.GetTypeByMetadataName("C");
var implicitSymbols = typeSymbol.GetMembers("op_Implicit").Cast<MethodSymbol>();
var inSymbol = implicitSymbols.Where(sym => sym.ReturnType.SpecialType == SpecialType.System_Int32).Single();
var outSymbol = implicitSymbols.Where(sym => sym != inSymbol).Single();
var inConversion = new Conversion(ConversionKind.ImplicitUserDefined, inSymbol, false);
var outConversion = new Conversion(ConversionKind.ImplicitUserDefined, outSymbol, false);
Assert.Equal(inConversion, compoundAssignment.GetInConversion());
Assert.Equal(outConversion, compoundAssignment.GetOutConversion());
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void ICompoundAssignment_BinaryOperatorInOutConversion()
{
string source = @"
class C
{
static void M()
{
var c = new C();
var x = 1;
/*<bind>*/c += x/*</bind>*/;
}
public static implicit operator C(int i)
{
return null;
}
public static implicit operator int(C c)
{
return 0;
}
}
";
string expectedOperationTree = @"
ICompoundAssignmentOperation (BinaryOperatorKind.Add) (OperationKind.CompoundAssignment, Type: C) (Syntax: 'c += x')
InConversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: System.Int32 C.op_Implicit(C c))
OutConversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: C C.op_Implicit(System.Int32 i))
Left:
ILocalReferenceOperation: c (OperationKind.LocalReference, Type: C) (Syntax: 'c')
Right:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x')
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<AssignmentExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void ICompoundAssignment_UnsignedRightShift()
{
string source = @"
class C
{
static void M()
{
int c = 1;
int x = 1;
/*<bind>*/c >>>= x/*</bind>*/;
}
}
";
string expectedOperationTree = @"
ICompoundAssignmentOperation (BinaryOperatorKind.UnsignedRightShift) (OperationKind.CompoundAssignment, Type: System.Int32) (Syntax: 'c >>>= x')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Left:
ILocalReferenceOperation: c (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'c')
Right:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x')
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<AssignmentExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void ICompoundAssignment_BinaryOperatorInConversion_InvalidMissingOutConversion()
{
string source = @"
class C
{
static void M()
{
var c = new C();
var x = 1;
/*<bind>*/c += x/*</bind>*/;
}
public static implicit operator int(C c)
{
return 0;
}
}
";
string expectedOperationTree = @"
ICompoundAssignmentOperation (BinaryOperatorKind.Add) (OperationKind.CompoundAssignment, Type: C, IsInvalid) (Syntax: 'c += x')
InConversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: System.Int32 C.op_Implicit(C c))
OutConversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Left:
ILocalReferenceOperation: c (OperationKind.LocalReference, Type: C, IsInvalid) (Syntax: 'c')
Right:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'x')
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0029: Cannot implicitly convert type 'int' to 'C'
// /*<bind>*/c += x/*</bind>*/;
Diagnostic(ErrorCode.ERR_NoImplicitConv, "c += x").WithArguments("int", "C").WithLocation(8, 19)
};
VerifyOperationTreeAndDiagnosticsForTest<AssignmentExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void ICompoundAssignment_BinaryOperatorOutConversion_InvalidMissingInConversion()
{
string source = @"
class C
{
static void M()
{
var c = new C();
var x = 1;
/*<bind>*/c += x/*</bind>*/;
}
public static implicit operator C(int i)
{
return null;
}
}
";
string expectedOperationTree = @"
ICompoundAssignmentOperation (BinaryOperatorKind.None) (OperationKind.CompoundAssignment, Type: ?, IsInvalid) (Syntax: 'c += x')
InConversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Left:
ILocalReferenceOperation: c (OperationKind.LocalReference, Type: C, IsInvalid) (Syntax: 'c')
Right:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'x')
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0019: Operator '+=' cannot be applied to operands of type 'C' and 'int'
// /*<bind>*/c += x/*</bind>*/;
Diagnostic(ErrorCode.ERR_BadBinaryOps, "c += x").WithArguments("+=", "C", "int").WithLocation(8, 19)
};
VerifyOperationTreeAndDiagnosticsForTest<AssignmentExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void ICompoundAssignment_UserDefinedBinaryOperator_InConversion()
{
string source = @"
class C
{
static void M()
{
var c = new C();
var x = 1;
/*<bind>*/c += x/*</bind>*/;
}
public static implicit operator C(int i)
{
return null;
}
public static implicit operator int(C c)
{
return 0;
}
public static C operator +(int c1, C c2)
{
return null;
}
}
";
string expectedOperationTree = @"
ICompoundAssignmentOperation (BinaryOperatorKind.Add) (OperatorMethod: C C.op_Addition(System.Int32 c1, C c2)) (OperationKind.CompoundAssignment, Type: C) (Syntax: 'c += x')
InConversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: System.Int32 C.op_Implicit(C c))
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Left:
ILocalReferenceOperation: c (OperationKind.LocalReference, Type: C) (Syntax: 'c')
Right:
IConversionOperation (TryCast: False, Unchecked) (OperatorMethod: C C.op_Implicit(System.Int32 i)) (OperationKind.Conversion, Type: C, IsImplicit) (Syntax: 'x')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: C C.op_Implicit(System.Int32 i))
Operand:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x')
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<AssignmentExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void ICompoundAssignment_UserDefinedBinaryOperator_UnsignedRightShift()
{
string source = @"
class C
{
static void M()
{
var c = new C();
var x = 1;
/*<bind>*/c >>>= x/*</bind>*/;
}
public static C operator >>>(C c1, int c2)
{
return null;
}
}
";
string expectedOperationTree = @"
ICompoundAssignmentOperation (BinaryOperatorKind.UnsignedRightShift) (OperatorMethod: C C.op_UnsignedRightShift(C c1, System.Int32 c2)) (OperationKind.CompoundAssignment, Type: C) (Syntax: 'c >>>= x')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Left:
ILocalReferenceOperation: c (OperationKind.LocalReference, Type: C) (Syntax: 'c')
Right:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x')
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<AssignmentExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void ICompoundAssignment_UserDefinedBinaryOperator_OutConversion()
{
string source = @"
class C
{
static void M()
{
var c = new C();
var x = 1;
/*<bind>*/c += x/*</bind>*/;
}
public static implicit operator C(int i)
{
return null;
}
public static implicit operator int(C c)
{
return 0;
}
public static int operator +(C c1, C c2)
{
return 0;
}
}
";
string expectedOperationTree = @"
ICompoundAssignmentOperation (BinaryOperatorKind.Add) (OperatorMethod: System.Int32 C.op_Addition(C c1, C c2)) (OperationKind.CompoundAssignment, Type: C) (Syntax: 'c += x')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: C C.op_Implicit(System.Int32 i))
Left:
ILocalReferenceOperation: c (OperationKind.LocalReference, Type: C) (Syntax: 'c')
Right:
IConversionOperation (TryCast: False, Unchecked) (OperatorMethod: C C.op_Implicit(System.Int32 i)) (OperationKind.Conversion, Type: C, IsImplicit) (Syntax: 'x')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: C C.op_Implicit(System.Int32 i))
Operand:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x')
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<AssignmentExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void ICompoundAssignment_UserDefinedBinaryOperator_InOutConversion()
{
string source = @"
class C
{
static void M()
{
var c = new C();
var x = 1;
/*<bind>*/c += x/*</bind>*/;
}
public static implicit operator C(int i)
{
return null;
}
public static implicit operator int(C c)
{
return 0;
}
public static int operator +(int c1, C c2)
{
return 0;
}
}
";
string expectedOperationTree = @"
ICompoundAssignmentOperation (BinaryOperatorKind.Add) (OperatorMethod: System.Int32 C.op_Addition(System.Int32 c1, C c2)) (OperationKind.CompoundAssignment, Type: C) (Syntax: 'c += x')
InConversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: System.Int32 C.op_Implicit(C c))
OutConversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: C C.op_Implicit(System.Int32 i))
Left:
ILocalReferenceOperation: c (OperationKind.LocalReference, Type: C) (Syntax: 'c')
Right:
IConversionOperation (TryCast: False, Unchecked) (OperatorMethod: C C.op_Implicit(System.Int32 i)) (OperationKind.Conversion, Type: C, IsImplicit) (Syntax: 'x')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: C C.op_Implicit(System.Int32 i))
Operand:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x')
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<AssignmentExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void ICompoundAssignment_UserDefinedBinaryOperator_InvalidMissingInConversion()
{
string source = @"
class C
{
static void M()
{
var c = new C();
var x = 1;
/*<bind>*/c += x/*</bind>*/;
}
public static implicit operator C(int i)
{
return null;
}
public static int operator +(int c1, C c2)
{
return 0;
}
}
";
string expectedOperationTree = @"
ICompoundAssignmentOperation (BinaryOperatorKind.None) (OperationKind.CompoundAssignment, Type: ?, IsInvalid) (Syntax: 'c += x')
InConversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Left:
ILocalReferenceOperation: c (OperationKind.LocalReference, Type: C, IsInvalid) (Syntax: 'c')
Right:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'x')
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0019: Operator '+=' cannot be applied to operands of type 'C' and 'int'
// /*<bind>*/c += x/*</bind>*/;
Diagnostic(ErrorCode.ERR_BadBinaryOps, "c += x").WithArguments("+=", "C", "int").WithLocation(8, 19)
};
VerifyOperationTreeAndDiagnosticsForTest<AssignmentExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void ICompoundAssignment_UserDefinedBinaryOperator_InvalidMissingOutConversion()
{
string source = @"
class C
{
static void M()
{
var c = new C();
var x = 1;
/*<bind>*/c += x/*</bind>*/;
}
public static implicit operator int(C c)
{
return 0;
}
public static int operator +(int c1, C c2)
{
return 0;
}
}
";
string expectedOperationTree = @"
ICompoundAssignmentOperation (BinaryOperatorKind.Add) (OperationKind.CompoundAssignment, Type: C, IsInvalid) (Syntax: 'c += x')
InConversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: System.Int32 C.op_Implicit(C c))
OutConversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Left:
ILocalReferenceOperation: c (OperationKind.LocalReference, Type: C, IsInvalid) (Syntax: 'c')
Right:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'x')
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0029: Cannot implicitly convert type 'int' to 'C'
// /*<bind>*/c += x/*</bind>*/;
Diagnostic(ErrorCode.ERR_NoImplicitConv, "c += x").WithArguments("int", "C").WithLocation(8, 19)
};
VerifyOperationTreeAndDiagnosticsForTest<AssignmentExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation, CompilerFeature.Dataflow)]
[Fact]
public void CompoundAssignment_01()
{
string source = @"
using System;
class C
{
void M(int[] a, int? b, int c)
/*<bind>*/{
a[0] += b ?? c;
}/*</bind>*/
}
";
var expectedDiagnostics = DiagnosticDescription.None;
string expectedFlowGraph = @"
Block[B0] - Entry
Statements (0)
Next (Regular) Block[B1]
Entering: {R1}
.locals {R1}
{
CaptureIds: [0] [2]
Block[B1] - Block
Predecessors: [B0]
Statements (1)
IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'a[0]')
Value:
IArrayElementReferenceOperation (OperationKind.ArrayElementReference, Type: System.Int32) (Syntax: 'a[0]')
Array reference:
IParameterReferenceOperation: a (OperationKind.ParameterReference, Type: System.Int32[]) (Syntax: 'a')
Indices(1):
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0) (Syntax: '0')
Next (Regular) Block[B2]
Entering: {R2}
.locals {R2}
{
CaptureIds: [1]
Block[B2] - Block
Predecessors: [B1]
Statements (1)
IFlowCaptureOperation: 1 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'b')
Value:
IParameterReferenceOperation: b (OperationKind.ParameterReference, Type: System.Int32?) (Syntax: 'b')
Jump if True (Regular) to Block[B4]
IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsImplicit) (Syntax: 'b')
Operand:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Int32?, IsImplicit) (Syntax: 'b')
Leaving: {R2}
Next (Regular) Block[B3]
Block[B3] - Block
Predecessors: [B2]
Statements (1)
IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'b')
Value:
IInvocationOperation ( System.Int32 System.Int32?.GetValueOrDefault()) (OperationKind.Invocation, Type: System.Int32, IsImplicit) (Syntax: 'b')
Instance Receiver:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Int32?, IsImplicit) (Syntax: 'b')
Arguments(0)
Next (Regular) Block[B5]
Leaving: {R2}
}
Block[B4] - Block
Predecessors: [B2]
Statements (1)
IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'c')
Value:
IParameterReferenceOperation: c (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'c')
Next (Regular) Block[B5]
Block[B5] - Block
Predecessors: [B3] [B4]
Statements (1)
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'a[0] += b ?? c;')
Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add) (OperationKind.CompoundAssignment, Type: System.Int32) (Syntax: 'a[0] += b ?? c')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Left:
IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Int32, IsImplicit) (Syntax: 'a[0]')
Right:
IFlowCaptureReferenceOperation: 2 (OperationKind.FlowCaptureReference, Type: System.Int32, IsImplicit) (Syntax: 'b ?? c')
Next (Regular) Block[B6]
Leaving: {R1}
}
Block[B6] - Exit
Predecessors: [B5]
Statements (0)
";
VerifyFlowGraphAndDiagnosticsForTest<BlockSyntax>(source, expectedFlowGraph, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation, CompilerFeature.Dataflow)]
[Fact]
public void CompoundAssignment_02()
{
string source = @"
using System;
class C
{
void M(int[] a, int? b, int c)
/*<bind>*/{
a[0] -= b ?? c;
}/*</bind>*/
}
";
var expectedDiagnostics = DiagnosticDescription.None;
string expectedFlowGraph = @"
Block[B0] - Entry
Statements (0)
Next (Regular) Block[B1]
Entering: {R1}
.locals {R1}
{
CaptureIds: [0] [2]
Block[B1] - Block
Predecessors: [B0]
Statements (1)
IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'a[0]')
Value:
IArrayElementReferenceOperation (OperationKind.ArrayElementReference, Type: System.Int32) (Syntax: 'a[0]')
Array reference:
IParameterReferenceOperation: a (OperationKind.ParameterReference, Type: System.Int32[]) (Syntax: 'a')
Indices(1):
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0) (Syntax: '0')
Next (Regular) Block[B2]
Entering: {R2}
.locals {R2}
{
CaptureIds: [1]
Block[B2] - Block
Predecessors: [B1]
Statements (1)
IFlowCaptureOperation: 1 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'b')
Value:
IParameterReferenceOperation: b (OperationKind.ParameterReference, Type: System.Int32?) (Syntax: 'b')
Jump if True (Regular) to Block[B4]
IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsImplicit) (Syntax: 'b')
Operand:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Int32?, IsImplicit) (Syntax: 'b')
Leaving: {R2}
Next (Regular) Block[B3]
Block[B3] - Block
Predecessors: [B2]
Statements (1)
IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'b')
Value:
IInvocationOperation ( System.Int32 System.Int32?.GetValueOrDefault()) (OperationKind.Invocation, Type: System.Int32, IsImplicit) (Syntax: 'b')
Instance Receiver:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Int32?, IsImplicit) (Syntax: 'b')
Arguments(0)
Next (Regular) Block[B5]
Leaving: {R2}
}
Block[B4] - Block
Predecessors: [B2]
Statements (1)
IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'c')
Value:
IParameterReferenceOperation: c (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'c')
Next (Regular) Block[B5]
Block[B5] - Block
Predecessors: [B3] [B4]
Statements (1)
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'a[0] -= b ?? c;')
Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Subtract) (OperationKind.CompoundAssignment, Type: System.Int32) (Syntax: 'a[0] -= b ?? c')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Left:
IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Int32, IsImplicit) (Syntax: 'a[0]')
Right:
IFlowCaptureReferenceOperation: 2 (OperationKind.FlowCaptureReference, Type: System.Int32, IsImplicit) (Syntax: 'b ?? c')
Next (Regular) Block[B6]
Leaving: {R1}
}
Block[B6] - Exit
Predecessors: [B5]
Statements (0)
";
VerifyFlowGraphAndDiagnosticsForTest<BlockSyntax>(source, expectedFlowGraph, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation, CompilerFeature.Dataflow)]
[Fact]
public void CompoundAssignment_03()
{
string source = @"
using System;
class C
{
void M(int[] a, int? b, int c)
/*<bind>*/{
a[0] *= b ?? c;
}/*</bind>*/
}
";
var expectedDiagnostics = DiagnosticDescription.None;
string expectedFlowGraph = @"
Block[B0] - Entry
Statements (0)
Next (Regular) Block[B1]
Entering: {R1}
.locals {R1}
{
CaptureIds: [0] [2]
Block[B1] - Block
Predecessors: [B0]
Statements (1)
IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'a[0]')
Value:
IArrayElementReferenceOperation (OperationKind.ArrayElementReference, Type: System.Int32) (Syntax: 'a[0]')
Array reference:
IParameterReferenceOperation: a (OperationKind.ParameterReference, Type: System.Int32[]) (Syntax: 'a')
Indices(1):
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0) (Syntax: '0')
Next (Regular) Block[B2]
Entering: {R2}
.locals {R2}
{
CaptureIds: [1]
Block[B2] - Block
Predecessors: [B1]
Statements (1)
IFlowCaptureOperation: 1 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'b')
Value:
IParameterReferenceOperation: b (OperationKind.ParameterReference, Type: System.Int32?) (Syntax: 'b')
Jump if True (Regular) to Block[B4]
IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsImplicit) (Syntax: 'b')
Operand:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Int32?, IsImplicit) (Syntax: 'b')
Leaving: {R2}
Next (Regular) Block[B3]
Block[B3] - Block
Predecessors: [B2]
Statements (1)
IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'b')
Value:
IInvocationOperation ( System.Int32 System.Int32?.GetValueOrDefault()) (OperationKind.Invocation, Type: System.Int32, IsImplicit) (Syntax: 'b')
Instance Receiver:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Int32?, IsImplicit) (Syntax: 'b')
Arguments(0)
Next (Regular) Block[B5]
Leaving: {R2}
}
Block[B4] - Block
Predecessors: [B2]
Statements (1)
IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'c')
Value:
IParameterReferenceOperation: c (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'c')
Next (Regular) Block[B5]
Block[B5] - Block
Predecessors: [B3] [B4]
Statements (1)
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'a[0] *= b ?? c;')
Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Multiply) (OperationKind.CompoundAssignment, Type: System.Int32) (Syntax: 'a[0] *= b ?? c')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Left:
IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Int32, IsImplicit) (Syntax: 'a[0]')
Right:
IFlowCaptureReferenceOperation: 2 (OperationKind.FlowCaptureReference, Type: System.Int32, IsImplicit) (Syntax: 'b ?? c')
Next (Regular) Block[B6]
Leaving: {R1}
}
Block[B6] - Exit
Predecessors: [B5]
Statements (0)
";
VerifyFlowGraphAndDiagnosticsForTest<BlockSyntax>(source, expectedFlowGraph, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation, CompilerFeature.Dataflow)]
[Fact]
public void CompoundAssignment_04()
{
string source = @"
using System;
class C
{
void M(int[] a, int? b, int c)
/*<bind>*/{
a[0] /= b ?? c;
}/*</bind>*/
}
";
var expectedDiagnostics = DiagnosticDescription.None;
string expectedFlowGraph = @"
Block[B0] - Entry
Statements (0)
Next (Regular) Block[B1]
Entering: {R1}
.locals {R1}
{
CaptureIds: [0] [2]
Block[B1] - Block
Predecessors: [B0]
Statements (1)
IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'a[0]')
Value:
IArrayElementReferenceOperation (OperationKind.ArrayElementReference, Type: System.Int32) (Syntax: 'a[0]')
Array reference:
IParameterReferenceOperation: a (OperationKind.ParameterReference, Type: System.Int32[]) (Syntax: 'a')
Indices(1):
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0) (Syntax: '0')
Next (Regular) Block[B2]
Entering: {R2}
.locals {R2}
{
CaptureIds: [1]
Block[B2] - Block
Predecessors: [B1]
Statements (1)
IFlowCaptureOperation: 1 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'b')
Value:
IParameterReferenceOperation: b (OperationKind.ParameterReference, Type: System.Int32?) (Syntax: 'b')
Jump if True (Regular) to Block[B4]
IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsImplicit) (Syntax: 'b')
Operand:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Int32?, IsImplicit) (Syntax: 'b')
Leaving: {R2}
Next (Regular) Block[B3]
Block[B3] - Block
Predecessors: [B2]
Statements (1)
IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'b')
Value:
IInvocationOperation ( System.Int32 System.Int32?.GetValueOrDefault()) (OperationKind.Invocation, Type: System.Int32, IsImplicit) (Syntax: 'b')
Instance Receiver:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Int32?, IsImplicit) (Syntax: 'b')
Arguments(0)
Next (Regular) Block[B5]
Leaving: {R2}
}
Block[B4] - Block
Predecessors: [B2]
Statements (1)
IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'c')
Value:
IParameterReferenceOperation: c (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'c')
Next (Regular) Block[B5]
Block[B5] - Block
Predecessors: [B3] [B4]
Statements (1)
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'a[0] /= b ?? c;')
Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Divide) (OperationKind.CompoundAssignment, Type: System.Int32) (Syntax: 'a[0] /= b ?? c')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Left:
IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Int32, IsImplicit) (Syntax: 'a[0]')
Right:
IFlowCaptureReferenceOperation: 2 (OperationKind.FlowCaptureReference, Type: System.Int32, IsImplicit) (Syntax: 'b ?? c')
Next (Regular) Block[B6]
Leaving: {R1}
}
Block[B6] - Exit
Predecessors: [B5]
Statements (0)
";
VerifyFlowGraphAndDiagnosticsForTest<BlockSyntax>(source, expectedFlowGraph, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation, CompilerFeature.Dataflow)]
[Fact]
public void CompoundAssignment_05()
{
string source = @"
using System;
class C
{
void M(int[] a, int? b, int c)
/*<bind>*/{
a[0] %= b ?? c;
}/*</bind>*/
}
";
var expectedDiagnostics = DiagnosticDescription.None;
string expectedFlowGraph = @"
Block[B0] - Entry
Statements (0)
Next (Regular) Block[B1]
Entering: {R1}
.locals {R1}
{
CaptureIds: [0] [2]
Block[B1] - Block
Predecessors: [B0]
Statements (1)
IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'a[0]')
Value:
IArrayElementReferenceOperation (OperationKind.ArrayElementReference, Type: System.Int32) (Syntax: 'a[0]')
Array reference:
IParameterReferenceOperation: a (OperationKind.ParameterReference, Type: System.Int32[]) (Syntax: 'a')
Indices(1):
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0) (Syntax: '0')
Next (Regular) Block[B2]
Entering: {R2}
.locals {R2}
{
CaptureIds: [1]
Block[B2] - Block
Predecessors: [B1]
Statements (1)
IFlowCaptureOperation: 1 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'b')
Value:
IParameterReferenceOperation: b (OperationKind.ParameterReference, Type: System.Int32?) (Syntax: 'b')
Jump if True (Regular) to Block[B4]
IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsImplicit) (Syntax: 'b')
Operand:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Int32?, IsImplicit) (Syntax: 'b')
Leaving: {R2}
Next (Regular) Block[B3]
Block[B3] - Block
Predecessors: [B2]
Statements (1)
IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'b')
Value:
IInvocationOperation ( System.Int32 System.Int32?.GetValueOrDefault()) (OperationKind.Invocation, Type: System.Int32, IsImplicit) (Syntax: 'b')
Instance Receiver:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Int32?, IsImplicit) (Syntax: 'b')
Arguments(0)
Next (Regular) Block[B5]
Leaving: {R2}
}
Block[B4] - Block
Predecessors: [B2]
Statements (1)
IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'c')
Value:
IParameterReferenceOperation: c (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'c')
Next (Regular) Block[B5]
Block[B5] - Block
Predecessors: [B3] [B4]
Statements (1)
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'a[0] %= b ?? c;')
Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Remainder) (OperationKind.CompoundAssignment, Type: System.Int32) (Syntax: 'a[0] %= b ?? c')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Left:
IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Int32, IsImplicit) (Syntax: 'a[0]')
Right:
IFlowCaptureReferenceOperation: 2 (OperationKind.FlowCaptureReference, Type: System.Int32, IsImplicit) (Syntax: 'b ?? c')
Next (Regular) Block[B6]
Leaving: {R1}
}
Block[B6] - Exit
Predecessors: [B5]
Statements (0)
";
VerifyFlowGraphAndDiagnosticsForTest<BlockSyntax>(source, expectedFlowGraph, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation, CompilerFeature.Dataflow)]
[Fact]
public void CompoundAssignment_06()
{
string source = @"
using System;
class C
{
void M(int[] a, int? b, int c)
/*<bind>*/{
a[0] &= b ?? c;
}/*</bind>*/
}
";
var expectedDiagnostics = DiagnosticDescription.None;
string expectedFlowGraph = @"
Block[B0] - Entry
Statements (0)
Next (Regular) Block[B1]
Entering: {R1}
.locals {R1}
{
CaptureIds: [0] [2]
Block[B1] - Block
Predecessors: [B0]
Statements (1)
IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'a[0]')
Value:
IArrayElementReferenceOperation (OperationKind.ArrayElementReference, Type: System.Int32) (Syntax: 'a[0]')
Array reference:
IParameterReferenceOperation: a (OperationKind.ParameterReference, Type: System.Int32[]) (Syntax: 'a')
Indices(1):
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0) (Syntax: '0')
Next (Regular) Block[B2]
Entering: {R2}
.locals {R2}
{
CaptureIds: [1]
Block[B2] - Block
Predecessors: [B1]
Statements (1)
IFlowCaptureOperation: 1 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'b')
Value:
IParameterReferenceOperation: b (OperationKind.ParameterReference, Type: System.Int32?) (Syntax: 'b')
Jump if True (Regular) to Block[B4]
IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsImplicit) (Syntax: 'b')
Operand:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Int32?, IsImplicit) (Syntax: 'b')
Leaving: {R2}
Next (Regular) Block[B3]
Block[B3] - Block
Predecessors: [B2]
Statements (1)
IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'b')
Value:
IInvocationOperation ( System.Int32 System.Int32?.GetValueOrDefault()) (OperationKind.Invocation, Type: System.Int32, IsImplicit) (Syntax: 'b')
Instance Receiver:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Int32?, IsImplicit) (Syntax: 'b')
Arguments(0)
Next (Regular) Block[B5]
Leaving: {R2}
}
Block[B4] - Block
Predecessors: [B2]
Statements (1)
IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'c')
Value:
IParameterReferenceOperation: c (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'c')
Next (Regular) Block[B5]
Block[B5] - Block
Predecessors: [B3] [B4]
Statements (1)
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'a[0] &= b ?? c;')
Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.And) (OperationKind.CompoundAssignment, Type: System.Int32) (Syntax: 'a[0] &= b ?? c')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Left:
IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Int32, IsImplicit) (Syntax: 'a[0]')
Right:
IFlowCaptureReferenceOperation: 2 (OperationKind.FlowCaptureReference, Type: System.Int32, IsImplicit) (Syntax: 'b ?? c')
Next (Regular) Block[B6]
Leaving: {R1}
}
Block[B6] - Exit
Predecessors: [B5]
Statements (0)
";
VerifyFlowGraphAndDiagnosticsForTest<BlockSyntax>(source, expectedFlowGraph, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation, CompilerFeature.Dataflow)]
[Fact]
public void CompoundAssignment_07()
{
string source = @"
using System;
class C
{
void M(int[] a, int? b, int c)
/*<bind>*/{
a[0] |= b ?? c;
}/*</bind>*/
}
";
var expectedDiagnostics = DiagnosticDescription.None;
string expectedFlowGraph = @"
Block[B0] - Entry
Statements (0)
Next (Regular) Block[B1]
Entering: {R1}
.locals {R1}
{
CaptureIds: [0] [2]
Block[B1] - Block
Predecessors: [B0]
Statements (1)
IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'a[0]')
Value:
IArrayElementReferenceOperation (OperationKind.ArrayElementReference, Type: System.Int32) (Syntax: 'a[0]')
Array reference:
IParameterReferenceOperation: a (OperationKind.ParameterReference, Type: System.Int32[]) (Syntax: 'a')
Indices(1):
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0) (Syntax: '0')
Next (Regular) Block[B2]
Entering: {R2}
.locals {R2}
{
CaptureIds: [1]
Block[B2] - Block
Predecessors: [B1]
Statements (1)
IFlowCaptureOperation: 1 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'b')
Value:
IParameterReferenceOperation: b (OperationKind.ParameterReference, Type: System.Int32?) (Syntax: 'b')
Jump if True (Regular) to Block[B4]
IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsImplicit) (Syntax: 'b')
Operand:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Int32?, IsImplicit) (Syntax: 'b')
Leaving: {R2}
Next (Regular) Block[B3]
Block[B3] - Block
Predecessors: [B2]
Statements (1)
IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'b')
Value:
IInvocationOperation ( System.Int32 System.Int32?.GetValueOrDefault()) (OperationKind.Invocation, Type: System.Int32, IsImplicit) (Syntax: 'b')
Instance Receiver:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Int32?, IsImplicit) (Syntax: 'b')
Arguments(0)
Next (Regular) Block[B5]
Leaving: {R2}
}
Block[B4] - Block
Predecessors: [B2]
Statements (1)
IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'c')
Value:
IParameterReferenceOperation: c (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'c')
Next (Regular) Block[B5]
Block[B5] - Block
Predecessors: [B3] [B4]
Statements (1)
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'a[0] |= b ?? c;')
Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Or) (OperationKind.CompoundAssignment, Type: System.Int32) (Syntax: 'a[0] |= b ?? c')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Left:
IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Int32, IsImplicit) (Syntax: 'a[0]')
Right:
IFlowCaptureReferenceOperation: 2 (OperationKind.FlowCaptureReference, Type: System.Int32, IsImplicit) (Syntax: 'b ?? c')
Next (Regular) Block[B6]
Leaving: {R1}
}
Block[B6] - Exit
Predecessors: [B5]
Statements (0)
";
VerifyFlowGraphAndDiagnosticsForTest<BlockSyntax>(source, expectedFlowGraph, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation, CompilerFeature.Dataflow)]
[Fact]
public void CompoundAssignment_08()
{
string source = @"
using System;
class C
{
void M(int[] a, int? b, int c)
/*<bind>*/{
a[0] ^= b ?? c;
}/*</bind>*/
}
";
var expectedDiagnostics = DiagnosticDescription.None;
string expectedFlowGraph = @"
Block[B0] - Entry
Statements (0)
Next (Regular) Block[B1]
Entering: {R1}
.locals {R1}
{
CaptureIds: [0] [2]
Block[B1] - Block
Predecessors: [B0]
Statements (1)
IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'a[0]')
Value:
IArrayElementReferenceOperation (OperationKind.ArrayElementReference, Type: System.Int32) (Syntax: 'a[0]')
Array reference:
IParameterReferenceOperation: a (OperationKind.ParameterReference, Type: System.Int32[]) (Syntax: 'a')
Indices(1):
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0) (Syntax: '0')
Next (Regular) Block[B2]
Entering: {R2}
.locals {R2}
{
CaptureIds: [1]
Block[B2] - Block
Predecessors: [B1]
Statements (1)
IFlowCaptureOperation: 1 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'b')
Value:
IParameterReferenceOperation: b (OperationKind.ParameterReference, Type: System.Int32?) (Syntax: 'b')
Jump if True (Regular) to Block[B4]
IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsImplicit) (Syntax: 'b')
Operand:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Int32?, IsImplicit) (Syntax: 'b')
Leaving: {R2}
Next (Regular) Block[B3]
Block[B3] - Block
Predecessors: [B2]
Statements (1)
IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'b')
Value:
IInvocationOperation ( System.Int32 System.Int32?.GetValueOrDefault()) (OperationKind.Invocation, Type: System.Int32, IsImplicit) (Syntax: 'b')
Instance Receiver:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Int32?, IsImplicit) (Syntax: 'b')
Arguments(0)
Next (Regular) Block[B5]
Leaving: {R2}
}
Block[B4] - Block
Predecessors: [B2]
Statements (1)
IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'c')
Value:
IParameterReferenceOperation: c (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'c')
Next (Regular) Block[B5]
Block[B5] - Block
Predecessors: [B3] [B4]
Statements (1)
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'a[0] ^= b ?? c;')
Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.ExclusiveOr) (OperationKind.CompoundAssignment, Type: System.Int32) (Syntax: 'a[0] ^= b ?? c')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Left:
IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Int32, IsImplicit) (Syntax: 'a[0]')
Right:
IFlowCaptureReferenceOperation: 2 (OperationKind.FlowCaptureReference, Type: System.Int32, IsImplicit) (Syntax: 'b ?? c')
Next (Regular) Block[B6]
Leaving: {R1}
}
Block[B6] - Exit
Predecessors: [B5]
Statements (0)
";
VerifyFlowGraphAndDiagnosticsForTest<BlockSyntax>(source, expectedFlowGraph, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation, CompilerFeature.Dataflow)]
[Fact]
public void CompoundAssignment_09()
{
string source = @"
using System;
class C
{
void M(int[] a, int? b, int c)
/*<bind>*/{
a[0] <<= b ?? c;
}/*</bind>*/
}
";
var expectedDiagnostics = DiagnosticDescription.None;
string expectedFlowGraph = @"
Block[B0] - Entry
Statements (0)
Next (Regular) Block[B1]
Entering: {R1}
.locals {R1}
{
CaptureIds: [0] [2]
Block[B1] - Block
Predecessors: [B0]
Statements (1)
IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'a[0]')
Value:
IArrayElementReferenceOperation (OperationKind.ArrayElementReference, Type: System.Int32) (Syntax: 'a[0]')
Array reference:
IParameterReferenceOperation: a (OperationKind.ParameterReference, Type: System.Int32[]) (Syntax: 'a')
Indices(1):
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0) (Syntax: '0')
Next (Regular) Block[B2]
Entering: {R2}
.locals {R2}
{
CaptureIds: [1]
Block[B2] - Block
Predecessors: [B1]
Statements (1)
IFlowCaptureOperation: 1 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'b')
Value:
IParameterReferenceOperation: b (OperationKind.ParameterReference, Type: System.Int32?) (Syntax: 'b')
Jump if True (Regular) to Block[B4]
IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsImplicit) (Syntax: 'b')
Operand:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Int32?, IsImplicit) (Syntax: 'b')
Leaving: {R2}
Next (Regular) Block[B3]
Block[B3] - Block
Predecessors: [B2]
Statements (1)
IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'b')
Value:
IInvocationOperation ( System.Int32 System.Int32?.GetValueOrDefault()) (OperationKind.Invocation, Type: System.Int32, IsImplicit) (Syntax: 'b')
Instance Receiver:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Int32?, IsImplicit) (Syntax: 'b')
Arguments(0)
Next (Regular) Block[B5]
Leaving: {R2}
}
Block[B4] - Block
Predecessors: [B2]
Statements (1)
IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'c')
Value:
IParameterReferenceOperation: c (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'c')
Next (Regular) Block[B5]
Block[B5] - Block
Predecessors: [B3] [B4]
Statements (1)
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'a[0] <<= b ?? c;')
Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.LeftShift) (OperationKind.CompoundAssignment, Type: System.Int32) (Syntax: 'a[0] <<= b ?? c')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Left:
IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Int32, IsImplicit) (Syntax: 'a[0]')
Right:
IFlowCaptureReferenceOperation: 2 (OperationKind.FlowCaptureReference, Type: System.Int32, IsImplicit) (Syntax: 'b ?? c')
Next (Regular) Block[B6]
Leaving: {R1}
}
Block[B6] - Exit
Predecessors: [B5]
Statements (0)
";
VerifyFlowGraphAndDiagnosticsForTest<BlockSyntax>(source, expectedFlowGraph, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation, CompilerFeature.Dataflow)]
[Fact]
public void CompoundAssignment_10()
{
string source = @"
using System;
class C
{
void M(int[] a, int? b, int c)
/*<bind>*/{
a[0] >>= b ?? c;
}/*</bind>*/
}
";
var expectedDiagnostics = DiagnosticDescription.None;
string expectedFlowGraph = @"
Block[B0] - Entry
Statements (0)
Next (Regular) Block[B1]
Entering: {R1}
.locals {R1}
{
CaptureIds: [0] [2]
Block[B1] - Block
Predecessors: [B0]
Statements (1)
IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'a[0]')
Value:
IArrayElementReferenceOperation (OperationKind.ArrayElementReference, Type: System.Int32) (Syntax: 'a[0]')
Array reference:
IParameterReferenceOperation: a (OperationKind.ParameterReference, Type: System.Int32[]) (Syntax: 'a')
Indices(1):
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0) (Syntax: '0')
Next (Regular) Block[B2]
Entering: {R2}
.locals {R2}
{
CaptureIds: [1]
Block[B2] - Block
Predecessors: [B1]
Statements (1)
IFlowCaptureOperation: 1 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'b')
Value:
IParameterReferenceOperation: b (OperationKind.ParameterReference, Type: System.Int32?) (Syntax: 'b')
Jump if True (Regular) to Block[B4]
IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsImplicit) (Syntax: 'b')
Operand:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Int32?, IsImplicit) (Syntax: 'b')
Leaving: {R2}
Next (Regular) Block[B3]
Block[B3] - Block
Predecessors: [B2]
Statements (1)
IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'b')
Value:
IInvocationOperation ( System.Int32 System.Int32?.GetValueOrDefault()) (OperationKind.Invocation, Type: System.Int32, IsImplicit) (Syntax: 'b')
Instance Receiver:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Int32?, IsImplicit) (Syntax: 'b')
Arguments(0)
Next (Regular) Block[B5]
Leaving: {R2}
}
Block[B4] - Block
Predecessors: [B2]
Statements (1)
IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'c')
Value:
IParameterReferenceOperation: c (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'c')
Next (Regular) Block[B5]
Block[B5] - Block
Predecessors: [B3] [B4]
Statements (1)
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'a[0] >>= b ?? c;')
Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.RightShift) (OperationKind.CompoundAssignment, Type: System.Int32) (Syntax: 'a[0] >>= b ?? c')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Left:
IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Int32, IsImplicit) (Syntax: 'a[0]')
Right:
IFlowCaptureReferenceOperation: 2 (OperationKind.FlowCaptureReference, Type: System.Int32, IsImplicit) (Syntax: 'b ?? c')
Next (Regular) Block[B6]
Leaving: {R1}
}
Block[B6] - Exit
Predecessors: [B5]
Statements (0)
";
VerifyFlowGraphAndDiagnosticsForTest<BlockSyntax>(source, expectedFlowGraph, expectedDiagnostics);
}
}
}
|