File: IOperation\IOperationTests_StackAllocArrayCreationAndInitializer.cs
Web Access
Project: src\src\Compilers\CSharp\Test\IOperation\Microsoft.CodeAnalysis.CSharp.IOperation.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.IOperation.UnitTests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
#nullable disable
 
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
    public class IOperationTests_StackAllocArrayCreationAndInitializer : SemanticModelTestBase
    {
        [Fact]
        public void SimpleStackAllocArrayCreation_PrimitiveType()
        {
            string source = @"
class C
{
    public void F()
    {
        var a = /*<bind>*/stackalloc int[1]/*</bind>*/;
    }
}
";
            string expectedOperationTree = @"
IOperation:  (OperationKind.None, Type: System.Int32*, IsInvalid) (Syntax: 'stackalloc int[1]')
  Children(1):
      ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
";
            var expectedDiagnostics = new DiagnosticDescription[] {
                // file.cs(6,27): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context
                //         var a = /*<bind>*/stackalloc int[1]/*</bind>*/;
                Diagnostic(ErrorCode.ERR_UnsafeNeeded, "stackalloc int[1]").WithLocation(6, 27)
            };
 
            VerifyOperationTreeAndDiagnosticsForTest<StackAllocArrayCreationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
        }
 
        [Fact]
        public void SimpleStackAllocArrayCreation_UserDefinedType()
        {
            string source = @"
struct M { }
 
class C
{
    public void F()
    {
        var a = /*<bind>*/stackalloc M[1]/*</bind>*/;
    }
}
";
            string expectedOperationTree = @"
IOperation:  (OperationKind.None, Type: M*, IsInvalid) (Syntax: 'stackalloc M[1]')
  Children(1):
      ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
";
            var expectedDiagnostics = new DiagnosticDescription[] {
                // file.cs(8,27): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context
                //         var a = /*<bind>*/stackalloc M[1]/*</bind>*/;
                Diagnostic(ErrorCode.ERR_UnsafeNeeded, "stackalloc M[1]").WithLocation(8, 27)
            };
 
            VerifyOperationTreeAndDiagnosticsForTest<StackAllocArrayCreationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
        }
 
        [Fact]
        public void SimpleStackAllocArrayCreation_ConstantDimension()
        {
            string source = @"
struct M { }
 
class C
{
    public void F()
    {
        const int dimension = 1;
        var a = /*<bind>*/stackalloc M[dimension]/*</bind>*/;
    }
}
";
            string expectedOperationTree = @"
IOperation:  (OperationKind.None, Type: M*, IsInvalid) (Syntax: 'stackalloc M[dimension]')
  Children(1):
      ILocalReferenceOperation: dimension (OperationKind.LocalReference, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: 'dimension')
";
            var expectedDiagnostics = new DiagnosticDescription[] {
                // file.cs(9,27): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context
                //         var a = /*<bind>*/stackalloc M[dimension]/*</bind>*/;
                Diagnostic(ErrorCode.ERR_UnsafeNeeded, "stackalloc M[dimension]").WithLocation(9, 27)
            };
 
            VerifyOperationTreeAndDiagnosticsForTest<StackAllocArrayCreationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
        }
 
        [Fact]
        public void SimpleStackAllocArrayCreation_NonConstantDimension()
        {
            string source = @"
struct M { }
 
class C
{
    public void F(int dimension)
    {
        var a = /*<bind>*/stackalloc M[dimension]/*</bind>*/;
    }
}
";
            string expectedOperationTree = @"
IOperation:  (OperationKind.None, Type: M*, IsInvalid) (Syntax: 'stackalloc M[dimension]')
  Children(1):
      IParameterReferenceOperation: dimension (OperationKind.ParameterReference, Type: System.Int32, IsInvalid) (Syntax: 'dimension')
";
            var expectedDiagnostics = new DiagnosticDescription[] {
                // file.cs(8,27): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context
                //         var a = /*<bind>*/stackalloc M[dimension]/*</bind>*/;
                Diagnostic(ErrorCode.ERR_UnsafeNeeded, "stackalloc M[dimension]").WithLocation(8, 27)
            };
 
            VerifyOperationTreeAndDiagnosticsForTest<StackAllocArrayCreationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
        }
 
        [Fact]
        public void SimpleStackAllocArrayCreation_DimensionWithImplicitConversion()
        {
            string source = @"
struct M { }
 
class C
{
    public void F(char dimension)
    {
        var a = /*<bind>*/stackalloc M[dimension]/*</bind>*/;
    }
}
";
            string expectedOperationTree = @"
IOperation:  (OperationKind.None, Type: M*, IsInvalid) (Syntax: 'stackalloc M[dimension]')
  Children(1):
      IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Int32, IsInvalid, IsImplicit) (Syntax: 'dimension')
        Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: True, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
        Operand: 
          IParameterReferenceOperation: dimension (OperationKind.ParameterReference, Type: System.Char, IsInvalid) (Syntax: 'dimension')
";
            var expectedDiagnostics = new DiagnosticDescription[] {
                // file.cs(8,27): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context
                //         var a = /*<bind>*/stackalloc M[dimension]/*</bind>*/;
                Diagnostic(ErrorCode.ERR_UnsafeNeeded, "stackalloc M[dimension]").WithLocation(8, 27)
            };
 
            VerifyOperationTreeAndDiagnosticsForTest<StackAllocArrayCreationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
        }
 
        [Fact]
        public void SimpleStackAllocArrayCreation_DimensionWithExplicitConversion()
        {
            string source = @"
struct M { }
 
class C
{
    public void F(object dimension)
    {
        var a = /*<bind>*/stackalloc M[(int)dimension]/*</bind>*/;
    }
}
";
            string expectedOperationTree = @"
IOperation:  (OperationKind.None, Type: M*, IsInvalid) (Syntax: 'stackalloc  ... )dimension]')
  Children(1):
      IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Int32, IsInvalid) (Syntax: '(int)dimension')
        Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
        Operand: 
          IParameterReferenceOperation: dimension (OperationKind.ParameterReference, Type: System.Object, IsInvalid) (Syntax: 'dimension')
