Skip to content

Commit

Permalink
Fix detection of DisableRuntimeMarshalling delegate interop to only w…
Browse files Browse the repository at this point in the history
…arn when the delegate type is in an assembly with DisableRuntimeMarshalling
  • Loading branch information
jkoritzinsky committed Aug 19, 2022
1 parent efa5f8d commit 860d69f
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ public override void Initialize(AnalysisContext context)
var disabledRuntimeMarshallingAssemblyAnalyzer = new DisabledRuntimeMarshallingAssemblyAnalyzer(context.Compilation, autoLayoutCache);
disabledRuntimeMarshallingAssemblyAnalyzer.RegisterActions(context);
}
var delegateInteropUsageAnalyzer = new DelegateInteropUsageAnalyzer(context.Compilation, autoLayoutCache);
var delegateInteropUsageAnalyzer = new DelegateInteropUsageAnalyzer(context.Compilation, autoLayoutCache, disableRuntimeMarshallingAttribute);
delegateInteropUsageAnalyzer.RegisterActions(context, hasDisableRuntimeMarshallingAttribute);
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ private sealed class DelegateInteropUsageAnalyzer
private readonly IMethodSymbol? _getFunctionPointerForDelegateNonGeneric;
private readonly IMethodSymbol? _getFunctionPointerForDelegateGeneric;
private readonly AutoLayoutTypeCache _autoLayoutCache;
private readonly INamedTypeSymbol _disableRuntimeMarshallingAttribute;

public DelegateInteropUsageAnalyzer(Compilation compilation, AutoLayoutTypeCache autoLayoutCache)
public DelegateInteropUsageAnalyzer(Compilation compilation, AutoLayoutTypeCache autoLayoutCache, INamedTypeSymbol disableRuntimeMarshallingAttribute)
{
if (compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeInteropServicesMarshal, out var marshalType))
{
Expand All @@ -34,6 +35,7 @@ public DelegateInteropUsageAnalyzer(Compilation compilation, AutoLayoutTypeCache
}

_autoLayoutCache = autoLayoutCache;
_disableRuntimeMarshallingAttribute = disableRuntimeMarshallingAttribute;
}

public void RegisterActions(CompilationStartAnalysisContext context, bool hasDisableRuntimeMarshallingAttribute)
Expand Down Expand Up @@ -88,7 +90,10 @@ private void AnalyzeInvocation(OperationAnalysisContext context)

void AnalyzeDelegateType(OperationAnalysisContext context, IOperation operation, INamedTypeSymbol delegateType)
{
AnalyzeMethodSignature(_autoLayoutCache, context.ReportDiagnostic, delegateType.DelegateInvokeMethod, ImmutableArray.Create(operation.Syntax.GetLocation()), FeatureUnsupportedWhenRuntimeMarshallingDisabledDelegateUsage);
if (delegateType.ContainingAssembly.HasAttribute(_disableRuntimeMarshallingAttribute))
{
AnalyzeMethodSignature(_autoLayoutCache, context.ReportDiagnostic, delegateType.DelegateInvokeMethod, ImmutableArray.Create(operation.Syntax.GetLocation()), FeatureUnsupportedWhenRuntimeMarshallingDisabledDelegateUsage);
}
}
}

Expand Down Expand Up @@ -132,7 +137,10 @@ private void AnalyzeMethod(Action<Diagnostic> reportDiagnostic, IMethodSymbol sy

void AnalyzeDelegateMethodSignature(INamedTypeSymbol delegateType, ISymbol signatureSymbol)
{
AnalyzeMethodSignature(_autoLayoutCache, reportDiagnostic, delegateType.DelegateInvokeMethod, signatureSymbol.Locations, FeatureUnsupportedWhenRuntimeMarshallingDisabledDelegateUsage);
if (delegateType.ContainingAssembly.HasAttribute(_disableRuntimeMarshallingAttribute))
{
AnalyzeMethodSignature(_autoLayoutCache, reportDiagnostic, delegateType.DelegateInvokeMethod, signatureSymbol.Locations, FeatureUnsupportedWhenRuntimeMarshallingDisabledDelegateUsage);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -803,6 +803,55 @@ class C
await VerifyCSAnalyzerWithAdditionalAssemblyAsync(source, delegateDefinition);
}

[Fact]
[WorkItem(6094, "https://github.com/dotnet/roslyn-analyzers/issues/6094")]
public async Task CS_DelegateWith_NonBlittableParameter_PInvokeUsage_NoDisableRuntimeMarshalling_DoesNotEmit_Diagnostic()
{
string source = @"
using System;
using System.Runtime.InteropServices;
internal delegate void DelegateType(string[] str);
class C
{
[DllImport(""Native"")]
public static extern void PInvoke(DelegateType d);
[DllImport(""Native"")]
public static extern DelegateType PInvoke();
[DllImport(""Native"")]
public static extern void PInvokeArray(DelegateType[] d);
[DllImport(""Native"")]
public static extern DelegateType[] PInvokeArray();
}
";
await VerifyCSAnalyzerAsync(source);
}

[Fact]
[WorkItem(6094, "https://github.com/dotnet/roslyn-analyzers/issues/5995")]
public async Task CS_DelegateWithClassReturnValue_NoUnmanagedFunctionPointer_MarshalAPIUsage_NoDisableRuntimeMarshalling_DoesNotEmit_Diagnostic()
{
string source = @"
using System;
using System.Runtime.InteropServices;
public delegate string DelegateType();
class C
{
public static void M(DelegateType d, IntPtr i)
{
_ = Marshal.GetFunctionPointerForDelegate((Delegate)d);
_ = Marshal.GetFunctionPointerForDelegate(d);
_ = Marshal.GetDelegateForFunctionPointer(i, typeof(DelegateType));
_ = Marshal.GetDelegateForFunctionPointer<DelegateType>(i);
}
}
";
await VerifyCSAnalyzerAsync(source);
}

[Fact]
public async Task VB_DelegateWithClassReturnValue_Emits_Diagnostic()
{
Expand Down

0 comments on commit 860d69f

Please sign in to comment.