File: IOperation\IOperationTests_IConstructorBodyOperation.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 System.Linq;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
    [CompilerTrait(CompilerFeature.IOperation)]
    public class IOperationTests_IConstructorBodyOperation : SemanticModelTestBase
    {
        [Fact]
        public void ConstructorBody_01()
        {
            string source = @"
class C
{
    public C()
}
";
            var compilation = CreateCompilation(source);
 
            compilation.VerifyDiagnostics(
                // file.cs(4,15): error CS1002: ; expected
                //     public C()
                Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(4, 15),
                // file.cs(4,12): error CS0501: 'C.C()' must declare a body because it is not marked abstract, extern, or partial
                //     public C()
                Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "C").WithArguments("C.C()").WithLocation(4, 12)
                );
 
            var tree = compilation.SyntaxTrees.Single();
            var model = compilation.GetSemanticModel(tree);
 
            var node1 = tree.GetRoot().DescendantNodes().OfType<ConstructorDeclarationSyntax>().Single();
            Assert.Null(model.GetOperation(node1));
        }
 
        [CompilerTrait(CompilerFeature.Dataflow)]
        [Fact]
        public void ConstructorBody_02()
        {
            // No body, initializer without declarations
            string source = @"
class C
{
    public C() : base()
}
";
            var compilation = CreateCompilation(source);
 
            compilation.VerifyDiagnostics(
                // (4,24): error CS1002: ; expected
                //     public C() : base()
                Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(4, 24),
                // (4,12): error CS0501: 'C.C()' must declare a body because it is not marked abstract, extern, or partial
                //     public C() : base()
                Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "C").WithArguments("C.C()").WithLocation(4, 12)
                );
 
            var tree = compilation.SyntaxTrees.Single();
            var node1 = tree.GetRoot().DescendantNodes().OfType<ConstructorDeclarationSyntax>().Single();
 
            compilation.VerifyOperationTree(node1, expectedOperationTree:
@"
IConstructorBodyOperation (OperationKind.ConstructorBody, Type: null, IsInvalid) (Syntax: 'public C() : base()')
  Initializer: 
    IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid, IsImplicit) (Syntax: ': base()')
      Expression: 
        IInvocationOperation ( System.Object..ctor()) (OperationKind.Invocation, Type: System.Void, IsInvalid) (Syntax: ': base()')
          Instance Receiver: 
            IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: System.Object, IsInvalid, IsImplicit) (Syntax: ': base()')
          Arguments(0)
  BlockBody: 
    null
  ExpressionBody: 
    null
");
            VerifyFlowGraph(compilation, node1, expectedFlowGraph:
@"
Block[B0] - Entry
    Statements (0)
    Next (Regular) Block[B1]
Block[B1] - Block
    Predecessors: [B0]
    Statements (1)
        IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid, IsImplicit) (Syntax: ': base()')
          Expression: 
            IInvocationOperation ( System.Object..ctor()) (OperationKind.Invocation, Type: System.Void, IsInvalid) (Syntax: ': base()')
              Instance Receiver: 
                IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: System.Object, IsInvalid, IsImplicit) (Syntax: ': base()')
              Arguments(0)
 
    Next (Regular) Block[B2]
Block[B2] - Exit
    Predecessors: [B1]
    Statements (0)
");
        }
 
        [CompilerTrait(CompilerFeature.Dataflow)]
        [Fact]
        public void ConstructorBody_03()
        {
            // Block body, initializer without declarations
            string source = @"
class C
{
    public C() : base()
    { throw null; }
}
";
            var compilation = CreateCompilation(source);
 
            compilation.VerifyDiagnostics();
 
            var tree = compilation.SyntaxTrees.Single();
            var node1 = tree.GetRoot().DescendantNodes().OfType<ConstructorDeclarationSyntax>().Single();
 
            compilation.VerifyOperationTree(node1, expectedOperationTree:
@"
    IConstructorBodyOperation (OperationKind.ConstructorBody, Type: null) (Syntax: 'public C()  ... row null; }')
      Initializer: 
        IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: ': base()')
          Expression: 
            IInvocationOperation ( System.Object..ctor()) (OperationKind.Invocation, Type: System.Void) (Syntax: ': base()')
              Instance Receiver: 
                IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: System.Object, IsImplicit) (Syntax: ': base()')
              Arguments(0)
      BlockBody: 
        IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ throw null; }')
          IThrowOperation (OperationKind.Throw, Type: null) (Syntax: 'throw null;')
            IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Exception, Constant: null, IsImplicit) (Syntax: 'null')
              Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null)
              Operand: 
                ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'null')
      ExpressionBody: 
        null
