Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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,40 @@ .maxstack 3
""");
}

[Fact]
public void UnionDeclaration_01()
{
var comp0Ref = CreateCompilation([UnionAttributeSource, IUnionSource]).ToMetadataReference();

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, references: [comp0Ref], options: TestOptions.ReleaseExe);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be using the locally defined CompileAndVerify helper which passes

emitOptions: EmitOptions.Default.WithInstrumentationKinds(ImmutableArray.Create(InstrumentationKind.TestCoverage))

instead of the base class helper?

@AlekseyTs AlekseyTs Jul 29, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! Overloading base helpers is fragile because the new overloads might not be used by a specific call site.

checker.CompleteCheck(verifier.Compilation, source);
verifier.VerifyDiagnostics();

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

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

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

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

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
}
""");
Comment thread
AlekseyTs marked this conversation as resolved.
Resolved
}
}
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