";
            var expectedDiagnostics = new DiagnosticDescription[] {
                // file.cs(8,27): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context
                //         var a = /*<bind>*/stackalloc M[(int)dimension]/*</bind>*/;
                Diagnostic(ErrorCode.ERR_UnsafeNeeded, "stackalloc M[(int)dimension]").WithLocation(8, 27)
            };
 
            VerifyOperationTreeAndDiagnosticsForTest<StackAllocArrayCreationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
        }
 
        [Fact]
        public void StackAllocArrayCreationWithInitializer_PrimitiveType()
        {
            string source = @"
class C
{
    public void F()
    {
        var a = /*<bind>*/stackalloc int[] { 42 }/*</bind>*/;
    }
}
";
            string expectedOperationTree = @"
IOperation:  (OperationKind.None, Type: System.Int32*, IsInvalid) (Syntax: 'stackalloc int[] { 42 }')
  Children(2):
      ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid, IsImplicit) (Syntax: 'stackalloc int[] { 42 }')
      ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 42, IsInvalid) (Syntax: '42')
";
            var expectedDiagnostics = new DiagnosticDescription[] {
                // file.cs(6,27): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context
                //         var a = /*<bind>*/stackalloc int[] { 42 }/*</bind>*/;
                Diagnostic(ErrorCode.ERR_UnsafeNeeded, "stackalloc int[] { 42 }").WithLocation(6, 27)
            };
 
            VerifyOperationTreeAndDiagnosticsForTest<StackAllocArrayCreationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
        }
 
        [Fact]
        public void StackAllocArrayCreationWithInitializer_PrimitiveTypeWithExplicitDimension()
        {
            string source = @"
class C
{
    public void F()
    {
        var a = /*<bind>*/stackalloc int[1] { 42 }/*</bind>*/;
    }
}
";
            string expectedOperationTree = @"
IOperation:  (OperationKind.None, Type: System.Int32*, IsInvalid) (Syntax: 'stackalloc int[1] { 42 }')
  Children(2):
      ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
      ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 42, IsInvalid) (Syntax: '42')