");
 
            VerifyFlowGraph(compilation, node1, expectedFlowGraph:
@"
    Block[B0] - Entry
        Statements (0)
        Next (Regular) Block[B1]
    Block[B1] - Block
        Predecessors: [B0]
        Statements (1)
            IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: ': base()')
              Expression: 
                IInvocationOperation ( System.Object..ctor()) (OperationKind.Invocation, Type: System.Void) (Syntax: ': base()')
                  Instance Receiver: 
                    IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: System.Object, IsImplicit) (Syntax: ': base()')
                  Arguments(0)
        Next (Throw) Block[null]
            IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Exception, Constant: null, IsImplicit) (Syntax: 'null')
              Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null)
                (ImplicitReference)
              Operand: 
                ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'null')
    Block[B2] - Exit [UnReachable]
        Predecessors (0)
        Statements (0)
");
        }
 
        [CompilerTrait(CompilerFeature.Dataflow)]
        [Fact]
        public void ConstructorBody_04()
        {
            // Expression body, initializer without declarations
            string source = @"
class C
{
    public C() : base()
    => throw null;
}
";
            var compilation = CreateCompilation(source);
 
            compilation.VerifyDiagnostics();
 
            var tree = compilation.SyntaxTrees.Single();
            var node1 = tree.GetRoot().DescendantNodes().OfType<ConstructorDeclarationSyntax>().Single();
 
            compilation.VerifyOperationTree(node1, expectedOperationTree:
@"
    IConstructorBodyOperation (OperationKind.ConstructorBody, Type: null) (Syntax: 'public C()  ... throw null;')
      Initializer: 
        IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: ': base()')
          Expression: 
            IInvocationOperation ( System.Object..ctor()) (OperationKind.Invocation, Type: System.Void) (Syntax: ': base()')
              Instance Receiver: 
                IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: System.Object, IsImplicit) (Syntax: ': base()')
              Arguments(0)
      BlockBody: 
        null
      ExpressionBody: 
        IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '=> throw null')
          IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: 'throw null')
            Expression: 
              IThrowOperation (OperationKind.Throw, Type: null) (Syntax: 'throw null')
                IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Exception, Constant: null, IsImplicit) (Syntax: 'null')
                  Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null)
                  Operand: 
                    ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'null')
");
 
            VerifyFlowGraph(compilation, node1, expectedFlowGraph:
@"
    Block[B0] - Entry
        Statements (0)
        Next (Regular) Block[B1]
    Block[B1] - Block
        Predecessors: [B0]
        Statements (1)
            IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: ': base()')
              Expression: 
                IInvocationOperation ( System.Object..ctor()) (OperationKind.Invocation, Type: System.Void) (Syntax: ': base()')
                  Instance Receiver: 
                    IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: System.Object, IsImplicit) (Syntax: ': base()')
                  Arguments(0)
        Next (Throw) Block[null]
            IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Exception, Constant: null, IsImplicit) (Syntax: 'null')
              Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null)
                (ImplicitReference)
              Operand: 
                ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'null')
    Block[B2] - Exit [UnReachable]
        Predecessors (0)
        Statements (0)
");
        }
 
        [CompilerTrait(CompilerFeature.Dataflow)]
        [Fact]
        public void ConstructorBody_05()
        {
            // Block body, no initializer
            string source = @"
class C
{
    public C()
    { throw null; }
}
";
            var compilation = CreateCompilation(source);
 
            compilation.VerifyDiagnostics();
 
            var tree = compilation.SyntaxTrees.Single();
            var node1 = tree.GetRoot().DescendantNodes().OfType<ConstructorDeclarationSyntax>().Single();
 
            compilation.VerifyOperationTree(node1, expectedOperationTree:
@"
    IConstructorBodyOperation (OperationKind.ConstructorBody, Type: null) (Syntax: 'public C() ... row null; }')
      Initializer:
        IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: 'public C() ... row null; }')
          Expression:
            IInvocationOperation ( System.Object..ctor()) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 'public C() ... row null; }')
              Instance Receiver:
                IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'public C() ... row null; }')
              Arguments(0)
      BlockBody:
        IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ throw null; }')
          IThrowOperation (OperationKind.Throw, Type: null) (Syntax: 'throw null;')
            IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Exception, Constant: null, IsImplicit) (Syntax: 'null')
              Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null)
              Operand:
                ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'null')
      ExpressionBody:
        null
");
 
            VerifyFlowGraph(compilation, node1, expectedFlowGraph:
@"
    Block[B0] - Entry
        Statements (0)
        Next (Regular) Block[B1]
    Block[B1] - Block
        Predecessors: [B0]
        Statements (1)
            IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: 'public C() ... row null; }')
              Expression:
                IInvocationOperation ( System.Object..ctor()) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 'public C() ... row null; }')
                  Instance Receiver:
                    IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'public C() ... row null; }')
                  Arguments(0)
        Next (Throw) Block[null]
            IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Exception, Constant: null, IsImplicit) (Syntax: 'null')
              Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null)
                (ImplicitReference)
              Operand:
                ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'null')
    Block[B2] - Exit [UnReachable]
        Predecessors (0)
        Statements (0)
