diff --git a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs index 51c68f938936abf191645dcbf4b4576a281db41f..73c0ef699c0f81200155527c326c8fcdb47773ef 100644 --- a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs +++ b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs @@ -1726,12 +1726,19 @@ private ILockOperation CreateBoundLockStatementOperation(BoundLockStatement boun { Lazy expression = new Lazy(() => Create(boundLockStatement.Argument)); Lazy body = new Lazy(() => Create(boundLockStatement.Body)); + // If there is no Enter2 method, then there will be no lock taken reference + bool legacyMode = _semanticModel.Compilation.CommonGetWellKnownTypeMember(WellKnownMember.System_Threading_Monitor__Enter2) == null; + ILocalSymbol lockTakenSymbol = + legacyMode ? null : new SynthesizedLocal(_semanticModel.GetEnclosingSymbol(boundLockStatement.Syntax.SpanStart) as MethodSymbol, + (TypeSymbol)_semanticModel.Compilation.GetSpecialType(SpecialType.System_Boolean), + SynthesizedLocalKind.LockTaken, + syntaxOpt: boundLockStatement.Argument.Syntax); SyntaxNode syntax = boundLockStatement.Syntax; ITypeSymbol type = null; Optional constantValue = default(Optional); bool isImplicit = boundLockStatement.WasCompilerGenerated; - return new LazyLockStatement(expression, body, _semanticModel, syntax, type, constantValue, isImplicit); + return new LazyLockStatement(expression, body, lockTakenSymbol, _semanticModel, syntax, type, constantValue, isImplicit); } private IInvalidOperation CreateBoundBadStatementOperation(BoundBadStatement boundBadStatement) diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_ILockStatement.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_ILockStatement.cs index e75837660c01b5fa79f3ff86633e58f3e866174d..1bd0f5c9450da2514e06821f39856e758b972fc0 100644 --- a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_ILockStatement.cs +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_ILockStatement.cs @@ -430,78 +430,82 @@ void M(object source1, object source2, object source3) IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Object, IsImplicit) (Syntax: 'source1 ?? source2') Next (Regular) Block[B5] - Entering: {R1} {R2} + Entering: {R1} {R2} {R3} -.try {R1, R2} +.locals {R1} { - Block[B5] - Block - Predecessors: [B4] - Statements (2) - IInvocationOperation (void System.Threading.Monitor.Enter(System.Object obj, ref System.Boolean lockTaken)) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 'source1 ?? source2') - Instance Receiver: - null - Arguments(2): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: obj) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'source1 ?? source2') - IFlowCaptureReferenceOperation: 2 (OperationKind.FlowCaptureReference, Type: System.Object, IsImplicit) (Syntax: 'source1 ?? source2') - 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) - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: lockTaken) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'source1 ?? source2') - IFlowCaptureReferenceOperation: 3 (OperationKind.FlowCaptureReference, Type: System.Boolean, IsImplicit) (Syntax: 'source1 ?? source2') - 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) - - IFlowCaptureOperation: 4 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'source3') - Value: - IParameterReferenceOperation: source3 (OperationKind.ParameterReference, Type: System.Object) (Syntax: 'source3') - - Jump if True (Regular) to Block[B10] - IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsImplicit) (Syntax: 'source3') - Operand: - IFlowCaptureReferenceOperation: 4 (OperationKind.FlowCaptureReference, Type: System.Object, IsImplicit) (Syntax: 'source3') - Finalizing: {R3} - Leaving: {R2} {R1} - - Next (Regular) Block[B6] - Block[B6] - Block - Predecessors: [B5] - Statements (1) - IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'source3?.ToString();') - Expression: - IInvocationOperation (virtual System.String System.Object.ToString()) (OperationKind.Invocation, Type: System.String) (Syntax: '.ToString()') + Locals: [System.Boolean ?] + .try {R2, R3} + { + Block[B5] - Block + Predecessors: [B4] + Statements (2) + IInvocationOperation (void System.Threading.Monitor.Enter(System.Object obj, ref System.Boolean lockTaken)) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 'source1 ?? source2') Instance Receiver: - IFlowCaptureReferenceOperation: 4 (OperationKind.FlowCaptureReference, Type: System.Object, IsImplicit) (Syntax: 'source3') - Arguments(0) - - Next (Regular) Block[B10] - Finalizing: {R3} - Leaving: {R2} {R1} -} -.finally {R3} -{ - Block[B7] - Block - Predecessors (0) - Statements (0) - Jump if False (Regular) to Block[B9] - IFlowCaptureReferenceOperation: 3 (OperationKind.FlowCaptureReference, Type: System.Boolean, IsImplicit) (Syntax: 'source1 ?? source2') - - Next (Regular) Block[B8] - Block[B8] - Block - Predecessors: [B7] - Statements (1) - IInvocationOperation (void System.Threading.Monitor.Exit(System.Object obj)) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 'source1 ?? source2') - Instance Receiver: - null - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: obj) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'source1 ?? source2') - IFlowCaptureReferenceOperation: 2 (OperationKind.FlowCaptureReference, Type: System.Object, IsImplicit) (Syntax: 'source1 ?? source2') - 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) - - Next (Regular) Block[B9] - Block[B9] - Block - Predecessors: [B7] [B8] - Statements (0) - Next (StructuredExceptionHandling) Block[null] + null + Arguments(2): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: obj) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'source1 ?? source2') + IFlowCaptureReferenceOperation: 2 (OperationKind.FlowCaptureReference, Type: System.Object, IsImplicit) (Syntax: 'source1 ?? source2') + 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) + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: lockTaken) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'source1 ?? source2') + ILocalReferenceOperation: (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Boolean, Constant: null, IsImplicit) (Syntax: 'source1 ?? source2') + 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) + + IFlowCaptureOperation: 3 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'source3') + Value: + IParameterReferenceOperation: source3 (OperationKind.ParameterReference, Type: System.Object) (Syntax: 'source3') + + Jump if True (Regular) to Block[B10] + IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsImplicit) (Syntax: 'source3') + Operand: + IFlowCaptureReferenceOperation: 3 (OperationKind.FlowCaptureReference, Type: System.Object, IsImplicit) (Syntax: 'source3') + Finalizing: {R4} + Leaving: {R3} {R2} {R1} + + Next (Regular) Block[B6] + Block[B6] - Block + Predecessors: [B5] + Statements (1) + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'source3?.ToString();') + Expression: + IInvocationOperation (virtual System.String System.Object.ToString()) (OperationKind.Invocation, Type: System.String) (Syntax: '.ToString()') + Instance Receiver: + IFlowCaptureReferenceOperation: 3 (OperationKind.FlowCaptureReference, Type: System.Object, IsImplicit) (Syntax: 'source3') + Arguments(0) + + Next (Regular) Block[B10] + Finalizing: {R4} + Leaving: {R3} {R2} {R1} + } + .finally {R4} + { + Block[B7] - Block + Predecessors (0) + Statements (0) + Jump if False (Regular) to Block[B9] + ILocalReferenceOperation: (OperationKind.LocalReference, Type: System.Boolean, Constant: null, IsImplicit) (Syntax: 'source1 ?? source2') + + Next (Regular) Block[B8] + Block[B8] - Block + Predecessors: [B7] + Statements (1) + IInvocationOperation (void System.Threading.Monitor.Exit(System.Object obj)) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 'source1 ?? source2') + Instance Receiver: + null + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: obj) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'source1 ?? source2') + IFlowCaptureReferenceOperation: 2 (OperationKind.FlowCaptureReference, Type: System.Object, IsImplicit) (Syntax: 'source1 ?? source2') + 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) + + Next (Regular) Block[B9] + Block[B9] - Block + Predecessors: [B7] [B8] + Statements (0) + Next (StructuredExceptionHandling) Block[null] + } } Block[B10] - Exit @@ -629,64 +633,68 @@ void M(int input1, bool input2) IParameterReferenceOperation: input1 (OperationKind.ParameterReference, Type: System.Int32, IsInvalid) (Syntax: 'input1') Next (Regular) Block[B2] - Entering: {R1} {R2} + Entering: {R1} {R2} {R3} -.try {R1, R2} +.locals {R1} { - Block[B2] - Block - Predecessors: [B1] - Statements (2) - IInvocationOperation (void System.Threading.Monitor.Enter(System.Object obj, ref System.Boolean lockTaken)) (OperationKind.Invocation, Type: System.Void, IsInvalid, IsImplicit) (Syntax: 'input1') - Instance Receiver: - null - Arguments(2): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: obj) (OperationKind.Argument, Type: null, IsInvalid, IsImplicit) (Syntax: 'input1') - IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Object, IsInvalid, IsImplicit) (Syntax: 'input1') - 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) - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: lockTaken) (OperationKind.Argument, Type: null, IsInvalid, IsImplicit) (Syntax: 'input1') - IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Boolean, IsInvalid, IsImplicit) (Syntax: 'input1') - 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) - - IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'input2 = true;') - Expression: - ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Boolean) (Syntax: 'input2 = true') - Left: - IParameterReferenceOperation: input2 (OperationKind.ParameterReference, Type: System.Boolean) (Syntax: 'input2') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.Boolean, Constant: True) (Syntax: 'true') - - Next (Regular) Block[B6] - Finalizing: {R3} - Leaving: {R2} {R1} -} -.finally {R3} -{ - Block[B3] - Block - Predecessors (0) - Statements (0) - Jump if False (Regular) to Block[B5] - IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Boolean, IsInvalid, IsImplicit) (Syntax: 'input1') - - Next (Regular) Block[B4] - Block[B4] - Block - Predecessors: [B3] - Statements (1) - IInvocationOperation (void System.Threading.Monitor.Exit(System.Object obj)) (OperationKind.Invocation, Type: System.Void, IsInvalid, IsImplicit) (Syntax: 'input1') - Instance Receiver: - null - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: obj) (OperationKind.Argument, Type: null, IsInvalid, IsImplicit) (Syntax: 'input1') - IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Object, IsInvalid, IsImplicit) (Syntax: 'input1') - 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) - - Next (Regular) Block[B5] - Block[B5] - Block - Predecessors: [B3] [B4] - Statements (0) - Next (StructuredExceptionHandling) Block[null] + Locals: [System.Boolean ?] + .try {R2, R3} + { + Block[B2] - Block + Predecessors: [B1] + Statements (2) + IInvocationOperation (void System.Threading.Monitor.Enter(System.Object obj, ref System.Boolean lockTaken)) (OperationKind.Invocation, Type: System.Void, IsInvalid, IsImplicit) (Syntax: 'input1') + Instance Receiver: + null + Arguments(2): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: obj) (OperationKind.Argument, Type: null, IsInvalid, IsImplicit) (Syntax: 'input1') + IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Object, IsInvalid, IsImplicit) (Syntax: 'input1') + 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) + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: lockTaken) (OperationKind.Argument, Type: null, IsInvalid, IsImplicit) (Syntax: 'input1') + ILocalReferenceOperation: (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Boolean, Constant: null, IsInvalid, IsImplicit) (Syntax: 'input1') + 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) + + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'input2 = true;') + Expression: + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Boolean) (Syntax: 'input2 = true') + Left: + IParameterReferenceOperation: input2 (OperationKind.ParameterReference, Type: System.Boolean) (Syntax: 'input2') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.Boolean, Constant: True) (Syntax: 'true') + + Next (Regular) Block[B6] + Finalizing: {R4} + Leaving: {R3} {R2} {R1} + } + .finally {R4} + { + Block[B3] - Block + Predecessors (0) + Statements (0) + Jump if False (Regular) to Block[B5] + ILocalReferenceOperation: (OperationKind.LocalReference, Type: System.Boolean, Constant: null, IsInvalid, IsImplicit) (Syntax: 'input1') + + Next (Regular) Block[B4] + Block[B4] - Block + Predecessors: [B3] + Statements (1) + IInvocationOperation (void System.Threading.Monitor.Exit(System.Object obj)) (OperationKind.Invocation, Type: System.Void, IsInvalid, IsImplicit) (Syntax: 'input1') + Instance Receiver: + null + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: obj) (OperationKind.Argument, Type: null, IsInvalid, IsImplicit) (Syntax: 'input1') + IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Object, IsInvalid, IsImplicit) (Syntax: 'input1') + 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) + + Next (Regular) Block[B5] + Block[B5] - Block + Predecessors: [B3] [B4] + Statements (0) + Next (StructuredExceptionHandling) Block[null] + } } Block[B6] - Exit @@ -732,64 +740,68 @@ void M(bool input2) ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'null') Next (Regular) Block[B2] - Entering: {R1} {R2} - -.try {R1, R2} -{ - Block[B2] - Block - Predecessors: [B1] - Statements (2) - IInvocationOperation (void System.Threading.Monitor.Enter(System.Object obj, ref System.Boolean lockTaken)) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 'null') - Instance Receiver: - null - Arguments(2): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: obj) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'null') - IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Object, Constant: null, IsImplicit) (Syntax: 'null') - 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) - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: lockTaken) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'null') - IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Boolean, IsImplicit) (Syntax: 'null') - 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) - - IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'input2 = true;') - Expression: - ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Boolean) (Syntax: 'input2 = true') - Left: - IParameterReferenceOperation: input2 (OperationKind.ParameterReference, Type: System.Boolean) (Syntax: 'input2') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.Boolean, Constant: True) (Syntax: 'true') + Entering: {R1} {R2} {R3} - Next (Regular) Block[B6] - Finalizing: {R3} - Leaving: {R2} {R1} -} -.finally {R3} +.locals {R1} { - Block[B3] - Block - Predecessors (0) - Statements (0) - Jump if False (Regular) to Block[B5] - IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Boolean, IsImplicit) (Syntax: 'null') - - Next (Regular) Block[B4] - Block[B4] - Block - Predecessors: [B3] - Statements (1) - IInvocationOperation (void System.Threading.Monitor.Exit(System.Object obj)) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 'null') - Instance Receiver: - null - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: obj) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'null') - IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Object, Constant: null, IsImplicit) (Syntax: 'null') - 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) - - Next (Regular) Block[B5] - Block[B5] - Block - Predecessors: [B3] [B4] - Statements (0) - Next (StructuredExceptionHandling) Block[null] + Locals: [System.Boolean ?] + .try {R2, R3} + { + Block[B2] - Block + Predecessors: [B1] + Statements (2) + IInvocationOperation (void System.Threading.Monitor.Enter(System.Object obj, ref System.Boolean lockTaken)) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 'null') + Instance Receiver: + null + Arguments(2): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: obj) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'null') + IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Object, Constant: null, IsImplicit) (Syntax: 'null') + 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) + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: lockTaken) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'null') + ILocalReferenceOperation: (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Boolean, Constant: null, IsImplicit) (Syntax: 'null') + 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) + + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'input2 = true;') + Expression: + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Boolean) (Syntax: 'input2 = true') + Left: + IParameterReferenceOperation: input2 (OperationKind.ParameterReference, Type: System.Boolean) (Syntax: 'input2') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.Boolean, Constant: True) (Syntax: 'true') + + Next (Regular) Block[B6] + Finalizing: {R4} + Leaving: {R3} {R2} {R1} + } + .finally {R4} + { + Block[B3] - Block + Predecessors (0) + Statements (0) + Jump if False (Regular) to Block[B5] + ILocalReferenceOperation: (OperationKind.LocalReference, Type: System.Boolean, Constant: null, IsImplicit) (Syntax: 'null') + + Next (Regular) Block[B4] + Block[B4] - Block + Predecessors: [B3] + Statements (1) + IInvocationOperation (void System.Threading.Monitor.Exit(System.Object obj)) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 'null') + Instance Receiver: + null + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: obj) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'null') + IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Object, Constant: null, IsImplicit) (Syntax: 'null') + 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) + + Next (Regular) Block[B5] + Block[B5] - Block + Predecessors: [B3] [B4] + Statements (0) + Next (StructuredExceptionHandling) Block[null] + } } Block[B6] - Exit @@ -917,59 +929,63 @@ void M(P input, bool b) IParameterReferenceOperation: input (OperationKind.ParameterReference, Type: P) (Syntax: 'input') Next (Regular) Block[B2] - Entering: {R1} {R2} + Entering: {R1} {R2} {R3} -.try {R1, R2} +.locals {R1} { - Block[B2] - Block - Predecessors: [B1] - Statements (2) - IInvocationOperation (void System.Threading.Monitor.Enter(System.Object obj, ref System.Boolean lockTaken)) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 'input') - Instance Receiver: - null - Arguments(2): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: obj) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'input') - IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Object, IsImplicit) (Syntax: 'input') - 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) - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: lockTaken) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'input') - IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Boolean, IsImplicit) (Syntax: 'input') - 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) - - IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'b = true;') - Expression: - ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Boolean) (Syntax: 'b = true') - Left: - IParameterReferenceOperation: b (OperationKind.ParameterReference, Type: System.Boolean) (Syntax: 'b') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.Boolean, Constant: True) (Syntax: 'true') - - Next (Regular) Block[B6] - Finalizing: {R3} - Leaving: {R2} {R1} -} -.finally {R3} -{ - Block[B3] - Block - Predecessors (0) - Statements (0) - Jump if False (Regular) to Block[B5] - IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Boolean, IsImplicit) (Syntax: 'input') - - Next (Regular) Block[B4] - Block[B4] - Block - Predecessors: [B3] - Statements (1) - IInvalidOperation (OperationKind.Invalid, Type: null, IsImplicit) (Syntax: 'input') - Children(1): - IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Object, IsImplicit) (Syntax: 'input') - - Next (Regular) Block[B5] - Block[B5] - Block - Predecessors: [B3] [B4] - Statements (0) - Next (StructuredExceptionHandling) Block[null] + Locals: [System.Boolean ?] + .try {R2, R3} + { + Block[B2] - Block + Predecessors: [B1] + Statements (2) + IInvocationOperation (void System.Threading.Monitor.Enter(System.Object obj, ref System.Boolean lockTaken)) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 'input') + Instance Receiver: + null + Arguments(2): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: obj) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'input') + IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Object, IsImplicit) (Syntax: 'input') + 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) + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: lockTaken) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'input') + ILocalReferenceOperation: (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Boolean, Constant: null, IsImplicit) (Syntax: 'input') + 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) + + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'b = true;') + Expression: + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Boolean) (Syntax: 'b = true') + Left: + IParameterReferenceOperation: b (OperationKind.ParameterReference, Type: System.Boolean) (Syntax: 'b') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.Boolean, Constant: True) (Syntax: 'true') + + Next (Regular) Block[B6] + Finalizing: {R4} + Leaving: {R3} {R2} {R1} + } + .finally {R4} + { + Block[B3] - Block + Predecessors (0) + Statements (0) + Jump if False (Regular) to Block[B5] + ILocalReferenceOperation: (OperationKind.LocalReference, Type: System.Boolean, Constant: null, IsImplicit) (Syntax: 'input') + + Next (Regular) Block[B4] + Block[B4] - Block + Predecessors: [B3] + Statements (1) + IInvalidOperation (OperationKind.Invalid, Type: null, IsImplicit) (Syntax: 'input') + Children(1): + IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Object, IsImplicit) (Syntax: 'input') + + Next (Regular) Block[B5] + Block[B5] - Block + Predecessors: [B3] [B4] + Statements (0) + Next (StructuredExceptionHandling) Block[null] + } } Block[B6] - Exit diff --git a/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs b/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs index a44ac7f6b46529e0577ccca89e03bb1d7558af13..0f1167e15a37bcadd13871172b274bfe29858848 100644 --- a/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs +++ b/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs @@ -3512,9 +3512,10 @@ public override void Accept(OperationVisitor visitor) /// internal abstract partial class BaseLockStatement : Operation, ILockOperation { - protected BaseLockStatement(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + protected BaseLockStatement(ILocalSymbol lockTakenSymbol, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : base(OperationKind.Lock, semanticModel, syntax, type, constantValue, isImplicit) { + LockTakenSymbol = lockTakenSymbol; } public override IEnumerable Children @@ -3539,6 +3540,7 @@ public override IEnumerable Children /// Body of the lock, to be executed while holding the lock. /// public abstract IOperation Body { get; } + public ILocalSymbol LockTakenSymbol { get; } public override void Accept(OperationVisitor visitor) { visitor.VisitLock(this); @@ -3554,8 +3556,8 @@ public override void Accept(OperationVisitor visitor) /// internal sealed partial class LockStatement : BaseLockStatement, ILockOperation { - public LockStatement(IOperation lockedValue, IOperation body, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) + public LockStatement(IOperation lockedValue, IOperation body, ILocalSymbol lockTakenSymbol, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(lockTakenSymbol, semanticModel, syntax, type, constantValue, isImplicit) { LockedValue = SetParentOperation(lockedValue, this); Body = SetParentOperation(body, this); @@ -3573,8 +3575,8 @@ internal sealed partial class LazyLockStatement : BaseLockStatement, ILockOperat private readonly Lazy _lazyLockedValue; private readonly Lazy _lazyBody; - public LazyLockStatement(Lazy lockedValue, Lazy body, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) + public LazyLockStatement(Lazy lockedValue, Lazy body, ILocalSymbol lockTakenSymbol, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(lockTakenSymbol, semanticModel, syntax, type, constantValue, isImplicit) { _lazyLockedValue = lockedValue ?? throw new System.ArgumentNullException(nameof(lockedValue)); _lazyBody = body ?? throw new System.ArgumentNullException(nameof(body)); diff --git a/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs b/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs index 9f25715ddee33552d50ef7198d147e8e7e31bff3..836494710d98b09df04fde19fdcdd28712f53be1 100644 --- a/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs +++ b/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs @@ -3212,37 +3212,38 @@ public override IOperation VisitLock(ILockOperation operation, int? captureIdFor // If Monitor.Enter(object, ref bool) is available: // - // L $lock = `LockedValue`; - // bool $lockTaken = false; + // L $lock = `LockedValue`; + // bool $lockTaken = false; // try // { // Monitor.Enter($lock, ref $lockTaken); - // `body` + // `body` // } // finally - // { - // if ($lockTaken) Monitor.Exit($lock); + // { + // if ($lockTaken) Monitor.Exit($lock); // } // If Monitor.Enter(object, ref bool) is not available: // // L $lock = `LockedValue`; // Monitor.Enter($lock); // NB: before try-finally so we don't Exit if an exception prevents us from acquiring the lock. - // try + // try // { // `body` - // } - // finally + // } + // finally // { - // Monitor.Exit($lock); + // Monitor.Exit($lock); // } // If original type of the LockedValue object is System.Object, VB calls runtime helper (if one is available) - // Microsoft.VisualBasic.CompilerServices.ObjectFlowControl.CheckForSyncLockOnValueType to ensure no value type is - // used. + // Microsoft.VisualBasic.CompilerServices.ObjectFlowControl.CheckForSyncLockOnValueType to ensure no value type is + // used. // For simplicity, we will not synthesize this call because its presence is unlikely to affect graph analysis. IOperation lockedValue = Visit(operation.LockedValue); + var baseLockStatement = (BaseLockStatement)operation; if (!objectType.Equals(lockedValue.Type)) { @@ -3258,6 +3259,7 @@ public override IOperation VisitLock(ILockOperation operation, int? captureIdFor if (legacyMode) { + Debug.Assert(baseLockStatement.LockTakenSymbol == null); enterMethod = (IMethodSymbol)_compilation.CommonGetWellKnownTypeMember(WellKnownMember.System_Threading_Monitor__Enter); // Monitor.Enter($lock); @@ -3281,6 +3283,10 @@ public override IOperation VisitLock(ILockOperation operation, int? captureIdFor enterMethod.ReturnType, constantValue: default, isImplicit: true)); } } + else + { + EnterRegion(new RegionBuilder(ControlFlowRegionKind.LocalLifetime, locals: ImmutableArray.Create(baseLockStatement.LockTakenSymbol))); + } var afterTryFinally = new BasicBlockBuilder(BasicBlockKind.Block); @@ -3291,7 +3297,8 @@ public override IOperation VisitLock(ILockOperation operation, int? captureIdFor if (!legacyMode) { // Monitor.Enter($lock, ref $lockTaken); - lockTaken = new FlowCaptureReference(_captureIdDispenser.GetNextId(), lockedValue.Syntax, _compilation.GetSpecialType(SpecialType.System_Boolean), constantValue: default); + lockTaken = new LocalReferenceExpression(baseLockStatement.LockTakenSymbol, isDeclaration: true, semanticModel: null, lockedValue.Syntax, + baseLockStatement.LockTakenSymbol.Type, constantValue: null, isImplicit: true); AddStatement(new InvocationExpression(enterMethod, instance: null, isVirtual: false, ImmutableArray.Create( new ArgumentOperation(lockedValue, @@ -3330,7 +3337,8 @@ public override IOperation VisitLock(ILockOperation operation, int? captureIdFor if (!legacyMode) { // if ($lockTaken) - IOperation condition = OperationCloner.CloneOperation(lockTaken); + IOperation condition = new LocalReferenceExpression(baseLockStatement.LockTakenSymbol, isDeclaration: false, semanticModel: null, lockedValue.Syntax, + baseLockStatement.LockTakenSymbol.Type, constantValue: null, isImplicit: true); condition = Operation.SetParentOperation(condition, null); LinkBlocks(CurrentBasicBlock, condition, jumpIfTrue: false, RegularBranch(endOfFinally)); _currentBasicBlock = null; @@ -3365,6 +3373,11 @@ public override IOperation VisitLock(ILockOperation operation, int? captureIdFor LeaveRegion(); Debug.Assert(_currentRegion.Kind == ControlFlowRegionKind.TryAndFinally); LeaveRegion(); + if (!legacyMode) + { + Debug.Assert(_currentRegion.Kind == ControlFlowRegionKind.LocalLifetime); + LeaveRegion(); + } AppendNewBlock(afterTryFinally, linkToPrevious: false); diff --git a/src/Compilers/Core/Portable/Operations/OperationCloner.cs b/src/Compilers/Core/Portable/Operations/OperationCloner.cs index 67315079deaa014cbf19cbb7f51305d672d41a1b..b895af18c61a5d96cb86b2d593def2b8d46de8d2 100644 --- a/src/Compilers/Core/Portable/Operations/OperationCloner.cs +++ b/src/Compilers/Core/Portable/Operations/OperationCloner.cs @@ -153,7 +153,8 @@ public override IOperation VisitReturn(IReturnOperation operation, object argume public override IOperation VisitLock(ILockOperation operation, object argument) { - return new LockStatement(Visit(operation.LockedValue), Visit(operation.Body), ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); + var baseLockStatement = (BaseLockStatement)operation; + return new LockStatement(Visit(operation.LockedValue), Visit(operation.Body), baseLockStatement.LockTakenSymbol, baseLockStatement.SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); } public override IOperation VisitTry(ITryOperation operation, object argument) diff --git a/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb b/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb index 7e9bbf3fd93f6b2a5c31476a2c8f5db9829359d4..0edf7160b7c15a9f9e956fea0e23a7e68ce016db 100644 --- a/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb +++ b/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb @@ -1422,11 +1422,18 @@ Namespace Microsoft.CodeAnalysis.Operations Private Function CreateBoundSyncLockStatementOperation(boundSyncLockStatement As BoundSyncLockStatement) As ILockOperation Dim expression As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundSyncLockStatement.LockExpression)) Dim body As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundSyncLockStatement.Body)) + Dim legacyMode = _semanticModel.Compilation.CommonGetWellKnownTypeMember(WellKnownMember.System_Threading_Monitor__Enter2) Is Nothing + Dim lockTakenSymbol As ILocalSymbol = + If(legacyMode, Nothing, + New SynthesizedLocal(DirectCast(_semanticModel.GetEnclosingSymbol(boundSyncLockStatement.Syntax.SpanStart), Symbol), + DirectCast(_semanticModel.Compilation.GetSpecialType(SpecialType.System_Boolean), TypeSymbol), + SynthesizedLocalKind.LockTaken, + syntaxOpt:=boundSyncLockStatement.LockExpression.Syntax)) Dim syntax As SyntaxNode = boundSyncLockStatement.Syntax Dim type As ITypeSymbol = Nothing Dim constantValue As [Optional](Of Object) = New [Optional](Of Object)() Dim isImplicit As Boolean = boundSyncLockStatement.WasCompilerGenerated - Return New LazyLockStatement(expression, body, _semanticModel, syntax, type, constantValue, isImplicit) + Return New LazyLockStatement(expression, body, lockTakenSymbol, _semanticModel, syntax, type, constantValue, isImplicit) End Function Private Function CreateBoundNoOpStatementOperation(boundNoOpStatement As BoundNoOpStatement) As IEmptyOperation diff --git a/src/Compilers/VisualBasic/Test/IOperation/IOperation/IOperationTests_ILockStatement.vb b/src/Compilers/VisualBasic/Test/IOperation/IOperation/IOperationTests_ILockStatement.vb index f28952da067a24cf7e6ad8a168444c69d5cc1a2e..86c834202f8eaeeeef8d44eed5037b5154ba80f8 100644 --- a/src/Compilers/VisualBasic/Test/IOperation/IOperation/IOperationTests_ILockStatement.vb +++ b/src/Compilers/VisualBasic/Test/IOperation/IOperation/IOperationTests_ILockStatement.vb @@ -392,64 +392,68 @@ Block[B1] - Block ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'Nothing') Next (Regular) Block[B2] - Entering: {R1} {R2} + Entering: {R1} {R2} {R3} -.try {R1, R2} +.locals {R1} { - Block[B2] - Block - Predecessors: [B1] - Statements (2) - IInvocationOperation (Sub System.Threading.Monitor.Enter(obj As System.Object, ByRef lockTaken As System.Boolean)) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 'Nothing') - Instance Receiver: - null - Arguments(2): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: obj) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'Nothing') - IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Object, Constant: null, IsImplicit) (Syntax: 'Nothing') - 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) - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: lockTaken) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'Nothing') - IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Boolean, IsImplicit) (Syntax: 'Nothing') - 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) - - IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'input = true') - Expression: - ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Boolean, IsImplicit) (Syntax: 'input = true') - Left: - IParameterReferenceOperation: input (OperationKind.ParameterReference, Type: System.Boolean) (Syntax: 'input') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.Boolean, Constant: True) (Syntax: 'true') - - Next (Regular) Block[B6] - Finalizing: {R3} - Leaving: {R2} {R1} -} -.finally {R3} -{ - Block[B3] - Block - Predecessors (0) - Statements (0) - Jump if False (Regular) to Block[B5] - IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Boolean, IsImplicit) (Syntax: 'Nothing') - - Next (Regular) Block[B4] - Block[B4] - Block - Predecessors: [B3] - Statements (1) - IInvocationOperation (Sub System.Threading.Monitor.Exit(obj As System.Object)) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 'Nothing') - Instance Receiver: - null - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: obj) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'Nothing') - IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Object, Constant: null, IsImplicit) (Syntax: 'Nothing') - 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) - - Next (Regular) Block[B5] - Block[B5] - Block - Predecessors: [B3] [B4] - Statements (0) - Next (StructuredExceptionHandling) Block[null] + Locals: [ As System.Boolean] + .try {R2, R3} + { + Block[B2] - Block + Predecessors: [B1] + Statements (2) + IInvocationOperation (Sub System.Threading.Monitor.Enter(obj As System.Object, ByRef lockTaken As System.Boolean)) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 'Nothing') + Instance Receiver: + null + Arguments(2): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: obj) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'Nothing') + IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Object, Constant: null, IsImplicit) (Syntax: 'Nothing') + 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) + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: lockTaken) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'Nothing') + ILocalReferenceOperation: (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Boolean, Constant: null, IsImplicit) (Syntax: 'Nothing') + 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) + + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'input = true') + Expression: + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Boolean, IsImplicit) (Syntax: 'input = true') + Left: + IParameterReferenceOperation: input (OperationKind.ParameterReference, Type: System.Boolean) (Syntax: 'input') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.Boolean, Constant: True) (Syntax: 'true') + + Next (Regular) Block[B6] + Finalizing: {R4} + Leaving: {R3} {R2} {R1} + } + .finally {R4} + { + Block[B3] - Block + Predecessors (0) + Statements (0) + Jump if False (Regular) to Block[B5] + ILocalReferenceOperation: (OperationKind.LocalReference, Type: System.Boolean, Constant: null, IsImplicit) (Syntax: 'Nothing') + + Next (Regular) Block[B4] + Block[B4] - Block + Predecessors: [B3] + Statements (1) + IInvocationOperation (Sub System.Threading.Monitor.Exit(obj As System.Object)) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 'Nothing') + Instance Receiver: + null + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: obj) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'Nothing') + IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Object, Constant: null, IsImplicit) (Syntax: 'Nothing') + 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) + + Next (Regular) Block[B5] + Block[B5] - Block + Predecessors: [B3] [B4] + Statements (0) + Next (StructuredExceptionHandling) Block[null] + } } Block[B6] - Exit