";
            var expectedDiagnostics = new DiagnosticDescription[] {
                // file.cs(6,27): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context
                //         var a = /*<bind>*/stackalloc int[1] { 42 }/*</bind>*/;
                Diagnostic(ErrorCode.ERR_UnsafeNeeded, "stackalloc int[1] { 42 }").WithLocation(6, 27)
            };
 
            VerifyOperationTreeAndDiagnosticsForTest<StackAllocArrayCreationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
        }
 
        [Fact]
        public void StackAllocArrayCreationWithInitializerErrorCase_PrimitiveTypeWithIncorrectExplicitDimension()
        {
            string source = @"
class C
{
    public void F()
    {
        var a = /*<bind>*/stackalloc int[2] { 42 }/*</bind>*/;
    }
}
";
            string expectedOperationTree = @"
IOperation:  (OperationKind.None, Type: System.Int32*, IsInvalid) (Syntax: 'stackalloc int[2] { 42 }')
  Children(2):
      ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2, IsInvalid) (Syntax: '2')
      ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 42, IsInvalid) (Syntax: '42')
";
            var expectedDiagnostics = new DiagnosticDescription[] {
                // file.cs(6,27): error CS0847: An array initializer of length '2' is expected
                //         var a = /*<bind>*/stackalloc int[2] { 42 }/*</bind>*/;
                Diagnostic(ErrorCode.ERR_ArrayInitializerIncorrectLength, "stackalloc int[2] { 42 }").WithArguments("2").WithLocation(6, 27)
            };
 
            VerifyOperationTreeAndDiagnosticsForTest<StackAllocArrayCreationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
        }
 
        [Fact]
        public void StackAllocArrayCreationWithInitializerErrorCase_PrimitiveTypeWithNonConstantExplicitDimension()
        {
            string source = @"
class C
{
    public void F(int dimension)
    {
        var a = /*<bind>*/stackalloc int[dimension] { 42 }/*</bind>*/;
    }
}
";
            string expectedOperationTree = @"
IOperation:  (OperationKind.None, Type: System.Int32*, IsInvalid) (Syntax: 'stackalloc  ... ion] { 42 }')
  Children(2):
      IParameterReferenceOperation: dimension (OperationKind.ParameterReference, Type: System.Int32, IsInvalid) (Syntax: 'dimension')
      ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 42) (Syntax: '42')
";
            var expectedDiagnostics = new DiagnosticDescription[] {
                // file.cs(6,42): error CS0150: A constant value is expected
                //         var a = /*<bind>*/stackalloc int[dimension] { 42 }/*</bind>*/;
                Diagnostic(ErrorCode.ERR_ConstantExpected, "dimension").WithLocation(6, 42)
            };
 
            VerifyOperationTreeAndDiagnosticsForTest<StackAllocArrayCreationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
        }
 
        [Fact]
        public void StackAllocArrayCreationWithInitializer_UserDefinedType()
        {
            string source = @"
struct M { }
 
class C
{
    public void F()
    {
        var a = /*<bind>*/stackalloc M[] { new M() }/*</bind>*/;
    }
}
";
            string expectedOperationTree = @"
IOperation:  (OperationKind.None, Type: M*, IsInvalid) (Syntax: 'stackalloc  ... { new M() }')
  Children(2):
      ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid, IsImplicit) (Syntax: 'stackalloc  ... { new M() }')
      IObjectCreationOperation (Constructor: M..ctor()) (OperationKind.ObjectCreation, Type: M, IsInvalid) (Syntax: 'new M()')
        Arguments(0)
        Initializer: 
          null