");
        }
 
        [CompilerTrait(CompilerFeature.Dataflow)]
        [Fact]
        public void ConstructorBody_06()
        {
            // Expression body, no initializer
            string source = @"
class C
{
    public C()
    => throw null;
}
";
            var compilation = CreateCompilation(source);
 
            compilation.VerifyDiagnostics();
 
            var tree = compilation.SyntaxTrees.Single();
            var node1 = tree.GetRoot().DescendantNodes().OfType<ConstructorDeclarationSyntax>().Single();
 
            compilation.VerifyOperationTree(node1, expectedOperationTree:
@"
    IConstructorBodyOperation (OperationKind.ConstructorBody, Type: null) (Syntax: 'public C() ... throw null;')
      Initializer:
        IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: 'public C() ... throw null;')
          Expression:
            IInvocationOperation ( System.Object..ctor()) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 'public C() ... throw null;')
              Instance Receiver:
                IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'public C() ... throw null;')
              Arguments(0)
      BlockBody:
        null
      ExpressionBody:
        IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '=> throw null')
          IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: 'throw null')
            Expression:
              IThrowOperation (OperationKind.Throw, Type: null) (Syntax: 'throw null')
                IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Exception, Constant: null, IsImplicit) (Syntax: 'null')
                  Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null)
                  Operand:
                    ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'null')
");
 
            VerifyFlowGraph(compilation, node1, expectedFlowGraph:
@"
    Block[B0] - Entry
        Statements (0)
        Next (Regular) Block[B1]
    Block[B1] - Block
        Predecessors: [B0]
        Statements (1)
            IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: 'public C() ... throw null;')
              Expression:
                IInvocationOperation ( System.Object..ctor()) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 'public C() ... throw null;')
                  Instance Receiver:
                    IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'public C() ... throw null;')
                  Arguments(0)
        Next (Throw) Block[null]
            IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Exception, Constant: null, IsImplicit) (Syntax: 'null')
              Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null)
                (ImplicitReference)
              Operand:
                ILiteralOperation (OperationKind.Literal, Type: null, Constant: null) (Syntax: 'null')
    Block[B2] - Exit [UnReachable]
        Predecessors (0)
        Statements (0)
");
        }
 
        [CompilerTrait(CompilerFeature.Dataflow)]
        [Fact]
        public void ConstructorBody_07()
        {
            // Block and expression body, no initializer
            string source = @"
class C
{
    public C()
    { throw null; }
    => throw null;
}
";
            var compilation = CreateCompilation(source);
 
            compilation.VerifyDiagnostics(
                // (4,5): error CS8057: Block bodies and expression bodies cannot both be provided.
                //     public C()
                Diagnostic(ErrorCode.ERR_BlockBodyAndExpressionBody, @"public C()
    { throw null; }
    => throw null;").WithLocation(4, 5)
                );
 
            var tree = compilation.SyntaxTrees.Single();
            var node1 = tree.GetRoot().DescendantNodes().OfType<ConstructorDeclarationSyntax>().Single();
 
            compilation.VerifyOperationTree(node1, expectedOperationTree:
@"
    IConstructorBodyOperation (OperationKind.ConstructorBody, Type: null, IsInvalid) (Syntax: 'public C() ... throw null;')
      Initializer:
        IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid, IsImplicit) (Syntax: 'public C() ... throw null;')
          Expression:
            IInvocationOperation ( System.Object..ctor()) (OperationKind.Invocation, Type: System.Void, IsInvalid, IsImplicit) (Syntax: 'public C() ... throw null;')
              Instance Receiver:
                IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsInvalid, IsImplicit) (Syntax: 'public C() ... throw null;')
              Arguments(0)
      BlockBody:
        IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsInvalid) (Syntax: '{ throw null; }')
          IThrowOperation (OperationKind.Throw, Type: null, IsInvalid) (Syntax: 'throw null;')
            IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Exception, Constant: null, IsInvalid, IsImplicit) (Syntax: 'null')
              Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null)
              Operand:
                ILiteralOperation (OperationKind.Literal, Type: null, Constant: null, IsInvalid) (Syntax: 'null')
      ExpressionBody:
        IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsInvalid) (Syntax: '=> throw null')
          IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid, IsImplicit) (Syntax: 'throw null')
            Expression:
              IThrowOperation (OperationKind.Throw, Type: null, IsInvalid) (Syntax: 'throw null')
                IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Exception, Constant: null, IsInvalid, IsImplicit) (Syntax: 'null')
                  Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null)
                  Operand:
                    ILiteralOperation (OperationKind.Literal, Type: null, Constant: null, IsInvalid) (Syntax: 'null')
