From dca5ef23c04e053cc932972eae28fb6b59e79cbc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Mar 2026 17:36:14 +0000 Subject: [PATCH 1/3] Initial plan From 9b97051fa204b6fa87ef1634df8fb77a0d4e8b9e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Mar 2026 18:10:34 +0000 Subject: [PATCH 2/3] Fix GeneratedComInterface to add unsafe to derived interface when base has unsafe methods Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com> Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/0c4933d7-3aef-4bef-8952-d134aa2a2767 --- .../ComInterfaceGenerator.cs | 23 +++++++++++++++---- .../CodeSnippets.cs | 19 +++++++++++++++ .../Compiles.cs | 1 + 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.cs index 4d71dc9d788a99..cc971956da709d 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.cs @@ -150,11 +150,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) GenerateImplementationInterface(x, ct).NormalizeWhitespace(), GenerateInterfaceImplementationVtable(x, ct).NormalizeWhitespace(), GenerateImplementationVTableMethods(x, ct).NormalizeWhitespace(), - x.Interface.Info.TypeDefinitionContext.WrapMemberInContainingSyntaxWithUnsafeModifier(TypeDeclaration(x.Interface.Info.ContainingSyntax.TypeKind, x.Interface.Info.ContainingSyntax.Identifier) - .WithModifiers(x.Interface.Info.ContainingSyntax.Modifiers) - .WithTypeParameterList(x.Interface.Info.ContainingSyntax.TypeParameters) - .WithMembers(List(x.ShadowingMethods.Select(m => m.Shadow)))) - .NormalizeWhitespace(), + GenerateShadowingMethodsInterface(x), GenerateImplementationVTable(x, ct).NormalizeWhitespace(), GenerateInterfaceInformation(x.Interface.Info, ct).NormalizeWhitespace(), GenerateIUnknownDerivedAttributeApplication(x.Interface.Info, ct).NormalizeWhitespace() @@ -231,6 +227,23 @@ private static MemberDeclarationSyntax GenerateIUnknownDerivedAttributeApplicati .WithTypeParameterList(context.ContainingSyntax.TypeParameters) .AddAttributeLists(AttributeList(SingletonSeparatedList(s_iUnknownDerivedAttributeTemplate)))); + private static MemberDeclarationSyntax GenerateShadowingMethodsInterface(ComInterfaceAndMethodsContext interfaceMethods) + { + var shadowingMethods = interfaceMethods.ShadowingMethods.Select(m => m.Shadow).ToImmutableArray(); + bool needsUnsafe = shadowingMethods.Any( + static m => m.DescendantNodes().OfType().Any() + || m.DescendantNodes().OfType().Any()); + var containingSyntax = interfaceMethods.Interface.Info.ContainingSyntax; + return interfaceMethods.Interface.Info.TypeDefinitionContext.WrapMemberInContainingSyntaxWithUnsafeModifier( + TypeDeclaration(containingSyntax.TypeKind, containingSyntax.Identifier) + .WithModifiers(needsUnsafe + ? containingSyntax.Modifiers.AddToModifiers(SyntaxKind.UnsafeKeyword) + : containingSyntax.Modifiers) + .WithTypeParameterList(containingSyntax.TypeParameters) + .WithMembers(List(shadowingMethods))) + .NormalizeWhitespace(); + } + private static bool IsHResultLikeType(ManagedTypeInfo type) { string typeName = type.FullTypeName.Split('.', ':')[^1]; diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs index 514b400c3f1c91..ad68b2dfb5761e 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs @@ -701,6 +701,25 @@ unsafe partial interface INativeDerived : INativeAPIBase } """; + public string DerivedComInterfaceTypeWithUnsafeBaseMethod => $$""" + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.Marshalling; + + [assembly:DisableRuntimeMarshalling] + + {{GeneratedComInterface()}} + partial interface IComInterfaceBase + { + unsafe void Method(void* pBuffer); + } + {{GeneratedComInterface()}} + partial interface IComInterfaceDerived : IComInterfaceBase + { + void Method2(); + } + """; + public class ManagedToUnmanaged : IVirtualMethodIndexSignatureProvider { public MarshalDirection Direction => MarshalDirection.ManagedToUnmanaged; diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs index b255a2a29a44df..c0806b2853d8f5 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs @@ -350,6 +350,7 @@ public static IEnumerable ComInterfaceSnippetsToCompile() yield return new object[] { ID(), codeSnippets.ForwarderWithPreserveSigAndRefKind("in") }; yield return new object[] { ID(), codeSnippets.ForwarderWithPreserveSigAndRefKind("out") }; yield return new object[] { ID(), codeSnippets.ComInterfaceWithNativeMarshalling }; + yield return new object[] { ID(), codeSnippets.DerivedComInterfaceTypeWithUnsafeBaseMethod }; } public static IEnumerable ManagedToUnmanagedComInterfaceSnippetsToCompile() From 2ccd618bc41ac7a032570925d8f44700c1baa050 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Mar 2026 18:37:42 +0000 Subject: [PATCH 3/3] Unconditionally add unsafe to generated shadowing methods interface Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com> Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/f6544f27-a7ba-4d9a-8e9d-bd9ad2ce3100 --- .../gen/ComInterfaceGenerator/ComInterfaceGenerator.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.cs index cc971956da709d..116ee786fb86cd 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.cs @@ -229,18 +229,12 @@ private static MemberDeclarationSyntax GenerateIUnknownDerivedAttributeApplicati private static MemberDeclarationSyntax GenerateShadowingMethodsInterface(ComInterfaceAndMethodsContext interfaceMethods) { - var shadowingMethods = interfaceMethods.ShadowingMethods.Select(m => m.Shadow).ToImmutableArray(); - bool needsUnsafe = shadowingMethods.Any( - static m => m.DescendantNodes().OfType().Any() - || m.DescendantNodes().OfType().Any()); var containingSyntax = interfaceMethods.Interface.Info.ContainingSyntax; return interfaceMethods.Interface.Info.TypeDefinitionContext.WrapMemberInContainingSyntaxWithUnsafeModifier( TypeDeclaration(containingSyntax.TypeKind, containingSyntax.Identifier) - .WithModifiers(needsUnsafe - ? containingSyntax.Modifiers.AddToModifiers(SyntaxKind.UnsafeKeyword) - : containingSyntax.Modifiers) + .WithModifiers(containingSyntax.Modifiers.AddToModifiers(SyntaxKind.UnsafeKeyword)) .WithTypeParameterList(containingSyntax.TypeParameters) - .WithMembers(List(shadowingMethods))) + .WithMembers(List(interfaceMethods.ShadowingMethods.Select(m => m.Shadow)))) .NormalizeWhitespace(); }