Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4109,6 +4109,92 @@ .maxstack 3
""");
}

[Fact]
public void UnionDeclaration_01()
{
string source = """
_ = (TestUnion)123;
Microsoft.CodeAnalysis.Runtime.Instrumentation.FlushPayload();

public union TestUnion(string, int);
""" + InstrumentationHelperSource;

var checker = new CSharpInstrumentationChecker();
checker.Method(7, 1, snippet: "", expectBodySpan: false)
.True("_ = (TestUnion)123;")
.True("Microsoft.CodeAnalysis.Runtime.Instrumentation.FlushPayload();");

var verifier = CompileAndVerify([source, UnionAttributeSource, IUnionSource], options: TestOptions.ReleaseExe);
checker.CompleteCheck(verifier.Compilation, source);
verifier.VerifyDiagnostics();

AssertNotInstrumented(verifier, "TestUnion.Value.get");
AssertInstrumented(verifier, "TestUnion..ctor(int)");
AssertInstrumented(verifier, "TestUnion..ctor(string)");

verifier.VerifyIL("TestUnion..ctor(int)", """
{
// Code size 63 (0x3f)
.maxstack 5
IL_0000: ldsfld "bool[][] <PrivateImplementationDetails>.PayloadRoot0"
IL_0005: ldtoken "TestUnion..ctor(int)"
IL_000a: ldelem.ref
IL_000b: brtrue.s IL_0032
IL_000d: ldsfld "System.Guid <PrivateImplementationDetails>.MVID"
IL_0012: ldtoken "TestUnion..ctor(int)"
IL_0017: ldtoken Source Document 0
IL_001c: ldsfld "bool[][] <PrivateImplementationDetails>.PayloadRoot0"
IL_0021: ldtoken "TestUnion..ctor(int)"
IL_0026: ldelema "bool[]"
IL_002b: ldc.i4.0
IL_002c: call "bool[] Microsoft.CodeAnalysis.Runtime.Instrumentation.CreatePayload(System.Guid, int, int, ref bool[], int)"
IL_0031: pop
IL_0032: ldarg.0
IL_0033: ldarg.1
IL_0034: box "int"
IL_0039: stfld "object TestUnion.<Value>k__BackingField"
IL_003e: ret
}
""");

verifier = CompileAndVerify([source, UnionAttributeSource, IUnionSource], options: TestOptions.DebugExe);
checker.CompleteCheck(verifier.Compilation, source);
verifier.VerifyDiagnostics();

AssertNotInstrumented(verifier, "TestUnion.Value.get");
AssertInstrumented(verifier, "TestUnion..ctor(int)");
AssertInstrumented(verifier, "TestUnion..ctor(string)");

verifier.VerifyIL("TestUnion..ctor(int)", """
{
// Code size 66 (0x42)
.maxstack 5
.locals init (bool[] V_0)
IL_0000: ldsfld "bool[][] <PrivateImplementationDetails>.PayloadRoot0"
IL_0005: ldtoken "TestUnion..ctor(int)"
IL_000a: ldelem.ref
IL_000b: stloc.0
IL_000c: ldloc.0
IL_000d: brtrue.s IL_0034
IL_000f: ldsfld "System.Guid <PrivateImplementationDetails>.MVID"
IL_0014: ldtoken "TestUnion..ctor(int)"
IL_0019: ldtoken Source Document 0
IL_001e: ldsfld "bool[][] <PrivateImplementationDetails>.PayloadRoot0"
IL_0023: ldtoken "TestUnion..ctor(int)"
IL_0028: ldelema "bool[]"
IL_002d: ldc.i4.0
IL_002e: call "bool[] Microsoft.CodeAnalysis.Runtime.Instrumentation.CreatePayload(System.Guid, int, int, ref bool[], int)"
IL_0033: stloc.0
IL_0034: ldarg.0
IL_0035: ldarg.1
IL_0036: box "int"
IL_003b: stfld "object TestUnion.<Value>k__BackingField"
IL_0040: nop
IL_0041: ret
}
""");
}

private static void AssertNotInstrumented(CompilationVerifier verifier, string qualifiedMethodName)
=> AssertInstrumented(verifier, qualifiedMethodName, expected: false);

Expand All @@ -4123,7 +4209,7 @@ private static void AssertInstrumented(CompilationVerifier verifier, string qual
Assert.True(expected == instrumented, $"Method '{qualifiedMethodName}' should {(expected ? "be" : "not be")} instrumented. Actual IL:{Environment.NewLine}{il}");
}

private CompilationVerifier CompileAndVerify(string source, string expectedOutput = null, CSharpCompilationOptions options = null, CSharpParseOptions parseOptions = null, Verification verify = default)
private CompilationVerifier CompileAndVerify(CSharpTestSource source, string expectedOutput = null, CSharpCompilationOptions options = null, CSharpParseOptions parseOptions = null, Verification verify = default)
{
return base.CompileAndVerify(
source,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ private static string WithHelpers(string source, bool displayContainingType = fa
"""
};