");
 
            VerifyFlowGraph(compilation, node1, expectedFlowGraph:
@"
    Block[B0] - Entry
        Statements (0)
        Next (Regular) Block[B1]
    Block[B1] - Block
        Predecessors: [B0]
        Statements (1)
            IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid, IsImplicit) (Syntax: 'public C() ... throw null;')
              Expression:
                IInvocationOperation ( System.Object..ctor()) (OperationKind.Invocation, Type: System.Void, IsInvalid, IsImplicit) (Syntax: 'public C() ... throw null;')
                  Instance Receiver:
                    IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsInvalid, IsImplicit) (Syntax: 'public C() ... throw null;')
                  Arguments(0)
        Next (Throw) Block[null]
            IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Exception, Constant: null, IsInvalid, IsImplicit) (Syntax: 'null')
              Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null)
                (ImplicitReference)
              Operand:
                ILiteralOperation (OperationKind.Literal, Type: null, Constant: null, IsInvalid) (Syntax: 'null')
    .erroneous body {R1}
    {
        Block[B2] - Block [UnReachable]
            Predecessors (0)
            Statements (0)
            Next (Throw) Block[null]
                IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Exception, Constant: null, IsInvalid, IsImplicit) (Syntax: 'null')
                  Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null)
                    (ImplicitReference)
                  Operand:
                    ILiteralOperation (OperationKind.Literal, Type: null, Constant: null, IsInvalid) (Syntax: 'null')
    }
    Block[B3] - Exit [UnReachable]
        Predecessors (0)
        Statements (0)
");
        }
 
        [Fact]
        public void ConstructorBody_08()
        {
            // No body, no initializer
            string source = @"
class C
{
    public C();
}
";
            var compilation = CreateCompilation(source);
 
            compilation.VerifyDiagnostics(
                // file.cs(4,12): error CS0501: 'C.C()' must declare a body because it is not marked abstract, extern, or partial
                //     public C();
                Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "C").WithArguments("C.C()").WithLocation(4, 12)
                );
 
            var tree = compilation.SyntaxTrees.Single();
            var model = compilation.GetSemanticModel(tree);
 
            var node1 = tree.GetRoot().DescendantNodes().OfType<ConstructorDeclarationSyntax>().Single();
            Assert.Null(model.GetOperation(node1));
        }
 
        [CompilerTrait(CompilerFeature.Dataflow)]
        [Fact]
        public void ConstructorBody_09()
        {
            // Block and expression body, initializer without declarations
            string source = @"
class C
{
    public C(int i1, int i2, int j1, int j2) : base()
    { i1 = i2; }
    => j1 = j2;
}
";
            var compilation = CreateCompilation(source);
 
            compilation.VerifyDiagnostics(
                // (4,5): error CS8057: Block bodies and expression bodies cannot both be provided.
                //     public C(int i1, int i2, int j1, int j2) : base()
                Diagnostic(ErrorCode.ERR_BlockBodyAndExpressionBody, @"public C(int i1, int i2, int j1, int j2) : base()
    { i1 = i2; }
    => j1 = j2;").WithLocation(4, 5));
 
            var tree = compilation.SyntaxTrees.Single();
            var node1 = tree.GetRoot().DescendantNodes().OfType<ConstructorDeclarationSyntax>().Single();
 
            VerifyFlowGraph(compilation, node1, expectedFlowGraph:
@"
Block[B0] - Entry
    Statements (0)
    Next (Regular) Block[B1]
Block[B1] - Block
    Predecessors: [B0]
    Statements (2)
        IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid, IsImplicit) (Syntax: ': base()')
          Expression: 
            IInvocationOperation ( System.Object..ctor()) (OperationKind.Invocation, Type: System.Void, IsInvalid) (Syntax: ': base()')
              Instance Receiver: 
                IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: System.Object, IsInvalid, IsImplicit) (Syntax: ': base()')
              Arguments(0)
 
        IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid) (Syntax: 'i1 = i2;')
          Expression: 
            ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32, IsInvalid) (Syntax: 'i1 = i2')
              Left: 
                IParameterReferenceOperation: i1 (OperationKind.ParameterReference, Type: System.Int32, IsInvalid) (Syntax: 'i1')
              Right: 
                IParameterReferenceOperation: i2 (OperationKind.ParameterReference, Type: System.Int32, IsInvalid) (Syntax: 'i2')
 
    Next (Regular) Block[B3]
 
.erroneous body {R1}
{
    Block[B2] - Block [UnReachable]
        Predecessors (0)
        Statements (1)
            IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid, IsImplicit) (Syntax: 'j1 = j2')
              Expression: 
                ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32, IsInvalid) (Syntax: 'j1 = j2')
                  Left: 
                    IParameterReferenceOperation: j1 (OperationKind.ParameterReference, Type: System.Int32, IsInvalid) (Syntax: 'j1')
                  Right: 
                    IParameterReferenceOperation: j2 (OperationKind.ParameterReference, Type: System.Int32, IsInvalid) (Syntax: 'j2')
 
        Next (Regular) Block[B3]
            Leaving: {R1}
}
 
Block[B3] - Exit
    Predecessors: [B1] [B2]
    Statements (0)
