-
Notifications
You must be signed in to change notification settings - Fork 5.3k
[ILLink] stub -> throw PNSE #123326
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
[ILLink] stub -> throw PNSE #123326
Changes from all commits
f8f41b8
cad50de
bf27e48
61c3609
c1f22e1
d5908e6
423d3ad
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3350,6 +3350,9 @@ protected virtual void ProcessMethod(MethodDefinition method, in DependencyInfo | |
| #endif | ||
| var methodOrigin = new MessageOrigin(method); | ||
|
|
||
| // Check for [UnsupportedOSPlatform] early to potentially skip body scanning | ||
| TryMarkMethodForUnsupportedPlatform(method); | ||
|
|
||
| bool markedForCall = | ||
| reason.Kind == DependencyKind.DirectCall || | ||
| reason.Kind == DependencyKind.VirtualCall || | ||
|
|
@@ -3582,7 +3585,71 @@ void MarkNewCodeDependencies(MethodDefinition method, MessageOrigin origin) | |
| case MethodAction.ConvertToThrow: | ||
| MarkAndCacheConvertToThrowExceptionCtor(new DependencyInfo(DependencyKind.UnreachableBodyRequirement, method), origin); | ||
| break; | ||
|
|
||
| case MethodAction.ConvertToPNSE: | ||
| MarkAndCacheConvertToThrowPNSECtor(new DependencyInfo(DependencyKind.UnreachableBodyRequirement, method), origin); | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Checks if the method has [UnsupportedOSPlatform] attribute matching the target OS | ||
| /// and marks it for PNSE conversion if so. | ||
| /// </summary> | ||
| /// <returns>True if the method was marked for PNSE conversion.</returns> | ||
| bool TryMarkMethodForUnsupportedPlatform(MethodDefinition method) | ||
| { | ||
| if (Context.TargetOS is null) | ||
| return false; | ||
|
|
||
| // Check method-level attributes | ||
| if (HasMatchingUnsupportedOSPlatformAttribute(method)) | ||
| { | ||
| Annotations.SetAction(method, MethodAction.ConvertToPNSE); | ||
| return true; | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Checks if the property has [UnsupportedOSPlatform] attribute matching the target OS | ||
| /// and marks its getter/setter for PNSE conversion if so. | ||
| /// </summary> | ||
| void TryMarkPropertyForUnsupportedPlatform(PropertyDefinition property) | ||
| { | ||
| if (Context.TargetOS is null) | ||
| return; | ||
|
|
||
| if (!HasMatchingUnsupportedOSPlatformAttribute(property)) | ||
| return; | ||
|
|
||
| if (property.GetMethod is not null) | ||
| Annotations.SetAction(property.GetMethod, MethodAction.ConvertToPNSE); | ||
|
|
||
| if (property.SetMethod is not null) | ||
| Annotations.SetAction(property.SetMethod, MethodAction.ConvertToPNSE); | ||
| } | ||
|
Comment on lines
+3600
to
+3632
|
||
|
|
||
| /// <summary> | ||
| /// Checks if the provider has [UnsupportedOSPlatform] attribute matching the target OS. | ||
| /// </summary> | ||
| bool HasMatchingUnsupportedOSPlatformAttribute(ICustomAttributeProvider provider) | ||
| { | ||
| if (!provider.HasCustomAttributes) | ||
| return false; | ||
|
|
||
| foreach (var attribute in Context.CustomAttributes.GetCustomAttributes(provider, "System.Runtime.Versioning", "UnsupportedOSPlatformAttribute")) | ||
| { | ||
| if (attribute.ConstructorArguments.Count > 0 && | ||
| attribute.ConstructorArguments[0].Value is string platformName && | ||
| string.Equals(platformName, Context.TargetOS, StringComparison.OrdinalIgnoreCase)) | ||
| { | ||
| return true; | ||
| } | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| protected virtual void MarkAndCacheConvertToThrowExceptionCtor(DependencyInfo reason, MessageOrigin origin) | ||
|
|
@@ -3611,6 +3678,32 @@ protected virtual void MarkAndCacheConvertToThrowExceptionCtor(DependencyInfo re | |
| throw new LinkerFatalErrorException(MessageContainer.CreateErrorMessage(null, DiagnosticId.CouldNotFindConstructor, objectType.GetDisplayName())); | ||
| } | ||
|
|
||
| protected virtual void MarkAndCacheConvertToThrowPNSECtor(DependencyInfo reason, MessageOrigin origin) | ||
| { | ||
| if (Context.MarkedKnownMembers.PlatformNotSupportedExceptionCtor != null) | ||
| return; | ||
|
|
||
| var pnse = BCL.FindPredefinedType(WellKnownType.System_PlatformNotSupportedException, Context); | ||
| if (pnse == null) | ||
| throw new LinkerFatalErrorException(MessageContainer.CreateErrorMessage(null, DiagnosticId.CouldNotFindType, "System.PlatformNotSupportedException")); | ||
|
|
||
| MarkType(pnse, reason, origin); | ||
|
|
||
| var pnseCtor = MarkMethodIf(pnse.Methods, KnownMembers.IsPlatformNotSupportedExceptionCtor, reason, origin); | ||
| Context.MarkedKnownMembers.PlatformNotSupportedExceptionCtor = pnseCtor ?? | ||
| throw new LinkerFatalErrorException(MessageContainer.CreateErrorMessage(null, DiagnosticId.CouldNotFindConstructor, pnse.GetDisplayName())); | ||
|
|
||
| var objectType = BCL.FindPredefinedType(WellKnownType.System_Object, Context); | ||
| if (objectType == null) | ||
| throw new NotSupportedException("Missing predefined 'System.Object' type"); | ||
|
|
||
| MarkType(objectType, reason, origin); | ||
|
|
||
| var objectCtor = MarkMethodIf(objectType.Methods, MethodDefinitionExtensions.IsDefaultConstructor, reason, origin); | ||
| Context.MarkedKnownMembers.ObjectCtor = objectCtor ?? | ||
| throw new LinkerFatalErrorException(MessageContainer.CreateErrorMessage(null, DiagnosticId.CouldNotFindConstructor, objectType.GetDisplayName())); | ||
| } | ||
|
|
||
| bool MarkDisablePrivateReflectionAttribute() | ||
| { | ||
| if (Context.MarkedKnownMembers.DisablePrivateReflectionAttributeCtor != null) | ||
|
|
@@ -3743,6 +3836,11 @@ protected virtual bool ShouldParseMethodBody(MethodDefinition method) | |
| default: | ||
| return false; | ||
| } | ||
| // Skip body scanning for methods that will be stubbed - their bodies will be replaced | ||
| case MethodAction.ConvertToStub: | ||
| case MethodAction.ConvertToThrow: | ||
| case MethodAction.ConvertToPNSE: | ||
| return false; | ||
| default: | ||
| return false; | ||
| } | ||
|
|
@@ -3755,6 +3853,9 @@ protected internal void MarkProperty(PropertyDefinition prop, in DependencyInfo | |
|
|
||
| var propertyOrigin = new MessageOrigin(prop); | ||
|
|
||
| // Check for [UnsupportedOSPlatform] on the property and mark getter/setter for PNSE | ||
| TryMarkPropertyForUnsupportedPlatform(prop); | ||
|
|
||
| // Consider making this more similar to MarkEvent method? | ||
| MarkCustomAttributes(prop, new DependencyInfo(DependencyKind.CustomAttribute, prop), propertyOrigin); | ||
| DoAdditionalPropertyProcessing(prop); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -39,5 +39,6 @@ public enum MethodAction | |
| ForceParse, | ||
| ConvertToStub, | ||
| ConvertToThrow, | ||
| ConvertToPNSE, | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spelling error: "replaces" should be "replaced" to match the grammatical structure and be consistent with similar documentation in the file (see line 244 for the same error pattern).