Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more DataFlow tests from linker to NativeAOT #72777

Merged
merged 7 commits into from
Aug 1, 2022
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ internal static bool TryGetRequiresAttribute(TypeSystemEntity member, string req
decoded = ecmaMethod.GetDecodedCustomAttribute("System.Diagnostics.CodeAnalysis", requiresAttributeName);
break;
case MetadataType type:
var ecmaType = type as EcmaType;
var ecmaType = type.GetTypeDefinition() as EcmaType;
if (ecmaType == null)
return false;
decoded = ecmaType.GetDecodedCustomAttribute("System.Diagnostics.CodeAnalysis", requiresAttributeName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,10 @@ public static bool IsTypeInterestingForDataflow(TypeDesc type)
if (type.IsWellKnownType(WellKnownType.String))
return true;

// ByRef over an interesting type is itself interesting
if (type is ByRefType byRefType)
type = byRefType.ParameterType;

if (!type.IsDefType)
return false;

Expand Down Expand Up @@ -584,7 +588,7 @@ protected override TypeAnnotations CreateValueFromKey(TypeDesc key)
{
if (typeGenericParameterAnnotations == null)
typeGenericParameterAnnotations = new DynamicallyAccessedMemberTypes[ecmaType.Instantiation.Length];
typeGenericParameterAnnotations[genericParameter.Index] = annotation;
typeGenericParameterAnnotations[genericParameterIndex] = annotation;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1237,6 +1237,14 @@ private void HandleCall(
ValueNodeList methodArguments = PopCallArguments(currentStack, calledMethod, callingMethodBody, isNewObj,
offset, out newObjValue);

// Multi-dimensional array access is represented as a call to a special Get method on the array (runtime provided method)
// We don't track multi-dimensional arrays in any way, so return unknown value.
if (calledMethod is ArrayMethod { Kind: ArrayMethodKind.Get })
{
currentStack.Push(new StackSlot(UnknownValue.Instance));
return;
}
vitek-karas marked this conversation as resolved.
Show resolved Hide resolved

var dereferencedMethodParams = new List<MultiValue>();
foreach (var argument in methodArguments)
dereferencedMethodParams.Add(DereferenceValue(argument, locals, ref interproceduralState));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// 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;

namespace Mono.Linker.Tests.Cases.Expectations.Assertions
{
[AttributeUsage (AttributeTargets.Class)]
public sealed class KeptPrivateImplementationDetailsAttribute : KeptAttribute
{
public KeptPrivateImplementationDetailsAttribute (string methodName)
{
if (string.IsNullOrEmpty (methodName))
throw new ArgumentException ("Value cannot be null or empty.", nameof (methodName));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
// 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.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text;
using Mono.Linker.Tests.Cases.Expectations.Assertions;

namespace Mono.Linker.Tests.Cases.DataFlow
{
[ExpectedNoWarnings]
public class ApplyTypeAnnotations
{
public static void Main ()
{
TestFromTypeOf ();
TestFromTypeGetTypeOverConstant ();
TestFromStringContantWithAnnotation ();
TestFromStringConstantWithGeneric ();
TestFromStringConstantWithGenericAndAssemblyQualified ();
TestFromStringConstantWithGenericAndAssemblyQualifiedInvalidAssembly ();
TestFromStringConstantWithGenericAndAssemblyQualifiedNonExistingAssembly ();
}

[Kept]
static void TestFromTypeOf ()
{
RequireCombination (typeof (FromTypeOfTestType));
}

[Kept]
class FromTypeOfTestType
{
[Kept]
public FromTypeOfTestType () { }
public FromTypeOfTestType (int i) { }

[Kept]
public void PublicMethod () { }
private void PrivateMethod () { }

[Kept]
public bool _publicField;
private bool _privateField;

[Kept]
[KeptBackingField]
public bool PublicProperty { [Kept] get; [Kept] set; }
private bool PrivateProperty { get; set; }
}

[Kept]
static void TestFromTypeGetTypeOverConstant ()
{
RequireCombination (Type.GetType ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromTypeGetTypeOverConstantTestType"));
}

[Kept]
class FromTypeGetTypeOverConstantTestType
{
[Kept]
public FromTypeGetTypeOverConstantTestType () { }
public FromTypeGetTypeOverConstantTestType (int i) { }

[Kept]
public void PublicMethod () { }
private void PrivateMethod () { }

[Kept]
public bool _publicField;
private bool _privateField;

[Kept]
[KeptBackingField]
public bool PublicProperty { [Kept] get; [Kept] set; }
private bool PrivateProperty { get; set; }
}

[Kept]
static void TestFromStringContantWithAnnotation ()
{
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithAnnotationTestType");
}

[Kept]
class FromStringConstantWithAnnotationTestType
{
[Kept]
public FromStringConstantWithAnnotationTestType () { }
public FromStringConstantWithAnnotationTestType (int i) { }

[Kept]
public void PublicMethod () { }
private void PrivateMethod () { }

[Kept]
public bool _publicField;
private bool _privateField;

[Kept]
[KeptBackingField]
public bool PublicProperty { [Kept] get; [Kept] set; }
private bool PrivateProperty { get; set; }
}

[Kept]
private static void RequireCombination (
[KeptAttributeAttribute(typeof(DynamicallyAccessedMembersAttribute))]
[DynamicallyAccessedMembers(
DynamicallyAccessedMemberTypes.PublicParameterlessConstructor |
DynamicallyAccessedMemberTypes.PublicFields |
DynamicallyAccessedMemberTypes.PublicMethods |
DynamicallyAccessedMemberTypes.PublicProperties)]
Type type)
{
}

[Kept]
private static void RequireCombinationOnString (
[KeptAttributeAttribute(typeof(DynamicallyAccessedMembersAttribute))]
[DynamicallyAccessedMembers(
DynamicallyAccessedMemberTypes.PublicParameterlessConstructor |
DynamicallyAccessedMemberTypes.PublicFields |
DynamicallyAccessedMemberTypes.PublicMethods |
DynamicallyAccessedMemberTypes.PublicProperties)]
string typeName)
{
}

[Kept]
class FromStringConstantWithGenericInner
{
}

[Kept]
[KeptMember (".ctor()")]
class FromStringConstantWithGeneric<T>
{
[Kept]
public T GetValue () { return default (T); }
}

[Kept]
class FromStringConstantWithGenericInnerInner
{
[Kept]
public void Method ()
{
}

int unusedField;
}

[Kept]
class FromStringConstantWithGenericInnerOne<
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
[KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))]
T>
{
}

[Kept]
class FromStringConstantWithGenericInnerTwo
{
void UnusedMethod ()
{
}
}

[Kept]
class FromStringConstantWitGenericInnerMultiDimArray
{
}

[Kept]
class FromStringConstantWithMultiDimArray
{
public void UnusedMethod () { }
}

[Kept]
[KeptMember (".ctor()")]
class FromStringConstantWithGenericTwoParameters<T, S>
{
}

[Kept]
static void TestFromStringConstantWithGeneric ()
{
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGeneric`1[[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericInner]]");
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericTwoParameters`2[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericInnerOne`1[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericInnerInner],Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericInnerTwo]");
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGeneric`1[[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWitGenericInnerMultiDimArray[,]]]");
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithMultiDimArray[,]");
}

[Kept]
[KeptMember (".ctor()")]
class FromStringConstantWithGenericAndAssemblyQualified<T>
{
[Kept]
public T GetValue () { return default (T); }
}

[Kept]
static void TestFromStringConstantWithGenericAndAssemblyQualified ()
{
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericAndAssemblyQualified`1[[Mono.Linker.Tests.Cases.Expectations.Assertions.KeptAttribute,Mono.Linker.Tests.Cases.Expectations]]");
}

class InvalidAssemblyNameType
{
}

[Kept]
static void TestFromStringConstantWithGenericAndAssemblyQualifiedInvalidAssembly ()
{
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+InvalidAssemblyNameType,Invalid/Assembly/Name");
}

class NonExistingAssemblyType
{
}

[Kept]
static void TestFromStringConstantWithGenericAndAssemblyQualifiedNonExistingAssembly ()
{
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+InvalidAssemblyNameType,NonExistingAssembly");
}
}
}
Loading