");
        }
 
        [CompilerTrait(CompilerFeature.Dataflow)]
        [Fact]
        public void ConstructorBody_10()
        {
            // Verify block body with a return statement, followed by throw in expression body.
            // This caught an assert when attempting to link current basic block which was already linked to exit.
            string source = @"
class C
{
    public C()
    { return; }
    => throw null;
}
";
            var compilation = CreateCompilation(source);
 
            compilation.VerifyDiagnostics(
                // (4,5): error CS8057: Block bodies and expression bodies cannot both be provided.
                //     public C()
                Diagnostic(ErrorCode.ERR_BlockBodyAndExpressionBody, @"public C()
    { return; }
    => throw null;").WithLocation(4, 5)
            );
 
            var tree = compilation.SyntaxTrees.Single();
            var node1 = tree.GetRoot().DescendantNodes().OfType<ConstructorDeclarationSyntax>().Single();
 
            VerifyFlowGraph(compilation, node1, expectedFlowGraph:
@"
    Block[B0] - Entry
        Statements (0)
        Next (Regular) Block[B1]
    Block[B1] - Block
        Predecessors: [B0]
        Statements (1)
            IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid, IsImplicit) (Syntax: 'public C() ... throw null;')
              Expression:
                IInvocationOperation ( System.Object..ctor()) (OperationKind.Invocation, Type: System.Void, IsInvalid, IsImplicit) (Syntax: 'public C() ... throw null;')
                  Instance Receiver:
                    IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsInvalid, IsImplicit) (Syntax: 'public C() ... throw null;')
                  Arguments(0)
        Next (Regular) Block[B3]
    .erroneous body {R1}
    {
        Block[B2] - Block [UnReachable]
            Predecessors (0)
            Statements (0)
            Next (Throw) Block[null]
                IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Exception, Constant: null, IsInvalid, IsImplicit) (Syntax: 'null')
                  Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null)
                    (ImplicitReference)
                  Operand:
                    ILiteralOperation (OperationKind.Literal, Type: null, Constant: null, IsInvalid) (Syntax: 'null')
    }
    Block[B3] - Exit
        Predecessors: [B1]
        Statements (0)
");
        }
 
        [CompilerTrait(CompilerFeature.Dataflow)]
        [Fact]
        public void ConstructorBody_11()
        {
            // Block body, initializer with declarations
            string source = @"
class C : Base
{
    C(int p) : base(out var i)
    {
        p = i;
    }
}
 
class Base
{
    protected Base(out int i)
    {
        i = 1;
    }
}
";
            var compilation = CreateCompilation(source);
 
            compilation.VerifyDiagnostics();
 
            var tree = compilation.SyntaxTrees.Single();
            var node1 = tree.GetRoot().DescendantNodes().OfType<ConstructorDeclarationSyntax>().First();
 
            VerifyFlowGraph(compilation, node1, expectedFlowGraph:
@"
Block[B0] - Entry
    Statements (0)
    Next (Regular) Block[B1]
        Entering: {R1}
 
.locals {R1}
{
    Locals: [System.Int32 i]
    Block[B1] - Block
        Predecessors: [B0]
        Statements (2)
            IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: ': base(out var i)')
              Expression: 
                IInvocationOperation ( Base..ctor(out System.Int32 i)) (OperationKind.Invocation, Type: System.Void) (Syntax: ': base(out var i)')
                  Instance Receiver: 
                    IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: Base, IsImplicit) (Syntax: ': base(out var i)')
                  Arguments(1):
                      IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: i) (OperationKind.Argument, Type: null) (Syntax: 'out var i')
                        IDeclarationExpressionOperation (OperationKind.DeclarationExpression, Type: System.Int32) (Syntax: 'var i')
                          ILocalReferenceOperation: i (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'i')
                        InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
                        OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
 
            IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'p = i;')
              Expression: 
                ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32) (Syntax: 'p = i')
                  Left: 
                    IParameterReferenceOperation: p (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'p')
                  Right: 
                    ILocalReferenceOperation: i (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'i')
 
        Next (Regular) Block[B2]
            Leaving: {R1}
}
 
Block[B2] - Exit
    Predecessors: [B1]
    Statements (0)