";
            var expectedDiagnostics = new DiagnosticDescription[] {
                // file.cs(8,27): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context
                //         var a = /*<bind>*/stackalloc M[] { new M() }/*</bind>*/;
                Diagnostic(ErrorCode.ERR_UnsafeNeeded, "stackalloc M[] { new M() }").WithLocation(8, 27)
            };
 
            VerifyOperationTreeAndDiagnosticsForTest<StackAllocArrayCreationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
        }
 
        [Fact]
        public void StackAllocArrayCreationWithInitializer_ImplicitlyTyped()
        {
            string source = @"
struct M { }
 
class C
{
    public void F()
    {
        var a = /*<bind>*/stackalloc[] { new M() }/*</bind>*/;
    }
}
";
            string expectedOperationTree = @"
IOperation:  (OperationKind.None, Type: M*, IsInvalid) (Syntax: 'stackalloc[] { new M() }')
  Children(2):
      ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid, IsImplicit) (Syntax: 'stackalloc[] { new M() }')
      IObjectCreationOperation (Constructor: M..ctor()) (OperationKind.ObjectCreation, Type: M, IsInvalid) (Syntax: 'new M()')
        Arguments(0)
        Initializer: 
          null
";
            var expectedDiagnostics = new DiagnosticDescription[] {
                // file.cs(8,27): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context
                //         var a = /*<bind>*/stackalloc[] { new M() }/*</bind>*/;
                Diagnostic(ErrorCode.ERR_UnsafeNeeded, "stackalloc[] { new M() }").WithLocation(8, 27)
            };
 
            VerifyOperationTreeAndDiagnosticsForTest<ImplicitStackAllocArrayCreationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
        }
 
        [Fact]
        public void StackAllocArrayCreationWithInitializerErrorCase_ImplicitlyTypedWithoutInitializerAndDimension()
        {
            string source = @"
class C
{
    public void F(int dimension)
    {
        var x = /*<bind>*/stackalloc[]/*</bind>*/;
    }
}
";
            string expectedOperationTree = @"
IOperation:  (OperationKind.None, Type: ?*, IsInvalid) (Syntax: 'stackalloc[]/*</bind>*/')
  Children(1):
      ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0, IsInvalid, IsImplicit) (Syntax: 'stackalloc[]/*</bind>*/')
";
            var expectedDiagnostics = new DiagnosticDescription[] {
                // file.cs(6,50): error CS1514: { expected
                //         var x = /*<bind>*/stackalloc[]/*</bind>*/;
                Diagnostic(ErrorCode.ERR_LbraceExpected, ";").WithLocation(6, 50),
                // file.cs(6,50): error CS1513: } expected
                //         var x = /*<bind>*/stackalloc[]/*</bind>*/;
                Diagnostic(ErrorCode.ERR_RbraceExpected, ";").WithLocation(6, 50),
                // file.cs(6,27): error CS0826: No best type found for implicitly-typed array
                //         var x = /*<bind>*/stackalloc[]/*</bind>*/;
                Diagnostic(ErrorCode.ERR_ImplicitlyTypedArrayNoBestType, "stackalloc[]/*</bind>*/").WithLocation(6, 27)
            };
 
            VerifyOperationTreeAndDiagnosticsForTest<ImplicitStackAllocArrayCreationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
        }
 
        [Fact]
        public void StackAllocArrayCreationWithInitializerErrorCase_ImplicitlyTypedWithoutInitializer()
        {
            string source = @"
class C
{
    public void F(int dimension)
    {
        var x = /*<bind>*/stackalloc[2]/*</bind>*/;
    }
}
";
            string expectedOperationTree = @"
IOperation:  (OperationKind.None, Type: ?*, IsInvalid) (Syntax: 'stackalloc[2]/*</bind>*/')
  Children(1):
      ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0, IsInvalid, IsImplicit) (Syntax: 'stackalloc[2]/*</bind>*/')
