提交 07acd716 编写于 作者: N Neal Gafter 提交者: GitHub

Implement code gen for expression-bodied ctor and dtor (#13765)

* Implement code gen for expression-bodied ctor and dtor

Plaigarized from @lachbaer in #13758
Fixes #13578
Fixes #13691
Fixes #13692
上级 35884974
......@@ -514,7 +514,7 @@ internal static BoundBlock ConstructDestructorBody(MethodSymbol method, BoundBlo
var syntax = block.Syntax;
Debug.Assert(method.MethodKind == MethodKind.Destructor);
Debug.Assert(syntax.Kind() == SyntaxKind.Block);
Debug.Assert(syntax.Kind() == SyntaxKind.Block || syntax.Kind() == SyntaxKind.ArrowExpressionClause);
// If this is a destructor and a base type has a Finalize method (see GetBaseTypeFinalizeMethod for exact
// requirements), then we need to call that method in a finally block. Otherwise, just return block as-is.
......@@ -523,20 +523,25 @@ internal static BoundBlock ConstructDestructorBody(MethodSymbol method, BoundBlo
if ((object)baseTypeFinalize != null)
{
BoundStatement baseFinalizeCall = new BoundSequencePointWithSpan( //sequence point to mimic Dev10
BoundStatement baseFinalizeCall = new BoundExpressionStatement(
syntax,
new BoundExpressionStatement(
BoundCall.Synthesized(
syntax,
BoundCall.Synthesized(
new BoundBaseReference(
syntax,
new BoundBaseReference(
syntax,
method.ContainingType)
{ WasCompilerGenerated = true },
baseTypeFinalize)
)
{ WasCompilerGenerated = true },
((BlockSyntax)syntax).CloseBraceToken.Span);
method.ContainingType)
{ WasCompilerGenerated = true },
baseTypeFinalize))
{ WasCompilerGenerated = true };
if (syntax.Kind() == SyntaxKind.Block)
{
//sequence point to mimic Dev10
baseFinalizeCall = new BoundSequencePointWithSpan(
syntax,
baseFinalizeCall,
((BlockSyntax)syntax).CloseBraceToken.Span);
}
return new BoundBlock(
syntax,
......
......@@ -1551,11 +1551,6 @@ private static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationSta
body = (BoundBlock)binder.BindEmbeddedBlock(blockSyntax, diagnostics);
importChain = binder.ImportChain;
if (method.MethodKind == MethodKind.Destructor)
{
return MethodBodySynthesizer.ConstructDestructorBody(method, body);
}
foreach (var iterator in binder.MethodSymbolsWithYield)
{
foreach (var parameter in iterator.Parameters)
......@@ -1591,7 +1586,7 @@ private static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationSta
binder = new ExecutableCodeBinder(arrowExpression, sourceMethod, binder);
importChain = binder.ImportChain;
// Add locals
return binder.BindExpressionBodyAsBlock(arrowExpression, diagnostics);
body = binder.BindExpressionBodyAsBlock(arrowExpression, diagnostics);
}
else
{
......@@ -1610,6 +1605,11 @@ private static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationSta
body = null;
}
if (method.MethodKind == MethodKind.Destructor && body != null)
{
return MethodBodySynthesizer.ConstructDestructorBody(method, body);
}
var constructorInitializer = BindConstructorInitializerIfAny(method, compilationState, diagnostics);
ImmutableArray<BoundStatement> statements;
......
......@@ -75,7 +75,8 @@ .maxstack 1
");
}
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/13692")]
[Fact]
[CompilerTrait(CompilerFeature.ExpressionBody)]
public void ExpressionBodiedClassDestructor()
{
var text = @"
......@@ -128,7 +129,8 @@ .maxstack 1
");
}
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/13692")]
[Fact]
[CompilerTrait(CompilerFeature.ExpressionBody)]
public void ExpressionBodiedSubClassDestructor()
{
var text = @"
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.CSharp.UnitTests;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using System.Linq;
using Xunit;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.Semantic.UnitTests.Semantics
{
/// <summary>
/// Contains tests for expression-bodied members in the semantic model.
/// </summary>
[CompilerTrait(CompilerFeature.ExpressionBody)]
public class ExpressionBodiedMemberTests : SemanticModelTestBase
{
[Fact]
......@@ -346,7 +348,7 @@ static void Main()
CompileAndVerify(source, expectedOutput: "GetAction 1");
}
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/13691")]
[Fact, WorkItem(13691, "https://github.com/dotnet/roslyn/issues/13691")]
public void RunCtorProp()
{
string source = @"
......@@ -366,7 +368,7 @@ static void Main()
CompileAndVerify(source, expectedOutput: "12");
}
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/13691")]
[Fact, WorkItem(13691, "https://github.com/dotnet/roslyn/issues/13691")]
public void RunCtorWithBase01()
{
string source = @"
......@@ -383,14 +385,14 @@ static void Main()
CompileAndVerify(source, expectedOutput: "1");
}
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/13691")]
[Fact, WorkItem(13691, "https://github.com/dotnet/roslyn/issues/13691")]
public void RunCtorWithBase02()
{
string source = @"
using System;
public class Base
{
Base(int i) { Console.Write(i); }
public Base(int i) { Console.Write(i); }
}
public class Program : Base
{
......@@ -951,5 +953,31 @@ public class D
Assert.Equal($"System.Int32 y{i}", model.LookupSymbols(nodes[i].SpanStart, name: $"y{i}").Single().ToTestDisplayString());
}
}
[Fact, WorkItem(13578, "https://github.com/dotnet/roslyn/issues/13578")]
public void ExpressionBodiesNotSupported()
{
var source = @"
using System;
public class C
{
C() => Console.WriteLine(1);
~C() => Console.WriteLine(2);
int P { set => Console.WriteLine(value); }
}
";
CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular).VerifyDiagnostics();
CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular6).VerifyDiagnostics(
// (5,9): error CS8059: Feature 'expression body constructor and destructor' is not available in C# 6. Please use language version 7 or greater.
// C() => Console.WriteLine(1);
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion6, "=> Console.WriteLine(1)").WithArguments("expression body constructor and destructor", "7").WithLocation(5, 9),
// (6,10): error CS8059: Feature 'expression body constructor and destructor' is not available in C# 6. Please use language version 7 or greater.
// ~C() => Console.WriteLine(2);
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion6, "=> Console.WriteLine(2)").WithArguments("expression body constructor and destructor", "7").WithLocation(6, 10),
// (7,17): error CS8059: Feature 'expression body property accessor' is not available in C# 6. Please use language version 7 or greater.
// int P { set => Console.WriteLine(value); }
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion6, "=> Console.WriteLine(value)").WithArguments("expression body property accessor", "7").WithLocation(7, 17)
);
}
}
}
......@@ -5,6 +5,7 @@
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
......@@ -5566,5 +5567,157 @@ class C1
var file = this.ParseFile(text, parseOptions: TestOptions.Regular);
Assert.Equal(0, file.Errors().Length);
}
[Fact]
[WorkItem(13578, "https://github.com/dotnet/roslyn/issues/13578")]
[CompilerTrait(CompilerFeature.ExpressionBody)]
public void ExpressionBodiedCtorDtorProp()
{
UsingTree(@"
class C
{
C() : base() => M();
C() => M();
~C() => M();
int P { set => M(); }
}
");
N(SyntaxKind.CompilationUnit);
{
N(SyntaxKind.ClassDeclaration);
{
N(SyntaxKind.ClassKeyword);
N(SyntaxKind.IdentifierToken);
N(SyntaxKind.OpenBraceToken);
N(SyntaxKind.ConstructorDeclaration);
{
N(SyntaxKind.IdentifierToken);
N(SyntaxKind.ParameterList);
{
N(SyntaxKind.OpenParenToken);
N(SyntaxKind.CloseParenToken);
}
N(SyntaxKind.BaseConstructorInitializer);
{
N(SyntaxKind.ColonToken);
N(SyntaxKind.BaseKeyword);
N(SyntaxKind.ArgumentList);
{
N(SyntaxKind.OpenParenToken);
N(SyntaxKind.CloseParenToken);
}
}
N(SyntaxKind.ArrowExpressionClause);
{
N(SyntaxKind.EqualsGreaterThanToken);
N(SyntaxKind.InvocationExpression);
{
N(SyntaxKind.IdentifierName);
{
N(SyntaxKind.IdentifierToken);
}
N(SyntaxKind.ArgumentList);
{
N(SyntaxKind.OpenParenToken);
N(SyntaxKind.CloseParenToken);
}
}
}
N(SyntaxKind.SemicolonToken);
}
N(SyntaxKind.ConstructorDeclaration);
{
N(SyntaxKind.IdentifierToken);
N(SyntaxKind.ParameterList);
{
N(SyntaxKind.OpenParenToken);
N(SyntaxKind.CloseParenToken);
}
N(SyntaxKind.ArrowExpressionClause);
{
N(SyntaxKind.EqualsGreaterThanToken);
N(SyntaxKind.InvocationExpression);
{
N(SyntaxKind.IdentifierName);
{
N(SyntaxKind.IdentifierToken);
}
N(SyntaxKind.ArgumentList);
{
N(SyntaxKind.OpenParenToken);
N(SyntaxKind.CloseParenToken);
}
}
}
N(SyntaxKind.SemicolonToken);
}
N(SyntaxKind.DestructorDeclaration);
{
N(SyntaxKind.TildeToken);
N(SyntaxKind.IdentifierToken);
N(SyntaxKind.ParameterList);
{
N(SyntaxKind.OpenParenToken);
N(SyntaxKind.CloseParenToken);
}
N(SyntaxKind.ArrowExpressionClause);
{
N(SyntaxKind.EqualsGreaterThanToken);
N(SyntaxKind.InvocationExpression);
{
N(SyntaxKind.IdentifierName);
{
N(SyntaxKind.IdentifierToken);
}
N(SyntaxKind.ArgumentList);
{
N(SyntaxKind.OpenParenToken);
N(SyntaxKind.CloseParenToken);
}
}
}
N(SyntaxKind.SemicolonToken);
}
N(SyntaxKind.PropertyDeclaration);
{
N(SyntaxKind.PredefinedType);
{
N(SyntaxKind.IntKeyword);
}
N(SyntaxKind.IdentifierToken);
N(SyntaxKind.AccessorList);
{
N(SyntaxKind.OpenBraceToken);
N(SyntaxKind.SetAccessorDeclaration);
{
N(SyntaxKind.SetKeyword);
N(SyntaxKind.ArrowExpressionClause);
{
N(SyntaxKind.EqualsGreaterThanToken);
N(SyntaxKind.InvocationExpression);
{
N(SyntaxKind.IdentifierName);
{
N(SyntaxKind.IdentifierToken);
}
N(SyntaxKind.ArgumentList);
{
N(SyntaxKind.OpenParenToken);
N(SyntaxKind.CloseParenToken);
}
}
}
N(SyntaxKind.SemicolonToken);
}
N(SyntaxKind.CloseBraceToken);
}
}
N(SyntaxKind.CloseBraceToken);
}
N(SyntaxKind.EndOfFileToken);
}
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册