");
        }
 
        [CompilerTrait(CompilerFeature.Dataflow)]
        [Fact]
        public void ConstructorBody_12()
        {
            // Expression body, initializer with declarations
            string source = @"
class C : Base
{
    C(int p) : base(out var i)
    => p = i;
}
 
class Base
{
    protected Base(out int i)
    {
        i = 1;
    }
}
";
            var compilation = CreateCompilation(source);
 
            compilation.VerifyDiagnostics();
 
            var tree = compilation.SyntaxTrees.Single();
            var node1 = tree.GetRoot().DescendantNodes().OfType<ConstructorDeclarationSyntax>().First();
 
            VerifyFlowGraph(compilation, node1, expectedFlowGraph:
@"
Block[B0] - Entry
    Statements (0)
    Next (Regular) Block[B1]
        Entering: {R1}
 
.locals {R1}
{
    Locals: [System.Int32 i]
    Block[B1] - Block
        Predecessors: [B0]
        Statements (2)
            IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: ': base(out var i)')
              Expression: 
                IInvocationOperation ( Base..ctor(out System.Int32 i)) (OperationKind.Invocation, Type: System.Void) (Syntax: ': base(out var i)')
                  Instance Receiver: 
                    IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: Base, IsImplicit) (Syntax: ': base(out var i)')
                  Arguments(1):
                      IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: i) (OperationKind.Argument, Type: null) (Syntax: 'out var i')
                        IDeclarationExpressionOperation (OperationKind.DeclarationExpression, Type: System.Int32) (Syntax: 'var i')
                          ILocalReferenceOperation: i (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'i')
                        InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
                        OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
 
            IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: 'p = i')
              Expression: 
                ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32) (Syntax: 'p = i')
                  Left: 
                    IParameterReferenceOperation: p (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'p')
                  Right: 
                    ILocalReferenceOperation: i (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'i')
 
        Next (Regular) Block[B2]
            Leaving: {R1}
}
 
Block[B2] - Exit
    Predecessors: [B1]
    Statements (0)
");
        }
 
        [CompilerTrait(CompilerFeature.Dataflow)]
        [Fact]
        public void ConstructorBody_13()
        {
            // No body, initializer with declarations
            string source = @"
class C : Base
{
    C() : base(out var i)
}
 
class Base
{
    protected Base(out int i)
    {
        i = 1;
    }
}
";
            var compilation = CreateCompilation(source);
 
            compilation.VerifyDiagnostics(
                // (4,26): error CS1002: ; expected
                //     C() : base(out var i)
                Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(4, 26),
                // (4,5): error CS0501: 'C.C()' must declare a body because it is not marked abstract, extern, or partial
                //     C() : base(out var i)
                Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "C").WithArguments("C.C()").WithLocation(4, 5));
 
            var tree = compilation.SyntaxTrees.Single();
            var node1 = tree.GetRoot().DescendantNodes().OfType<ConstructorDeclarationSyntax>().First();
 
            VerifyFlowGraph(compilation, node1, expectedFlowGraph:
@"
Block[B0] - Entry
    Statements (0)
    Next (Regular) Block[B1]
        Entering: {R1}
 
.locals {R1}
{
    Locals: [System.Int32 i]
    Block[B1] - Block
        Predecessors: [B0]
        Statements (1)
            IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid, IsImplicit) (Syntax: ': base(out var i)')
              Expression: 
                IInvocationOperation ( Base..ctor(out System.Int32 i)) (OperationKind.Invocation, Type: System.Void, IsInvalid) (Syntax: ': base(out var i)')
                  Instance Receiver: 
                    IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: Base, IsInvalid, IsImplicit) (Syntax: ': base(out var i)')
                  Arguments(1):
                      IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: i) (OperationKind.Argument, Type: null) (Syntax: 'out var i')
                        IDeclarationExpressionOperation (OperationKind.DeclarationExpression, Type: System.Int32) (Syntax: 'var i')
                          ILocalReferenceOperation: i (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'i')
                        InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
                        OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
 
        Next (Regular) Block[B2]
            Leaving: {R1}
}
 
Block[B2] - Exit
    Predecessors: [B1]
    Statements (0)