";
            var expectedDiagnostics = new DiagnosticDescription[] {
                // file.cs(6,38): error CS8381: "Invalid rank specifier: expected ']'
                //         var x = /*<bind>*/stackalloc[2]/*</bind>*/;
                Diagnostic(ErrorCode.ERR_InvalidStackAllocArray, "2").WithLocation(6, 38),
                // file.cs(6,51): error CS1514: { expected
                //         var x = /*<bind>*/stackalloc[2]/*</bind>*/;
                Diagnostic(ErrorCode.ERR_LbraceExpected, ";").WithLocation(6, 51),
                // file.cs(6,51): error CS1513: } expected
                //         var x = /*<bind>*/stackalloc[2]/*</bind>*/;
                Diagnostic(ErrorCode.ERR_RbraceExpected, ";").WithLocation(6, 51),
                // file.cs(6,27): error CS0826: No best type found for implicitly-typed array
                //         var x = /*<bind>*/stackalloc[2]/*</bind>*/;
                Diagnostic(ErrorCode.ERR_ImplicitlyTypedArrayNoBestType, "stackalloc[2]/*</bind>*/").WithLocation(6, 27)
            };
 
            VerifyOperationTreeAndDiagnosticsForTest<ImplicitStackAllocArrayCreationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
        }
 
        [Fact]
        public void StackAllocArrayCreationWithInitializer_MultipleInitializersWithConversions()
        {
            string source = @"
class C
{
    public void F()
    {
        var a = 42;
        var b = /*<bind>*/stackalloc[] { 2, a, default }/*</bind>*/;
    }
}
";
            string expectedOperationTree = @"
IOperation:  (OperationKind.None, Type: System.Int32*, IsInvalid) (Syntax: 'stackalloc[ ... , default }')
  Children(4):
      ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 3, IsInvalid, IsImplicit) (Syntax: 'stackalloc[ ... , default }')
      ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2, IsInvalid) (Syntax: '2')
      ILocalReferenceOperation: a (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'a')
      IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Int32, Constant: 0, IsInvalid, IsImplicit) (Syntax: 'default')
        Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
        Operand: 
          IDefaultValueOperation (OperationKind.DefaultValue, Type: System.Int32, Constant: 0, IsInvalid) (Syntax: 'default')
";
            var expectedDiagnostics = new DiagnosticDescription[] {
                // file.cs(7,27): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context
                //         var b = /*<bind>*/stackalloc[] { 2, a, default }/*</bind>*/;
                Diagnostic(ErrorCode.ERR_UnsafeNeeded, "stackalloc[] { 2, a, default }").WithLocation(7, 27)
            };
 
            VerifyOperationTreeAndDiagnosticsForTest<ImplicitStackAllocArrayCreationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
        }
 
        [Fact]
        public void StackAllocArrayCreationErrorCase_MissingDimension()
        {
            string source = @"
class C
{
    public void F()
    {
        var a = /*<bind>*/stackalloc int[]/*</bind>*/;
    }
}
";
            string expectedOperationTree = @"
IOperation:  (OperationKind.None, Type: System.Int32*, IsInvalid) (Syntax: 'stackalloc int[]')
  Children(1):
      IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: '')
        Children(0)
";
            var expectedDiagnostics = new DiagnosticDescription[] {
                // file.cs(6,41): error CS1586: Array creation must have array size or array initializer
                //         var a = /*<bind>*/stackalloc int[]/*</bind>*/;
                Diagnostic(ErrorCode.ERR_MissingArraySize, "[]").WithLocation(6, 41)
            };
 
            VerifyOperationTreeAndDiagnosticsForTest<StackAllocArrayCreationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
        }
 
        [Fact]
        public void StackAllocArrayCreationErrorCase_InvalidInitializer()
        {
            string source = @"
class C
{
    public void F()
    {
        var a = /*<bind>*/stackalloc int[] { 1 }/*</bind>*/;
    }
}
";
            string expectedOperationTree = @"
IOperation:  (OperationKind.None, Type: System.Int32*, IsInvalid) (Syntax: 'stackalloc int[] { 1 }')
  Children(2):
      ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid, IsImplicit) (Syntax: 'stackalloc int[] { 1 }')
      ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
