提交 e0e67352 编写于 作者: C Charles Stoner

Merge pull request #7244 from cston/120921

Add implicit return to original .ctor block
......@@ -812,9 +812,6 @@ public override object VisitField(FieldSymbol symbol, TypeCompilationState argum
try
{
bool includeInitializersInBody;
BoundBlock body;
// if synthesized method returns its body in lowered form
if (methodSymbol.SynthesizesLoweredBoundBody)
{
......@@ -833,17 +830,19 @@ public override object VisitField(FieldSymbol symbol, TypeCompilationState argum
return;
}
bool includeInitializersInBody = false;
BoundBlock body;
bool originalBodyNested = false;
// initializers that have been analyzed but not yet lowered.
BoundStatementList analyzedInitializers = null;
ImportChain importChain;
ImportChain importChain = null;
var hasTrailingExpression = false;
if (methodSymbol.IsScriptConstructor)
{
body = new BoundBlock(methodSymbol.GetNonNullSyntaxNode(), ImmutableArray<LocalSymbol>.Empty, ImmutableArray<BoundStatement>.Empty) { WasCompilerGenerated = true };
includeInitializersInBody = false;
importChain = null;
}
else if (methodSymbol.IsScriptInitializer)
{
......@@ -857,9 +856,6 @@ public override object VisitField(FieldSymbol symbol, TypeCompilationState argum
DataFlowPass.Analyze(_compilation, methodSymbol, initializerStatements, unusedDiagnostics, requireOutParamsAssigned: false);
DiagnosticsPass.IssueDiagnostics(_compilation, initializerStatements, unusedDiagnostics, methodSymbol);
unusedDiagnostics.Free();
includeInitializersInBody = false;
importChain = null;
}
else
{
......@@ -867,7 +863,7 @@ public override object VisitField(FieldSymbol symbol, TypeCompilationState argum
includeInitializersInBody = !processedInitializers.BoundInitializers.IsDefaultOrEmpty &&
!HasThisConstructorInitializer(methodSymbol);
body = BindMethodBody(methodSymbol, compilationState, diagsForCurrentMethod, out importChain);
body = BindMethodBody(methodSymbol, compilationState, diagsForCurrentMethod, out importChain, out originalBodyNested);
// lower initializers just once. the lowered tree will be reused when emitting all constructors
// with field initializers. Once lowered, these initializers will be stashed in processedInitializers.LoweredInitializers
......@@ -922,7 +918,7 @@ public override object VisitField(FieldSymbol symbol, TypeCompilationState argum
BoundBlock flowAnalyzedBody = null;
if (body != null)
{
flowAnalyzedBody = FlowAnalysisPass.Rewrite(methodSymbol, body, diagsForCurrentMethod, hasTrailingExpression);
flowAnalyzedBody = FlowAnalysisPass.Rewrite(methodSymbol, body, diagsForCurrentMethod, hasTrailingExpression: hasTrailingExpression, originalBodyNested: originalBodyNested);
}
bool hasErrors = _hasDeclarationErrors || diagsForCurrentMethod.HasAnyErrors() || processedInitializers.HasErrors;
......@@ -1455,37 +1451,17 @@ private BoundStatement ChainImplicitStructConstructor(MethodSymbol methodSymbol,
// NOTE: can return null if the method has no body.
internal static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationState compilationState, DiagnosticBag diagnostics)
{
ImportChain unused;
return BindMethodBody(method, compilationState, diagnostics, out unused);
ImportChain importChain;
bool originalBodyNested;
return BindMethodBody(method, compilationState, diagnostics, out importChain, out originalBodyNested);
}
// NOTE: can return null if the method has no body.
private static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationState compilationState, DiagnosticBag diagnostics, out ImportChain importChain)
private static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationState compilationState, DiagnosticBag diagnostics, out ImportChain importChain, out bool originalBodyNested)
{
originalBodyNested = false;
importChain = null;
var compilation = method.DeclaringCompilation;
BoundStatement constructorInitializer = null;
// delegates have constructors but not constructor initializers
if (method.MethodKind == MethodKind.Constructor && !method.ContainingType.IsDelegateType() && !method.IsExtern)
{
var initializerInvocation = BindConstructorInitializer(method, diagnostics, compilation);
if (initializerInvocation != null)
{
var ctorCall = initializerInvocation as BoundCall;
if (ctorCall != null && !ctorCall.HasAnyErrors && ctorCall.Method != method && ctorCall.Method.ContainingType == method.ContainingType)
{
// Detect and report indirect cycles in the ctor-initializer call graph.
compilationState.ReportCtorInitializerCycles(method, ctorCall.Method, ctorCall.Syntax, diagnostics);
}
constructorInitializer = new BoundExpressionStatement(initializerInvocation.Syntax, initializerInvocation) { WasCompilerGenerated = true };
Debug.Assert(initializerInvocation.HasAnyErrors || constructorInitializer.IsConstructorInitializer(), "Please keep this bound node in sync with BoundNodeExtensions.IsConstructorInitializer.");
}
}
BoundBlock body;
var sourceMethod = method as SourceMethodSymbol;
......@@ -1508,6 +1484,7 @@ private static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationSta
return null;
}
var compilation = method.DeclaringCompilation;
var factory = compilation.GetBinderFactory(sourceMethod.SyntaxTree);
var blockSyntax = sourceMethod.BodySyntax as BlockSyntax;
......@@ -1518,8 +1495,14 @@ private static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationSta
Binder binder = new ExecutableCodeBinder(blockSyntax, sourceMethod, inMethodBinder);
body = binder.BindBlock(blockSyntax, diagnostics);
importChain = binder.ImportChain;
if (method.MethodKind == MethodKind.Destructor)
{
return MethodBodySynthesizer.ConstructDestructorBody(method, body);
}
if (inMethodBinder.IsDirectlyInIterator)
{
foreach (var parameter in method.Parameters)
......@@ -1570,27 +1553,19 @@ private static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationSta
}
else
{
// synthesized methods should return their bound bodies
// synthesized methods should return their bound bodies
body = null;
}
var constructorInitializer = BindConstructorInitializerIfAny(method, compilationState, diagnostics);
ImmutableArray<BoundStatement> statements;
if (constructorInitializer == null)
{
if (body != null)
{
// most common case - we just have a single block for the body.
if (method.MethodKind == MethodKind.Destructor)
{
return MethodBodySynthesizer.ConstructDestructorBody(method, body);
}
else
{
return body;
}
return body;
}
statements = ImmutableArray<BoundStatement>.Empty;
}
else if (body == null)
......@@ -1600,11 +1575,38 @@ private static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationSta
else
{
statements = ImmutableArray.Create(constructorInitializer, body);
originalBodyNested = true;
}
return new BoundBlock(method.GetNonNullSyntaxNode(), ImmutableArray<LocalSymbol>.Empty, statements) { WasCompilerGenerated = true };
}
private static BoundStatement BindConstructorInitializerIfAny(MethodSymbol method, TypeCompilationState compilationState, DiagnosticBag diagnostics)
{
// delegates have constructors but not constructor initializers
if (method.MethodKind == MethodKind.Constructor && !method.ContainingType.IsDelegateType() && !method.IsExtern)
{
var compilation = method.DeclaringCompilation;
var initializerInvocation = BindConstructorInitializer(method, diagnostics, compilation);
if (initializerInvocation != null)
{
var ctorCall = initializerInvocation as BoundCall;
if (ctorCall != null && !ctorCall.HasAnyErrors && ctorCall.Method != method && ctorCall.Method.ContainingType == method.ContainingType)
{
// Detect and report indirect cycles in the ctor-initializer call graph.
compilationState.ReportCtorInitializerCycles(method, ctorCall.Method, ctorCall.Syntax, diagnostics);
}
var constructorInitializer = new BoundExpressionStatement(initializerInvocation.Syntax, initializerInvocation) { WasCompilerGenerated = true };
Debug.Assert(initializerInvocation.HasAnyErrors || constructorInitializer.IsConstructorInitializer(), "Please keep this bound node in sync with BoundNodeExtensions.IsConstructorInitializer.");
return constructorInitializer;
}
}
return null;
}
/// <summary>
/// Bind the (implicit or explicit) constructor initializer of a constructor symbol.
/// </summary>
......
......@@ -19,12 +19,14 @@ internal class FlowAnalysisPass
/// <param name="block">the method's body</param>
/// <param name="diagnostics">the receiver of the reported diagnostics</param>
/// <param name="hasTrailingExpression">indicates whether this Script had a trailing expression</param>
/// <param name="originalBodyNested">the original method body is the last statement in the block</param>
/// <returns>the rewritten block for the method (with a return statement possibly inserted)</returns>
public static BoundBlock Rewrite(
MethodSymbol method,
BoundBlock block,
DiagnosticBag diagnostics,
bool hasTrailingExpression)
bool hasTrailingExpression,
bool originalBodyNested)
{
#if DEBUG
// We should only see a trailingExpression if we're in a Script initializer.
......@@ -39,7 +41,7 @@ internal class FlowAnalysisPass
// we don't analyze synthesized void methods.
if ((method.IsImplicitlyDeclared && !method.IsScriptInitializer) || Analyze(compilation, method, block, diagnostics))
{
block = AppendImplicitReturn(block, method, (CSharpSyntaxNode)(method as SourceMethodSymbol)?.BodySyntax);
block = AppendImplicitReturn(block, method, (CSharpSyntaxNode)(method as SourceMethodSymbol)?.BodySyntax, originalBodyNested);
}
}
else if (Analyze(compilation, method, block, diagnostics))
......@@ -78,6 +80,25 @@ internal class FlowAnalysisPass
return block;
}
private static BoundBlock AppendImplicitReturn(BoundBlock body, MethodSymbol method, CSharpSyntaxNode syntax, bool originalBodyNested)
{
if (originalBodyNested)
{
var statements = body.Statements;
int n = statements.Length;
var builder = ArrayBuilder<BoundStatement>.GetInstance(n);
builder.AddRange(statements, n - 1);
builder.Add(AppendImplicitReturn((BoundBlock)statements[n - 1], method, syntax));
return body.Update(body.Locals, builder.ToImmutableAndFree());
}
else
{
return AppendImplicitReturn(body, method, syntax);
}
}
// insert the implicit "return" statement at the end of the method body
// Normally, we wouldn't bother attaching syntax trees to compiler-generated nodes, but these
// ones are going to have sequence points.
......@@ -109,14 +130,7 @@ internal static BoundBlock AppendImplicitReturn(BoundBlock body, MethodSymbol me
{ WasCompilerGenerated = true };
}
switch (body.Kind)
{
case BoundKind.Block:
return body.Update(body.Locals, body.Statements.Add(ret));
default:
return new BoundBlock(syntax, ImmutableArray<LocalSymbol>.Empty, ImmutableArray.Create(ret, body));
}
return body.Update(body.Locals, body.Statements.Add(ret));
}
private static bool Analyze(
......
......@@ -585,8 +585,8 @@ public static void Main(string[] args)
<entry offset=""0x8"" startLine=""7"" startColumn=""2"" endLine=""7"" endColumn=""3"" />
</sequencePoints>
<scope startOffset=""0x0"" endOffset=""0x9"">
<scope startOffset=""0x7"" endOffset=""0x8"">
<local name=""d"" il_index=""0"" il_start=""0x7"" il_end=""0x8"" attributes=""0"" />
<scope startOffset=""0x7"" endOffset=""0x9"">
<local name=""d"" il_index=""0"" il_start=""0x7"" il_end=""0x9"" attributes=""0"" />
</scope>
</scope>
</method>
......
......@@ -553,8 +553,8 @@ public C(int a, int b) : base(() => a)
</sequencePoints>
<scope startOffset=""0x0"" endOffset=""0x6c"">
<local name=""CS$&lt;&gt;8__locals0"" il_index=""0"" il_start=""0x0"" il_end=""0x6c"" attributes=""0"" />
<scope startOffset=""0x27"" endOffset=""0x6b"">
<local name=""CS$&lt;&gt;8__locals1"" il_index=""1"" il_start=""0x27"" il_end=""0x6b"" attributes=""0"" />
<scope startOffset=""0x27"" endOffset=""0x6c"">
<local name=""CS$&lt;&gt;8__locals1"" il_index=""1"" il_start=""0x27"" il_end=""0x6c"" attributes=""0"" />
</scope>
</scope>
</method>
......
......@@ -572,6 +572,136 @@ void Method()
</symbols>");
}
[WorkItem(7244)]
[Fact]
public void ConstructorsWithoutInitializers()
{
var source =
@"class C
{
C()
{
object o;
}
C(object x)
{
object y = x;
}
}";
var c = CreateCompilationWithMscorlibAndSystemCore(source, options: TestOptions.DebugDll);
c.VerifyPdb("C..ctor",
@"<symbols>
<methods>
<method containingType=""C"" name="".ctor"">
<customDebugInfo>
<using>
<namespace usingCount=""0"" />
</using>
<encLocalSlotMap>
<slot kind=""0"" offset=""18"" />
</encLocalSlotMap>
</customDebugInfo>
<sequencePoints>
<entry offset=""0x0"" startLine=""3"" startColumn=""5"" endLine=""3"" endColumn=""8"" />
<entry offset=""0x7"" startLine=""4"" startColumn=""5"" endLine=""4"" endColumn=""6"" />
<entry offset=""0x8"" startLine=""6"" startColumn=""5"" endLine=""6"" endColumn=""6"" />
</sequencePoints>
<scope startOffset=""0x0"" endOffset=""0x9"">
<scope startOffset=""0x7"" endOffset=""0x9"">
<local name=""o"" il_index=""0"" il_start=""0x7"" il_end=""0x9"" attributes=""0"" />
</scope>
</scope>
</method>
<method containingType=""C"" name="".ctor"" parameterNames=""x"">
<customDebugInfo>
<forward declaringType=""C"" methodName="".ctor"" />
<encLocalSlotMap>
<slot kind=""0"" offset=""18"" />
</encLocalSlotMap>
</customDebugInfo>
<sequencePoints>
<entry offset=""0x0"" startLine=""7"" startColumn=""5"" endLine=""7"" endColumn=""16"" />
<entry offset=""0x7"" startLine=""8"" startColumn=""5"" endLine=""8"" endColumn=""6"" />
<entry offset=""0x8"" startLine=""9"" startColumn=""9"" endLine=""9"" endColumn=""22"" />
<entry offset=""0xa"" startLine=""10"" startColumn=""5"" endLine=""10"" endColumn=""6"" />
</sequencePoints>
<scope startOffset=""0x0"" endOffset=""0xb"">
<scope startOffset=""0x7"" endOffset=""0xb"">
<local name=""y"" il_index=""0"" il_start=""0x7"" il_end=""0xb"" attributes=""0"" />
</scope>
</scope>
</method>
</methods>
</symbols>");
}
[WorkItem(7244)]
[Fact]
public void ConstructorsWithInitializers()
{
var source =
@"class C
{
static object G = 1;
object F = G;
C()
{
object o;
}
C(object x)
{
object y = x;
}
}";
var c = CreateCompilationWithMscorlibAndSystemCore(source, options: TestOptions.DebugDll);
c.VerifyPdb("C..ctor",
@"<symbols>
<methods>
<method containingType=""C"" name="".ctor"">
<customDebugInfo>
<using>
<namespace usingCount=""0"" />
</using>
<encLocalSlotMap>
<slot kind=""0"" offset=""18"" />
</encLocalSlotMap>
</customDebugInfo>
<sequencePoints>
<entry offset=""0x0"" startLine=""4"" startColumn=""5"" endLine=""4"" endColumn=""18"" />
<entry offset=""0xb"" startLine=""5"" startColumn=""5"" endLine=""5"" endColumn=""8"" />
<entry offset=""0x12"" startLine=""6"" startColumn=""5"" endLine=""6"" endColumn=""6"" />
<entry offset=""0x13"" startLine=""8"" startColumn=""5"" endLine=""8"" endColumn=""6"" />
</sequencePoints>
<scope startOffset=""0x0"" endOffset=""0x14"">
<scope startOffset=""0x12"" endOffset=""0x14"">
<local name=""o"" il_index=""0"" il_start=""0x12"" il_end=""0x14"" attributes=""0"" />
</scope>
</scope>
</method>
<method containingType=""C"" name="".ctor"" parameterNames=""x"">
<customDebugInfo>
<forward declaringType=""C"" methodName="".ctor"" />
<encLocalSlotMap>
<slot kind=""0"" offset=""18"" />
</encLocalSlotMap>
</customDebugInfo>
<sequencePoints>
<entry offset=""0x0"" startLine=""4"" startColumn=""5"" endLine=""4"" endColumn=""18"" />
<entry offset=""0xb"" startLine=""9"" startColumn=""5"" endLine=""9"" endColumn=""16"" />
<entry offset=""0x12"" startLine=""10"" startColumn=""5"" endLine=""10"" endColumn=""6"" />
<entry offset=""0x13"" startLine=""11"" startColumn=""9"" endLine=""11"" endColumn=""22"" />
<entry offset=""0x15"" startLine=""12"" startColumn=""5"" endLine=""12"" endColumn=""6"" />
</sequencePoints>
<scope startOffset=""0x0"" endOffset=""0x16"">
<scope startOffset=""0x12"" endOffset=""0x16"">
<local name=""y"" il_index=""0"" il_start=""0x12"" il_end=""0x16"" attributes=""0"" />
</scope>
</scope>
</method>
</methods>
</symbols>");
}
/// <summary>
/// Although the debugging info attached to DebuggerHidden method is not used by the debugger
/// (the debugger doesn't ever stop in the method) Dev11 emits the info and so do we.
......
......@@ -26,7 +26,7 @@ internal ImmutableArray<Diagnostic> FlowDiagnostics(CSharpCompilation compilatio
var boundBody = MethodCompiler.BindMethodBody(sourceSymbol, new TypeCompilationState(sourceSymbol.ContainingType, compilation, null), new DiagnosticBag());
if (boundBody != null)
{
FlowAnalysisPass.Rewrite(sourceSymbol, boundBody, flowDiagnostics, hasTrailingExpression: false);
FlowAnalysisPass.Rewrite(sourceSymbol, boundBody, flowDiagnostics, hasTrailingExpression: false, originalBodyNested: false);
}
}
......
......@@ -5982,6 +5982,25 @@ public static void Main()
);
}
[Fact]
public void FieldAssignedInReferencedConstructor()
{
var text =
@"struct S
{
private readonly object _x;
S(object o)
{
_x = o;
}
S(object x, object y) : this(x ?? y)
{
}
}";
var comp = CreateCompilationWithMscorlib(text);
comp.VerifyDiagnostics(); // No CS0171 for S._x
}
[Fact()]
public void CS0172ERR_AmbigQM()
{
......@@ -19730,6 +19749,28 @@ public static void Main()
this.CompileAndVerify(source: text, expectedOutput: expected, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular.WithStrictFeature()).VerifyDiagnostics(fullExpected);
}
[Fact]
public void CS0472WRN_NubExprIsConstBool_ConstructorInitializer()
{
var text =
@"class A
{
internal A(bool b)
{
}
}
class B : A
{
B(int i) : base(i == null)
{
}
}";
CreateCompilationWithMscorlib(text).VerifyDiagnostics(
// (9,21): warning CS0472: The result of the expression is always 'false' since a value of type 'int' is never equal to 'null' of type 'int?'
// B(int i) : base(i == null)
Diagnostic(ErrorCode.WRN_NubExprIsConstBool, "i == null").WithArguments("false", "int", "int?").WithLocation(9, 21));
}
[Fact]
public void CS0612WRN_DeprecatedSymbol()
{
......
......@@ -3,16 +3,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis.CodeGen;
using Microsoft.CodeAnalysis.CSharp.Emit;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
......@@ -23,60 +19,24 @@ public abstract class CompilingTestBase : CSharpTestBase
private const string DefaultMethodName = "M";
internal static BoundBlock ParseAndBindMethodBody(string program, string typeName = DefaultTypeName, string methodName = DefaultMethodName)
{
var body = ParseAndBindMethodBody(program, false, typeName, methodName);
return (BoundBlock)body;
}
internal static BoundStatement ParseAndBindMethodBody(string program, bool lower, string typeName = DefaultTypeName, string methodName = DefaultMethodName)
{
var compilation = CreateCompilationWithMscorlib(program);
var method = (MethodSymbol)compilation.GlobalNamespace.GetTypeMembers(typeName).Single().GetMembers(methodName).Single();
var diagnostics = DiagnosticBag.GetInstance();
try
{
// Provide an Emit.Module so that the lowering passes will be run
var module = new PEAssemblyBuilder(
(SourceAssemblySymbol)compilation.Assembly,
emitOptions: EmitOptions.Default,
outputKind: OutputKind.ConsoleApplication,
serializationProperties: GetDefaultModulePropertiesForSerialization(),
manifestResources: Enumerable.Empty<ResourceDescription>());
TypeCompilationState compilationState = new TypeCompilationState(method.ContainingType, compilation, module);
var block = MethodCompiler.BindMethodBody(method, compilationState, diagnostics);
if ((block == null) || !lower)
{
return block;
}
StateMachineTypeSymbol stateMachineTypeOpt;
VariableSlotAllocator lazyVariableSlotAllocator = null;
var lambdaDebugInfoBuilder = ArrayBuilder<LambdaDebugInfo>.GetInstance();
var closureDebugInfoBuilder = ArrayBuilder<ClosureDebugInfo>.GetInstance();
var body = MethodCompiler.LowerBodyOrInitializer(
method: method,
methodOrdinal: 0,
body: block,
previousSubmissionFields: null,
compilationState: compilationState,
diagnostics: diagnostics,
lazyVariableSlotAllocator: ref lazyVariableSlotAllocator,
lambdaDebugInfoBuilder: lambdaDebugInfoBuilder,
closureDebugInfoBuilder: closureDebugInfoBuilder,
stateMachineTypeOpt: out stateMachineTypeOpt);
lambdaDebugInfoBuilder.Free();
closureDebugInfoBuilder.Free();
return body;
}
finally
{
diagnostics.Free();
}
// Provide an Emit.Module so that the lowering passes will be run
var module = new PEAssemblyBuilder(
(SourceAssemblySymbol)compilation.Assembly,
emitOptions: EmitOptions.Default,
outputKind: OutputKind.ConsoleApplication,
serializationProperties: GetDefaultModulePropertiesForSerialization(),
manifestResources: Enumerable.Empty<ResourceDescription>());
TypeCompilationState compilationState = new TypeCompilationState(method.ContainingType, compilation, module);
var diagnostics = DiagnosticBag.GetInstance();
var block = MethodCompiler.BindMethodBody(method, compilationState, diagnostics);
diagnostics.Free();
return block;
}
public static string DumpDiagnostic(Diagnostic diagnostic)
......
......@@ -429,6 +429,118 @@ End Class
</symbols>)
End Sub
<Fact()>
Public Sub ConstructorsWithoutInitializers()
Dim source =
<compilation>
<file><![CDATA[
Class C
Sub New()
Dim o As Object
End Sub
Sub New(x As Object)
Dim y As Object = x
End Sub
End Class
]]></file>
</compilation>
Dim compilation = CreateCompilationWithMscorlib(source, TestOptions.DebugDll)
compilation.VerifyPdb("C..ctor",
<symbols>
<methods>
<method containingType="C" name=".ctor">
<customDebugInfo>
<encLocalSlotMap>
<slot kind="0" offset="4"/>
</encLocalSlotMap>
</customDebugInfo>
<sequencePoints>
<entry offset="0x0" startLine="2" startColumn="5" endLine="2" endColumn="14"/>
<entry offset="0x8" startLine="4" startColumn="5" endLine="4" endColumn="12"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0x9">
<currentnamespace name=""/>
<local name="o" il_index="0" il_start="0x0" il_end="0x9" attributes="0"/>
</scope>
</method>
<method containingType="C" name=".ctor" parameterNames="x">
<customDebugInfo>
<encLocalSlotMap>
<slot kind="0" offset="4"/>
</encLocalSlotMap>
</customDebugInfo>
<sequencePoints>
<entry offset="0x0" startLine="5" startColumn="5" endLine="5" endColumn="25"/>
<entry offset="0x8" startLine="6" startColumn="13" endLine="6" endColumn="28"/>
<entry offset="0xf" startLine="7" startColumn="5" endLine="7" endColumn="12"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0x10">
<importsforward declaringType="C" methodName=".ctor"/>
<local name="y" il_index="0" il_start="0x0" il_end="0x10" attributes="0"/>
</scope>
</method>
</methods>
</symbols>)
End Sub
<Fact()>
Public Sub ConstructorsWithInitializers()
Dim source =
<compilation>
<file><![CDATA[
Class C
Shared G As Object = 1
Private F As Object = G
Sub New()
Dim o As Object
End Sub
Sub New(x As Object)
Dim y As Object = x
End Sub
End Class
]]></file>
</compilation>
Dim compilation = CreateCompilationWithMscorlib(source, TestOptions.DebugDll)
compilation.VerifyPdb("C..ctor",
<symbols>
<methods>
<method containingType="C" name=".ctor">
<customDebugInfo>
<encLocalSlotMap>
<slot kind="0" offset="4"/>
</encLocalSlotMap>
</customDebugInfo>
<sequencePoints>
<entry offset="0x0" startLine="4" startColumn="5" endLine="4" endColumn="14"/>
<entry offset="0x8" startLine="3" startColumn="13" endLine="3" endColumn="28"/>
<entry offset="0x18" startLine="6" startColumn="5" endLine="6" endColumn="12"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0x19">
<importsforward declaringType="C" methodName=".cctor"/>
<local name="o" il_index="0" il_start="0x0" il_end="0x19" attributes="0"/>
</scope>
</method>
<method containingType="C" name=".ctor" parameterNames="x">
<customDebugInfo>
<encLocalSlotMap>
<slot kind="0" offset="4"/>
</encLocalSlotMap>
</customDebugInfo>
<sequencePoints>
<entry offset="0x0" startLine="7" startColumn="5" endLine="7" endColumn="25"/>
<entry offset="0x8" startLine="3" startColumn="13" endLine="3" endColumn="28"/>
<entry offset="0x18" startLine="8" startColumn="13" endLine="8" endColumn="28"/>
<entry offset="0x1f" startLine="9" startColumn="5" endLine="9" endColumn="12"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0x20">
<importsforward declaringType="C" methodName=".cctor"/>
<local name="y" il_index="0" il_start="0x0" il_end="0x20" attributes="0"/>
</scope>
</method>
</methods>
</symbols>)
End Sub
<Fact()>
Public Sub TryCatchFinally()
Dim source =
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册