");
        }
 
        [CompilerTrait(CompilerFeature.Dataflow)]
        [Fact]
        public void ConstructorBody_14()
        {
            // Block and expression body, initializer with declarations
            string source = @"
class C : Base
{
    C(int j1, int j2) : base(out var i1, out var i2)
    { i1 = j1; }
    => j2 = i2;
}
 
class Base
{
    protected Base(out int i1, out int i2)
    {
        i1 = 1;
        i2 = 1;
    }
}
";
            var compilation = CreateCompilation(source);
 
            compilation.VerifyDiagnostics(
                // (4,5): error CS8057: Block bodies and expression bodies cannot both be provided.
                //     C(int j1, int j2) : base(out var i1, out var i2)
                Diagnostic(ErrorCode.ERR_BlockBodyAndExpressionBody, @"C(int j1, int j2) : base(out var i1, out var i2)
    { i1 = j1; }
    => j2 = i2;").WithLocation(4, 5));
 
            var tree = compilation.SyntaxTrees.Single();
            var node1 = tree.GetRoot().DescendantNodes().OfType<ConstructorDeclarationSyntax>().First();
 
            VerifyFlowGraph(compilation, node1, expectedFlowGraph:
@"
Block[B0] - Entry
    Statements (0)
    Next (Regular) Block[B1]
        Entering: {R1}
 
.locals {R1}
{
    Locals: [System.Int32 i1] [System.Int32 i2]
    Block[B1] - Block
        Predecessors: [B0]
        Statements (2)
            IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid, IsImplicit) (Syntax: ': base(out  ... out var i2)')
              Expression: 
                IInvocationOperation ( Base..ctor(out System.Int32 i1, out System.Int32 i2)) (OperationKind.Invocation, Type: System.Void, IsInvalid) (Syntax: ': base(out  ... out var i2)')
                  Instance Receiver: 
                    IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: Base, IsInvalid, IsImplicit) (Syntax: ': base(out  ... out var i2)')
                  Arguments(2):
                      IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: i1) (OperationKind.Argument, Type: null, IsInvalid) (Syntax: 'out var i1')
                        IDeclarationExpressionOperation (OperationKind.DeclarationExpression, Type: System.Int32, IsInvalid) (Syntax: 'var i1')
                          ILocalReferenceOperation: i1 (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'i1')
                        InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
                        OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
                      IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: i2) (OperationKind.Argument, Type: null, IsInvalid) (Syntax: 'out var i2')
                        IDeclarationExpressionOperation (OperationKind.DeclarationExpression, Type: System.Int32, IsInvalid) (Syntax: 'var i2')
                          ILocalReferenceOperation: i2 (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'i2')
                        InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
                        OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
 
            IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid) (Syntax: 'i1 = j1;')
              Expression: 
                ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32, IsInvalid) (Syntax: 'i1 = j1')
                  Left: 
                    ILocalReferenceOperation: i1 (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'i1')
                  Right: 
                    IParameterReferenceOperation: j1 (OperationKind.ParameterReference, Type: System.Int32, IsInvalid) (Syntax: 'j1')
 
        Next (Regular) Block[B3]
            Leaving: {R1}
 
    .erroneous body {R2}
    {
        Block[B2] - Block [UnReachable]
            Predecessors (0)
            Statements (1)
                IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid, IsImplicit) (Syntax: 'j2 = i2')
                  Expression: 
                    ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32, IsInvalid) (Syntax: 'j2 = i2')
                      Left: 
                        IParameterReferenceOperation: j2 (OperationKind.ParameterReference, Type: System.Int32, IsInvalid) (Syntax: 'j2')
                      Right: 
                        ILocalReferenceOperation: i2 (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'i2')
 
            Next (Regular) Block[B3]
                Leaving: {R2} {R1}
    }
}
 
Block[B3] - Exit
    Predecessors: [B1] [B2]
    Statements (0)
");
        }
 
        [CompilerTrait(CompilerFeature.Dataflow)]
        [Fact]
        public void ConstructorBody_15()
        {
            // Verify "this" initializer with control flow in initializer.
            string source = @"
class C
{
    C(int? i, int j, int k, int p) : this(i ?? j) 
    {
        p = k;
    }
 
    C(int i)
    {
    }
}
";
            var compilation = CreateCompilation(source);
 
            compilation.VerifyDiagnostics();
 
            var tree = compilation.SyntaxTrees.Single();
            var node1 = tree.GetRoot().DescendantNodes().OfType<ConstructorDeclarationSyntax>().First();
 
            VerifyFlowGraph(compilation, node1, expectedFlowGraph:
@"
Block[B0] - Entry
    Statements (0)
    Next (Regular) Block[B1]
        Entering: {R1}
 
.locals {R1}
{
    CaptureIds: [0] [2]
    Block[B1] - Block
        Predecessors: [B0]
        Statements (1)
            IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: ': this(i ?? j)')
              Value: 
                IInstanceReferenceOperation (ReferenceKind: ContainingTypeInstance) (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: ': this(i ?? j)')
 
        Next (Regular) Block[B2]
            Entering: {R2}
 
    .locals {R2}
    {
        CaptureIds: [1]
        Block[B2] - Block
            Predecessors: [B1]
            Statements (1)
                IFlowCaptureOperation: 1 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'i')
                  Value: 
                    IParameterReferenceOperation: i (OperationKind.ParameterReference, Type: System.Int32?) (Syntax: 'i')
 
            Jump if True (Regular) to Block[B4]
                IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsImplicit) (Syntax: 'i')
                  Operand: 
                    IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Int32?, IsImplicit) (Syntax: 'i')
                Leaving: {R2}
 
            Next (Regular) Block[B3]
        Block[B3] - Block
            Predecessors: [B2]
            Statements (1)
                IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'i')
                  Value: 
                    IInvocationOperation ( System.Int32 System.Int32?.GetValueOrDefault()) (OperationKind.Invocation, Type: System.Int32, IsImplicit) (Syntax: 'i')
                      Instance Receiver: 
                        IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Int32?, IsImplicit) (Syntax: 'i')
                      Arguments(0)
 
            Next (Regular) Block[B5]
                Leaving: {R2}
    }
 
    Block[B4] - Block
        Predecessors: [B2]
        Statements (1)
            IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'j')
              Value: 
                IParameterReferenceOperation: j (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'j')
 
        Next (Regular) Block[B5]
    Block[B5] - Block
        Predecessors: [B3] [B4]
        Statements (1)
            IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: ': this(i ?? j)')
              Expression: 
                IInvocationOperation ( C..ctor(System.Int32 i)) (OperationKind.Invocation, Type: System.Void) (Syntax: ': this(i ?? j)')
                  Instance Receiver: 
                    IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: C, IsImplicit) (Syntax: ': this(i ?? j)')
                  Arguments(1):
                      IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: i) (OperationKind.Argument, Type: null) (Syntax: 'i ?? j')
                        IFlowCaptureReferenceOperation: 2 (OperationKind.FlowCaptureReference, Type: System.Int32, IsImplicit) (Syntax: 'i ?? j')
                        InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
                        OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
 
        Next (Regular) Block[B6]
            Leaving: {R1}
}
 