";
            var expectedDiagnostics = new DiagnosticDescription[] {
                // file.cs(6,27): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context
                //         var a = /*<bind>*/stackalloc int[] { 1 }/*</bind>*/;
                Diagnostic(ErrorCode.ERR_UnsafeNeeded, "stackalloc int[] { 1 }").WithLocation(6, 27)
            };
 
            VerifyOperationTreeAndDiagnosticsForTest<StackAllocArrayCreationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
        }
 
        [Fact]
        public void StackAllocArrayCreationErrorCase_MissingExplicitCast()
        {
            string source = @"
class C
{
    public void F(object b)
    {
        var a = /*<bind>*/stackalloc int[b]/*</bind>*/;
    }
}
";
            string expectedOperationTree = @"
IOperation:  (OperationKind.None, Type: System.Int32*, IsInvalid) (Syntax: 'stackalloc int[b]')
  Children(1):
      IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Int32, IsInvalid, IsImplicit) (Syntax: 'b')
        Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
        Operand: 
          IParameterReferenceOperation: b (OperationKind.ParameterReference, Type: System.Object, IsInvalid) (Syntax: 'b')
";
            var expectedDiagnostics = new DiagnosticDescription[] {
                // file.cs(6,42): error CS0266: Cannot implicitly convert type 'object' to 'int'. An explicit conversion exists (are you missing a cast?)
                //         var a = /*<bind>*/stackalloc int[b]/*</bind>*/;
                Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "b").WithArguments("object", "int").WithLocation(6, 42),
                // file.cs(6,27): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context
                //         var a = /*<bind>*/stackalloc int[b]/*</bind>*/;
                Diagnostic(ErrorCode.ERR_UnsafeNeeded, "stackalloc int[b]").WithLocation(6, 27)
            };
 
            VerifyOperationTreeAndDiagnosticsForTest<StackAllocArrayCreationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
        }
 
        [Fact]
        public void StackAllocArrayCreation_InvocationExpressionAsDimension()
        {
            string source = @"
class C
{
    public void F()
    {
        var a = /*<bind>*/stackalloc int[M()]/*</bind>*/;
    }
 
    public int M() => 1;
}
";
            string expectedOperationTree = @"
IOperation:  (OperationKind.None, Type: System.Int32*, IsInvalid) (Syntax: 'stackalloc int[M()]')
  Children(1):
      IInvocationOperation ( System.Int32 C.M()) (OperationKind.Invocation, Type: System.Int32, IsInvalid) (Syntax: 'M()')
        Instance Receiver: 
          IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsInvalid, IsImplicit) (Syntax: 'M')
        Arguments(0)
";
            var expectedDiagnostics = new DiagnosticDescription[] {
                // file.cs(6,27): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context
                //         var a = /*<bind>*/stackalloc int[M()]/*</bind>*/;
                Diagnostic(ErrorCode.ERR_UnsafeNeeded, "stackalloc int[M()]").WithLocation(6, 27)
            };
 
            VerifyOperationTreeAndDiagnosticsForTest<StackAllocArrayCreationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
        }
 
        [Fact]
        public void StackAllocArrayCreation_InvocationExpressionWithConversionAsDimension()
        {
            string source = @"
class C
{
    public void F()
    {
        var a = /*<bind>*/stackalloc int[(int)M()]/*</bind>*/;
    }
 
    public object M() => null;
}
";
            string expectedOperationTree = @"
IOperation:  (OperationKind.None, Type: System.Int32*, IsInvalid) (Syntax: 'stackalloc int[(int)M()]')
  Children(1):
      IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Int32, IsInvalid) (Syntax: '(int)M()')
        Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
        Operand: 
          IInvocationOperation ( System.Object C.M()) (OperationKind.Invocation, Type: System.Object, IsInvalid) (Syntax: 'M()')
            Instance Receiver: 
              IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsInvalid, IsImplicit) (Syntax: 'M')
            Arguments(0)
