diff --git a/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs b/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs index 3e8151e3388c2..f177c27818018 100644 --- a/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs +++ b/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs @@ -1753,6 +1753,76 @@ internal PointerTypeSymbol CreatePointerTypeSymbol(TypeSymbol elementType) #endregion + #region Operations + + /// + /// Gets the low-level operation corresponding to the method's body. + /// + /// The method symbol. + /// An optional cancellation token. + /// The low-level operation corresponding to the method's body. + protected override IOperation GetLowLevelOperationCore(IMethodSymbol method, CancellationToken cancellationToken = default) + { + IOperation result = null; + var csmethod = method.EnsureCSharpSymbolOrNull(nameof(method)); + + if ((object)csmethod != null && csmethod.IsFromCompilation(this)) + { + var body = LowerMethodBody(csmethod); + + if (body != null) + { + var operationFactory = new Semantics.CSharpOperationFactory(null); + result = operationFactory.Create(body); + } + } + + return result; + } + + private BoundStatement LowerMethodBody(MethodSymbol method) + { + BoundStatement result = null; + + // We don't want to support synthesized bodies + // (like auto-property accessors, etc.) + if (method is SourceMemberMethodSymbol sourceMethod && sourceMethod.BodySyntax != null) + { + var compilationState = new TypeCompilationState(method.ContainingType, this, null); + var diagnostics = DiagnosticBag.GetInstance(); + var body = MethodCompiler.BindMethodBody(method, compilationState, diagnostics); + + if (body != null && !body.HasErrors && !diagnostics.HasAnyErrors()) + { + const int methodOrdinal = -1; + var dynamicAnalysisSpans = ImmutableArray.Empty; + + result = LocalRewriter.Rewrite( + this, + method, + methodOrdinal, + method.ContainingType, + body, + compilationState, + previousSubmissionFields: null, + allowOmissionOfConditionalCalls: true, + instrumentForDynamicAnalysis: false, + debugDocumentProvider: null, + dynamicAnalysisSpans: ref dynamicAnalysisSpans, + diagnostics: diagnostics, + sawLambdas: out bool sawLambdas, + sawLocalFunctions: out bool sawLocalFunctions, + sawAwaitInExceptionHandler: out bool sawAwaitInExceptionHandler); + } + + diagnostics.Free(); + } + + return result; + } + + #endregion + #region Binding /// diff --git a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs index 12f2029312428..c9333c3426c0c 100644 --- a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs +++ b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs @@ -254,6 +254,21 @@ private IOperation CreateInternal(BoundNode boundNode) return CreateBoundPatternSwitchLabelOperation((BoundPatternSwitchLabel)boundNode); case BoundKind.IsPatternExpression: return CreateBoundIsPatternExpressionOperation((BoundIsPatternExpression)boundNode); + + // To support BoundNodes after lowering phase. + case BoundKind.SequencePoint: + return CreateBoundSequencePointOperation((BoundSequencePoint)boundNode); + case BoundKind.SequencePointWithSpan: + return CreateBoundSequencePointWithSpanOperation((BoundSequencePointWithSpan)boundNode); + case BoundKind.SequencePointExpression: + return CreateBoundSequencePointExpressionOperation((BoundSequencePointExpression)boundNode); + case BoundKind.StatementList: + return CreateBoundStatementListOperation((BoundStatementList)boundNode); + case BoundKind.ConditionalGoto: + return CreateBoundConditionalGotoOperation((BoundConditionalGoto)boundNode); + case BoundKind.Sequence: + return CreateBoundSequenceOperation((BoundSequence)boundNode); + default: var constantValue = ConvertToOptional((boundNode as BoundExpression)?.ConstantValue); bool isImplicit = boundNode.WasCompilerGenerated; @@ -426,7 +441,7 @@ private IEventAssignmentExpression CreateBoundEventAssignmentOperatorOperation(B return new LazyEventAssignmentExpression(eventReference, handlerValue, adds, _semanticModel, syntax, type, constantValue, isImplicit); } - private IParameterReferenceExpression CreateBoundParameterOperation(BoundParameter boundParameter) + private IParameterReferenceExpression CreateBoundParameterOperation(BoundParameter boundParameter) { IParameterSymbol parameter = boundParameter.ParameterSymbol; SyntaxNode syntax = boundParameter.Syntax; @@ -1064,7 +1079,7 @@ private IParameterInitializer CreateBoundParameterEqualsValueOperation(BoundPara private IBlockStatement CreateBoundBlockOperation(BoundBlock boundBlock) { Lazy> statements = - new Lazy>(() => boundBlock.Statements.Select(s => Create(s)).Where(s => s.Kind != OperationKind.None).ToImmutableArray()); + new Lazy>(() => boundBlock.Statements.Select(s => Create(s)).Where(s => s != null && s.Kind != OperationKind.None).ToImmutableArray()); ImmutableArray locals = boundBlock.Locals.As(); SyntaxNode syntax = boundBlock.Syntax; @@ -1506,5 +1521,59 @@ private IIsPatternExpression CreateBoundIsPatternExpressionOperation(BoundIsPatt bool isImplicit = boundIsPatternExpression.WasCompilerGenerated; return new LazyIsPatternExpression(expression, pattern, _semanticModel, syntax, type, constantValue, isImplicit); } + + private IOperation CreateBoundSequencePointOperation(BoundSequencePoint boundSequencePoint) + { + return Create(boundSequencePoint.StatementOpt); + } + + private IOperation CreateBoundSequencePointWithSpanOperation(BoundSequencePointWithSpan boundSequencePointWithSpan) + { + return Create(boundSequencePointWithSpan.StatementOpt); + } + + private IOperation CreateBoundSequencePointExpressionOperation(BoundSequencePointExpression boundSequencePointExpression) + { + return Create(boundSequencePointExpression.Expression); + } + + private IBlockStatement CreateBoundStatementListOperation(BoundStatementList boundStatementList) + { + Lazy> statements = + new Lazy>(() => boundStatementList.Statements.Select(s => Create(s)).Where(s => s != null).ToImmutableArray()); + + ImmutableArray locals = ImmutableArray.Empty; + SyntaxNode syntax = boundStatementList.Syntax; + ITypeSymbol type = null; + Optional constantValue = default(Optional); + bool isImplicit = boundStatementList.WasCompilerGenerated; + return new LazyBlockStatement(statements, locals, _semanticModel, syntax, type, constantValue, isImplicit); + } + + private IConditionalGotoStatement CreateBoundConditionalGotoOperation(BoundConditionalGoto boundConditionalGoto) + { + Lazy condition = new Lazy(() => Create(boundConditionalGoto.Condition)); + ILabelSymbol target = boundConditionalGoto.Label; + bool jumpIfTrue = boundConditionalGoto.JumpIfTrue; + SyntaxNode syntax = boundConditionalGoto.Syntax; + ITypeSymbol type = null; + Optional constantValue = default(Optional); + bool isImplicit = boundConditionalGoto.WasCompilerGenerated; + return new LazyConditionalGotoStatement(condition, target, jumpIfTrue, _semanticModel, syntax, type, constantValue, isImplicit); + } + + private ISequenceExpression CreateBoundSequenceOperation(BoundSequence boundSequence) + { + Lazy> expressions = + new Lazy>(() => boundSequence.SideEffects.Select(s => Create(s)).Where(s => s != null).ToImmutableArray()); + + Lazy value = new Lazy(() => Create(boundSequence.Value)); + ImmutableArray locals = boundSequence.Locals.As(); + SyntaxNode syntax = boundSequence.Syntax; + ITypeSymbol type = null; + Optional constantValue = default(Optional); + bool isImplicit = boundSequence.WasCompilerGenerated; + return new LazySequenceExpression(expressions, value, locals, _semanticModel, syntax, type, constantValue, isImplicit); + } } } diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_GetLowLevelOperation.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_GetLowLevelOperation.cs new file mode 100644 index 0000000000000..c2dd0113f6cac --- /dev/null +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_GetLowLevelOperation.cs @@ -0,0 +1,168 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Diagnostics; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Semantics; +using Microsoft.CodeAnalysis.Test.Utilities; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests +{ + public partial class IOperationTests : SemanticModelTestBase + { + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void GetLowLevelOperation_FromMethod() + { + string source = @" +class C +{ + /**/ + static int Method(int p) + { + return p; + } + /**/ +} +"; + string expectedOperationTree = @" +IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') + IReturnStatement (OperationKind.ReturnStatement) (Syntax: 'return p;') + ReturnedValue: IParameterReferenceExpression: p (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'p') +"; + var expectedDiagnostics = DiagnosticDescription.None; + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, useLoweredTree: true); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void GetLowLevelOperation_FromConstructor() + { + string source = @" +class C +{ + private int _field = 0; + + /**/ + public C(int p) + { + _field = p; + } + /**/ +} +"; + string expectedOperationTree = @" +IBlockStatement (2 statements) (OperationKind.BlockStatement) (Syntax: 'public C(in ... }') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'public C(in ... }') + Expression: IInvocationExpression ( System.Object..ctor()) (OperationKind.InvocationExpression, Type: System.Object) (Syntax: 'public C(in ... }') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: C) (Syntax: 'public C(in ... }') + Arguments(0) + IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: '_field = p;') + Expression: ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: '_field = p') + Left: IFieldReferenceExpression: System.Int32 C._field (OperationKind.FieldReferenceExpression, Type: System.Int32) (Syntax: '_field') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: C) (Syntax: '_field') + Right: IParameterReferenceExpression: p (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'p') +"; + var expectedDiagnostics = DiagnosticDescription.None; + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, useLoweredTree: true); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void GetLowLevelOperation_FromFinalizer() + { + string source = @" +class C +{ + private int _field = 0; + + /**/ + ~C() + { + _field += 0; + } + /**/ +} +"; + string expectedOperationTree = @" +IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') + ITryStatement (OperationKind.TryStatement) (Syntax: '{ ... }') + Body: IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: '_field += 0;') + Expression: ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: '_field += 0') + Left: IFieldReferenceExpression: System.Int32 C._field (OperationKind.FieldReferenceExpression, Type: System.Int32) (Syntax: '_field') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: C) (Syntax: '_field') + Right: IFieldReferenceExpression: System.Int32 C._field (OperationKind.FieldReferenceExpression, Type: System.Int32) (Syntax: '_field') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: C) (Syntax: '_field') + Catch clauses(0) + Finally: IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: '{ ... }') + Expression: IInvocationExpression ( void System.Object.Finalize()) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: '{ ... }') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.BaseClass) (OperationKind.InstanceReferenceExpression, Type: C) (Syntax: '{ ... }') + Arguments(0) +"; + var expectedDiagnostics = DiagnosticDescription.None; + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, useLoweredTree: true); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void GetLowLevelOperation_FromPropertyAccessorGet() + { + string source = @" +class C +{ + private int _property = 0; + + int Property + { + /**/ + get { return _property; } + /**/ + } +} +"; + string expectedOperationTree = @" +IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ return _property; }') + IReturnStatement (OperationKind.ReturnStatement) (Syntax: 'return _property;') + ReturnedValue: IFieldReferenceExpression: System.Int32 C._property (OperationKind.FieldReferenceExpression, Type: System.Int32) (Syntax: '_property') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: C) (Syntax: '_property') +"; + var expectedDiagnostics = DiagnosticDescription.None; + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, useLoweredTree: true); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void GetLowLevelOperation_FromPropertyAccessorSet() + { + string source = @" +class C +{ + private int _property = 0; + + int Property + { + get { return _property; } + /**/ + set { _property = value; } + /**/ + } +} +"; + string expectedOperationTree = @" +IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ _property = value; }') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: '_property = value;') + Expression: ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: '_property = value') + Left: IFieldReferenceExpression: System.Int32 C._property (OperationKind.FieldReferenceExpression, Type: System.Int32) (Syntax: '_property') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: C) (Syntax: '_property') + Right: IParameterReferenceExpression: value (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'value') + +"; + var expectedDiagnostics = DiagnosticDescription.None; + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, useLoweredTree: true); + } + } +} diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IConditionalGotoStatement.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IConditionalGotoStatement.cs new file mode 100644 index 0000000000000..38e312eeb8258 --- /dev/null +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IConditionalGotoStatement.cs @@ -0,0 +1,221 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Diagnostics; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Semantics; +using Microsoft.CodeAnalysis.Test.Utilities; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests +{ + public partial class IOperationTests : SemanticModelTestBase + { + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void IConditionalGotoStatement_FromIf() + { + string source = @" +class C +{ + /**/ + static void Method(int p) + { + if (p < 0) p = 0; + } + /**/ +} +"; + string expectedOperationTree = @" +IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') + IBlockStatement (3 statements) (OperationKind.BlockStatement) (Syntax: 'if (p < 0) p = 0;') + IConditionalGotoStatement (JumpIfTrue: False, Target: label_0) (OperationKind.ConditionalGotoStatement) (Syntax: 'p < 0') + Condition: IBinaryOperatorExpression (BinaryOperatorKind.LessThan) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) (Syntax: 'p < 0') + Left: IParameterReferenceExpression: p (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'p') + Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 0) (Syntax: '0') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'p = 0;') + Expression: ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: 'p = 0') + Left: IParameterReferenceExpression: p (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'p') + Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 0) (Syntax: '0') + ILabeledStatement (Label: label_0) (OperationKind.LabeledStatement) (Syntax: 'if (p < 0) p = 0;') + Statement: null +"; + var expectedDiagnostics = DiagnosticDescription.None; + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, useLoweredTree: true); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void IConditionalGotoStatement_FromIfElse() + { + string source = @" +class C +{ + /**/ + static void Method(int p) + { + if (p < 0) p = 0; + else p = 1; + } + /**/ +} +"; + string expectedOperationTree = @" +IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') + IBlockStatement (6 statements) (OperationKind.BlockStatement) (Syntax: 'if (p < 0) ... else p = 1;') + IConditionalGotoStatement (JumpIfTrue: False, Target: label_0) (OperationKind.ConditionalGotoStatement) (Syntax: 'p < 0') + Condition: IBinaryOperatorExpression (BinaryOperatorKind.LessThan) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) (Syntax: 'p < 0') + Left: IParameterReferenceExpression: p (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'p') + Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 0) (Syntax: '0') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'p = 0;') + Expression: ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: 'p = 0') + Left: IParameterReferenceExpression: p (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'p') + Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 0) (Syntax: '0') + IBranchStatement (BranchKind.GoTo, Label: label_1) (OperationKind.BranchStatement) (Syntax: 'if (p < 0) ... else p = 1;') + ILabeledStatement (Label: label_0) (OperationKind.LabeledStatement) (Syntax: 'if (p < 0) ... else p = 1;') + Statement: null + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'p = 1;') + Expression: ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: 'p = 1') + Left: IParameterReferenceExpression: p (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'p') + Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') + ILabeledStatement (Label: label_1) (OperationKind.LabeledStatement) (Syntax: 'if (p < 0) ... else p = 1;') + Statement: null +"; + var expectedDiagnostics = DiagnosticDescription.None; + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, useLoweredTree: true); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void IConditionalGotoStatement_FromWhile() + { + string source = @" +class C +{ + /**/ + static void Method(int p) + { + while (p > 0) p = 0; + } + /**/ +} +"; + string expectedOperationTree = @" +IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') + IBlockStatement (6 statements) (OperationKind.BlockStatement) (Syntax: 'while (p > 0) p = 0;') + IBranchStatement (BranchKind.GoTo, Label: label_0) (OperationKind.BranchStatement) (Syntax: 'while (p > 0) p = 0;') + ILabeledStatement (Label: label_1) (OperationKind.LabeledStatement) (Syntax: 'while (p > 0) p = 0;') + Statement: null + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'p = 0;') + Expression: ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: 'p = 0') + Left: IParameterReferenceExpression: p (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'p') + Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 0) (Syntax: '0') + ILabeledStatement (Label: label_0) (OperationKind.LabeledStatement) (Syntax: 'while (p > 0) p = 0;') + Statement: null + IConditionalGotoStatement (JumpIfTrue: True, Target: label_1) (OperationKind.ConditionalGotoStatement) (Syntax: 'p > 0') + Condition: IBinaryOperatorExpression (BinaryOperatorKind.GreaterThan) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) (Syntax: 'p > 0') + Left: IParameterReferenceExpression: p (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'p') + Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 0) (Syntax: '0') + ILabeledStatement (Label: label_2) (OperationKind.LabeledStatement) (Syntax: 'while (p > 0) p = 0;') + Statement: null +"; + var expectedDiagnostics = DiagnosticDescription.None; + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, useLoweredTree: true); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void IConditionalGotoStatement_FromDoWhile() + { + string source = @" +class C +{ + /**/ + static void Method(int p) + { + do p = 0; while (p > 0); + } + /**/ +} +"; + string expectedOperationTree = @" +IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') + IBlockStatement (5 statements) (OperationKind.BlockStatement) (Syntax: 'do p = 0; while (p > 0);') + ILabeledStatement (Label: label_0) (OperationKind.LabeledStatement) (Syntax: 'do p = 0; while (p > 0);') + Statement: null + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'p = 0;') + Expression: ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: 'p = 0') + Left: IParameterReferenceExpression: p (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'p') + Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 0) (Syntax: '0') + ILabeledStatement (Label: label_1) (OperationKind.LabeledStatement) (Syntax: 'do p = 0; while (p > 0);') + Statement: null + IConditionalGotoStatement (JumpIfTrue: True, Target: label_0) (OperationKind.ConditionalGotoStatement) (Syntax: 'do p = 0; while (p > 0);') + Condition: IBinaryOperatorExpression (BinaryOperatorKind.GreaterThan) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) (Syntax: 'p > 0') + Left: IParameterReferenceExpression: p (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'p') + Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 0) (Syntax: '0') + ILabeledStatement (Label: label_2) (OperationKind.LabeledStatement) (Syntax: 'do p = 0; while (p > 0);') + Statement: null +"; + var expectedDiagnostics = DiagnosticDescription.None; + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, useLoweredTree: true); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/21866")] + public void IConditionalGotoStatement_FromFor() + { + string source = @" +class C +{ + /**/ + static void Method(int p) + { + for (var i = 0; i < p; ++i) p = 0; + } + /**/ +} +"; + string expectedOperationTree = @" +IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') + IBlockStatement (9 statements, 1 locals) (OperationKind.BlockStatement) (Syntax: 'for (var i ... ++i) p = 0;') + Locals: Local_1: System.Int32 i + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'i = 0') + Expression: ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: 'i = 0') + Left: ILocalReferenceExpression: i (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'i = 0') + Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 0) (Syntax: '0') + IBranchStatement (BranchKind.GoTo, Label: label_0) (OperationKind.BranchStatement) (Syntax: 'for (var i ... ++i) p = 0;') + ILabeledStatement (Label: label_1) (OperationKind.LabeledStatement) (Syntax: 'for (var i ... ++i) p = 0;') + Statement: null + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'p = 0;') + Expression: ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: 'p = 0') + Left: IParameterReferenceExpression: p (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'p') + Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 0) (Syntax: '0') + ILabeledStatement (Label: label_2) (OperationKind.LabeledStatement) (Syntax: 'for (var i ... ++i) p = 0;') + Statement: null + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: '++i') + Expression: ISequenceExpression (OperationKind.SequenceExpression) (Syntax: '++i') + Locals: Local_1: System.Int32 ? + SideEffects(2): + ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: '++i') + Left: ILocalReferenceExpression: (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: '++i') + Right: IBinaryOperatorExpression (BinaryOperatorKind.Add) (OperationKind.BinaryOperatorExpression, Type: System.Int32) (Syntax: '++i') + Left: ILocalReferenceExpression: i (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'i') + Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '++i') + ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: '++i') + Left: ILocalReferenceExpression: i (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'i') + Right: ILocalReferenceExpression: (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: '++i') + Value: ILocalReferenceExpression: (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: '++i') + ILabeledStatement (Label: label_0) (OperationKind.LabeledStatement) (Syntax: 'for (var i ... ++i) p = 0;') + Statement: null + IConditionalGotoStatement (JumpIfTrue: True, Target: label_1) (OperationKind.ConditionalGotoStatement) (Syntax: 'i < p') + Condition: IBinaryOperatorExpression (BinaryOperatorKind.LessThan) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) (Syntax: 'i < p') + Left: ILocalReferenceExpression: i (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'i') + Right: IParameterReferenceExpression: p (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'p') + ILabeledStatement (Label: label_3) (OperationKind.LabeledStatement) (Syntax: 'for (var i ... ++i) p = 0;') + Statement: null +"; + var expectedDiagnostics = DiagnosticDescription.None; + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, useLoweredTree: true); + } + } +} diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IForEachLoopStatement.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IForEachLoopStatement.cs index 7fdc1a27b7d61..35ea556ac6d4d 100644 --- a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IForEachLoopStatement.cs +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IForEachLoopStatement.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Test.Utilities; @@ -179,7 +179,7 @@ static void Main() Left: ILocalReferenceExpression: num (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'num') Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 3) (Syntax: '3') IfTrue: IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IBranchStatement (BranchKind.Break, Label: label_0) (OperationKind.BranchStatement) (Syntax: 'break;') IfFalse: null IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'System.Cons ... eLine(num);') Expression: IInvocationExpression (void System.Console.WriteLine(System.Int32 value)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'System.Cons ... teLine(num)') @@ -226,7 +226,7 @@ static void Main() Left: ILocalReferenceExpression: num (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'num') Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 3) (Syntax: '3') IfTrue: IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') - IBranchStatement (BranchKind.Continue) (OperationKind.BranchStatement) (Syntax: 'continue;') + IBranchStatement (BranchKind.Continue, Label: label_0) (OperationKind.BranchStatement) (Syntax: 'continue;') IfFalse: null IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'System.Cons ... eLine(num);') Expression: IInvocationExpression (void System.Console.WriteLine(System.Int32 value)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'System.Cons ... teLine(num)') diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IForLoopStatement.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IForLoopStatement.cs index aee721e5cecce..abc9ecdffbbda 100644 --- a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IForLoopStatement.cs +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IForLoopStatement.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Test.Utilities; @@ -99,7 +99,7 @@ static void Main() Right: IBinaryOperatorExpression (BinaryOperatorKind.Add) (OperationKind.BinaryOperatorExpression, Type: System.Int32) (Syntax: 'i + 1') Left: ILocalReferenceExpression: i (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'i') Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IBranchStatement (BranchKind.Break, Label: label_0) (OperationKind.BranchStatement) (Syntax: 'break;') "; VerifyOperationTreeForTest(source, expectedOperationTree); } @@ -146,7 +146,7 @@ static void Main() Right: IBinaryOperatorExpression (BinaryOperatorKind.Add) (OperationKind.BinaryOperatorExpression, Type: System.Int32) (Syntax: 'i + 1') Left: ILocalReferenceExpression: i (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'i') Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IBranchStatement (BranchKind.Break, Label: label_0) (OperationKind.BranchStatement) (Syntax: 'break;') "; VerifyOperationTreeForTest(source, expectedOperationTree); } @@ -197,7 +197,7 @@ static void Main() Condition: IBinaryOperatorExpression (BinaryOperatorKind.GreaterThan) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) (Syntax: 'i > 2') Left: ILocalReferenceExpression: i (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'i') Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 2) (Syntax: '2') - IfTrue: IBranchStatement (BranchKind.Continue) (OperationKind.BranchStatement) (Syntax: 'continue;') + IfTrue: IBranchStatement (BranchKind.Continue, Label: label_0) (OperationKind.BranchStatement) (Syntax: 'continue;') IfFalse: null IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'j = j + 1;') Expression: ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: 'j = j + 1') @@ -255,7 +255,7 @@ static void Main() Condition: IBinaryOperatorExpression (BinaryOperatorKind.GreaterThan) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) (Syntax: 'i > 3') Left: ILocalReferenceExpression: i (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'i') Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 3) (Syntax: '3') - IfTrue: IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IfTrue: IBranchStatement (BranchKind.Break, Label: label_0) (OperationKind.BranchStatement) (Syntax: 'break;') IfFalse: null IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'j = j + 1;') Expression: ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: 'j = j + 1') @@ -296,7 +296,7 @@ static void Main() Condition: IBinaryOperatorExpression (BinaryOperatorKind.GreaterThan) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) (Syntax: 'i > 4') Left: ILocalReferenceExpression: i (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'i') Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 4) (Syntax: '4') - IfTrue: IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IfTrue: IBranchStatement (BranchKind.Break, Label: label_0) (OperationKind.BranchStatement) (Syntax: 'break;') IfFalse: null IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'i = i + 2;') Expression: ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: 'i = i + 2') @@ -760,7 +760,7 @@ static void Main(string[] args) Condition: IBinaryOperatorExpression (BinaryOperatorKind.Equals) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) (Syntax: 'j == 5') Left: ILocalReferenceExpression: j (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'j') Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 5) (Syntax: '5') - IfTrue: IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IfTrue: IBranchStatement (BranchKind.Break, Label: label_0) (OperationKind.BranchStatement) (Syntax: 'break;') IfFalse: null "; VerifyOperationTreeForTest(source, expectedOperationTree); @@ -831,7 +831,7 @@ static void Main(string[] args) Left: ILocalReferenceExpression: j (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'j') Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 2) (Syntax: '2') Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 0) (Syntax: '0') - IfTrue: IBranchStatement (BranchKind.Continue) (OperationKind.BranchStatement) (Syntax: 'continue;') + IfTrue: IBranchStatement (BranchKind.Continue, Label: label_0) (OperationKind.BranchStatement) (Syntax: 'continue;') IfFalse: null IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'i = i + 1;') Expression: ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: 'i = i + 1') diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.cs index 7cf39d01cc956..a76a8ff31987f 100644 --- a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.cs +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; @@ -760,13 +760,13 @@ public void M(int x) Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase) (Syntax: 'case var y ... break;') Clauses: - IPatternCaseClause (Label Symbol: case var y when (x >= 10):) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case var y ... (x >= 10):') + IPatternCaseClause (Label: case var y when (x >= 10):) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case var y ... (x >= 10):') Pattern: IDeclarationPattern (Declared Symbol: System.Int32 y) (OperationKind.DeclarationPattern) (Syntax: 'var y') Guard Expression: IBinaryOperatorExpression (BinaryOperatorKind.GreaterThanOrEqual) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) (Syntax: 'x >= 10') Left: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'x') Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 10) (Syntax: '10') Body: - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IBranchStatement (BranchKind.Break, Label: label_1) (OperationKind.BranchStatement) (Syntax: 'break;') "; var expectedDiagnostics = DiagnosticDescription.None; @@ -799,18 +799,18 @@ public void M(int x) Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase) (Syntax: 'case var y ... break;') Clauses: - IPatternCaseClause (Label Symbol: case var y when (x >= 10):) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case var y ... (x >= 10):') + IPatternCaseClause (Label: case var y when (x >= 10):) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case var y ... (x >= 10):') Pattern: IDeclarationPattern (Declared Symbol: System.Int32 y) (OperationKind.DeclarationPattern) (Syntax: 'var y') Guard Expression: IBinaryOperatorExpression (BinaryOperatorKind.GreaterThanOrEqual) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) (Syntax: 'x >= 10') Left: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'x') Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 10) (Syntax: '10') Body: - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IBranchStatement (BranchKind.Break, Label: label_1) (OperationKind.BranchStatement) (Syntax: 'break;') ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase) (Syntax: 'default:/*< ... break;') Clauses: IDefaultCaseClause (CaseKind.Default) (OperationKind.DefaultCaseClause) (Syntax: 'default:') Body: - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IBranchStatement (BranchKind.Break, Label: label_1) (OperationKind.BranchStatement) (Syntax: 'break;') "; var expectedDiagnostics = DiagnosticDescription.None; diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IPatternSwitchCase.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IPatternSwitchCase.cs index 73a4525bea2b1..83c90fe55a822 100644 --- a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IPatternSwitchCase.cs +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IPatternSwitchCase.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Test.Utilities; @@ -34,11 +34,11 @@ void M() Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase) (Syntax: 'case var y: ... break;') Clauses: - IPatternCaseClause (Label Symbol: case var y:) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case var y:') + IPatternCaseClause (Label: case var y:) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case var y:') Pattern: IDeclarationPattern (Declared Symbol: System.Int32? y) (OperationKind.DeclarationPattern) (Syntax: 'var y') Guard Expression: null Body: - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IBranchStatement (BranchKind.Break, Label: label_1) (OperationKind.BranchStatement) (Syntax: 'break;') "; var expectedDiagnostics = DiagnosticDescription.None; @@ -70,11 +70,11 @@ void M() Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase) (Syntax: 'case int y: ... break;') Clauses: - IPatternCaseClause (Label Symbol: case int y:) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case int y:') + IPatternCaseClause (Label: case int y:) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case int y:') Pattern: IDeclarationPattern (Declared Symbol: System.Int32 y) (OperationKind.DeclarationPattern) (Syntax: 'int y') Guard Expression: null Body: - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IBranchStatement (BranchKind.Break, Label: label_1) (OperationKind.BranchStatement) (Syntax: 'break;') "; var expectedDiagnostics = DiagnosticDescription.None; @@ -105,11 +105,11 @@ void M(object x) Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase) (Syntax: 'case X y:/* ... break;') Clauses: - IPatternCaseClause (Label Symbol: case X y:) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case X y:') + IPatternCaseClause (Label: case X y:) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case X y:') Pattern: IDeclarationPattern (Declared Symbol: X y) (OperationKind.DeclarationPattern) (Syntax: 'X y') Guard Expression: null Body: - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IBranchStatement (BranchKind.Break, Label: label_1) (OperationKind.BranchStatement) (Syntax: 'break;') "; var expectedDiagnostics = DiagnosticDescription.None; @@ -140,11 +140,11 @@ void M(object x) where T : class Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase) (Syntax: 'case T y:/* ... break;') Clauses: - IPatternCaseClause (Label Symbol: case T y:) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case T y:') + IPatternCaseClause (Label: case T y:) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case T y:') Pattern: IDeclarationPattern (Declared Symbol: T y) (OperationKind.DeclarationPattern) (Syntax: 'T y') Guard Expression: null Body: - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IBranchStatement (BranchKind.Break, Label: label_1) (OperationKind.BranchStatement) (Syntax: 'break;') "; var expectedDiagnostics = DiagnosticDescription.None; @@ -175,11 +175,11 @@ void M(object x) where T : class Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase, IsInvalid) (Syntax: 'case dynami ... break;') Clauses: - IPatternCaseClause (Label Symbol: case dynamic y:) (CaseKind.Pattern) (OperationKind.PatternCaseClause, IsInvalid) (Syntax: 'case dynamic y:') + IPatternCaseClause (Label: case dynamic y:) (CaseKind.Pattern) (OperationKind.PatternCaseClause, IsInvalid) (Syntax: 'case dynamic y:') Pattern: IDeclarationPattern (Declared Symbol: dynamic y) (OperationKind.DeclarationPattern, IsInvalid) (Syntax: 'dynamic y') Guard Expression: null Body: - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IBranchStatement (BranchKind.Break, Label: label_1) (OperationKind.BranchStatement) (Syntax: 'break;') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS8208: It is not legal to use the type 'dynamic' in a pattern. @@ -216,21 +216,21 @@ void M(object x) Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase) (Syntax: 'case null: ... break;') Clauses: - IPatternCaseClause (Label Symbol: case null:) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case null:') + IPatternCaseClause (Label: case null:) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case null:') Pattern: IConstantPattern (OperationKind.ConstantPattern) (Syntax: 'case null:') Value: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Object, Constant: null) (Syntax: 'null') Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null) Operand: ILiteralExpression (OperationKind.LiteralExpression, Type: null, Constant: null) (Syntax: 'null') Guard Expression: null Body: - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IBranchStatement (BranchKind.Break, Label: label_1) (OperationKind.BranchStatement) (Syntax: 'break;') ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase) (Syntax: 'case X y:/* ... break;') Clauses: - IPatternCaseClause (Label Symbol: case X y:) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case X y:') + IPatternCaseClause (Label: case X y:) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case X y:') Pattern: IDeclarationPattern (Declared Symbol: X y) (OperationKind.DeclarationPattern) (Syntax: 'X y') Guard Expression: null Body: - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IBranchStatement (BranchKind.Break, Label: label_1) (OperationKind.BranchStatement) (Syntax: 'break;') "; var expectedDiagnostics = DiagnosticDescription.None; @@ -262,17 +262,17 @@ void M(object x) Sections: ISwitchCase (2 case clauses, 1 statements) (OperationKind.SwitchCase) (Syntax: 'case null: ... break;') Clauses: - IPatternCaseClause (Label Symbol: case null:) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case null:') + IPatternCaseClause (Label: case null:) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case null:') Pattern: IConstantPattern (OperationKind.ConstantPattern) (Syntax: 'case null:') Value: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Object, Constant: null) (Syntax: 'null') Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null) Operand: ILiteralExpression (OperationKind.LiteralExpression, Type: null, Constant: null) (Syntax: 'null') Guard Expression: null - IPatternCaseClause (Label Symbol: case X y:) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case X y:') + IPatternCaseClause (Label: case X y:) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case X y:') Pattern: IDeclarationPattern (Declared Symbol: X y) (OperationKind.DeclarationPattern) (Syntax: 'X y') Guard Expression: null Body: - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IBranchStatement (BranchKind.Break, Label: label_2) (OperationKind.BranchStatement) (Syntax: 'break;') "; var expectedDiagnostics = DiagnosticDescription.None; @@ -305,18 +305,18 @@ void M(object x) Sections: ISwitchCase (3 case clauses, 1 statements) (OperationKind.SwitchCase) (Syntax: 'case null: ... break;') Clauses: - IPatternCaseClause (Label Symbol: case null:) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case null:') + IPatternCaseClause (Label: case null:) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case null:') Pattern: IConstantPattern (OperationKind.ConstantPattern) (Syntax: 'case null:') Value: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Object, Constant: null) (Syntax: 'null') Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null) Operand: ILiteralExpression (OperationKind.LiteralExpression, Type: null, Constant: null) (Syntax: 'null') Guard Expression: null - IPatternCaseClause (Label Symbol: case X y:) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case X y:') + IPatternCaseClause (Label: case X y:) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case X y:') Pattern: IDeclarationPattern (Declared Symbol: X y) (OperationKind.DeclarationPattern) (Syntax: 'X y') Guard Expression: null IDefaultCaseClause (CaseKind.Default) (OperationKind.DefaultCaseClause) (Syntax: 'default:') Body: - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IBranchStatement (BranchKind.Break, Label: label_2) (OperationKind.BranchStatement) (Syntax: 'break;') "; var expectedDiagnostics = DiagnosticDescription.None; @@ -347,7 +347,7 @@ void M(object x) Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase) (Syntax: 'case X y wh ... break;') Clauses: - IPatternCaseClause (Label Symbol: case X y when x != null:) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case X y when x != null:') + IPatternCaseClause (Label: case X y when x != null:) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case X y when x != null:') Pattern: IDeclarationPattern (Declared Symbol: X y) (OperationKind.DeclarationPattern) (Syntax: 'X y') Guard Expression: IBinaryOperatorExpression (BinaryOperatorKind.NotEquals) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) (Syntax: 'x != null') Left: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Object) (Syntax: 'x') @@ -355,7 +355,7 @@ void M(object x) Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null) Operand: ILiteralExpression (OperationKind.LiteralExpression, Type: null, Constant: null) (Syntax: 'null') Body: - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IBranchStatement (BranchKind.Break, Label: label_1) (OperationKind.BranchStatement) (Syntax: 'break;') "; var expectedDiagnostics = DiagnosticDescription.None; @@ -386,13 +386,13 @@ void M(object x) Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase) (Syntax: 'case X y wh ... break;') Clauses: - IPatternCaseClause (Label Symbol: case X y when x is X z :) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case X y when x is X z :') + IPatternCaseClause (Label: case X y when x is X z :) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case X y when x is X z :') Pattern: IDeclarationPattern (Declared Symbol: X y) (OperationKind.DeclarationPattern) (Syntax: 'X y') Guard Expression: IIsPatternExpression (OperationKind.IsPatternExpression, Type: System.Boolean) (Syntax: 'x is X z') Expression: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Object) (Syntax: 'x') Pattern: IDeclarationPattern (Declared Symbol: X z) (OperationKind.DeclarationPattern) (Syntax: 'X z') Body: - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IBranchStatement (BranchKind.Break, Label: label_1) (OperationKind.BranchStatement) (Syntax: 'break;') "; var expectedDiagnostics = DiagnosticDescription.None; @@ -423,14 +423,14 @@ void M(object x) Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase, IsInvalid) (Syntax: 'case X y wh ... break;') Clauses: - IPatternCaseClause (Label Symbol: case X y when :) (CaseKind.Pattern) (OperationKind.PatternCaseClause, IsInvalid) (Syntax: 'case X y when :') + IPatternCaseClause (Label: case X y when :) (CaseKind.Pattern) (OperationKind.PatternCaseClause, IsInvalid) (Syntax: 'case X y when :') Pattern: IDeclarationPattern (Declared Symbol: X y) (OperationKind.DeclarationPattern) (Syntax: 'X y') Guard Expression: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Boolean, IsInvalid) (Syntax: '') Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) Operand: IInvalidExpression (OperationKind.InvalidExpression, Type: ?, IsInvalid) (Syntax: '') Children(0) Body: - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IBranchStatement (BranchKind.Break, Label: label_1) (OperationKind.BranchStatement) (Syntax: 'break;') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS1525: Invalid expression term ':' @@ -465,13 +465,13 @@ void M(object x) Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase, IsInvalid) (Syntax: 'case X y wh ... break;') Clauses: - IPatternCaseClause (Label Symbol: case X y when x:) (CaseKind.Pattern) (OperationKind.PatternCaseClause, IsInvalid) (Syntax: 'case X y when x:') + IPatternCaseClause (Label: case X y when x:) (CaseKind.Pattern) (OperationKind.PatternCaseClause, IsInvalid) (Syntax: 'case X y when x:') Pattern: IDeclarationPattern (Declared Symbol: X y) (OperationKind.DeclarationPattern) (Syntax: 'X y') Guard Expression: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Boolean, IsInvalid) (Syntax: 'x') Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) Operand: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Object, IsInvalid) (Syntax: 'x') Body: - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IBranchStatement (BranchKind.Break, Label: label_1) (OperationKind.BranchStatement) (Syntax: 'break;') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0266: Cannot implicitly convert type 'object' to 'bool'. An explicit conversion exists (are you missing a cast?) @@ -540,12 +540,12 @@ void M(object x) Sections: ISwitchCase (2 case clauses, 1 statements) (OperationKind.SwitchCase) (Syntax: 'case X y: ... break;') Clauses: - IPatternCaseClause (Label Symbol: case X y:) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case X y:') + IPatternCaseClause (Label: case X y:) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case X y:') Pattern: IDeclarationPattern (Declared Symbol: X y) (OperationKind.DeclarationPattern) (Syntax: 'X y') Guard Expression: null IDefaultCaseClause (CaseKind.Default) (OperationKind.DefaultCaseClause) (Syntax: 'default:') Body: - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IBranchStatement (BranchKind.Break, Label: label_1) (OperationKind.BranchStatement) (Syntax: 'break;') "; var expectedDiagnostics = DiagnosticDescription.None; @@ -578,12 +578,12 @@ void M(object x) Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase, IsInvalid) (Syntax: 'case typeof ... break;') Clauses: - IPatternCaseClause (Label Symbol: case typeof(X):) (CaseKind.Pattern) (OperationKind.PatternCaseClause, IsInvalid) (Syntax: 'case typeof(X):') + IPatternCaseClause (Label: case typeof(X):) (CaseKind.Pattern) (OperationKind.PatternCaseClause, IsInvalid) (Syntax: 'case typeof(X):') Pattern: IConstantPattern (OperationKind.ConstantPattern, IsInvalid) (Syntax: 'case typeof(X):') Value: ITypeOfExpression (Type: X) (OperationKind.TypeOfExpression, Type: System.Type, IsInvalid) (Syntax: 'typeof(X)') Guard Expression: null Body: - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IBranchStatement (BranchKind.Break, Label: label_1) (OperationKind.BranchStatement) (Syntax: 'break;') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0150: A constant value is expected @@ -621,11 +621,11 @@ void M(object x) Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase, IsInvalid) (Syntax: 'case Undefi ... break;') Clauses: - IPatternCaseClause (Label Symbol: case UndefinedType y:) (CaseKind.Pattern) (OperationKind.PatternCaseClause, IsInvalid) (Syntax: 'case UndefinedType y:') + IPatternCaseClause (Label: case UndefinedType y:) (CaseKind.Pattern) (OperationKind.PatternCaseClause, IsInvalid) (Syntax: 'case UndefinedType y:') Pattern: IDeclarationPattern (Declared Symbol: UndefinedType y) (OperationKind.DeclarationPattern, IsInvalid) (Syntax: 'UndefinedType y') Guard Expression: null Body: - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IBranchStatement (BranchKind.Break, Label: label_1) (OperationKind.BranchStatement) (Syntax: 'break;') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0246: The type or namespace name 'UndefinedType' could not be found (are you missing a using directive or an assembly reference?) @@ -660,11 +660,11 @@ void M(int? x) Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase, IsInvalid) (Syntax: 'case X y:/* ... break;') Clauses: - IPatternCaseClause (Label Symbol: case X y:) (CaseKind.Pattern) (OperationKind.PatternCaseClause, IsInvalid) (Syntax: 'case X y:') + IPatternCaseClause (Label: case X y:) (CaseKind.Pattern) (OperationKind.PatternCaseClause, IsInvalid) (Syntax: 'case X y:') Pattern: IDeclarationPattern (Declared Symbol: X y) (OperationKind.DeclarationPattern, IsInvalid) (Syntax: 'X y') Guard Expression: null Body: - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IBranchStatement (BranchKind.Break, Label: label_1) (OperationKind.BranchStatement) (Syntax: 'break;') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS8121: An expression of type 'int?' cannot be handled by a pattern of type 'X'. @@ -700,11 +700,11 @@ void M(int? x) Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase, IsInvalid) (Syntax: 'case int y: ... break;') Clauses: - IPatternCaseClause (Label Symbol: case int y:) (CaseKind.Pattern) (OperationKind.PatternCaseClause, IsInvalid) (Syntax: 'case int y:') + IPatternCaseClause (Label: case int y:) (CaseKind.Pattern) (OperationKind.PatternCaseClause, IsInvalid) (Syntax: 'case int y:') Pattern: IDeclarationPattern (Declared Symbol: System.Int32 y) (OperationKind.DeclarationPattern, IsInvalid) (Syntax: 'int y') Guard Expression: null Body: - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IBranchStatement (BranchKind.Break, Label: label_1) (OperationKind.BranchStatement) (Syntax: 'break;') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0136: A local or parameter named 'y' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter @@ -752,7 +752,7 @@ void M(int? x) IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'const int y') Variables: Local_1: System.Int32 y Initializer: null - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IBranchStatement (BranchKind.Break, Label: label_0) (OperationKind.BranchStatement) (Syntax: 'break;') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS1525: Invalid expression term 'const' @@ -806,25 +806,25 @@ void M(object p) Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase) (Syntax: 'case int x: ... break;') Clauses: - IPatternCaseClause (Label Symbol: case int x:) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case int x:') + IPatternCaseClause (Label: case int x:) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case int x:') Pattern: IDeclarationPattern (Declared Symbol: System.Int32 x) (OperationKind.DeclarationPattern) (Syntax: 'int x') Guard Expression: null Body: - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IBranchStatement (BranchKind.Break, Label: label_1) (OperationKind.BranchStatement) (Syntax: 'break;') ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase, IsInvalid) (Syntax: 'case int y: ... break;') Clauses: - IPatternCaseClause (Label Symbol: case int y:) (CaseKind.Pattern) (OperationKind.PatternCaseClause, IsInvalid) (Syntax: 'case int y:') + IPatternCaseClause (Label: case int y:) (CaseKind.Pattern) (OperationKind.PatternCaseClause, IsInvalid) (Syntax: 'case int y:') Pattern: IDeclarationPattern (Declared Symbol: System.Int32 y) (OperationKind.DeclarationPattern, IsInvalid) (Syntax: 'int y') Guard Expression: null Body: - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IBranchStatement (BranchKind.Break, Label: label_1) (OperationKind.BranchStatement) (Syntax: 'break;') ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase) (Syntax: 'case X z: ... break;') Clauses: - IPatternCaseClause (Label Symbol: case X z:) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case X z:') + IPatternCaseClause (Label: case X z:) (CaseKind.Pattern) (OperationKind.PatternCaseClause) (Syntax: 'case X z:') Pattern: IDeclarationPattern (Declared Symbol: X z) (OperationKind.DeclarationPattern) (Syntax: 'X z') Guard Expression: null Body: - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IBranchStatement (BranchKind.Break, Label: label_1) (OperationKind.BranchStatement) (Syntax: 'break;') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS8120: The switch case has already been handled by a previous case. diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_ISequenceExpression.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_ISequenceExpression.cs new file mode 100644 index 0000000000000..5d22df1846871 --- /dev/null +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_ISequenceExpression.cs @@ -0,0 +1,154 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Diagnostics; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Semantics; +using Microsoft.CodeAnalysis.Test.Utilities; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests +{ + public partial class IOperationTests : SemanticModelTestBase + { + [CompilerTrait(CompilerFeature.IOperation)] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/21866")] + public void ISequenceExpression_FromPostIncrement() + { + string source = @" +class C +{ + /**/ + static void Method(int p) + { + p++; + } + /**/ +} +"; + string expectedOperationTree = @" +IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'p++;') + Expression: ISequenceExpression (OperationKind.SequenceExpression) (Syntax: 'p++') + Locals: Local_1: System.Int32 ? + SideEffects(2): + ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: 'p++') + Left: ILocalReferenceExpression: (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'p++') + Right: IParameterReferenceExpression: p (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'p') + ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: 'p++') + Left: IParameterReferenceExpression: p (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'p') + Right: IBinaryOperatorExpression (BinaryOperatorKind.Add) (OperationKind.BinaryOperatorExpression, Type: System.Int32) (Syntax: 'p++') + Left: ILocalReferenceExpression: (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'p++') + Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: 'p++') + Value: ILocalReferenceExpression: (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'p++') +"; + var expectedDiagnostics = DiagnosticDescription.None; + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, useLoweredTree: true); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/21866")] + public void ISequenceExpression_FromPostDecrement() + { + string source = @" +class C +{ + /**/ + static void Method(int p) + { + p--; + } + /**/ +} +"; + string expectedOperationTree = @" +IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'p--;') + Expression: ISequenceExpression (OperationKind.SequenceExpression) (Syntax: 'p--') + Locals: Local_1: System.Int32 ? + SideEffects(2): + ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: 'p--') + Left: ILocalReferenceExpression: (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'p--') + Right: IParameterReferenceExpression: p (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'p') + ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: 'p--') + Left: IParameterReferenceExpression: p (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'p') + Right: IBinaryOperatorExpression (BinaryOperatorKind.Subtract) (OperationKind.BinaryOperatorExpression, Type: System.Int32) (Syntax: 'p--') + Left: ILocalReferenceExpression: (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'p--') + Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: 'p--') + Value: ILocalReferenceExpression: (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'p--') +"; + var expectedDiagnostics = DiagnosticDescription.None; + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, useLoweredTree: true); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/21866")] + public void ISequenceExpression_FromPreIncrement() + { + string source = @" +class C +{ + /**/ + static void Method(int p) + { + ++p; + } + /**/ +} +"; + string expectedOperationTree = @" +IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: '++p;') + Expression: ISequenceExpression (OperationKind.SequenceExpression) (Syntax: '++p') + Locals: Local_1: System.Int32 ? + SideEffects(2): + ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: '++p') + Left: ILocalReferenceExpression: (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: '++p') + Right: IBinaryOperatorExpression (BinaryOperatorKind.Add) (OperationKind.BinaryOperatorExpression, Type: System.Int32) (Syntax: '++p') + Left: IParameterReferenceExpression: p (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'p') + Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '++p') + ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: '++p') + Left: IParameterReferenceExpression: p (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'p') + Right: ILocalReferenceExpression: (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: '++p') + Value: ILocalReferenceExpression: (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: '++p') +"; + var expectedDiagnostics = DiagnosticDescription.None; + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, useLoweredTree: true); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/21866")] + public void ISequenceExpression_FromPreDecrement() + { + string source = @" +class C +{ + /**/ + static void Method(int p) + { + --p; + } + /**/ +} +"; + string expectedOperationTree = @" +IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: '--p;') + Expression: ISequenceExpression (OperationKind.SequenceExpression) (Syntax: '--p') + Locals: Local_1: System.Int32 ? + SideEffects(2): + ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: '--p') + Left: ILocalReferenceExpression: (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: '--p') + Right: IBinaryOperatorExpression (BinaryOperatorKind.Subtract) (OperationKind.BinaryOperatorExpression, Type: System.Int32) (Syntax: '--p') + Left: IParameterReferenceExpression: p (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'p') + Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '--p') + ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: '--p') + Left: IParameterReferenceExpression: p (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'p') + Right: ILocalReferenceExpression: (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: '--p') + Value: ILocalReferenceExpression: (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: '--p') +"; + var expectedDiagnostics = DiagnosticDescription.None; + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, useLoweredTree: true); + } + } +} diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IWhileUntilLoopStatement.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IWhileUntilLoopStatement.cs index 0b75e3b7c431a..d4e615a585f5d 100644 --- a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IWhileUntilLoopStatement.cs +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IWhileUntilLoopStatement.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Test.Utilities; @@ -188,7 +188,7 @@ static void Main() ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: ""While-loop break"") (Syntax: '""While-loop break""') InConversion: null OutConversion: null - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IBranchStatement (BranchKind.Break, Label: label_0) (OperationKind.BranchStatement) (Syntax: 'break;') IfFalse: null IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'Console.Wri ... tatement"");') Expression: IInvocationExpression (void System.Console.WriteLine(System.String value)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'Console.Wri ... statement"")') @@ -553,7 +553,7 @@ static void Main() Left: ILocalReferenceExpression: i (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'i') Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 9) (Syntax: '9') IfTrue: IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') - IBranchStatement (BranchKind.Continue) (OperationKind.BranchStatement) (Syntax: 'continue;') + IBranchStatement (BranchKind.Continue, Label: label_0) (OperationKind.BranchStatement) (Syntax: 'continue;') IfFalse: null IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'System.Cons ... iteLine(i);') Expression: IInvocationExpression (void System.Console.WriteLine(System.Int32 value)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'System.Cons ... riteLine(i)') diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_InvalidStatement.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_InvalidStatement.cs index 5e5d2d66335df..d70bed3c6e533 100644 --- a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_InvalidStatement.cs +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_InvalidStatement.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; @@ -119,7 +119,7 @@ static void Main(string[] args) Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) Operand: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1') Body: - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + IBranchStatement (BranchKind.Break, Label: label_0) (OperationKind.BranchStatement) (Syntax: 'break;') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0029: Cannot implicitly convert type 'int' to 'string' diff --git a/src/Compilers/Core/Portable/Compilation/Compilation.cs b/src/Compilers/Core/Portable/Compilation/Compilation.cs index 5343697480f5b..1009db0821845 100644 --- a/src/Compilers/Core/Portable/Compilation/Compilation.cs +++ b/src/Compilers/Core/Portable/Compilation/Compilation.cs @@ -1092,6 +1092,29 @@ protected abstract INamedTypeSymbol CommonCreateAnonymousTypeSymbol( #endregion + #region Operations + + /// + /// Gets the low-level operation corresponding to the method's body. + /// + /// The method symbol. + /// An optional cancellation token. + /// The low-level operation corresponding to the method's body. + internal IOperation GetLowLevelOperation(IMethodSymbol method, CancellationToken cancellationToken = default) + { + return GetLowLevelOperationCore(method, cancellationToken); + } + + /// + /// Gets the low-level operation corresponding to the method's body. + /// + /// The method symbol. + /// An optional cancellation token. + /// The low-level operation corresponding to the method's body. + protected abstract IOperation GetLowLevelOperationCore(IMethodSymbol method, CancellationToken cancellationToken = default); + + #endregion + #region Diagnostics internal const CompilationStage DefaultDiagnosticsStage = CompilationStage.Compile; diff --git a/src/Compilers/Core/Portable/Compilation/CompilationExtensions.cs b/src/Compilers/Core/Portable/Compilation/CompilationExtensions.cs new file mode 100644 index 0000000000000..5a998f4b5d8ce --- /dev/null +++ b/src/Compilers/Core/Portable/Compilation/CompilationExtensions.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; + +namespace Microsoft.CodeAnalysis +{ + public static class CompilationExtensions + { + /// + /// Gets the low-level operation corresponding to the method's body. + /// + /// The compilation containing the method symbol. + /// The method symbol. + /// An optional cancellation token. + /// The low-level operation corresponding to the method's body. + public static IOperation GetLowLevelOperation(this Compilation compilation, IMethodSymbol method, CancellationToken cancellationToken = default) + { + if (compilation == null) + { + throw new ArgumentNullException(nameof(compilation)); + } + + if (method == null) + { + throw new ArgumentNullException(nameof(method)); + } + + // This method implements an experimental feature. + // Do not remove the following feature flag check + // when releasing IOperation API. + if (!compilation.IsIOperationFeatureEnabled()) + { + throw new InvalidOperationException(CodeAnalysisResources.IOperationFeatureDisabled); + } + + return compilation.GetLowLevelOperation(method, cancellationToken); + } + } +} diff --git a/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs b/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs index 30e1d65c06c35..519bd93ceb848 100644 --- a/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs +++ b/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs @@ -736,7 +736,7 @@ internal sealed partial class LazyBinaryOperatorExpression : BaseBinaryOperatorE private readonly Lazy _lazyLeftOperand; private readonly Lazy _lazyRightOperand; - public LazyBinaryOperatorExpression(BinaryOperatorKind operatorKind, Lazy leftOperand, Lazy rightOperand, bool isLifted, bool isChecked, bool isCompareText, bool usesOperatorMethod, IMethodSymbol operatorMethod, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + public LazyBinaryOperatorExpression(BinaryOperatorKind operatorKind, Lazy leftOperand, Lazy rightOperand, bool isLifted, bool isChecked, bool isCompareText, bool usesOperatorMethod, IMethodSymbol operatorMethod, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : base(operatorKind, isLifted, isChecked, isCompareText, usesOperatorMethod, operatorMethod, semanticModel, syntax, type, constantValue, isImplicit) { _lazyLeftOperand = leftOperand ?? throw new System.ArgumentNullException(nameof(leftOperand)); @@ -817,6 +817,167 @@ public LazyBlockStatement(Lazy> statements, Immutable protected override ImmutableArray StatementsImpl => _lazyStatements.Value; } + /// + /// Represents a sequence of expressions. + /// + internal abstract partial class BaseSequenceExpression : Operation, ISequenceExpression + { + protected BaseSequenceExpression(ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(OperationKind.SequenceExpression, semanticModel, syntax, type, constantValue, isImplicit) + { + Locals = locals; + } + + protected abstract ImmutableArray SideEffectsImpl { get; } + protected abstract IOperation ValueImpl { get; } + + /// + /// Side effects of the expression. + /// + public ImmutableArray SideEffects => Operation.SetParentOperation(SideEffectsImpl, this); + /// + /// The value of the expression. + /// + public IOperation Value => Operation.SetParentOperation(ValueImpl, this); + /// + /// Local declarations contained within the expression. + /// + public ImmutableArray Locals { get; } + + public override IEnumerable Children + { + get + { + foreach (var operation in SideEffects) + { + yield return operation; + } + + yield return Value; + } + } + + public override void Accept(OperationVisitor visitor) + { + visitor.VisitSequenceExpression(this); + } + public override TResult Accept(OperationVisitor visitor, TArgument argument) + { + return visitor.VisitSequenceExpression(this, argument); + } + } + + /// + /// Represents a sequence of expressions. + /// + internal sealed partial class SequenceExpression : BaseSequenceExpression, ISequenceExpression + { + public SequenceExpression(ImmutableArray sideEffects, IOperation value, ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(locals, semanticModel, syntax, type, constantValue, isImplicit) + { + SideEffectsImpl = sideEffects; + ValueImpl = value; + } + + protected override ImmutableArray SideEffectsImpl { get; } + protected override IOperation ValueImpl { get; } + } + + /// + /// Represents a sequence of expressions. + /// + internal sealed partial class LazySequenceExpression : BaseSequenceExpression, ISequenceExpression + { + private readonly Lazy> _lazySideEffects; + private readonly Lazy _lazyValue; + + public LazySequenceExpression(Lazy> sideEffects, Lazy value, ImmutableArray locals, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(locals, semanticModel, syntax, type, constantValue, isImplicit) + { + _lazySideEffects = sideEffects; + _lazyValue = value ?? throw new System.ArgumentNullException(nameof(value)); + } + + protected override ImmutableArray SideEffectsImpl => _lazySideEffects.Value; + protected override IOperation ValueImpl => _lazyValue.Value; + } + + /// + /// Represents a conditional goto statement + /// + internal abstract partial class BaseConditionalGotoStatement : Operation, IConditionalGotoStatement + { + public BaseConditionalGotoStatement(ILabelSymbol target, bool jumpIfTrue, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(OperationKind.ConditionalGotoStatement, semanticModel, syntax, type, constantValue, isImplicit) + { + Target = target; + JumpIfTrue = jumpIfTrue; + } + + protected abstract IOperation ConditionImpl { get; } + + /// + /// Condition of the branch. + /// + public IOperation Condition => Operation.SetParentOperation(ConditionImpl, this); + /// + /// Label that is the target of the branch. + /// + public ILabelSymbol Target { get; } + /// + /// Indicates if the jump will be executed when the condition is true. + /// Otherwise, it will be executed when the condition is false. + /// + public bool JumpIfTrue { get; } + + public override IEnumerable Children + { + get + { + yield return Condition; + } + } + + public override void Accept(OperationVisitor visitor) + { + visitor.VisitConditionalGotoStatement(this); + } + public override TResult Accept(OperationVisitor visitor, TArgument argument) + { + return visitor.VisitConditionalGotoStatement(this, argument); + } + } + + /// + /// Represents a conditional goto statement + /// + internal sealed partial class ConditionalGotoStatement : BaseConditionalGotoStatement, IConditionalGotoStatement + { + public ConditionalGotoStatement(IOperation condition, ILabelSymbol target, bool jumpIfTrue, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(target, jumpIfTrue, semanticModel, syntax, type, constantValue, isImplicit) + { + ConditionImpl = condition; + } + + protected override IOperation ConditionImpl { get; } + } + + /// + /// Represents a conditional goto statement + /// + internal sealed partial class LazyConditionalGotoStatement : BaseConditionalGotoStatement, IConditionalGotoStatement + { + private readonly Lazy _lazyCondition; + + public LazyConditionalGotoStatement(Lazy condition, ILabelSymbol target, bool jumpIfTrue, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(target, jumpIfTrue, semanticModel, syntax, type, constantValue, isImplicit) + { + _lazyCondition = condition ?? throw new System.ArgumentNullException(nameof(condition)); + } + + protected override IOperation ConditionImpl => _lazyCondition.Value; + } + /// /// Represents a C# goto, break, or continue statement, or a VB GoTo, Exit ***, or Continue *** statement /// @@ -4710,7 +4871,7 @@ internal sealed partial class LazyUnaryOperatorExpression : BaseUnaryOperatorExp { private readonly Lazy _lazyOperand; - public LazyUnaryOperatorExpression(UnaryOperatorKind unaryOperationKind, Lazy operand, bool isLifted, bool isChecked, bool usesOperatorMethod, IMethodSymbol operatorMethod, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + public LazyUnaryOperatorExpression(UnaryOperatorKind unaryOperationKind, Lazy operand, bool isLifted, bool isChecked, bool usesOperatorMethod, IMethodSymbol operatorMethod, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : base(unaryOperationKind, isLifted, isChecked, usesOperatorMethod, operatorMethod, semanticModel, syntax, type, constantValue, isImplicit) { _lazyOperand = operand ?? throw new System.ArgumentNullException(nameof(operand)); @@ -5138,7 +5299,7 @@ internal sealed partial class LazyLocalFunctionStatement : BaseLocalFunctionStat { private readonly Lazy _lazyBody; - public LazyLocalFunctionStatement(IMethodSymbol symbol, Lazy body, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue,bool isImplicit) + public LazyLocalFunctionStatement(IMethodSymbol symbol, Lazy body, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : base(symbol, semanticModel, syntax, type, constantValue, isImplicit) { _lazyBody = body ?? throw new System.ArgumentNullException(nameof(body)); diff --git a/src/Compilers/Core/Portable/Operations/IConditionalGotoStatement.cs b/src/Compilers/Core/Portable/Operations/IConditionalGotoStatement.cs new file mode 100644 index 0000000000000..0ceabed24f268 --- /dev/null +++ b/src/Compilers/Core/Portable/Operations/IConditionalGotoStatement.cs @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.CodeAnalysis.Semantics +{ + /// + /// Represents a conditional goto. + /// + /// + /// This interface is reserved for implementation by its associated APIs. We reserve the right to + /// change it in the future. + /// + public interface IConditionalGotoStatement : IOperation + { + /// + /// Condition of the branch. + /// + IOperation Condition { get; } + /// + /// Label that is the target of the branch. + /// + ILabelSymbol Target { get; } + /// + /// Indicates if the jump will be executed when the condition is true. + /// Otherwise, it will be executed when the condition is false. + /// + bool JumpIfTrue { get; } + } +} diff --git a/src/Compilers/Core/Portable/Operations/ISequenceExpression.cs b/src/Compilers/Core/Portable/Operations/ISequenceExpression.cs new file mode 100644 index 0000000000000..00aaac1a6c8e2 --- /dev/null +++ b/src/Compilers/Core/Portable/Operations/ISequenceExpression.cs @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Immutable; + +namespace Microsoft.CodeAnalysis.Semantics +{ + /// + /// Represents a sequence of expressions. + /// + /// + /// This interface is reserved for implementation by its associated APIs. We reserve the right to + /// change it in the future. + /// + public interface ISequenceExpression : IOperation + { + /// + /// Side effects of the expression. + /// + ImmutableArray SideEffects { get; } + /// + /// The value of the expression. + /// + IOperation Value { get; } + /// + /// Local declarations contained within the expression. + /// + ImmutableArray Locals { get; } + } +} diff --git a/src/Compilers/Core/Portable/Operations/OperationKind.cs b/src/Compilers/Core/Portable/Operations/OperationKind.cs index 0f99c2fd56723..a34f5b5daab9b 100644 --- a/src/Compilers/Core/Portable/Operations/OperationKind.cs +++ b/src/Compilers/Core/Portable/Operations/OperationKind.cs @@ -215,5 +215,12 @@ public enum OperationKind /// Indicates an . DefaultCaseClause = 0x412, + + // Operations that occur only after lowering phase. + + /// Indicates an . + ConditionalGotoStatement = 0x413, + /// Indicates an . + SequenceExpression = 0x414 } } diff --git a/src/Compilers/Core/Portable/Operations/OperationVisitor.cs b/src/Compilers/Core/Portable/Operations/OperationVisitor.cs index 376dc1d3ca413..ea3d1c60bd33f 100644 --- a/src/Compilers/Core/Portable/Operations/OperationVisitor.cs +++ b/src/Compilers/Core/Portable/Operations/OperationVisitor.cs @@ -459,6 +459,16 @@ public virtual void VisitTupleExpression(ITupleExpression operation) { DefaultVisit(operation); } + + public virtual void VisitConditionalGotoStatement(IConditionalGotoStatement operation) + { + DefaultVisit(operation); + } + + public virtual void VisitSequenceExpression(ISequenceExpression operation) + { + DefaultVisit(operation); + } } /// @@ -924,5 +934,15 @@ public virtual TResult VisitTupleExpression(ITupleExpression operation, TArgumen { return DefaultVisit(operation, argument); } + + public virtual TResult VisitConditionalGotoStatement(IConditionalGotoStatement operation, TArgument argument) + { + return DefaultVisit(operation, argument); + } + + public virtual TResult VisitSequenceExpression(ISequenceExpression operation, TArgument argument) + { + return DefaultVisit(operation, argument); + } } } diff --git a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt index a8f2b7900d399..8d9ae058004df 100644 --- a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt @@ -2,6 +2,8 @@ *REMOVED*Microsoft.CodeAnalysis.Emit.EmitOptions.EmitOptions(bool metadataOnly = false, Microsoft.CodeAnalysis.Emit.DebugInformationFormat debugInformationFormat = (Microsoft.CodeAnalysis.Emit.DebugInformationFormat)0, string pdbFilePath = null, string outputNameOverride = null, int fileAlignment = 0, ulong baseAddress = 0, bool highEntropyVirtualAddressSpace = false, Microsoft.CodeAnalysis.SubsystemVersion subsystemVersion = default(Microsoft.CodeAnalysis.SubsystemVersion), string runtimeMetadataVersion = null, bool tolerateErrors = false, bool includePrivateMembers = false, System.Collections.Immutable.ImmutableArray instrumentationKinds = default(System.Collections.Immutable.ImmutableArray)) -> void *REMOVED*Microsoft.CodeAnalysis.IOperation.IsInvalid.get -> bool Microsoft.CodeAnalysis.CommandLineArguments.DisplayLangVersions.get -> bool +Microsoft.CodeAnalysis.CompilationExtensions +static Microsoft.CodeAnalysis.CompilationExtensions.GetLowLevelOperation(this Microsoft.CodeAnalysis.Compilation compilation, Microsoft.CodeAnalysis.IMethodSymbol method, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.IOperation Microsoft.CodeAnalysis.Diagnostics.AnalysisContext.RegisterOperationAction(System.Action action, params Microsoft.CodeAnalysis.OperationKind[] operationKinds) -> void Microsoft.CodeAnalysis.Diagnostics.CompilationStartAnalysisContext.RegisterOperationAction(System.Action action, params Microsoft.CodeAnalysis.OperationKind[] operationKinds) -> void Microsoft.CodeAnalysis.Diagnostics.OperationAnalysisContext @@ -49,6 +51,7 @@ Microsoft.CodeAnalysis.IOperation.Syntax.get -> Microsoft.CodeAnalysis.SyntaxNod Microsoft.CodeAnalysis.IOperation.Type.get -> Microsoft.CodeAnalysis.ITypeSymbol Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.AddressOfExpression = 515 -> Microsoft.CodeAnalysis.OperationKind +Microsoft.CodeAnalysis.OperationKind.AnonymousFunctionExpression = 273 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.AnonymousObjectCreationExpression = 287 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.Argument = 1031 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.ArrayCreationExpression = 276 -> Microsoft.CodeAnalysis.OperationKind @@ -59,11 +62,13 @@ Microsoft.CodeAnalysis.OperationKind.BinaryOperatorExpression = 270 -> Microsoft Microsoft.CodeAnalysis.OperationKind.BlockStatement = 2 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.BranchStatement = 8 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.CatchClause = 1032 -> Microsoft.CodeAnalysis.OperationKind +Microsoft.CodeAnalysis.OperationKind.CoalesceExpression = 272 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.CollectionElementInitializerExpression = 290 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.CompoundAssignmentExpression = 281 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.ConditionalAccessExpression = 284 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.ConditionalAccessInstanceExpression = 285 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.ConditionalExpression = 271 -> Microsoft.CodeAnalysis.OperationKind +Microsoft.CodeAnalysis.OperationKind.ConditionalGotoStatement = 1043 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.ConstantPattern = 1039 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.ConversionExpression = 258 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.DeclarationPattern = 1040 -> Microsoft.CodeAnalysis.OperationKind @@ -91,7 +96,6 @@ Microsoft.CodeAnalysis.OperationKind.InvocationExpression = 259 -> Microsoft.Cod Microsoft.CodeAnalysis.OperationKind.IsPatternExpression = 517 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.IsTypeExpression = 278 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.LabeledStatement = 7 -> Microsoft.CodeAnalysis.OperationKind -Microsoft.CodeAnalysis.OperationKind.AnonymousFunctionExpression = 273 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.LiteralExpression = 257 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.LocalFunctionStatement = 49 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.LocalReferenceExpression = 261 -> Microsoft.CodeAnalysis.OperationKind @@ -101,7 +105,6 @@ Microsoft.CodeAnalysis.OperationKind.MemberInitializerExpression = 289 -> Micros Microsoft.CodeAnalysis.OperationKind.MethodBindingExpression = 265 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.NameOfExpression = 291 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.None = 0 -> Microsoft.CodeAnalysis.OperationKind -Microsoft.CodeAnalysis.OperationKind.CoalesceExpression = 272 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.ObjectCreationExpression = 274 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.ObjectOrCollectionInitializerExpression = 288 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.OmittedArgumentExpression = 768 -> Microsoft.CodeAnalysis.OperationKind @@ -116,6 +119,7 @@ Microsoft.CodeAnalysis.OperationKind.PropertyReferenceExpression = 266 -> Micros Microsoft.CodeAnalysis.OperationKind.RangeCaseClause = 1036 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.RelationalCaseClause = 1035 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.ReturnStatement = 11 -> Microsoft.CodeAnalysis.OperationKind +Microsoft.CodeAnalysis.OperationKind.SequenceExpression = 1044 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.SimpleAssignmentExpression = 280 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.SingleValueCaseClause = 1034 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.SizeOfExpression = 514 -> Microsoft.CodeAnalysis.OperationKind @@ -198,6 +202,9 @@ Microsoft.CodeAnalysis.Semantics.ConversionKind.OperatorMethod = 5 -> Microsoft. Microsoft.CodeAnalysis.Semantics.ConversionKind.TryCast = 2 -> Microsoft.CodeAnalysis.Semantics.ConversionKind Microsoft.CodeAnalysis.Semantics.IAddressOfExpression Microsoft.CodeAnalysis.Semantics.IAddressOfExpression.Reference.get -> Microsoft.CodeAnalysis.IOperation +Microsoft.CodeAnalysis.Semantics.IAnonymousFunctionExpression +Microsoft.CodeAnalysis.Semantics.IAnonymousFunctionExpression.Body.get -> Microsoft.CodeAnalysis.Semantics.IBlockStatement +Microsoft.CodeAnalysis.Semantics.IAnonymousFunctionExpression.Symbol.get -> Microsoft.CodeAnalysis.IMethodSymbol Microsoft.CodeAnalysis.Semantics.IAnonymousObjectCreationExpression Microsoft.CodeAnalysis.Semantics.IAnonymousObjectCreationExpression.Initializers.get -> System.Collections.Immutable.ImmutableArray Microsoft.CodeAnalysis.Semantics.IArgument @@ -240,6 +247,9 @@ Microsoft.CodeAnalysis.Semantics.ICatchClause.CaughtType.get -> Microsoft.CodeAn Microsoft.CodeAnalysis.Semantics.ICatchClause.ExceptionLocal.get -> Microsoft.CodeAnalysis.ILocalSymbol Microsoft.CodeAnalysis.Semantics.ICatchClause.Filter.get -> Microsoft.CodeAnalysis.IOperation Microsoft.CodeAnalysis.Semantics.ICatchClause.Handler.get -> Microsoft.CodeAnalysis.Semantics.IBlockStatement +Microsoft.CodeAnalysis.Semantics.ICoalesceExpression +Microsoft.CodeAnalysis.Semantics.ICoalesceExpression.Expression.get -> Microsoft.CodeAnalysis.IOperation +Microsoft.CodeAnalysis.Semantics.ICoalesceExpression.WhenNull.get -> Microsoft.CodeAnalysis.IOperation Microsoft.CodeAnalysis.Semantics.ICollectionElementInitializerExpression Microsoft.CodeAnalysis.Semantics.ICollectionElementInitializerExpression.AddMethod.get -> Microsoft.CodeAnalysis.IMethodSymbol Microsoft.CodeAnalysis.Semantics.ICollectionElementInitializerExpression.Arguments.get -> System.Collections.Immutable.ImmutableArray @@ -256,6 +266,10 @@ Microsoft.CodeAnalysis.Semantics.IConditionalExpression Microsoft.CodeAnalysis.Semantics.IConditionalExpression.Condition.get -> Microsoft.CodeAnalysis.IOperation Microsoft.CodeAnalysis.Semantics.IConditionalExpression.WhenFalse.get -> Microsoft.CodeAnalysis.IOperation Microsoft.CodeAnalysis.Semantics.IConditionalExpression.WhenTrue.get -> Microsoft.CodeAnalysis.IOperation +Microsoft.CodeAnalysis.Semantics.IConditionalGotoStatement +Microsoft.CodeAnalysis.Semantics.IConditionalGotoStatement.Condition.get -> Microsoft.CodeAnalysis.IOperation +Microsoft.CodeAnalysis.Semantics.IConditionalGotoStatement.JumpIfTrue.get -> bool +Microsoft.CodeAnalysis.Semantics.IConditionalGotoStatement.Target.get -> Microsoft.CodeAnalysis.ILabelSymbol Microsoft.CodeAnalysis.Semantics.IConstantPattern Microsoft.CodeAnalysis.Semantics.IConstantPattern.Value.get -> Microsoft.CodeAnalysis.IOperation Microsoft.CodeAnalysis.Semantics.IConversionExpression @@ -348,9 +362,6 @@ Microsoft.CodeAnalysis.Semantics.IIsTypeExpression.Operand.get -> Microsoft.Code Microsoft.CodeAnalysis.Semantics.ILabeledStatement Microsoft.CodeAnalysis.Semantics.ILabeledStatement.Label.get -> Microsoft.CodeAnalysis.ILabelSymbol Microsoft.CodeAnalysis.Semantics.ILabeledStatement.Statement.get -> Microsoft.CodeAnalysis.IOperation -Microsoft.CodeAnalysis.Semantics.IAnonymousFunctionExpression -Microsoft.CodeAnalysis.Semantics.IAnonymousFunctionExpression.Body.get -> Microsoft.CodeAnalysis.Semantics.IBlockStatement -Microsoft.CodeAnalysis.Semantics.IAnonymousFunctionExpression.Symbol.get -> Microsoft.CodeAnalysis.IMethodSymbol Microsoft.CodeAnalysis.Semantics.ILiteralExpression Microsoft.CodeAnalysis.Semantics.ILocalFunctionStatement Microsoft.CodeAnalysis.Semantics.ILocalFunctionStatement.Body.get -> Microsoft.CodeAnalysis.Semantics.IBlockStatement @@ -374,9 +385,6 @@ Microsoft.CodeAnalysis.Semantics.IMethodBindingExpression.IsVirtual.get -> bool Microsoft.CodeAnalysis.Semantics.IMethodBindingExpression.Method.get -> Microsoft.CodeAnalysis.IMethodSymbol Microsoft.CodeAnalysis.Semantics.INameOfExpression Microsoft.CodeAnalysis.Semantics.INameOfExpression.Argument.get -> Microsoft.CodeAnalysis.IOperation -Microsoft.CodeAnalysis.Semantics.ICoalesceExpression -Microsoft.CodeAnalysis.Semantics.ICoalesceExpression.Expression.get -> Microsoft.CodeAnalysis.IOperation -Microsoft.CodeAnalysis.Semantics.ICoalesceExpression.WhenNull.get -> Microsoft.CodeAnalysis.IOperation Microsoft.CodeAnalysis.Semantics.IObjectCreationExpression Microsoft.CodeAnalysis.Semantics.IObjectCreationExpression.Constructor.get -> Microsoft.CodeAnalysis.IMethodSymbol Microsoft.CodeAnalysis.Semantics.IObjectCreationExpression.Initializer.get -> Microsoft.CodeAnalysis.Semantics.IObjectOrCollectionInitializerExpression @@ -409,6 +417,10 @@ Microsoft.CodeAnalysis.Semantics.IRelationalCaseClause.Relation.get -> Microsoft Microsoft.CodeAnalysis.Semantics.IRelationalCaseClause.Value.get -> Microsoft.CodeAnalysis.IOperation Microsoft.CodeAnalysis.Semantics.IReturnStatement Microsoft.CodeAnalysis.Semantics.IReturnStatement.ReturnedValue.get -> Microsoft.CodeAnalysis.IOperation +Microsoft.CodeAnalysis.Semantics.ISequenceExpression +Microsoft.CodeAnalysis.Semantics.ISequenceExpression.Locals.get -> System.Collections.Immutable.ImmutableArray +Microsoft.CodeAnalysis.Semantics.ISequenceExpression.SideEffects.get -> System.Collections.Immutable.ImmutableArray +Microsoft.CodeAnalysis.Semantics.ISequenceExpression.Value.get -> Microsoft.CodeAnalysis.IOperation Microsoft.CodeAnalysis.Semantics.ISimpleAssignmentExpression Microsoft.CodeAnalysis.Semantics.ISingleValueCaseClause Microsoft.CodeAnalysis.Semantics.ISingleValueCaseClause.Value.get -> Microsoft.CodeAnalysis.IOperation @@ -483,9 +495,9 @@ Microsoft.CodeAnalysis.Semantics.UnaryOperatorKind Microsoft.CodeAnalysis.Semantics.UnaryOperatorKind.BitwiseNegation = 1 -> Microsoft.CodeAnalysis.Semantics.UnaryOperatorKind Microsoft.CodeAnalysis.Semantics.UnaryOperatorKind.False = 6 -> Microsoft.CodeAnalysis.Semantics.UnaryOperatorKind Microsoft.CodeAnalysis.Semantics.UnaryOperatorKind.Invalid = 255 -> Microsoft.CodeAnalysis.Semantics.UnaryOperatorKind -Microsoft.CodeAnalysis.Semantics.UnaryOperatorKind.Not = 2 -> Microsoft.CodeAnalysis.Semantics.UnaryOperatorKind Microsoft.CodeAnalysis.Semantics.UnaryOperatorKind.Minus = 4 -> Microsoft.CodeAnalysis.Semantics.UnaryOperatorKind Microsoft.CodeAnalysis.Semantics.UnaryOperatorKind.None = 0 -> Microsoft.CodeAnalysis.Semantics.UnaryOperatorKind +Microsoft.CodeAnalysis.Semantics.UnaryOperatorKind.Not = 2 -> Microsoft.CodeAnalysis.Semantics.UnaryOperatorKind Microsoft.CodeAnalysis.Semantics.UnaryOperatorKind.Plus = 3 -> Microsoft.CodeAnalysis.Semantics.UnaryOperatorKind Microsoft.CodeAnalysis.Semantics.UnaryOperatorKind.True = 5 -> Microsoft.CodeAnalysis.Semantics.UnaryOperatorKind Microsoft.CodeAnalysis.SyntaxList.SyntaxList(System.Collections.Generic.IEnumerable nodes) -> void @@ -519,6 +531,7 @@ virtual Microsoft.CodeAnalysis.Diagnostics.CompilationStartAnalysisContext.Regis virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.DefaultVisit(Microsoft.CodeAnalysis.IOperation operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.Visit(Microsoft.CodeAnalysis.IOperation operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitAddressOfExpression(Microsoft.CodeAnalysis.Semantics.IAddressOfExpression operation) -> void +virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitAnonymousFunctionExpression(Microsoft.CodeAnalysis.Semantics.IAnonymousFunctionExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitAnonymousObjectCreationExpression(Microsoft.CodeAnalysis.Semantics.IAnonymousObjectCreationExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitArgument(Microsoft.CodeAnalysis.Semantics.IArgument operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitArrayCreationExpression(Microsoft.CodeAnalysis.Semantics.IArrayCreationExpression operation) -> void @@ -529,11 +542,13 @@ virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitBinaryOperatorExp virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitBlockStatement(Microsoft.CodeAnalysis.Semantics.IBlockStatement operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitBranchStatement(Microsoft.CodeAnalysis.Semantics.IBranchStatement operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitCatchClause(Microsoft.CodeAnalysis.Semantics.ICatchClause operation) -> void +virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitCoalesceExpression(Microsoft.CodeAnalysis.Semantics.ICoalesceExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitCollectionElementInitializerExpression(Microsoft.CodeAnalysis.Semantics.ICollectionElementInitializerExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitCompoundAssignmentExpression(Microsoft.CodeAnalysis.Semantics.ICompoundAssignmentExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitConditionalAccessExpression(Microsoft.CodeAnalysis.Semantics.IConditionalAccessExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitConditionalAccessInstanceExpression(Microsoft.CodeAnalysis.Semantics.IConditionalAccessInstanceExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitConditionalExpression(Microsoft.CodeAnalysis.Semantics.IConditionalExpression operation) -> void +virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitConditionalGotoStatement(Microsoft.CodeAnalysis.Semantics.IConditionalGotoStatement operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitConstantPattern(Microsoft.CodeAnalysis.Semantics.IConstantPattern operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitConversionExpression(Microsoft.CodeAnalysis.Semantics.IConversionExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitDeclarationPattern(Microsoft.CodeAnalysis.Semantics.IDeclarationPattern operation) -> void @@ -563,7 +578,6 @@ virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitInvocationExpress virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitIsPatternExpression(Microsoft.CodeAnalysis.Semantics.IIsPatternExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitIsTypeExpression(Microsoft.CodeAnalysis.Semantics.IIsTypeExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitLabeledStatement(Microsoft.CodeAnalysis.Semantics.ILabeledStatement operation) -> void -virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitAnonymousFunctionExpression(Microsoft.CodeAnalysis.Semantics.IAnonymousFunctionExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitLiteralExpression(Microsoft.CodeAnalysis.Semantics.ILiteralExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitLocalFunctionStatement(Microsoft.CodeAnalysis.Semantics.ILocalFunctionStatement operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitLocalReferenceExpression(Microsoft.CodeAnalysis.Semantics.ILocalReferenceExpression operation) -> void @@ -571,7 +585,6 @@ virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitLockStatement(Mic virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitMemberInitializerExpression(Microsoft.CodeAnalysis.Semantics.IMemberInitializerExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitMethodBindingExpression(Microsoft.CodeAnalysis.Semantics.IMethodBindingExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitNameOfExpression(Microsoft.CodeAnalysis.Semantics.INameOfExpression operation) -> void -virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitCoalesceExpression(Microsoft.CodeAnalysis.Semantics.ICoalesceExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitObjectCreationExpression(Microsoft.CodeAnalysis.Semantics.IObjectCreationExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitObjectOrCollectionInitializerExpression(Microsoft.CodeAnalysis.Semantics.IObjectOrCollectionInitializerExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitOmittedArgumentExpression(Microsoft.CodeAnalysis.Semantics.IOmittedArgumentExpression operation) -> void @@ -586,6 +599,7 @@ virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitPropertyReference virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitRangeCaseClause(Microsoft.CodeAnalysis.Semantics.IRangeCaseClause operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitRelationalCaseClause(Microsoft.CodeAnalysis.Semantics.IRelationalCaseClause operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitReturnStatement(Microsoft.CodeAnalysis.Semantics.IReturnStatement operation) -> void +virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitSequenceExpression(Microsoft.CodeAnalysis.Semantics.ISequenceExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitSimpleAssignmentExpression(Microsoft.CodeAnalysis.Semantics.ISimpleAssignmentExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitSingleValueCaseClause(Microsoft.CodeAnalysis.Semantics.ISingleValueCaseClause operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitSizeOfExpression(Microsoft.CodeAnalysis.Semantics.ISizeOfExpression operation) -> void @@ -608,6 +622,7 @@ virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitYieldBreakStateme virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.DefaultVisit(Microsoft.CodeAnalysis.IOperation operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.Visit(Microsoft.CodeAnalysis.IOperation operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitAddressOfExpression(Microsoft.CodeAnalysis.Semantics.IAddressOfExpression operation, TArgument argument) -> TResult +virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitAnonymousFunctionExpression(Microsoft.CodeAnalysis.Semantics.IAnonymousFunctionExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitAnonymousObjectCreationExpression(Microsoft.CodeAnalysis.Semantics.IAnonymousObjectCreationExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitArgument(Microsoft.CodeAnalysis.Semantics.IArgument operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitArrayCreationExpression(Microsoft.CodeAnalysis.Semantics.IArrayCreationExpression operation, TArgument argument) -> TResult @@ -618,11 +633,13 @@ virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.Vi virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitBlockStatement(Microsoft.CodeAnalysis.Semantics.IBlockStatement operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitBranchStatement(Microsoft.CodeAnalysis.Semantics.IBranchStatement operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitCatchClause(Microsoft.CodeAnalysis.Semantics.ICatchClause operation, TArgument argument) -> TResult +virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitCoalesceExpression(Microsoft.CodeAnalysis.Semantics.ICoalesceExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitCollectionElementInitializerExpression(Microsoft.CodeAnalysis.Semantics.ICollectionElementInitializerExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitCompoundAssignmentExpression(Microsoft.CodeAnalysis.Semantics.ICompoundAssignmentExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitConditionalAccessExpression(Microsoft.CodeAnalysis.Semantics.IConditionalAccessExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitConditionalAccessInstanceExpression(Microsoft.CodeAnalysis.Semantics.IConditionalAccessInstanceExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitConditionalExpression(Microsoft.CodeAnalysis.Semantics.IConditionalExpression operation, TArgument argument) -> TResult +virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitConditionalGotoStatement(Microsoft.CodeAnalysis.Semantics.IConditionalGotoStatement operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitConstantPattern(Microsoft.CodeAnalysis.Semantics.IConstantPattern operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitConversionExpression(Microsoft.CodeAnalysis.Semantics.IConversionExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitDeclarationPattern(Microsoft.CodeAnalysis.Semantics.IDeclarationPattern operation, TArgument argument) -> TResult @@ -652,7 +669,6 @@ virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.Vi virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitIsPatternExpression(Microsoft.CodeAnalysis.Semantics.IIsPatternExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitIsTypeExpression(Microsoft.CodeAnalysis.Semantics.IIsTypeExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitLabeledStatement(Microsoft.CodeAnalysis.Semantics.ILabeledStatement operation, TArgument argument) -> TResult -virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitAnonymousFunctionExpression(Microsoft.CodeAnalysis.Semantics.IAnonymousFunctionExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitLiteralExpression(Microsoft.CodeAnalysis.Semantics.ILiteralExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitLocalFunctionStatement(Microsoft.CodeAnalysis.Semantics.ILocalFunctionStatement operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitLocalReferenceExpression(Microsoft.CodeAnalysis.Semantics.ILocalReferenceExpression operation, TArgument argument) -> TResult @@ -660,7 +676,6 @@ virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.Vi virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitMemberInitializerExpression(Microsoft.CodeAnalysis.Semantics.IMemberInitializerExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitMethodBindingExpression(Microsoft.CodeAnalysis.Semantics.IMethodBindingExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitNameOfExpression(Microsoft.CodeAnalysis.Semantics.INameOfExpression operation, TArgument argument) -> TResult -virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitCoalesceExpression(Microsoft.CodeAnalysis.Semantics.ICoalesceExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitObjectCreationExpression(Microsoft.CodeAnalysis.Semantics.IObjectCreationExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitObjectOrCollectionInitializerExpression(Microsoft.CodeAnalysis.Semantics.IObjectOrCollectionInitializerExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitOmittedArgumentExpression(Microsoft.CodeAnalysis.Semantics.IOmittedArgumentExpression operation, TArgument argument) -> TResult @@ -675,6 +690,7 @@ virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.Vi virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitRangeCaseClause(Microsoft.CodeAnalysis.Semantics.IRangeCaseClause operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitRelationalCaseClause(Microsoft.CodeAnalysis.Semantics.IRelationalCaseClause operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitReturnStatement(Microsoft.CodeAnalysis.Semantics.IReturnStatement operation, TArgument argument) -> TResult +virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitSequenceExpression(Microsoft.CodeAnalysis.Semantics.ISequenceExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitSimpleAssignmentExpression(Microsoft.CodeAnalysis.Semantics.ISimpleAssignmentExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitSingleValueCaseClause(Microsoft.CodeAnalysis.Semantics.ISingleValueCaseClause operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitSizeOfExpression(Microsoft.CodeAnalysis.Semantics.ISizeOfExpression operation, TArgument argument) -> TResult @@ -693,4 +709,4 @@ virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.Vi virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitVariableDeclarationStatement(Microsoft.CodeAnalysis.Semantics.IVariableDeclarationStatement operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitWhileUntilLoopStatement(Microsoft.CodeAnalysis.Semantics.IWhileUntilLoopStatement operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitWithStatement(Microsoft.CodeAnalysis.Semantics.IWithStatement operation, TArgument argument) -> TResult -virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitYieldBreakStatement(Microsoft.CodeAnalysis.Semantics.IReturnStatement operation, TArgument argument) -> TResult +virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitYieldBreakStatement(Microsoft.CodeAnalysis.Semantics.IReturnStatement operation, TArgument argument) -> TResult \ No newline at end of file diff --git a/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs b/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs index c136527bac145..0701eda437fbd 100644 --- a/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs +++ b/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs @@ -1126,7 +1126,7 @@ public override string VisualizeLocalType(object type) #region IOperation tree validation - protected static (IOperation operation, SyntaxNode node) GetOperationAndSyntaxForTest(CSharpCompilation compilation) + protected static (IOperation operation, SyntaxNode node) GetOperationAndSyntaxForTest(CSharpCompilation compilation, bool useLoweredTree) where TSyntaxNode : SyntaxNode { var tree = compilation.SyntaxTrees[0]; @@ -1137,13 +1137,31 @@ protected static (IOperation operation, SyntaxNode node) GetOperationAndSyntaxFo return (null, null); } - return (model.GetOperationInternal(syntaxNode), syntaxNode); + IOperation operation; + + if (useLoweredTree) + { + var methodSymbol = model.GetDeclaredSymbolForNode(syntaxNode) as IMethodSymbol; + + if (methodSymbol == null) + { + return (null, null); + } + + operation = compilation.GetLowLevelOperation(methodSymbol); + } + else + { + operation = model.GetOperationInternal(syntaxNode); + } + + return (operation, syntaxNode); } - protected static string GetOperationTreeForTest(CSharpCompilation compilation) + protected static string GetOperationTreeForTest(CSharpCompilation compilation, bool useLoweredTree) where TSyntaxNode : SyntaxNode { - var (operation, syntax) = GetOperationAndSyntaxForTest(compilation); + var (operation, syntax) = GetOperationAndSyntaxForTest(compilation, useLoweredTree); return operation != null ? OperationTreeVerifier.GetOperationTree(compilation, operation) : null; } @@ -1152,35 +1170,35 @@ protected static string GetOperationTreeForTest(CSharpCompilation compilation, I return operation != null ? OperationTreeVerifier.GetOperationTree(compilation, operation) : null; } - protected static string GetOperationTreeForTest(string testSrc, string expectedOperationTree, CSharpCompilationOptions compilationOptions = null, CSharpParseOptions parseOptions = null) + protected static string GetOperationTreeForTest(string testSrc, string expectedOperationTree, bool useLoweredTree, CSharpCompilationOptions compilationOptions = null, CSharpParseOptions parseOptions = null) where TSyntaxNode : SyntaxNode { var compilation = CreateStandardCompilation(testSrc, new[] { SystemCoreRef, ValueTupleRef, SystemRuntimeFacadeRef }, options: compilationOptions ?? TestOptions.ReleaseDll, parseOptions: parseOptions); - return GetOperationTreeForTest(compilation); + return GetOperationTreeForTest(compilation, useLoweredTree); } - protected static void VerifyOperationTreeForTest(CSharpCompilation compilation, string expectedOperationTree, Action AdditionalOperationTreeVerifier = null) + protected static void VerifyOperationTreeForTest(CSharpCompilation compilation, string expectedOperationTree, Action AdditionalOperationTreeVerifier = null, bool useLoweredTree = false) where TSyntaxNode : SyntaxNode { - var (actualOperation, syntaxNode) = GetOperationAndSyntaxForTest(compilation); + var (actualOperation, syntaxNode) = GetOperationAndSyntaxForTest(compilation, useLoweredTree); var actualOperationTree = GetOperationTreeForTest(compilation, actualOperation); OperationTreeVerifier.Verify(expectedOperationTree, actualOperationTree); AdditionalOperationTreeVerifier?.Invoke(actualOperation, compilation, syntaxNode); } - protected static void VerifyOperationTreeForTest(string testSrc, string expectedOperationTree, CSharpCompilationOptions compilationOptions = null, CSharpParseOptions parseOptions = null) + protected static void VerifyOperationTreeForTest(string testSrc, string expectedOperationTree, CSharpCompilationOptions compilationOptions = null, CSharpParseOptions parseOptions = null, bool useLoweredTree = false) where TSyntaxNode : SyntaxNode { - var actualOperationTree = GetOperationTreeForTest(testSrc, expectedOperationTree, compilationOptions, parseOptions); + var actualOperationTree = GetOperationTreeForTest(testSrc, expectedOperationTree, useLoweredTree, compilationOptions, parseOptions); OperationTreeVerifier.Verify(expectedOperationTree, actualOperationTree); } - protected static void VerifyOperationTreeAndDiagnosticsForTest(CSharpCompilation compilation, string expectedOperationTree, DiagnosticDescription[] expectedDiagnostics, Action AdditionalOperationTreeVerifier = null) + protected static void VerifyOperationTreeAndDiagnosticsForTest(CSharpCompilation compilation, string expectedOperationTree, DiagnosticDescription[] expectedDiagnostics, Action AdditionalOperationTreeVerifier = null, bool useLoweredTree = false) where TSyntaxNode : SyntaxNode { var actualDiagnostics = compilation.GetDiagnostics().Where(d => d.Severity != DiagnosticSeverity.Hidden); actualDiagnostics.Verify(expectedDiagnostics); - VerifyOperationTreeForTest(compilation, expectedOperationTree, AdditionalOperationTreeVerifier); + VerifyOperationTreeForTest(compilation, expectedOperationTree, AdditionalOperationTreeVerifier, useLoweredTree); } private static readonly MetadataReference[] s_defaultOperationReferences = new[] { SystemRef, SystemCoreRef, ValueTupleRef, SystemRuntimeFacadeRef }; @@ -1191,12 +1209,13 @@ protected static void VerifyOperationTreeAndDiagnosticsForTest(stri CSharpCompilationOptions compilationOptions = null, CSharpParseOptions parseOptions = null, MetadataReference[] additionalReferences = null, - Action AdditionalOperationTreeVerifier = null) + Action AdditionalOperationTreeVerifier = null, + bool useLoweredTree = false) where TSyntaxNode : SyntaxNode { var references = additionalReferences == null ? s_defaultOperationReferences : additionalReferences.Concat(s_defaultOperationReferences); var compilation = CreateStandardCompilation(testSrc, references, sourceFileName: "file.cs", options: compilationOptions ?? TestOptions.ReleaseDll, parseOptions: parseOptions); - VerifyOperationTreeAndDiagnosticsForTest(compilation, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier); + VerifyOperationTreeAndDiagnosticsForTest(compilation, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier, useLoweredTree); } protected static MetadataReference VerifyOperationTreeAndDiagnosticsForTestWithIL(string testSrc, @@ -1206,11 +1225,12 @@ protected static MetadataReference VerifyOperationTreeAndDiagnosticsForTestWithI CSharpCompilationOptions compilationOptions = null, CSharpParseOptions parseOptions = null, MetadataReference[] additionalReferences = null, - Action AdditionalOperationTreeVerifier = null) + Action AdditionalOperationTreeVerifier = null, + bool useLoweredTree = false) where TSyntaxNode : SyntaxNode { var ilReference = CreateMetadataReferenceFromIlSource(ilSource); - VerifyOperationTreeAndDiagnosticsForTest(testSrc, expectedOperationTree, expectedDiagnostics, compilationOptions, parseOptions, new[] { ilReference }, AdditionalOperationTreeVerifier); + VerifyOperationTreeAndDiagnosticsForTest(testSrc, expectedOperationTree, expectedDiagnostics, compilationOptions, parseOptions, new[] { ilReference }, AdditionalOperationTreeVerifier, useLoweredTree); return ilReference; } diff --git a/src/Compilers/Test/Utilities/VisualBasic/BasicTestBase.vb b/src/Compilers/Test/Utilities/VisualBasic/BasicTestBase.vb index 2a3853de3b4df..f5e726f29a287 100644 --- a/src/Compilers/Test/Utilities/VisualBasic/BasicTestBase.vb +++ b/src/Compilers/Test/Utilities/VisualBasic/BasicTestBase.vb @@ -790,7 +790,7 @@ Public MustInherit Class BasicTestBaseBase #Region "IOperation tree validation" - Friend Shared Function GetOperationTreeForTest(Of TSyntaxNode As SyntaxNode)(compilation As VisualBasicCompilation, fileName As String, Optional which As Integer = 0) As (tree As String, syntax As SyntaxNode, operation As IOperation) + Friend Shared Function GetOperationTreeForTest(Of TSyntaxNode As SyntaxNode)(compilation As VisualBasicCompilation, fileName As String, useLoweredTree As Boolean, Optional which As Integer = 0) As (tree As String, syntax As SyntaxNode, operation As IOperation) Dim node As SyntaxNode = CompilationUtils.FindBindingText(Of TSyntaxNode)(compilation, fileName, which, prefixMatch:=True) If node Is Nothing Then Return Nothing @@ -798,7 +798,20 @@ Public MustInherit Class BasicTestBaseBase Dim tree = (From t In compilation.SyntaxTrees Where t.FilePath = fileName).Single() Dim semanticModel = compilation.GetSemanticModel(tree) - Dim operation = semanticModel.GetOperationInternal(node) + Dim operation As IOperation + + If useLoweredTree Then + Dim methodSymbol = DirectCast(semanticModel.GetDeclaredSymbolForNode(node), IMethodSymbol) + + If methodSymbol Is Nothing Then + Return (Nothing, Nothing, Nothing) + End If + + operation = compilation.GetLowLevelOperation(methodSymbol) + Else + operation = semanticModel.GetOperationInternal(node) + End If + If operation IsNot Nothing Then Return (OperationTreeVerifier.GetOperationTree(compilation, operation), node, operation) Else @@ -806,47 +819,47 @@ Public MustInherit Class BasicTestBaseBase End If End Function - Friend Shared Function GetOperationTreeForTest(Of TSyntaxNode As SyntaxNode)(testSrc As String, Optional compilationOptions As VisualBasicCompilationOptions = Nothing, Optional parseOptions As VisualBasicParseOptions = Nothing, Optional which As Integer = 0) As (tree As String, syntax As SyntaxNode, operation As IOperation, compilation As Compilation) + Friend Shared Function GetOperationTreeForTest(Of TSyntaxNode As SyntaxNode)(testSrc As String, useLoweredTree As Boolean, Optional compilationOptions As VisualBasicCompilationOptions = Nothing, Optional parseOptions As VisualBasicParseOptions = Nothing, Optional which As Integer = 0) As (tree As String, syntax As SyntaxNode, operation As IOperation, compilation As Compilation) Dim fileName = "a.vb" Dim syntaxTree = Parse(testSrc, fileName, parseOptions) Dim compilation = CreateCompilationWithMscorlib45AndVBRuntime({syntaxTree}, references:=DefaultVbReferences.Append({ValueTupleRef, SystemRuntimeFacadeRef}), options:=If(compilationOptions, TestOptions.ReleaseDll)) - Dim operationTree = GetOperationTreeForTest(Of TSyntaxNode)(compilation, fileName, which) + Dim operationTree = GetOperationTreeForTest(Of TSyntaxNode)(compilation, fileName, useLoweredTree, which) Return (operationTree.tree, operationTree.syntax, operationTree.operation, compilation) End Function - Friend Shared Sub VerifyOperationTreeForTest(Of TSyntaxNode As SyntaxNode)(compilation As VisualBasicCompilation, fileName As String, expectedOperationTree As String, Optional which As Integer = 0, Optional additionalOperationTreeVerifier As Action(Of IOperation, Compilation, SyntaxNode) = Nothing) - Dim operationTree = GetOperationTreeForTest(Of TSyntaxNode)(compilation, fileName, which) + Friend Shared Sub VerifyOperationTreeForTest(Of TSyntaxNode As SyntaxNode)(compilation As VisualBasicCompilation, fileName As String, expectedOperationTree As String, Optional which As Integer = 0, Optional additionalOperationTreeVerifier As Action(Of IOperation, Compilation, SyntaxNode) = Nothing, Optional useLoweredTree As Boolean = False) + Dim operationTree = GetOperationTreeForTest(Of TSyntaxNode)(compilation, fileName, useLoweredTree, which) OperationTreeVerifier.Verify(expectedOperationTree, operationTree.tree) If additionalOperationTreeVerifier IsNot Nothing Then additionalOperationTreeVerifier(operationTree.operation, compilation, operationTree.syntax) End If End Sub - Friend Shared Sub VerifyOperationTreeForTest(Of TSyntaxNode As SyntaxNode)(testSrc As String, expectedOperationTree As String, Optional compilationOptions As VisualBasicCompilationOptions = Nothing, Optional parseOptions As VisualBasicParseOptions = Nothing, Optional which As Integer = 0, Optional additionalOperationTreeVerifier As Action(Of IOperation, Compilation, SyntaxNode) = Nothing) - Dim operationTree = GetOperationTreeForTest(Of TSyntaxNode)(testSrc, compilationOptions, parseOptions, which) + Friend Shared Sub VerifyOperationTreeForTest(Of TSyntaxNode As SyntaxNode)(testSrc As String, expectedOperationTree As String, Optional compilationOptions As VisualBasicCompilationOptions = Nothing, Optional parseOptions As VisualBasicParseOptions = Nothing, Optional which As Integer = 0, Optional additionalOperationTreeVerifier As Action(Of IOperation, Compilation, SyntaxNode) = Nothing, Optional useLoweredTree As Boolean = False) + Dim operationTree = GetOperationTreeForTest(Of TSyntaxNode)(testSrc, useLoweredTree, compilationOptions, parseOptions, which) OperationTreeVerifier.Verify(expectedOperationTree, operationTree.tree) If additionalOperationTreeVerifier IsNot Nothing Then additionalOperationTreeVerifier(operationTree.operation, operationTree.compilation, operationTree.syntax) End If End Sub - Friend Shared Sub VerifyNoOperationTreeForTest(Of TSyntaxNode As SyntaxNode)(testSrc As String, Optional compilationOptions As VisualBasicCompilationOptions = Nothing, Optional parseOptions As VisualBasicParseOptions = Nothing, Optional which As Integer = 0) - Dim operationTree = GetOperationTreeForTest(Of TSyntaxNode)(testSrc, compilationOptions, parseOptions, which) + Friend Shared Sub VerifyNoOperationTreeForTest(Of TSyntaxNode As SyntaxNode)(testSrc As String, Optional compilationOptions As VisualBasicCompilationOptions = Nothing, Optional parseOptions As VisualBasicParseOptions = Nothing, Optional which As Integer = 0, Optional useLoweredTree As Boolean = False) + Dim operationTree = GetOperationTreeForTest(Of TSyntaxNode)(testSrc, useLoweredTree, compilationOptions, parseOptions, which) Assert.Null(operationTree.tree) End Sub - Friend Shared Sub VerifyOperationTreeAndDiagnosticsForTest(Of TSyntaxNode As SyntaxNode)(compilation As VisualBasicCompilation, fileName As String, expectedOperationTree As String, expectedDiagnostics As String, Optional which As Integer = 0, Optional additionalOperationTreeVerifier As Action(Of IOperation, Compilation, SyntaxNode) = Nothing) + Friend Shared Sub VerifyOperationTreeAndDiagnosticsForTest(Of TSyntaxNode As SyntaxNode)(compilation As VisualBasicCompilation, fileName As String, expectedOperationTree As String, expectedDiagnostics As String, Optional which As Integer = 0, Optional additionalOperationTreeVerifier As Action(Of IOperation, Compilation, SyntaxNode) = Nothing, Optional useLoweredTree As Boolean = False) compilation.AssertTheseDiagnostics(FilterString(expectedDiagnostics)) - VerifyOperationTreeForTest(Of TSyntaxNode)(compilation, fileName, expectedOperationTree, which, additionalOperationTreeVerifier) + VerifyOperationTreeForTest(Of TSyntaxNode)(compilation, fileName, expectedOperationTree, which, additionalOperationTreeVerifier, useLoweredTree) End Sub - Friend Shared Sub VerifyOperationTreeAndDiagnosticsForTest(Of TSyntaxNode As SyntaxNode)(testSrc As String, expectedOperationTree As String, expectedDiagnostics As String, Optional compilationOptions As VisualBasicCompilationOptions = Nothing, Optional parseOptions As VisualBasicParseOptions = Nothing, Optional which As Integer = 0, Optional additionalReferences As IEnumerable(Of MetadataReference) = Nothing, Optional additionalOperationTreeVerifier As Action(Of IOperation, Compilation, SyntaxNode) = Nothing) + Friend Shared Sub VerifyOperationTreeAndDiagnosticsForTest(Of TSyntaxNode As SyntaxNode)(testSrc As String, expectedOperationTree As String, expectedDiagnostics As String, Optional compilationOptions As VisualBasicCompilationOptions = Nothing, Optional parseOptions As VisualBasicParseOptions = Nothing, Optional which As Integer = 0, Optional additionalReferences As IEnumerable(Of MetadataReference) = Nothing, Optional additionalOperationTreeVerifier As Action(Of IOperation, Compilation, SyntaxNode) = Nothing, Optional useLoweredTree As Boolean = False) Dim fileName = "a.vb" Dim syntaxTree = Parse(testSrc, fileName, parseOptions) Dim references = DefaultVbReferences.Concat({ValueTupleRef, SystemRuntimeFacadeRef}) references = If(additionalReferences IsNot Nothing, references.Concat(additionalReferences), references) Dim compilation = CreateCompilationWithMscorlib45AndVBRuntime({syntaxTree}, references:=references, options:=If(compilationOptions, TestOptions.ReleaseDll)) - VerifyOperationTreeAndDiagnosticsForTest(Of TSyntaxNode)(compilation, fileName, expectedOperationTree, expectedDiagnostics, which, additionalOperationTreeVerifier) + VerifyOperationTreeAndDiagnosticsForTest(Of TSyntaxNode)(compilation, fileName, expectedOperationTree, expectedDiagnostics, which, additionalOperationTreeVerifier, useLoweredTree) End Sub Public Shared Function GetAssertTheseDiagnosticsString(allDiagnostics As ImmutableArray(Of Diagnostic), suppressInfos As Boolean) As String diff --git a/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb b/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb index 7a6a84386f5d1..cafc494a7b9bf 100644 --- a/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb +++ b/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb @@ -1836,6 +1836,65 @@ Namespace Microsoft.CodeAnalysis.VisualBasic #End Region +#Region "Operations" + + ''' + ''' Gets the low-level operation corresponding to the method's body. + ''' + ''' The method symbol. + ''' An optional cancellation token. + ''' The low-level operation corresponding to the method's body. + Protected Overrides Function GetLowLevelOperationCore(method As IMethodSymbol, Optional cancellationToken As CancellationToken = Nothing) As IOperation + Dim result As IOperation = Nothing + Dim vbmethod = method.EnsureVbSymbolOrNothing(Of MethodSymbol)(NameOf(method)) + + If vbmethod IsNot Nothing AndAlso vbmethod.IsFromCompilation(Me) Then + Dim body = LowerMethodBody(vbmethod) + + If body IsNot Nothing Then + Dim operationFactory = New Semantics.VisualBasicOperationFactory(Nothing) + result = operationFactory.Create(body) + End If + End If + + Return result + End Function + + Private Function LowerMethodBody(method As MethodSymbol) As BoundStatement + Dim result As BoundStatement = Nothing + Dim sourceMethod As SourceMethodSymbol = TryCast(method, SourceMethodSymbol) + + ' We don't want to support synthesized bodies + ' (Like auto-property accessors, etc.) + If sourceMethod IsNot Nothing AndAlso sourceMethod.BlockSyntax IsNot Nothing Then + Dim compilationState = New TypeCompilationState(Me, Nothing, Nothing) + Dim diagnostics = DiagnosticBag.GetInstance() + Dim body = method.GetBoundMethodBody(compilationState, diagnostics) + + If body IsNot Nothing AndAlso Not body.HasErrors AndAlso Not diagnostics.HasAnyErrors() Then + Dim sawLambdas As Boolean + + result = LocalRewriter.Rewrite( + body, + method, + compilationState, + previousSubmissionFields:=Nothing, + diagnostics:=diagnostics, + rewrittenNodes:=Nothing, + hasLambdas:=sawLambdas, + symbolsCapturedWithoutCopyCtor:=Nothing, + flags:=LocalRewriter.RewritingFlags.Default, + instrumenterOpt:=DebugInfoInjector.Singleton, + currentMethod:=Nothing) + End If + + diagnostics.Free() + End If + + Return result + End Function +#End Region + #Region "Binding" ''' diff --git a/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb b/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb index 87c6fc33cc576..4da805ab51b47 100644 --- a/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb +++ b/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb @@ -234,6 +234,21 @@ Namespace Microsoft.CodeAnalysis.Semantics Return Create(DirectCast(boundNode, BoundAnonymousTypeFieldInitializer).Value) Case BoundKind.AnonymousTypePropertyAccess Return CreateBoundAnonymousTypePropertyAccessOperation(DirectCast(boundNode, BoundAnonymousTypePropertyAccess)) + + ' To support BoundNodes after lowering phase. + Case BoundKind.SequencePoint + Return CreateBoundSequencePointOperation(DirectCast(boundNode, BoundSequencePoint)) + Case BoundKind.SequencePointWithSpan + Return CreateBoundSequencePointWithSpanOperation(DirectCast(boundNode, BoundSequencePointWithSpan)) + Case BoundKind.SequencePointExpression + Return CreateBoundSequencePointExpressionOperation(DirectCast(boundNode, BoundSequencePointExpression)) + Case BoundKind.StatementList + Return CreateBoundStatementListOperation(DirectCast(boundNode, BoundStatementList)) + Case BoundKind.ConditionalGoto + Return CreateBoundConditionalGotoOperation(DirectCast(boundNode, BoundConditionalGoto)) + Case BoundKind.Sequence + Return CreateBoundSequenceOperation(DirectCast(boundNode, BoundSequence)) + Case Else Dim constantValue = ConvertToOptional(TryCast(boundNode, BoundExpression)?.ConstantValueOpt) Dim isImplicit As Boolean = boundNode.WasCompilerGenerated @@ -990,7 +1005,7 @@ Namespace Microsoft.CodeAnalysis.Semantics Private Function CreateBoundBlockOperation(boundBlock As BoundBlock) As IBlockStatement Dim statements As Lazy(Of ImmutableArray(Of IOperation)) = New Lazy(Of ImmutableArray(Of IOperation))( Function() - Return boundBlock.Statements.Select(Function(n) Create(n)).Where(Function(s) s.Kind <> OperationKind.None).ToImmutableArray() + Return boundBlock.Statements.Select(Function(n) Create(n)).Where(Function(s) s IsNot Nothing AndAlso s.Kind <> OperationKind.None).ToImmutableArray() End Function) Dim locals As ImmutableArray(Of ILocalSymbol) = boundBlock.Locals.As(Of ILocalSymbol)() Dim syntax As SyntaxNode = boundBlock.Syntax @@ -1278,7 +1293,57 @@ Namespace Microsoft.CodeAnalysis.Semantics Dim isImplicit As Boolean = boundAnonymousTypePropertyAccess.WasCompilerGenerated Return New LazyPropertyReferenceExpression([property], instance, [property], argumentsInEvaluationOrder, _semanticModel, syntax, type, constantValue, isImplicit) End Function - End Class -End Namespace + Private Function CreateBoundSequencePointOperation(boundSequencePoint As BoundSequencePoint) As IOperation + Return Create(boundSequencePoint.StatementOpt) + End Function + + Private Function CreateBoundSequencePointWithSpanOperation(boundSequencePointWithSpan As BoundSequencePointWithSpan) As IOperation + Return Create(boundSequencePointWithSpan.StatementOpt) + End Function + + Private Function CreateBoundSequencePointExpressionOperation(boundSequencePointExpression As BoundSequencePointExpression) As IOperation + Return Create(boundSequencePointExpression.Expression) + End Function + + Private Function CreateBoundStatementListOperation(boundStatementList As BoundStatementList) As IBlockStatement + Dim statements As Lazy(Of ImmutableArray(Of IOperation)) = New Lazy(Of ImmutableArray(Of IOperation))( + Function() + Return boundStatementList.Statements.Select(Function(n) Create(n)).Where(Function(s) s IsNot Nothing).ToImmutableArray() + End Function) + + Dim locals As ImmutableArray(Of ILocalSymbol) = ImmutableArray(Of ILocalSymbol).Empty + Dim syntax As SyntaxNode = boundStatementList.Syntax + Dim type As ITypeSymbol = Nothing + Dim constantValue As [Optional](Of Object) = Nothing + Dim isImplicit As Boolean = boundStatementList.WasCompilerGenerated + Return New LazyBlockStatement(statements, locals, _semanticModel, syntax, type, constantValue, isImplicit) + End Function + + Private Function CreateBoundConditionalGotoOperation(boundConditionalGoto As BoundConditionalGoto) As IConditionalGotoStatement + Dim condition As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundConditionalGoto.Condition)) + Dim target As ILabelSymbol = boundConditionalGoto.Label + Dim jumpIfTrue As Boolean = boundConditionalGoto.JumpIfTrue + Dim syntax As SyntaxNode = boundConditionalGoto.Syntax + Dim Type As ITypeSymbol = Nothing + Dim constantValue As [Optional](Of Object) = Nothing + Dim isImplicit As Boolean = boundConditionalGoto.WasCompilerGenerated + Return New LazyConditionalGotoStatement(condition, target, jumpIfTrue, _semanticModel, syntax, Type, constantValue, isImplicit) + End Function + Private Function CreateBoundSequenceOperation(boundSequence As BoundSequence) As ISequenceExpression + Dim expressions As Lazy(Of ImmutableArray(Of IOperation)) = New Lazy(Of ImmutableArray(Of IOperation))( + Function() + Return boundSequence.SideEffects.Select(Function(n) Create(n)).Where(Function(s) s IsNot Nothing).ToImmutableArray() + End Function) + + Dim value As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundSequence.ValueOpt)) + Dim locals As ImmutableArray(Of ILocalSymbol) = boundSequence.Locals.As(Of ILocalSymbol) + Dim syntax As SyntaxNode = boundSequence.Syntax + Dim type As ITypeSymbol = Nothing + Dim constantValue As [Optional](Of Object) = Nothing + Dim isImplicit As Boolean = boundSequence.WasCompilerGenerated + Return New LazySequenceExpression(expressions, value, locals, _semanticModel, syntax, type, constantValue, isImplicit) + End Function + End Class +End Namespace diff --git a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_GetLowLevelOperation.vb b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_GetLowLevelOperation.vb new file mode 100644 index 0000000000000..5cd2bd3b7f0b6 --- /dev/null +++ b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_GetLowLevelOperation.vb @@ -0,0 +1,146 @@ +' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +Imports Microsoft.CodeAnalysis.Test.Utilities +Imports Microsoft.CodeAnalysis.VisualBasic.Syntax +Imports Roslyn.Test.Utilities + +Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics + + Partial Public Class IOperationTests + Inherits SemanticModelTestBase + + + + Public Sub GetLowLevelOperation_FromMethod() + Dim source = .Value + + Dim expectedOperationTree = .Value + + Dim expectedDiagnostics = String.Empty + + VerifyOperationTreeAndDiagnosticsForTest(Of MethodStatementSyntax)(source, expectedOperationTree, expectedDiagnostics, useLoweredTree:=True) + End Sub + + + + Public Sub GetLowLevelOperation_FromConstructor() + Dim source = .Value + + Dim expectedOperationTree = .Value + + Dim expectedDiagnostics = String.Empty + + VerifyOperationTreeAndDiagnosticsForTest(Of SubNewStatementSyntax)(source, expectedOperationTree, expectedDiagnostics, useLoweredTree:=True) + End Sub + + + + Public Sub GetLowLevelOperation_FromPropertyAccessorGet() + Dim source = .Value + + Dim expectedOperationTree = .Value + + Dim expectedDiagnostics = String.Empty + + VerifyOperationTreeAndDiagnosticsForTest(Of AccessorStatementSyntax)(source, expectedOperationTree, expectedDiagnostics, useLoweredTree:=True) + End Sub + + + + Public Sub GetLowLevelOperation_FromPropertyAccessorSet() + Dim source = .Value + + Dim expectedOperationTree = .Value + + Dim expectedDiagnostics = String.Empty + + VerifyOperationTreeAndDiagnosticsForTest(Of AccessorStatementSyntax)(source, expectedOperationTree, expectedDiagnostics, useLoweredTree:=True) + End Sub + End Class +End Namespace diff --git a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IConditionalGotoStatement.vb b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IConditionalGotoStatement.vb new file mode 100644 index 0000000000000..30da65de54f0d --- /dev/null +++ b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IConditionalGotoStatement.vb @@ -0,0 +1,331 @@ +' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +Imports Microsoft.CodeAnalysis.Test.Utilities +Imports Microsoft.CodeAnalysis.VisualBasic.Syntax +Imports Roslyn.Test.Utilities + +Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics + + Partial Public Class IOperationTests + Inherits SemanticModelTestBase + + + + Public Sub IConditionalGotoStatement_FromIf() + Dim source = .Value + + Dim expectedOperationTree = .Value + + Dim expectedDiagnostics = String.Empty + + VerifyOperationTreeAndDiagnosticsForTest(Of MethodStatementSyntax)(source, expectedOperationTree, expectedDiagnostics, useLoweredTree:=True) + End Sub + + + + Public Sub IConditionalGotoStatement_FromIfElse() + Dim source = .Value + + Dim expectedOperationTree = .Value + + Dim expectedDiagnostics = String.Empty + + VerifyOperationTreeAndDiagnosticsForTest(Of MethodStatementSyntax)(source, expectedOperationTree, expectedDiagnostics, useLoweredTree:=True) + End Sub + + + + Public Sub IConditionalGotoStatement_FromWhile() + Dim source = 0 + p = 0 + Loop + End Sub +End Class +]]>.Value + + Dim expectedOperationTree = 0') + Left: IParameterReferenceExpression: p (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'p') + Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 0) (Syntax: '0') + ILabeledStatement (Label: exit) (OperationKind.LabeledStatement) (Syntax: 'Do While p ... Loop') + Statement: null + ILabeledStatement (Label: exit) (OperationKind.LabeledStatement) (Syntax: 'End Sub') + Statement: null + IReturnStatement (OperationKind.ReturnStatement) (Syntax: 'End Sub') + ReturnedValue: null +]]>.Value + + Dim expectedDiagnostics = String.Empty + + VerifyOperationTreeAndDiagnosticsForTest(Of MethodStatementSyntax)(source, expectedOperationTree, expectedDiagnostics, useLoweredTree:=True) + End Sub + + + + Public Sub IConditionalGotoStatement_FromUntil() + Dim source = .Value + + Dim expectedOperationTree = .Value + + Dim expectedDiagnostics = String.Empty + + VerifyOperationTreeAndDiagnosticsForTest(Of MethodStatementSyntax)(source, expectedOperationTree, expectedDiagnostics, useLoweredTree:=True) + End Sub + + + + Public Sub IConditionalGotoStatement_FromDoWhile() + Dim source = 0 + End Sub +End Class +]]>.Value + + Dim expectedOperationTree = 0') + ILabeledStatement (Label: start) (OperationKind.LabeledStatement) (Syntax: 'Do') + Statement: null + IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: 'Do ... While p > 0') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'p = 0') + Expression: ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: 'p = 0') + Left: IParameterReferenceExpression: p (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'p') + Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 0) (Syntax: '0') + ILabeledStatement (Label: continue) (OperationKind.LabeledStatement) (Syntax: 'Do') + Statement: null + IConditionalGotoStatement (JumpIfTrue: True, Target: start) (OperationKind.ConditionalGotoStatement) (Syntax: 'Do') + Condition: IBinaryOperatorExpression (BinaryOperatorKind.GreaterThan, Checked) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) (Syntax: 'p > 0') + Left: IParameterReferenceExpression: p (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'p') + Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 0) (Syntax: '0') + ILabeledStatement (Label: exit) (OperationKind.LabeledStatement) (Syntax: 'Do') + Statement: null + ILabeledStatement (Label: exit) (OperationKind.LabeledStatement) (Syntax: 'End Sub') + Statement: null + IReturnStatement (OperationKind.ReturnStatement) (Syntax: 'End Sub') + ReturnedValue: null +]]>.Value + + Dim expectedDiagnostics = String.Empty + + VerifyOperationTreeAndDiagnosticsForTest(Of MethodStatementSyntax)(source, expectedOperationTree, expectedDiagnostics, useLoweredTree:=True) + End Sub + + + + Public Sub IConditionalGotoStatement_FromDoUntil() + Dim source = .Value + + Dim expectedOperationTree = .Value + + Dim expectedDiagnostics = String.Empty + + VerifyOperationTreeAndDiagnosticsForTest(Of MethodStatementSyntax)(source, expectedOperationTree, expectedDiagnostics, useLoweredTree:=True) + End Sub + + + + Public Sub IConditionalGotoStatement_FromFor() + Dim source = .Value + + Dim expectedOperationTree = As System.Int32 + Local_2: i As System.Int32 + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: '0') + Expression: ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: '0') + Left: ILocalReferenceExpression: i (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'i As Integer') + Right: ISequenceExpression (OperationKind.SequenceExpression) (Syntax: '0') + SideEffects(1): + ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: 'p') + Left: ILocalReferenceExpression: (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'p') + Right: IParameterReferenceExpression: p (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'p') + Value: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 0) (Syntax: '0') + IBranchStatement (BranchKind.GoTo, Label: PostIncrement) (OperationKind.BranchStatement) (Syntax: 'For i As In ... Next') + ILabeledStatement (Label: start) (OperationKind.LabeledStatement) (Syntax: 'For i As In ... Next') + Statement: null + IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: 'For i As In ... Next') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'p = 0') + Expression: ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: 'p = 0') + Left: IParameterReferenceExpression: p (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'p') + Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 0) (Syntax: '0') + ILabeledStatement (Label: continue) (OperationKind.LabeledStatement) (Syntax: 'For i As In ... Next') + Statement: null + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'For i As In ... Next') + Expression: ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: 'For i As In ... Next') + Left: ILocalReferenceExpression: i (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'i As Integer') + Right: IBinaryOperatorExpression (BinaryOperatorKind.Add, Checked) (OperationKind.BinaryOperatorExpression, Type: System.Int32) (Syntax: 'For i As In ... Next') + Left: ILocalReferenceExpression: i (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'i As Integer') + Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: 'For i As In ... Next') + ILabeledStatement (Label: PostIncrement) (OperationKind.LabeledStatement) (Syntax: 'For i As In ... Next') + Statement: null + IConditionalGotoStatement (JumpIfTrue: True, Target: start) (OperationKind.ConditionalGotoStatement) (Syntax: 'For i As In ... Next') + Condition: IBinaryOperatorExpression (BinaryOperatorKind.LessThanOrEqual) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) (Syntax: 'p') + Left: ILocalReferenceExpression: i (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'i As Integer') + Right: ILocalReferenceExpression: (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'p') + ILabeledStatement (Label: exit) (OperationKind.LabeledStatement) (Syntax: 'For i As In ... Next') + Statement: null + ILabeledStatement (Label: exit) (OperationKind.LabeledStatement) (Syntax: 'End Sub') + Statement: null + IReturnStatement (OperationKind.ReturnStatement) (Syntax: 'End Sub') + ReturnedValue: null +]]>.Value + + Dim expectedDiagnostics = String.Empty + + VerifyOperationTreeAndDiagnosticsForTest(Of MethodStatementSyntax)(source, expectedOperationTree, expectedDiagnostics, useLoweredTree:=True) + End Sub + End Class +End Namespace diff --git a/src/Test/Utilities/Portable/Compilation/OperationTreeVerifier.cs b/src/Test/Utilities/Portable/Compilation/OperationTreeVerifier.cs index d0929d50183f0..04fae233f2ab1 100644 --- a/src/Test/Utilities/Portable/Compilation/OperationTreeVerifier.cs +++ b/src/Test/Utilities/Portable/Compilation/OperationTreeVerifier.cs @@ -22,6 +22,7 @@ public sealed class OperationTreeVerifier : OperationWalker private readonly Compilation _compilation; private readonly IOperation _root; private readonly StringBuilder _builder; + private readonly IDictionary _labelIds; private const string indent = " "; private string _currentIndent; @@ -32,6 +33,7 @@ public OperationTreeVerifier(Compilation compilation, IOperation root, int initi _compilation = compilation; _root = root; _builder = new StringBuilder(); + _labelIds = new Dictionary(); _currentIndent = new string(' ', initialIndent); _pendingIndent = true; @@ -223,6 +225,33 @@ private void LogType(ITypeSymbol type, string header = "Type") LogString($"{header}: {typeStr}"); } + private void LogLabel(ILabelSymbol label, string header = "Label") + { + var labelStr = "null"; + + if (label != null) + { + var isKnownLabel = _labelIds.TryGetValue(label, out int labelId); + + if (!isKnownLabel) + { + labelId = _labelIds.Count; + _labelIds.Add(label, labelId); + } + + if (label.IsImplicitlyDeclared) + { + labelStr = $"label_{labelId}"; + } + else + { + labelStr = label.Name; + } + } + + LogString($"{header}: {labelStr}"); + } + private static string FormatBoolProperty(string propertyName, bool value) => $"{propertyName}: {(value ? "True" : "False")}"; #endregion @@ -308,7 +337,7 @@ internal void VisitRefKindArrayElement(RefKind element) } private void VisitArray(IEnumerable list, string header, bool logElementCount) - where T: IOperation + where T : IOperation { VisitArrayCommon(list, header, logElementCount, VisitOperationArrayElement); } @@ -474,12 +503,8 @@ public override void VisitLabeledStatement(ILabeledStatement operation) { LogString(nameof(ILabeledStatement)); - // TODO: Put a better workaround to skip compiler generated labels. - if (!operation.Label.IsImplicitlyDeclared) - { - LogString($" (Label: {operation.Label.Name})"); - } - + LogLabel(operation.Label, " (Label"); + LogString(")"); LogCommonPropertiesAndNewLine(operation); Visit(operation.Statement, "Statement"); @@ -488,9 +513,9 @@ public override void VisitLabeledStatement(ILabeledStatement operation) public override void VisitBranchStatement(IBranchStatement operation) { LogString(nameof(IBranchStatement)); - var kindStr = $"{nameof(BranchKind)}.{operation.BranchKind}"; - var labelStr = !operation.Target.IsImplicitlyDeclared ? $", Label: {operation.Target.Name}" : string.Empty; - LogString($" ({kindStr}{labelStr})"); + LogString($" ({nameof(BranchKind)}.{operation.BranchKind}, "); + LogLabel(operation.Target, "Label"); + LogString(")"); LogCommonPropertiesAndNewLine(operation); base.VisitBranchStatement(operation); @@ -1321,7 +1346,7 @@ public override void VisitIsPatternExpression(IIsPatternExpression operation) public override void VisitPatternCaseClause(IPatternCaseClause operation) { LogString(nameof(IPatternCaseClause)); - LogSymbol(operation.Label, " (Label Symbol"); + LogLabel(operation.Label, " (Label"); LogString(")"); LogCaseClauseCommon(operation); @@ -1329,6 +1354,27 @@ public override void VisitPatternCaseClause(IPatternCaseClause operation) Visit(operation.GuardExpression, "Guard Expression"); } + public override void VisitConditionalGotoStatement(IConditionalGotoStatement operation) + { + LogString(nameof(IConditionalGotoStatement)); + LogString($" (JumpIfTrue: {operation.JumpIfTrue}"); + LogLabel(operation.Target, ", Target"); + LogString(")"); + LogCommonPropertiesAndNewLine(operation); + + Visit(operation.Condition, "Condition"); + } + + public override void VisitSequenceExpression(ISequenceExpression operation) + { + LogString(nameof(ISequenceExpression)); + LogCommonPropertiesAndNewLine(operation); + + LogLocals(operation.Locals, header: "Locals"); + VisitArray(operation.SideEffects, "SideEffects", logElementCount: true); + Visit(operation.Value, "Value"); + } + #endregion } }