Block[B6] - Block
    Predecessors: [B5]
    Statements (1)
        IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'p = k;')
          Expression: 
            ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32) (Syntax: 'p = k')
              Left: 
                IParameterReferenceOperation: p (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'p')
              Right: 
                IParameterReferenceOperation: k (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'k')
 
    Next (Regular) Block[B7]
Block[B7] - Exit
    Predecessors: [B6]
    Statements (0)
");
        }
 
        [Fact]
        public void ConstructorBody_16()
        {
            string source = @"
class C
{
    extern public C();
}
";
            var compilation = CreateCompilation(source);
 
            compilation.VerifyDiagnostics(
                // (4,19): warning CS0824: Constructor 'C.C()' is marked external
                //     extern public C();
                Diagnostic(ErrorCode.WRN_ExternCtorNoImplementation, "C").WithArguments("C.C()").WithLocation(4, 19)
                );
 
            var tree = compilation.SyntaxTrees.Single();
            var model = compilation.GetSemanticModel(tree);
 
            var node1 = tree.GetRoot().DescendantNodes().OfType<ConstructorDeclarationSyntax>().Single();
            Assert.Null(model.GetOperation(node1));
        }
 
        [Fact]
        public void ConstructorBody_17()
        {
            string source = @"
class C
{
    static C() { }
}
";
            var compilation = CreateCompilation(source);
 
            compilation.VerifyDiagnostics();
 
            var tree = compilation.SyntaxTrees.Single();
            var model = compilation.GetSemanticModel(tree);
 
            var node1 = tree.GetRoot().DescendantNodes().OfType<ConstructorDeclarationSyntax>().Single();
            compilation.VerifyOperationTree(node1, """
                IConstructorBodyOperation (OperationKind.ConstructorBody, Type: null) (Syntax: 'static C() { }')
                  Initializer:
                    null
                  BlockBody:
                    IBlockOperation (0 statements) (OperationKind.Block, Type: null) (Syntax: '{ }')
                  ExpressionBody:
                    null
                """);
        }
 
        [Fact]
        public void ConstructorBody_18()
        {
            string source = @"
namespace System
{
    public class Object
    {
        public Object() { }
    }
 
    public class Void { }
}
";
            var compilation = CreateEmptyCompilation(source);
 
            compilation.VerifyDiagnostics();
 
            var tree = compilation.SyntaxTrees.Single();
            var model = compilation.GetSemanticModel(tree);
 
            var node1 = tree.GetRoot().DescendantNodes().OfType<ConstructorDeclarationSyntax>().Single();
            compilation.VerifyOperationTree(node1, """
                IConstructorBodyOperation (OperationKind.ConstructorBody, Type: null) (Syntax: 'public Object() { }')
                  Initializer:
                    null
                  BlockBody:
                    IBlockOperation (0 statements) (OperationKind.Block, Type: null) (Syntax: '{ }')
                  ExpressionBody:
                    null
                """);
        }
 
        [Fact]
        public void ConstructorBody_19()
        {
            string source = @"
class Base
{
    public Base(int x){}
}
 
class Program : Base
{
    Program()
    {}
}
";
            var compilation = CreateCompilation(source);
 
            compilation.VerifyEmitDiagnostics(
                // (9,5): error CS7036: There is no argument given that corresponds to the required parameter 'x' of 'Base.Base(int)'
                //     Program()
                Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "Program").WithArguments("x", "Base.Base(int)").WithLocation(9, 5)
                );
 
            var tree = compilation.SyntaxTrees.Single();
            var model = compilation.GetSemanticModel(tree);
 
            var node1 = tree.GetRoot().DescendantNodes().OfType<ConstructorDeclarationSyntax>().Skip(1).Single();
            compilation.VerifyOperationTree(node1, """
                IConstructorBodyOperation (OperationKind.ConstructorBody, Type: null, IsInvalid) (Syntax: 'Program() ... {}')
                Initializer:
                  IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid, IsImplicit) (Syntax: 'Program() ... {}')
                    Expression:
                      IInvalidOperation (OperationKind.Invalid, Type: System.Void, IsInvalid, IsImplicit) (Syntax: 'Program() ... {}')
                        Children(0)
                BlockBody:
                  IBlockOperation (0 statements) (OperationKind.Block, Type: null) (Syntax: '{}')
                ExpressionBody:
                  null
                """);
        }
    }
}