";
            var expectedDiagnostics = new DiagnosticDescription[] {
                // file.cs(6,27): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context
                //         var a = /*<bind>*/stackalloc int[(int)M()]/*</bind>*/;
                Diagnostic(ErrorCode.ERR_UnsafeNeeded, "stackalloc int[(int)M()]").WithLocation(6, 27)
            };
 
            VerifyOperationTreeAndDiagnosticsForTest<StackAllocArrayCreationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
        }
 
        [Fact]
        public void StackAllocArrayCreationErrorCase_InvocationExpressionAsDimension()
        {
            string source = @"
class C
{
    public static void F()
    {
        var a = /*<bind>*/stackalloc int[M()]/*</bind>*/;
    }
 
    public object M() => null;
}
";
            string expectedOperationTree = @"
    IOperation:  (OperationKind.None, Type: System.Int32*, IsInvalid) (Syntax: 'stackalloc int[M()]')
      Children(1):
          IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Int32, IsInvalid, IsImplicit) (Syntax: 'M()')
            Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
            Operand: 
              IInvalidOperation (OperationKind.Invalid, Type: System.Object, IsInvalid) (Syntax: 'M()')
                Children(0)
";
            var expectedDiagnostics = new DiagnosticDescription[] {
                // file.cs(6,42): error CS0120: An object reference is required for the non-static field, method, or property 'C.M()'
                //         var a = /*<bind>*/stackalloc int[M()]/*</bind>*/;
                Diagnostic(ErrorCode.ERR_ObjectRequired, "M").WithArguments("C.M()").WithLocation(6, 42)
            };
 
            VerifyOperationTreeAndDiagnosticsForTest<StackAllocArrayCreationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
        }
 
        [Fact]
        public void StackAllocArrayCreationErrorCase_InvocationExpressionWithConversionAsDimension()
        {
            string source = @"
class C
{
    public void F()
    {
        var a = /*<bind>*/stackalloc int[(int)M()]/*</bind>*/;
    }
 
    public C M() => new C();
}
";
            string expectedOperationTree = @"
IOperation:  (OperationKind.None, Type: System.Int32*, IsInvalid) (Syntax: 'stackalloc int[(int)M()]')
  Children(1):
      IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Int32, IsInvalid) (Syntax: '(int)M()')
        Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
        Operand: 
          IInvocationOperation ( C C.M()) (OperationKind.Invocation, Type: C, IsInvalid) (Syntax: 'M()')
            Instance Receiver: 
              IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsInvalid, IsImplicit) (Syntax: 'M')
            Arguments(0)
";
            var expectedDiagnostics = new DiagnosticDescription[] {
                // file.cs(6,42): error CS0030: Cannot convert type 'C' to 'int'
                //         var a = /*<bind>*/stackalloc int[(int)M()]/*</bind>*/;
                Diagnostic(ErrorCode.ERR_NoExplicitConv, "(int)M()").WithArguments("C", "int").WithLocation(6, 42)
            };
 
            VerifyOperationTreeAndDiagnosticsForTest<StackAllocArrayCreationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
        }
 
        [Fact]
        public void SimpleStackAllocArrayCreation_ConstantConversion()
        {
            string source = @"
class C
{
    public void F()
    {
        var a = /*<bind>*/stackalloc int[0.0]/*</bind>*/;
    }
}
";
            string expectedOperationTree = @"
IOperation:  (OperationKind.None, Type: System.Int32*, IsInvalid) (Syntax: 'stackalloc int[0.0]')
  Children(1):
      IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Int32, Constant: 0, IsInvalid, IsImplicit) (Syntax: '0.0')
        Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: True, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
        Operand: 
          ILiteralOperation (OperationKind.Literal, Type: System.Double, Constant: 0, IsInvalid) (Syntax: '0.0')
";
            var expectedDiagnostics = new DiagnosticDescription[] {
               // file.cs(6,42): error CS0266: Cannot implicitly convert type 'double' to 'int'. An explicit conversion exists (are you missing a cast?)
                //         var a = /*<bind>*/stackalloc int[0.0]/*</bind>*/;
                Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "0.0").WithArguments("double", "int").WithLocation(6, 42),
                // file.cs(6,27): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context
                //         var a = /*<bind>*/stackalloc int[0.0]/*</bind>*/;
                Diagnostic(ErrorCode.ERR_UnsafeNeeded, "stackalloc int[0.0]").WithLocation(6, 27)
            };
 
            VerifyOperationTreeAndDiagnosticsForTest<StackAllocArrayCreationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
        }
    }
}