From c0d12282be5b56bdab1942ec8b6bbbbc4636a7de Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Fri, 25 Aug 2017 11:19:12 -0700 Subject: [PATCH] Address PR feedback and add more unit tests --- .../CSharpOperationFactory_Methods.cs | 2 +- .../IOperationTests_IForEachLoopStatement.cs | 4 +- ...OperationTests_IUnaryOperatorExpression.cs | 12 +- .../Test/Semantic/Semantics/OperatorTests.cs | 454 +++++++++++++++++- .../Portable/Operations/UnaryOperatorKind.cs | 2 +- .../Core/Portable/PublicAPI.Unshipped.txt | 2 +- .../Operations/VisualBasicOperationFactory.vb | 2 +- .../VisualBasicOperationFactory_Methods.vb | 6 +- .../Semantic/IOperation/IOperationTests.vb | 4 +- ...perationTests_IBinaryOperatorExpression.vb | 211 ++++++++ .../IOperationTests_IForLoopStatement.vb | 52 +- ...OperationTests_IUnaryOperatorExpression.vb | 48 +- ...OperationTests_IWhileUntilLoopStatement.vb | 65 +-- .../Compilation/OperationTreeVerifier.cs | 15 +- .../Diagnostics/OperationTestAnalyzer.cs | 2 +- 15 files changed, 774 insertions(+), 107 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory_Methods.cs b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory_Methods.cs index 9705aee5f7a..abc64192d62 100644 --- a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory_Methods.cs +++ b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory_Methods.cs @@ -243,7 +243,7 @@ internal static UnaryOperatorKind DeriveUnaryOperatorKind(CSharp.UnaryOperatorKi return UnaryOperatorKind.Minus; case CSharp.UnaryOperatorKind.LogicalNegation: - return UnaryOperatorKind.LogicalNot; + return UnaryOperatorKind.Not; case CSharp.UnaryOperatorKind.BitwiseComplement: return UnaryOperatorKind.BitwiseNegation; diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IForEachLoopStatement.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IForEachLoopStatement.cs index f437dea21bc..6766fa61c91 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; @@ -474,7 +474,7 @@ static void Main() Variables: Local_1: System.Boolean b Initializer: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Boolean) (Syntax: '!x.Equals(null)') Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: IUnaryOperatorExpression (UnaryOperatorKind.LogicalNot) (OperationKind.UnaryOperatorExpression, Type: System.Object) (Syntax: '!x.Equals(null)') + Operand: IUnaryOperatorExpression (UnaryOperatorKind.Not) (OperationKind.UnaryOperatorExpression, Type: System.Object) (Syntax: '!x.Equals(null)') Operand: IInvocationExpression ( ? C.()) (OperationKind.InvocationExpression, Type: ?) (Syntax: 'x.Equals(null)') Instance Receiver: IOperation: (OperationKind.None) (Syntax: 'x.Equals') Arguments(1): diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IUnaryOperatorExpression.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IUnaryOperatorExpression.cs index e0acc44198f..f130a246133 100644 --- a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IUnaryOperatorExpression.cs +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IUnaryOperatorExpression.cs @@ -1357,7 +1357,7 @@ System.Boolean Method() "; string expectedOperationTree = @" -IUnaryOperatorExpression (UnaryOperatorKind.LogicalNot) (OperationKind.UnaryOperatorExpression, Type: System.Boolean) (Syntax: '!i') +IUnaryOperatorExpression (UnaryOperatorKind.Not) (OperationKind.UnaryOperatorExpression, Type: System.Boolean) (Syntax: '!i') Operand: ILocalReferenceExpression: i (OperationKind.LocalReferenceExpression, Type: System.Boolean) (Syntax: 'i') "; VerifyOperationTreeForTest(source, expectedOperationTree); @@ -1379,7 +1379,7 @@ System.Boolean Method() "; string expectedOperationTree = @" -IUnaryOperatorExpression (UnaryOperatorKind.LogicalNot) (OperationKind.UnaryOperatorExpression, Type: System.Boolean) (Syntax: '!Method()') +IUnaryOperatorExpression (UnaryOperatorKind.Not) (OperationKind.UnaryOperatorExpression, Type: System.Boolean) (Syntax: '!Method()') Operand: IInvocationExpression ( System.Boolean A.Method()) (OperationKind.InvocationExpression, Type: System.Boolean) (Syntax: 'Method()') Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: A) (Syntax: 'Method') Arguments(0) @@ -2133,7 +2133,7 @@ dynamic Method() "; string expectedOperationTree = @" -IUnaryOperatorExpression (UnaryOperatorKind.LogicalNot) (OperationKind.UnaryOperatorExpression, Type: dynamic) (Syntax: '!i') +IUnaryOperatorExpression (UnaryOperatorKind.Not) (OperationKind.UnaryOperatorExpression, Type: dynamic) (Syntax: '!i') Operand: ILocalReferenceExpression: i (OperationKind.LocalReferenceExpression, Type: dynamic) (Syntax: 'i') "; VerifyOperationTreeForTest(source, expectedOperationTree); @@ -2227,7 +2227,7 @@ dynamic Method() "; string expectedOperationTree = @" -IUnaryOperatorExpression (UnaryOperatorKind.LogicalNot) (OperationKind.UnaryOperatorExpression, Type: dynamic) (Syntax: '!Method()') +IUnaryOperatorExpression (UnaryOperatorKind.Not) (OperationKind.UnaryOperatorExpression, Type: dynamic) (Syntax: '!Method()') Operand: IInvocationExpression ( dynamic A.Method()) (OperationKind.InvocationExpression, Type: dynamic) (Syntax: 'Method()') Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: A) (Syntax: 'Method') Arguments(0) @@ -2527,7 +2527,7 @@ public struct CustomType } "; string expectedOperationTree = @" -IUnaryOperatorExpression (UnaryOperatorKind.LogicalNot) (OperatorMethod: CustomType CustomType.op_LogicalNot(CustomType x)) (OperationKind.UnaryOperatorExpression, Type: CustomType) (Syntax: '!i') +IUnaryOperatorExpression (UnaryOperatorKind.Not) (OperatorMethod: CustomType CustomType.op_LogicalNot(CustomType x)) (OperationKind.UnaryOperatorExpression, Type: CustomType) (Syntax: '!i') Operand: ILocalReferenceExpression: i (OperationKind.LocalReferenceExpression, Type: CustomType) (Syntax: 'i') "; VerifyOperationTreeForTest(source, expectedOperationTree); @@ -2693,7 +2693,7 @@ public struct CustomType } "; string expectedOperationTree = @" -IUnaryOperatorExpression (UnaryOperatorKind.LogicalNot) (OperatorMethod: CustomType CustomType.op_LogicalNot(CustomType x)) (OperationKind.UnaryOperatorExpression, Type: CustomType) (Syntax: '!Method()') +IUnaryOperatorExpression (UnaryOperatorKind.Not) (OperatorMethod: CustomType CustomType.op_LogicalNot(CustomType x)) (OperationKind.UnaryOperatorExpression, Type: CustomType) (Syntax: '!Method()') Operand: IInvocationExpression ( CustomType A.Method()) (OperationKind.InvocationExpression, Type: CustomType) (Syntax: 'Method()') Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: A) (Syntax: 'Method') Arguments(0) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/OperatorTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/OperatorTests.cs index 0df13a80e9c..7137feac218 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/OperatorTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/OperatorTests.cs @@ -695,7 +695,7 @@ static void Method(S a) IArgument (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument) (Syntax: '!a') IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Object) (Syntax: '!a') Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: IUnaryOperatorExpression (UnaryOperatorKind.LogicalNot) (OperatorMethod: S S.op_LogicalNot(S x)) (OperationKind.UnaryOperatorExpression, Type: S) (Syntax: '!a') + Operand: IUnaryOperatorExpression (UnaryOperatorKind.Not) (OperatorMethod: S S.op_LogicalNot(S x)) (OperationKind.UnaryOperatorExpression, Type: S) (Syntax: '!a') Operand: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: S) (Syntax: 'a') InConversion: null OutConversion: null @@ -708,7 +708,7 @@ static void Method(S a) Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) Operand: IUnaryOperatorExpression (UnaryOperatorKind.Plus) (OperatorMethod: S S.op_UnaryPlus(S x)) (OperationKind.UnaryOperatorExpression, Type: S) (Syntax: '+~!-a') Operand: IUnaryOperatorExpression (UnaryOperatorKind.BitwiseNegation) (OperatorMethod: S S.op_OnesComplement(S x)) (OperationKind.UnaryOperatorExpression, Type: S) (Syntax: '~!-a') - Operand: IUnaryOperatorExpression (UnaryOperatorKind.LogicalNot) (OperatorMethod: S S.op_LogicalNot(S x)) (OperationKind.UnaryOperatorExpression, Type: S) (Syntax: '!-a') + Operand: IUnaryOperatorExpression (UnaryOperatorKind.Not) (OperatorMethod: S S.op_LogicalNot(S x)) (OperationKind.UnaryOperatorExpression, Type: S) (Syntax: '!-a') Operand: IUnaryOperatorExpression (UnaryOperatorKind.Minus) (OperatorMethod: S S.op_UnaryNegation(S x)) (OperationKind.UnaryOperatorExpression, Type: S) (Syntax: '-a') Operand: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: S) (Syntax: 'a') InConversion: null @@ -802,6 +802,219 @@ static void Method(S a) VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void TestIncrementOperatorOverloading_Checked_IOperation() + { + string source = @" +using System; +struct S +{ + private string str; + public S(char chr) { this.str = chr.ToString(); } + public S(string str) { this.str = str; } + public static S operator +(S x) { return new S('(' + ('+' + x.str) + ')'); } + public static S operator -(S x) { return new S('(' + ('-' + x.str) + ')'); } + public static S operator ~(S x) { return new S('(' + ('~' + x.str) + ')'); } + public static S operator !(S x) { return new S('(' + ('!' + x.str) + ')'); } + public static S operator ++(S x) { return new S('(' + x.str + '+' + '1' + ')'); } + public static S operator --(S x) { return new S('(' + x.str + '-' + '1' + ')'); } + public override string ToString() { return this.str; } +} + +class C +{ + static void Method(S a) + /**/{ + checked + { + Console.Write(++a); + Console.Write(a++); + Console.Write(--a); + Console.Write(a--); + } + }/**/ +} +"; + string expectedOperationTree = @" +IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') + IBlockStatement (4 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'Console.Write(++a);') + Expression: IInvocationExpression (void System.Console.Write(System.Object value)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'Console.Write(++a)') + Instance Receiver: null + Arguments(1): + IArgument (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument) (Syntax: '++a') + IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Object) (Syntax: '++a') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + Operand: IIncrementExpression (PrefixIncrement) (OperatorMethod: S S.op_Increment(S x)) (OperationKind.IncrementExpression, Type: S) (Syntax: '++a') + Target: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: S) (Syntax: 'a') + InConversion: null + OutConversion: null + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'Console.Write(a++);') + Expression: IInvocationExpression (void System.Console.Write(System.Object value)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'Console.Write(a++)') + Instance Receiver: null + Arguments(1): + IArgument (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument) (Syntax: 'a++') + IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Object) (Syntax: 'a++') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + Operand: IIncrementExpression (PostfixIncrement) (OperatorMethod: S S.op_Increment(S x)) (OperationKind.IncrementExpression, Type: S) (Syntax: 'a++') + Target: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: S) (Syntax: 'a') + InConversion: null + OutConversion: null + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'Console.Write(--a);') + Expression: IInvocationExpression (void System.Console.Write(System.Object value)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'Console.Write(--a)') + Instance Receiver: null + Arguments(1): + IArgument (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument) (Syntax: '--a') + IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Object) (Syntax: '--a') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + Operand: IIncrementExpression (PrefixDecrement) (OperatorMethod: S S.op_Decrement(S x)) (OperationKind.IncrementExpression, Type: S) (Syntax: '--a') + Target: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: S) (Syntax: 'a') + InConversion: null + OutConversion: null + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'Console.Write(a--);') + Expression: IInvocationExpression (void System.Console.Write(System.Object value)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'Console.Write(a--)') + Instance Receiver: null + Arguments(1): + IArgument (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument) (Syntax: 'a--') + IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Object) (Syntax: 'a--') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + Operand: IIncrementExpression (PostfixDecrement) (OperatorMethod: S S.op_Decrement(S x)) (OperationKind.IncrementExpression, Type: S) (Syntax: 'a--') + Target: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: S) (Syntax: 'a') + InConversion: null + OutConversion: null +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void TestIncrementOperator_IOperation() + { + string source = @" +using System; +class C +{ + static void Method(int a) + /**/{ + Console.Write(++a); + Console.Write(a++); + Console.Write(--a); + Console.Write(a--); + }/**/ +} +"; + string expectedOperationTree = @" +IBlockStatement (4 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'Console.Write(++a);') + Expression: IInvocationExpression (void System.Console.Write(System.Int32 value)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'Console.Write(++a)') + Instance Receiver: null + Arguments(1): + IArgument (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument) (Syntax: '++a') + IIncrementExpression (PrefixIncrement) (OperationKind.IncrementExpression, Type: System.Int32) (Syntax: '++a') + Target: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'a') + InConversion: null + OutConversion: null + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'Console.Write(a++);') + Expression: IInvocationExpression (void System.Console.Write(System.Int32 value)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'Console.Write(a++)') + Instance Receiver: null + Arguments(1): + IArgument (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument) (Syntax: 'a++') + IIncrementExpression (PostfixIncrement) (OperationKind.IncrementExpression, Type: System.Int32) (Syntax: 'a++') + Target: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'a') + InConversion: null + OutConversion: null + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'Console.Write(--a);') + Expression: IInvocationExpression (void System.Console.Write(System.Int32 value)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'Console.Write(--a)') + Instance Receiver: null + Arguments(1): + IArgument (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument) (Syntax: '--a') + IIncrementExpression (PrefixDecrement) (OperationKind.IncrementExpression, Type: System.Int32) (Syntax: '--a') + Target: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'a') + InConversion: null + OutConversion: null + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'Console.Write(a--);') + Expression: IInvocationExpression (void System.Console.Write(System.Int32 value)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'Console.Write(a--)') + Instance Receiver: null + Arguments(1): + IArgument (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument) (Syntax: 'a--') + IIncrementExpression (PostfixDecrement) (OperationKind.IncrementExpression, Type: System.Int32) (Syntax: 'a--') + Target: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'a') + InConversion: null + OutConversion: null +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void TestIncrementOperator_Checked_IOperation() + { + string source = @" +using System; +class C +{ + static void Method(int a) + /**/{ + checked + { + Console.Write(++a); + Console.Write(a++); + Console.Write(--a); + Console.Write(a--); + } + }/**/ +} +"; + string expectedOperationTree = @" +IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') + IBlockStatement (4 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'Console.Write(++a);') + Expression: IInvocationExpression (void System.Console.Write(System.Int32 value)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'Console.Write(++a)') + Instance Receiver: null + Arguments(1): + IArgument (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument) (Syntax: '++a') + IIncrementExpression (PrefixIncrement, Checked) (OperationKind.IncrementExpression, Type: System.Int32) (Syntax: '++a') + Target: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'a') + InConversion: null + OutConversion: null + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'Console.Write(a++);') + Expression: IInvocationExpression (void System.Console.Write(System.Int32 value)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'Console.Write(a++)') + Instance Receiver: null + Arguments(1): + IArgument (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument) (Syntax: 'a++') + IIncrementExpression (PostfixIncrement, Checked) (OperationKind.IncrementExpression, Type: System.Int32) (Syntax: 'a++') + Target: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'a') + InConversion: null + OutConversion: null + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'Console.Write(--a);') + Expression: IInvocationExpression (void System.Console.Write(System.Int32 value)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'Console.Write(--a)') + Instance Receiver: null + Arguments(1): + IArgument (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument) (Syntax: '--a') + IIncrementExpression (PrefixDecrement, Checked) (OperationKind.IncrementExpression, Type: System.Int32) (Syntax: '--a') + Target: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'a') + InConversion: null + OutConversion: null + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'Console.Write(a--);') + Expression: IInvocationExpression (void System.Console.Write(System.Int32 value)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'Console.Write(a--)') + Instance Receiver: null + Arguments(1): + IArgument (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument) (Syntax: 'a--') + IIncrementExpression (PostfixDecrement, Checked) (OperationKind.IncrementExpression, Type: System.Int32) (Syntax: 'a--') + Target: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'a') + InConversion: null + OutConversion: null +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + [Fact] public void TestBinaryOperatorOverloading() { @@ -1686,6 +1899,239 @@ static void Main(S a, S b, S c, S d, S e, S f, S g, S h, S i) VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void TestUserDefinedCompoundAssignment_Checked_IOperation() + { + string source = @" +using System; +struct S +{ + private string str; + public S(char chr) { this.str = chr.ToString(); } + public S(string str) { this.str = str; } + public static S operator +(S x, S y) { return new S('(' + x.str + '+' + y.str + ')'); } + public static S operator -(S x, S y) { return new S('(' + x.str + '-' + y.str + ')'); } + public static S operator %(S x, S y) { return new S('(' + x.str + '%' + y.str + ')'); } + public static S operator /(S x, S y) { return new S('(' + x.str + '/' + y.str + ')'); } + public static S operator *(S x, S y) { return new S('(' + x.str + '*' + y.str + ')'); } + public static S operator &(S x, S y) { return new S('(' + x.str + '&' + y.str + ')'); } + public static S operator |(S x, S y) { return new S('(' + x.str + '|' + y.str + ')'); } + public static S operator ^(S x, S y) { return new S('(' + x.str + '^' + y.str + ')'); } + public static S operator <<(S x, int y) { return new S('(' + x.str + '<' + '<' + y.ToString() + ')'); } + public static S operator >>(S x, int y) { return new S('(' + x.str + '>' + '>' + y.ToString() + ')'); } + public override string ToString() { return this.str; } +} + +class C +{ + static void Main(S a, S b, S c, S d, S e, S f, S g, S h, S i) + /**/{ + a += b; + a -= c; + a *= d; + a /= e; + a %= f; + a <<= 10; + a >>= 20; + a &= g; + a |= h; + a ^= i; + }/**/ +} +"; + string expectedOperationTree = @" +IBlockStatement (10 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a += b;') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.Add) (OperatorMethod: S S.op_Addition(S x, S y)) (OperationKind.CompoundAssignmentExpression, Type: S) (Syntax: 'a += b') + Left: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: S) (Syntax: 'a') + Right: IParameterReferenceExpression: b (OperationKind.ParameterReferenceExpression, Type: S) (Syntax: 'b') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a -= c;') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.Subtract) (OperatorMethod: S S.op_Subtraction(S x, S y)) (OperationKind.CompoundAssignmentExpression, Type: S) (Syntax: 'a -= c') + Left: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: S) (Syntax: 'a') + Right: IParameterReferenceExpression: c (OperationKind.ParameterReferenceExpression, Type: S) (Syntax: 'c') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a *= d;') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.Multiply) (OperatorMethod: S S.op_Multiply(S x, S y)) (OperationKind.CompoundAssignmentExpression, Type: S) (Syntax: 'a *= d') + Left: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: S) (Syntax: 'a') + Right: IParameterReferenceExpression: d (OperationKind.ParameterReferenceExpression, Type: S) (Syntax: 'd') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a /= e;') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.Divide) (OperatorMethod: S S.op_Division(S x, S y)) (OperationKind.CompoundAssignmentExpression, Type: S) (Syntax: 'a /= e') + Left: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: S) (Syntax: 'a') + Right: IParameterReferenceExpression: e (OperationKind.ParameterReferenceExpression, Type: S) (Syntax: 'e') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a %= f;') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.Remainder) (OperatorMethod: S S.op_Modulus(S x, S y)) (OperationKind.CompoundAssignmentExpression, Type: S) (Syntax: 'a %= f') + Left: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: S) (Syntax: 'a') + Right: IParameterReferenceExpression: f (OperationKind.ParameterReferenceExpression, Type: S) (Syntax: 'f') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a <<= 10;') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.LeftShift) (OperatorMethod: S S.op_LeftShift(S x, System.Int32 y)) (OperationKind.CompoundAssignmentExpression, Type: S) (Syntax: 'a <<= 10') + Left: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: S) (Syntax: 'a') + Right: ILiteralExpression (Text: 10) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 10) (Syntax: '10') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a >>= 20;') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.RightShift) (OperatorMethod: S S.op_RightShift(S x, System.Int32 y)) (OperationKind.CompoundAssignmentExpression, Type: S) (Syntax: 'a >>= 20') + Left: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: S) (Syntax: 'a') + Right: ILiteralExpression (Text: 20) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 20) (Syntax: '20') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a &= g;') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.And) (OperatorMethod: S S.op_BitwiseAnd(S x, S y)) (OperationKind.CompoundAssignmentExpression, Type: S) (Syntax: 'a &= g') + Left: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: S) (Syntax: 'a') + Right: IParameterReferenceExpression: g (OperationKind.ParameterReferenceExpression, Type: S) (Syntax: 'g') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a |= h;') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.Or) (OperatorMethod: S S.op_BitwiseOr(S x, S y)) (OperationKind.CompoundAssignmentExpression, Type: S) (Syntax: 'a |= h') + Left: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: S) (Syntax: 'a') + Right: IParameterReferenceExpression: h (OperationKind.ParameterReferenceExpression, Type: S) (Syntax: 'h') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a ^= i;') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.ExclusiveOr) (OperatorMethod: S S.op_ExclusiveOr(S x, S y)) (OperationKind.CompoundAssignmentExpression, Type: S) (Syntax: 'a ^= i') + Left: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: S) (Syntax: 'a') + Right: IParameterReferenceExpression: i (OperationKind.ParameterReferenceExpression, Type: S) (Syntax: 'i') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void TestCompoundAssignment_IOperation() + { + string source = @" +class C +{ + static void M(int a, int b, int c, int d, int e, int f, int g, int h, int i) + /**/{ + a += b; + a -= c; + a *= d; + a /= e; + a %= f; + a <<= 10; + a >>= 20; + a &= g; + a |= h; + a ^= i; + }/**/ +} +"; + string expectedOperationTree = @" +IBlockStatement (10 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a += b;') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.Add) (OperationKind.CompoundAssignmentExpression, Type: System.Int32) (Syntax: 'a += b') + Left: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'a') + Right: IParameterReferenceExpression: b (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'b') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a -= c;') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.Subtract) (OperationKind.CompoundAssignmentExpression, Type: System.Int32) (Syntax: 'a -= c') + Left: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'a') + Right: IParameterReferenceExpression: c (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'c') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a *= d;') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.Multiply) (OperationKind.CompoundAssignmentExpression, Type: System.Int32) (Syntax: 'a *= d') + Left: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'a') + Right: IParameterReferenceExpression: d (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'd') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a /= e;') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.Divide) (OperationKind.CompoundAssignmentExpression, Type: System.Int32) (Syntax: 'a /= e') + Left: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'a') + Right: IParameterReferenceExpression: e (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'e') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a %= f;') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.Remainder) (OperationKind.CompoundAssignmentExpression, Type: System.Int32) (Syntax: 'a %= f') + Left: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'a') + Right: IParameterReferenceExpression: f (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'f') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a <<= 10;') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.LeftShift) (OperationKind.CompoundAssignmentExpression, Type: System.Int32) (Syntax: 'a <<= 10') + Left: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'a') + Right: ILiteralExpression (Text: 10) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 10) (Syntax: '10') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a >>= 20;') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.RightShift) (OperationKind.CompoundAssignmentExpression, Type: System.Int32) (Syntax: 'a >>= 20') + Left: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'a') + Right: ILiteralExpression (Text: 20) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 20) (Syntax: '20') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a &= g;') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.And) (OperationKind.CompoundAssignmentExpression, Type: System.Int32) (Syntax: 'a &= g') + Left: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'a') + Right: IParameterReferenceExpression: g (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'g') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a |= h;') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.Or) (OperationKind.CompoundAssignmentExpression, Type: System.Int32) (Syntax: 'a |= h') + Left: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'a') + Right: IParameterReferenceExpression: h (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'h') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a ^= i;') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.ExclusiveOr) (OperationKind.CompoundAssignmentExpression, Type: System.Int32) (Syntax: 'a ^= i') + Left: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'a') + Right: IParameterReferenceExpression: i (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'i') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void TestCompoundAssignment_Checked_IOperation() + { + string source = @" +class C +{ + static void M(int a, int b, int c, int d, int e, int f, int g, int h, int i) + /**/{ + checked + { + a += b; + a -= c; + a *= d; + a /= e; + a %= f; + a <<= 10; + a >>= 20; + a &= g; + a |= h; + a ^= i; + } + }/**/ +} +"; + string expectedOperationTree = @" +IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') + IBlockStatement (10 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a += b;') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignmentExpression, Type: System.Int32) (Syntax: 'a += b') + Left: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'a') + Right: IParameterReferenceExpression: b (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'b') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a -= c;') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.Subtract, Checked) (OperationKind.CompoundAssignmentExpression, Type: System.Int32) (Syntax: 'a -= c') + Left: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'a') + Right: IParameterReferenceExpression: c (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'c') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a *= d;') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.Multiply, Checked) (OperationKind.CompoundAssignmentExpression, Type: System.Int32) (Syntax: 'a *= d') + Left: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'a') + Right: IParameterReferenceExpression: d (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'd') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a /= e;') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.Divide, Checked) (OperationKind.CompoundAssignmentExpression, Type: System.Int32) (Syntax: 'a /= e') + Left: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'a') + Right: IParameterReferenceExpression: e (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'e') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a %= f;') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.Remainder) (OperationKind.CompoundAssignmentExpression, Type: System.Int32) (Syntax: 'a %= f') + Left: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'a') + Right: IParameterReferenceExpression: f (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'f') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a <<= 10;') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.LeftShift) (OperationKind.CompoundAssignmentExpression, Type: System.Int32) (Syntax: 'a <<= 10') + Left: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'a') + Right: ILiteralExpression (Text: 10) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 10) (Syntax: '10') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a >>= 20;') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.RightShift) (OperationKind.CompoundAssignmentExpression, Type: System.Int32) (Syntax: 'a >>= 20') + Left: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'a') + Right: ILiteralExpression (Text: 20) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 20) (Syntax: '20') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a &= g;') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.And) (OperationKind.CompoundAssignmentExpression, Type: System.Int32) (Syntax: 'a &= g') + Left: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'a') + Right: IParameterReferenceExpression: g (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'g') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a |= h;') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.Or) (OperationKind.CompoundAssignmentExpression, Type: System.Int32) (Syntax: 'a |= h') + Left: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'a') + Right: IParameterReferenceExpression: h (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'h') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a ^= i;') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.ExclusiveOr) (OperationKind.CompoundAssignmentExpression, Type: System.Int32) (Syntax: 'a ^= i') + Left: IParameterReferenceExpression: a (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'a') + Right: IParameterReferenceExpression: i (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'i') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + [Fact] public void TestUserDefinedBinaryOperatorOverloadResolution() { @@ -1871,12 +2317,12 @@ static void M(S s1, S? s2, int i1, int? i2) IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'i1 = !s1;') Expression: ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: 'i1 = !s1') Left: IParameterReferenceExpression: i1 (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'i1') - Right: IUnaryOperatorExpression (UnaryOperatorKind.LogicalNot) (OperatorMethod: System.Int32 S.op_LogicalNot(S s)) (OperationKind.UnaryOperatorExpression, Type: System.Int32) (Syntax: '!s1') + Right: IUnaryOperatorExpression (UnaryOperatorKind.Not) (OperatorMethod: System.Int32 S.op_LogicalNot(S s)) (OperationKind.UnaryOperatorExpression, Type: System.Int32) (Syntax: '!s1') Operand: IParameterReferenceExpression: s1 (OperationKind.ParameterReferenceExpression, Type: S) (Syntax: 's1') IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'i2 = !s2;') Expression: ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32?) (Syntax: 'i2 = !s2') Left: IParameterReferenceExpression: i2 (OperationKind.ParameterReferenceExpression, Type: System.Int32?) (Syntax: 'i2') - Right: IUnaryOperatorExpression (UnaryOperatorKind.LogicalNot, IsLifted) (OperatorMethod: System.Int32 S.op_LogicalNot(S s)) (OperationKind.UnaryOperatorExpression, Type: System.Int32?) (Syntax: '!s2') + Right: IUnaryOperatorExpression (UnaryOperatorKind.Not, IsLifted) (OperatorMethod: System.Int32 S.op_LogicalNot(S s)) (OperationKind.UnaryOperatorExpression, Type: System.Int32?) (Syntax: '!s2') Operand: IParameterReferenceExpression: s2 (OperationKind.ParameterReferenceExpression, Type: S?) (Syntax: 's2') IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'i1 = ~s1;') Expression: ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: 'i1 = ~s1') diff --git a/src/Compilers/Core/Portable/Operations/UnaryOperatorKind.cs b/src/Compilers/Core/Portable/Operations/UnaryOperatorKind.cs index fc19373156b..b26b2efb061 100644 --- a/src/Compilers/Core/Portable/Operations/UnaryOperatorKind.cs +++ b/src/Compilers/Core/Portable/Operations/UnaryOperatorKind.cs @@ -17,7 +17,7 @@ public enum UnaryOperatorKind /// /// Represents the C# '!' operator and VB 'Not' operator. /// - LogicalNot = 0x2, + Not = 0x2, /// /// Represents the unary '+' operator. diff --git a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt index e224b4c9696..39a94779b20 100644 --- a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt @@ -484,7 +484,7 @@ 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.LogicalNot = 2 -> 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.Plus = 3 -> Microsoft.CodeAnalysis.Semantics.UnaryOperatorKind diff --git a/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb b/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb index 056a0423c04..21b8689d167 100644 --- a/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb +++ b/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb @@ -275,7 +275,7 @@ Namespace Microsoft.CodeAnalysis.Semantics Dim type As ITypeSymbol = boundAssignmentOperator.Type Dim constantValue As [Optional](Of Object) = ConvertToOptional(boundAssignmentOperator.ConstantValueOpt) Dim isLifted As Boolean = boundAssignmentOperator.Type.IsNullableType() - Dim isChecked As Boolean = False + Dim isChecked As Boolean = temporaryRight.IsChecked Return New LazyCompoundAssignmentExpression(operatorKind, isLifted, isChecked, target, value, usesOperatorMethod, operatorMethod, _semanticModel, syntax, type, constantValue, isImplicit) Else Dim target As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundAssignmentOperator.Left)) diff --git a/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory_Methods.vb b/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory_Methods.vb index ad7a1ecd9fd..58d0480802c 100644 --- a/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory_Methods.vb +++ b/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory_Methods.vb @@ -456,7 +456,7 @@ Namespace Microsoft.CodeAnalysis.Semantics Case VisualBasic.UnaryOperatorKind.Minus Return UnaryOperatorKind.Minus Case VisualBasic.UnaryOperatorKind.Not - Return UnaryOperatorKind.LogicalNot + Return UnaryOperatorKind.Not Case VisualBasic.UnaryOperatorKind.IsTrue Return UnaryOperatorKind.True Case VisualBasic.UnaryOperatorKind.IsFalse @@ -499,9 +499,9 @@ Namespace Microsoft.CodeAnalysis.Semantics Case VisualBasic.BinaryOperatorKind.LessThanOrEqual Return BinaryOperatorKind.LessThanOrEqual Case VisualBasic.BinaryOperatorKind.Equals - Return If(leftOpt?.Type.SpecialType = SpecialType.System_Object, BinaryOperatorKind.ObjectValueEquals, BinaryOperatorKind.Equals) + Return If(leftOpt?.Type?.SpecialType = SpecialType.System_Object, BinaryOperatorKind.ObjectValueEquals, BinaryOperatorKind.Equals) Case VisualBasic.BinaryOperatorKind.NotEquals - Return If(leftOpt?.Type.SpecialType = SpecialType.System_Object, BinaryOperatorKind.ObjectValueNotEquals, BinaryOperatorKind.NotEquals) + Return If(leftOpt?.Type?.SpecialType = SpecialType.System_Object, BinaryOperatorKind.ObjectValueNotEquals, BinaryOperatorKind.NotEquals) Case VisualBasic.BinaryOperatorKind.Is Return BinaryOperatorKind.Equals Case VisualBasic.BinaryOperatorKind.IsNot diff --git a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests.vb b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests.vb index df8ce79d618..de9f1047287 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests.vb @@ -188,7 +188,7 @@ End Module comp.VerifyOperationTree(nodes(0), expectedOperationTree:=" IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'x += y') - Expression: ICompoundAssignmentExpression (BinaryOperatorKind.Add) (OperationKind.CompoundAssignmentExpression, Type: System.Int32) (Syntax: 'x += y') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignmentExpression, Type: System.Int32) (Syntax: 'x += y') Left: ILocalReferenceExpression: x (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'x') Right: ILocalReferenceExpression: y (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'y') ") @@ -214,7 +214,7 @@ IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'x += y') comp.VerifyOperationTree(nodes(1), expectedOperationTree:=" IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a += b') - Expression: ICompoundAssignmentExpression (BinaryOperatorKind.Add) (OperatorMethod: Function B2.op_Addition(x As B2, y As B2) As B2) (OperationKind.CompoundAssignmentExpression, Type: B2) (Syntax: 'a += b') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.Add, Checked) (OperatorMethod: Function B2.op_Addition(x As B2, y As B2) As B2) (OperationKind.CompoundAssignmentExpression, Type: B2) (Syntax: 'a += b') Left: ILocalReferenceExpression: a (OperationKind.LocalReferenceExpression, Type: B2) (Syntax: 'a') Right: ILocalReferenceExpression: b (OperationKind.LocalReferenceExpression, Type: B2) (Syntax: 'b') ") diff --git a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IBinaryOperatorExpression.vb b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IBinaryOperatorExpression.vb index d3d90ab7d5b..503928c844c 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IBinaryOperatorExpression.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IBinaryOperatorExpression.vb @@ -790,6 +790,217 @@ IBlockStatement (10 statements) (OperationKind.BlockStatement) (Syntax: 'Sub M(x VerifyOperationTreeAndDiagnosticsForTest(Of MethodBlockSyntax)(source, expectedOperationTree, expectedDiagnostics) End Sub + + + Public Sub TestBinaryCompoundOperators() + Dim source = >= 3 + End Sub +End Module]]>.Value + + ' We don't seem to be detecting "x ^= y" and "x &= y" as compound operator expressions. + ' See https://github.com/dotnet/roslyn/issues/21738 + Dim expectedOperationTree = >= 3') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.RightShift, Checked) (OperationKind.CompoundAssignmentExpression, Type: System.Int32) (Syntax: 'x >>= 3') + Left: ILocalReferenceExpression: x (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'x') + Right: ILiteralExpression (Text: 3) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 3) (Syntax: '3') + ILabelStatement (Label: exit) (OperationKind.LabelStatement) (Syntax: 'End Sub') + LabeledStatement: null + IReturnStatement (OperationKind.ReturnStatement) (Syntax: 'End Sub') + ReturnedValue: null +]]>.Value + + Dim expectedDiagnostics = String.Empty + + VerifyOperationTreeAndDiagnosticsForTest(Of MethodBlockSyntax)(source, expectedOperationTree, expectedDiagnostics) + End Sub + + + + Public Sub TestBinaryCompoundOperators_Unchecked() + Dim source = >= 3 + End Sub +End Module]]>.Value + + Dim expectedOperationTree = >= 3') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.RightShift) (OperationKind.CompoundAssignmentExpression, Type: System.Int32) (Syntax: 'x >>= 3') + Left: ILocalReferenceExpression: x (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'x') + Right: ILiteralExpression (Text: 3) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 3) (Syntax: '3') + ILabelStatement (Label: exit) (OperationKind.LabelStatement) (Syntax: 'End Sub') + LabeledStatement: null + IReturnStatement (OperationKind.ReturnStatement) (Syntax: 'End Sub') + ReturnedValue: null +]]>.Value + + Dim expectedDiagnostics = String.Empty + + Dim fileName = "a.vb" + Dim syntaxTree = Parse(source, fileName) + Dim references = DefaultVbReferences.Concat({ValueTupleRef, SystemRuntimeFacadeRef}) + Dim compilation = CreateCompilationWithMscorlib45AndVBRuntime({syntaxTree}, references:=references, options:=TestOptions.ReleaseDll.WithOverflowChecks(False)) + + VerifyOperationTreeAndDiagnosticsForTest(Of MethodBlockSyntax)(compilation, fileName, expectedOperationTree, expectedDiagnostics) + End Sub + Public Sub TestUserDefinedBinaryOperators() diff --git a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IForLoopStatement.vb b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IForLoopStatement.vb index e817cf052b9..2f49bccbf45 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IForLoopStatement.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IForLoopStatement.vb @@ -23,7 +23,7 @@ Public Class MyClass1 End Class ]]>.Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = .Value Dim expectedOperationTree = .Value @@ -464,7 +464,7 @@ End Class ]]>.Value Dim expectedOperationTree = .Value @@ -485,7 +485,7 @@ End Class ]]>.Value Dim expectedOperationTree = .Value @@ -506,7 +506,7 @@ End Class ]]>.Value Dim expectedOperationTree = .Value @@ -527,7 +527,7 @@ End Class ]]>.Value Dim expectedOperationTree = .Value @@ -548,7 +548,7 @@ End Class ]]>.Value Dim expectedOperationTree = .Value @@ -569,7 +569,7 @@ End Class ]]>.Value Dim expectedOperationTree = .Value @@ -590,7 +590,7 @@ End Class ]]>.Value Dim expectedOperationTree = .Value @@ -611,7 +611,7 @@ End Class ]]>.Value Dim expectedOperationTree = .Value @@ -632,7 +632,7 @@ End Class ]]>.Value Dim expectedOperationTree = .Value @@ -1113,7 +1113,7 @@ End Class ]]>.Value Dim expectedOperationTree = .Value Dim expectedOperationTree = .Value Dim expectedOperationTree = .Value Dim expectedOperationTree = .Value Dim expectedOperationTree = .Value Dim expectedOperationTree = .Value Dim expectedOperationTree = .Value Dim expectedOperationTree = .Value Dim expectedOperationTree = .Value Dim expectedOperationTree = .Value Dim expectedOperationTree = .Value @@ -1486,7 +1486,7 @@ End Enum ]]>.Value Dim expectedOperationTree = .Value Dim expectedOperationTree = .Value @@ -1702,7 +1702,7 @@ End CLass ]]>.Value Dim expectedOperationTree = .Value -Dim expectedOperationTree = .Value @@ -69,7 +69,7 @@ Class Program End Class ]]>.Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = .Value @@ -157,7 +157,7 @@ Class Program End Class ]]>.Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = = 0') Left: IParenthesizedExpression (OperationKind.ParenthesizedExpression, Type: System.Int32) (Syntax: '(InlineAssi ... (i, value))') @@ -318,9 +318,10 @@ IWhileUntilLoopStatement (IsTopTest: True, IsWhile: True) (LoopKind.WhileUntil) InConversion: null OutConversion: null IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'value -= 1') - Expression: ICompoundAssignmentExpression (BinaryOperatorKind.Subtract) (OperationKind.CompoundAssignmentExpression, Type: System.Int32) (Syntax: 'value -= 1') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.Subtract, Checked) (OperationKind.CompoundAssignmentExpression, Type: System.Int32) (Syntax: 'value -= 1') Left: ILocalReferenceExpression: value (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'value') - Right: ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1')]]>.Value + Right: ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') +]]>.Value VerifyOperationTreeForTest(Of WhileBlockSyntax)(source, expectedOperationTree) End Sub @@ -369,7 +370,7 @@ Class Program End Class ]]>.Value -Dim expectedOperationTree = .Value @@ -414,7 +415,7 @@ Even: End Class ]]>.Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = - Public Sub IWhileUntilLoopStatement_WhileConditionInVocationExpression() + Public Sub IWhileUntilLoopStatement_WhileConditionInvocationExpression() Dim source = .Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = 0 ... End While') Condition: IBinaryOperatorExpression (BinaryOperatorKind.GreaterThan, Checked) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) (Syntax: 'i > 0') Left: ILocalReferenceExpression: i (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'i') Right: ILiteralExpression (Text: 0) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 0) (Syntax: '0') Body: IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: 'While i > 0 ... End While') IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'i += 1') - Expression: ICompoundAssignmentExpression (BinaryOperatorKind.Add) (OperationKind.CompoundAssignmentExpression, Type: System.Int32) (Syntax: 'i += 1') + Expression: ICompoundAssignmentExpression (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignmentExpression, Type: System.Int32) (Syntax: 'i += 1') Left: ILocalReferenceExpression: i (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'i') Right: ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') ]]>.Value @@ -834,7 +835,7 @@ Class Program End Class ]]>.Value -Dim expectedOperationTree = .Value -Dim expectedOperationTree = 0') Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) @@ -1006,7 +1007,7 @@ End Module Dim expectedOperationTree =