Skip to content
Open
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 @@ -9,11 +9,6 @@ namespace ILLink.Shared.TrimAnalysis
{
internal partial record MethodParameterValue
{
public MethodParameterValue (IParameterSymbol parameterSymbol)
: this (new ParameterProxy (parameterSymbol)) { }
public MethodParameterValue (IMethodSymbol methodSymbol, ParameterIndex parameterIndex, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes)
: this (new (new (methodSymbol), parameterIndex), dynamicallyAccessedMemberTypes) { }

public MethodParameterValue (ParameterProxy parameter)
: this (parameter, FlowAnnotations.GetMethodParameterAnnotation (parameter)) { }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ namespace ILLink.Shared.TypeSystemProxy
{
internal partial struct ParameterProxy
{
public ParameterProxy (IParameterSymbol parameter)
public ParameterProxy (IParameterSymbol parameter, IMethodSymbol method)
{
Method = new ((IMethodSymbol) parameter.ContainingSymbol);
Index = (ParameterIndex) parameter.Ordinal + (Method.HasImplicitThis () ? 1 : 0);
Method = new (method);
Index = (ParameterIndex) parameter.Ordinal + (method.HasImplicitThis () ? 1 : 0);
}

public partial ReferenceKind GetReferenceKind ()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public override MultiValue VisitInstanceReference (IInstanceReferenceOperation i
// The instance reference operation represents a 'this' or 'base' reference to the containing type,
// so we get the annotation from the containing method.
if (instanceRef.Type != null && instanceRef.Type.IsTypeInterestingForDataflow ())
return new MethodParameterValue (Method, (ParameterIndex) 0, Method.GetDynamicallyAccessedMemberTypes ());
return new MethodParameterValue (new ParameterProxy (new (Method), (ParameterIndex) 0));

return TopValue;
}
Expand Down Expand Up @@ -187,7 +187,11 @@ public override MultiValue GetFieldTargetValue (IFieldSymbol field)

public override MultiValue GetParameterTargetValue (IParameterSymbol parameter)
{
return parameter.Type.IsTypeInterestingForDataflow () ? new MethodParameterValue (parameter) : TopValue;
// Skip analysis for extension members (we have no way to represent a parameter on an extension type).
if (parameter.ContainingSymbol is not IMethodSymbol method)
return TopValue;

return parameter.Type.IsTypeInterestingForDataflow () ? new MethodParameterValue (new ParameterProxy (parameter, method)) : TopValue;
}

public override void HandleAssignment (MultiValue source, MultiValue target, IOperation operation)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,12 @@ public Task EventDataFlow ()
return RunTest ();
}

[Fact]
public Task ExtensionsDataFlow ()
{
return RunTest ();
}

[Fact]
public Task FieldDataFlow ()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Diagnostics.CodeAnalysis;
using Mono.Linker.Tests.Cases.Expectations.Assertions;
using Mono.Linker.Tests.Cases.Expectations.Helpers;

namespace Mono.Linker.Tests.Cases.DataFlow
{
[SkipKeptItemsValidation]
[ExpectedNoWarnings]
public class ExtensionsDataFlow
{
public static void Main ()
{
TestExtensionMethod ();
TestExtensionMethodMismatch ();
TestExtensionMethodRequires ();
}

[ExpectedWarning ("IL2072", "GetWithMethods", nameof (Extensions.ExtensionMethod))]
static void TestExtensionMethod ()
{
GetWithFields ().ExtensionMethod ();
GetWithMethods ().ExtensionMethod ();
}

static void TestExtensionMethodMismatch ()
{
GetWithFields ().ExtensionMethodMismatch ();
}

[ExpectedWarning ("IL2026", nameof (Extensions.ExtensionMethodRequires))]
static void TestExtensionMethodRequires ()
{
GetWithFields ().ExtensionMethodRequires ();
}

[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)]
static Type GetWithFields () => null;

[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
static Type GetWithMethods () => null;
}

[ExpectedNoWarnings]
public static class Extensions
{
public static void ExtensionMethod ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] this Type type)
{
type.RequiresPublicFields ();
}

[ExpectedWarning ("IL2067", "RequiresPublicMethods")]
public static void ExtensionMethodMismatch ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] this Type type)
{
type.RequiresPublicMethods ();
}

[RequiresUnreferencedCode (nameof (ExtensionMethodRequires))]
public static void ExtensionMethodRequires ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] this Type type)
{
}
}
}
Loading