private CompilationVerifier CompileAndVerify(string source, string? ilVerifyMessage = null, string? expectedOutput = null, TargetFramework targetFramework = s_targetFramework)
private CompilationVerifier CompileAndVerify(CSharpTestSource source, string? ilVerifyMessage = null, string? expectedOutput = null, TargetFramework targetFramework = s_targetFramework)
=> CompileAndVerify(
source,
options: (expectedOutput != null) ? TestOptions.UnsafeDebugExe : TestOptions.UnsafeDebugDll,
Expand All @@ -200,7 +200,7 @@ private CompilationVerifier CompileAndVerify(string source, string? ilVerifyMess
expectedOutput: expectedOutput);

// Only used to diagnose test verification failures (rename CompileAndVerify to CompileAndVerifyFails and rerun).
public CompilationVerifier CompileAndVerifyFails(string source, string? ilVerifyMessage = null, string? expectedOutput = null)
public CompilationVerifier CompileAndVerifyFails(CSharpTestSource source, string? ilVerifyMessage = null, string? expectedOutput = null)
=> CompileAndVerify(
source,
options: (expectedOutput != null) ? TestOptions.UnsafeDebugExe : TestOptions.UnsafeDebugDll,
Expand Down Expand Up @@ -7447,6 +7447,50 @@ public void M()
M: L1 -> P'i1'[0]
E.M: Returned
Program.<Main>$: Returned
""");
}

[Fact]
public void UnionDeclaration_01()
{
var source = WithHelpers(@"
public union TestUnion(string, int);
");
var verifier = CompileAndVerify([source, UnionAttributeSource, IUnionSource]);

AssertNotInstrumented(verifier, "TestUnion.Value.get");
AssertInstrumented(verifier, "TestUnion..ctor(string)");
verifier.VerifyIL("TestUnion..ctor(int)", $$"""
{
// Code size 46 (0x2e)
.maxstack 3
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0)
IL_0000: ldtoken "TestUnion..ctor(int)"
IL_0005: call "Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)"
IL_000a: stloc.0
.try
{
IL_000b: ldloca.s V_0
IL_000d: ldarg.1
IL_000e: ldc.i4.0
IL_000f: call "void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(uint, int)"
IL_0014: nop
IL_0015: ldarg.0
IL_0016: ldarg.1
IL_0017: box "int"
IL_001c: stfld "object TestUnion.<Value>k__BackingField"
IL_0021: nop
IL_0022: leave.s IL_002d
}
finally
{
IL_0024: ldloca.s V_0
IL_0026: call "void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()"
IL_002b: nop
IL_002c: endfinally
}
IL_002d: ret
}
""");
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public sealed class ModuleCancellationTests : CSharpTestBase
{
private static readonly EmitOptions s_emitOptions = EmitOptions.Default.WithInstrumentationKinds([InstrumentationKind.ModuleCancellation]);

private CompilationVerifier CompileAndVerify(string source, string? expectedOutput = null, CSharpCompilationOptions? options = null, Verification? verification = null)
private CompilationVerifier CompileAndVerify(CSharpTestSource source, string? expectedOutput = null, CSharpCompilationOptions? options = null, Verification? verification = null)
=> CompileAndVerify(
source,
options: options ?? (expectedOutput != null ? TestOptions.UnsafeDebugExe : TestOptions.UnsafeDebugDll),
Expand Down Expand Up @@ -2801,4 +2801,31 @@ object G(CancellationToken token = default)
// definite assignment flow pass doesn't fail
CompileAndVerify(source).VerifyDiagnostics();
}

[Fact]
public void UnionDeclaration_01()
{
var source = """
public union TestUnion(string, int);
""";

var verifier = CompileAndVerify([source, UnionAttributeSource, IUnionSource]);

AssertNotInstrumented(verifier, "TestUnion.Value.get");

verifier.VerifyIL("TestUnion..ctor(int)", $$"""
{
// Code size 24 (0x18)
.maxstack 2
IL_0000: ldsflda "System.Threading.CancellationToken <PrivateImplementationDetails>.ModuleCancellationToken"
IL_0005: call "void System.Threading.CancellationToken.ThrowIfCancellationRequested()"
IL_000a: ldarg.0
IL_000b: ldarg.1
IL_000c: box "int"
IL_0011: stfld "object TestUnion.<Value>k__BackingField"
IL_0016: nop
IL_0017: ret
}
""");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public sealed class StackOverflowProbingTests : CSharpTestBase
{
private static readonly EmitOptions s_emitOptions = EmitOptions.Default.WithInstrumentationKinds([InstrumentationKind.StackOverflowProbing]);

private CompilationVerifier CompileAndVerify(string source, string? expectedOutput = null, CSharpCompilationOptions? options = null, Verification? verification = null)
private CompilationVerifier CompileAndVerify(CSharpTestSource source, string? expectedOutput = null, CSharpCompilationOptions? options = null, Verification? verification = null)
=> CompileAndVerify(
source,
options: options ?? (expectedOutput != null ? TestOptions.UnsafeDebugExe : TestOptions.UnsafeDebugDll),
Expand Down Expand Up @@ -764,4 +764,31 @@ .maxstack 2
}
""");
}

[Fact]
public void UnionDeclaration_01()
{
var source = """
public union TestUnion(string, int);
""";

var verifier = CompileAndVerify([source, UnionAttributeSource, IUnionSource]);

AssertNotInstrumented(verifier, "TestUnion.Value.get");

verifier.VerifyIL("TestUnion..ctor(int)", """
{
// Code size 20 (0x14)
.maxstack 2
IL_0000: call "void System.Runtime.CompilerServices.RuntimeHelpers.EnsureSufficientExecutionStack()"
IL_0005: nop
IL_0006: ldarg.0
IL_0007: ldarg.1
IL_0008: box "int"
IL_000d: stfld "object TestUnion.<Value>k__BackingField"
IL_0012: nop
IL_0013: ret
}
""");
}
}
Loading