@@ -39,7 +39,7 @@ public sealed class UsageBasedMetadataManager : GeneratingMetadataManager
39
39
40
40
internal readonly UsageBasedMetadataGenerationOptions _generationOptions ;
41
41
42
- private readonly FeatureSwitchHashtable _featureSwitchHashtable ;
42
+ private readonly LinkAttributesHashTable _linkAttributesHashTable ;
43
43
44
44
private static ( string AttributeName , DiagnosticId Id ) [ ] _requiresAttributeMismatchNameAndId = new [ ]
45
45
{
@@ -91,7 +91,7 @@ public UsageBasedMetadataManager(
91
91
FlowAnnotations = flowAnnotations ;
92
92
Logger = logger ;
93
93
94
- _featureSwitchHashtable = new FeatureSwitchHashtable ( Logger , new Dictionary < string , bool > ( featureSwitchValues ) ) ;
94
+ _linkAttributesHashTable = new LinkAttributesHashTable ( Logger , new Dictionary < string , bool > ( featureSwitchValues ) ) ;
95
95
FeatureSwitches = new Dictionary < string , bool > ( featureSwitchValues ) ;
96
96
97
97
_rootEntireAssembliesModules = new HashSet < string > ( rootEntireAssembliesModules ) ;
@@ -821,7 +821,7 @@ public bool GeneratesAttributeMetadata(TypeDesc attributeType)
821
821
var ecmaType = attributeType . GetTypeDefinition ( ) as EcmaType ;
822
822
if ( ecmaType != null )
823
823
{
824
- var moduleInfo = _featureSwitchHashtable . GetOrCreateValue ( ecmaType . EcmaModule ) ;
824
+ var moduleInfo = _linkAttributesHashTable . GetOrCreateValue ( ecmaType . EcmaModule ) ;
825
825
return ! moduleInfo . RemovedAttributes . Contains ( ecmaType ) ;
826
826
}
827
827
@@ -1070,12 +1070,12 @@ public bool IsBlocked(MethodDesc methodDef)
1070
1070
}
1071
1071
}
1072
1072
1073
- private sealed class FeatureSwitchHashtable : LockFreeReaderHashtable < EcmaModule , AssemblyFeatureInfo >
1073
+ private sealed class LinkAttributesHashTable : LockFreeReaderHashtable < EcmaModule , AssemblyFeatureInfo >
1074
1074
{
1075
1075
private readonly Dictionary < string , bool > _switchValues ;
1076
1076
private readonly Logger _logger ;
1077
1077
1078
- public FeatureSwitchHashtable ( Logger logger , Dictionary < string , bool > switchValues )
1078
+ public LinkAttributesHashTable ( Logger logger , Dictionary < string , bool > switchValues )
1079
1079
{
1080
1080
_logger = logger ;
1081
1081
_switchValues = switchValues ;
@@ -1103,19 +1103,30 @@ public AssemblyFeatureInfo(EcmaModule module, Logger logger, IReadOnlyDictionary
1103
1103
Module = module ;
1104
1104
RemovedAttributes = new HashSet < TypeDesc > ( ) ;
1105
1105
1106
- PEMemoryBlock resourceDirectory = module . PEReader . GetSectionData ( module . PEReader . PEHeaders . CorHeader . ResourcesDirectory . RelativeVirtualAddress ) ;
1106
+ // System.Private.CorLib has a special functionality that could delete an attribute in all modules.
1107
+ // In order to get the set of attributes that need to be removed the modules need collect both the
1108
+ // set of attributes in it's embedded XML file and the set inside System.Private.CorLib embedded
1109
+ // XML file
1110
+ ParseLinkAttributesXml ( module , logger , featureSwitchValues , globalAttributeRemoval : false ) ;
1111
+ ParseLinkAttributesXml ( module , logger , featureSwitchValues , globalAttributeRemoval : true ) ;
1112
+ }
1113
+
1114
+ public void ParseLinkAttributesXml ( EcmaModule module , Logger logger , IReadOnlyDictionary < string , bool > featureSwitchValues , bool globalAttributeRemoval )
1115
+ {
1116
+ EcmaModule xmlModule = globalAttributeRemoval ? ( EcmaModule ) module . Context . SystemModule : module ;
1117
+ PEMemoryBlock resourceDirectory = xmlModule . PEReader . GetSectionData ( xmlModule . PEReader . PEHeaders . CorHeader . ResourcesDirectory . RelativeVirtualAddress ) ;
1107
1118
1108
- foreach ( var resourceHandle in module . MetadataReader . ManifestResources )
1119
+ foreach ( var resourceHandle in xmlModule . MetadataReader . ManifestResources )
1109
1120
{
1110
- ManifestResource resource = module . MetadataReader . GetManifestResource ( resourceHandle ) ;
1121
+ ManifestResource resource = xmlModule . MetadataReader . GetManifestResource ( resourceHandle ) ;
1111
1122
1112
1123
// Don't try to process linked resources or resources in other assemblies
1113
1124
if ( ! resource . Implementation . IsNil )
1114
1125
{
1115
1126
continue ;
1116
1127
}
1117
1128
1118
- string resourceName = module . MetadataReader . GetString ( resource . Name ) ;
1129
+ string resourceName = xmlModule . MetadataReader . GetString ( resource . Name ) ;
1119
1130
if ( resourceName == "ILLink.LinkAttributes.xml" )
1120
1131
{
1121
1132
BlobReader reader = resourceDirectory . GetReader ( ( int ) resource . Offset , resourceDirectory . Length - ( int ) resource . Offset ) ;
@@ -1127,37 +1138,61 @@ public AssemblyFeatureInfo(EcmaModule module, Logger logger, IReadOnlyDictionary
1127
1138
ms = new UnmanagedMemoryStream ( reader . CurrentPointer , length ) ;
1128
1139
}
1129
1140
1130
- RemovedAttributes = LinkAttributesReader . GetRemovedAttributes ( logger , module . Context , ms , resource , module , "resource " + resourceName + " in " + module . ToString ( ) , featureSwitchValues ) ;
1141
+ RemovedAttributes . UnionWith ( LinkAttributesReader . GetRemovedAttributes ( logger , xmlModule . Context , ms , resource , module , "resource " + resourceName + " in " + module . ToString ( ) , featureSwitchValues , globalAttributeRemoval ) ) ;
1131
1142
}
1132
1143
}
1133
1144
}
1134
1145
}
1135
1146
1136
- private sealed class LinkAttributesReader : ProcessLinkerXmlBase
1147
+ internal sealed class LinkAttributesReader : ProcessLinkerXmlBase
1137
1148
{
1138
1149
private readonly HashSet < TypeDesc > _removedAttributes = new ( ) ;
1139
1150
1140
- public LinkAttributesReader ( Logger logger , TypeSystemContext context , Stream documentStream , ManifestResource resource , ModuleDesc resourceAssembly , string xmlDocumentLocation , IReadOnlyDictionary < string , bool > featureSwitchValues )
1141
- : base ( logger , context , documentStream , resource , resourceAssembly , xmlDocumentLocation , featureSwitchValues )
1151
+ public LinkAttributesReader ( Logger logger , TypeSystemContext context , Stream documentStream , ManifestResource resource , ModuleDesc resourceAssembly , string xmlDocumentLocation , IReadOnlyDictionary < string , bool > featureSwitchValues , bool globalAttributeRemoval )
1152
+ : base ( logger , context , documentStream , resource , resourceAssembly , xmlDocumentLocation , featureSwitchValues , globalAttributeRemoval )
1142
1153
{
1143
1154
}
1144
1155
1156
+ private static bool IsRemoveAttributeInstances ( string attributeName ) => attributeName == "RemoveAttributeInstances" || attributeName == "RemoveAttributeInstancesAttribute" ;
1157
+
1145
1158
private void ProcessAttribute ( TypeDesc type , XPathNavigator nav )
1146
1159
{
1147
1160
string internalValue = GetAttribute ( nav , "internal" ) ;
1148
- if ( internalValue == "RemoveAttributeInstances" && nav . IsEmptyElement )
1161
+ if ( ! string . IsNullOrEmpty ( internalValue ) )
1149
1162
{
1150
- _removedAttributes . Add ( type ) ;
1163
+ if ( ! IsRemoveAttributeInstances ( internalValue ) || ! nav . IsEmptyElement )
1164
+ {
1165
+ LogWarning ( nav , DiagnosticId . UnrecognizedInternalAttribute , internalValue ) ;
1166
+ }
1167
+ if ( IsRemoveAttributeInstances ( internalValue ) && nav . IsEmptyElement )
1168
+ {
1169
+ _removedAttributes . Add ( type ) ;
1170
+ }
1151
1171
}
1152
1172
}
1153
1173
1154
- public static HashSet < TypeDesc > GetRemovedAttributes ( Logger logger , TypeSystemContext context , Stream documentStream , ManifestResource resource , ModuleDesc resourceAssembly , string xmlDocumentLocation , IReadOnlyDictionary < string , bool > featureSwitchValues )
1174
+ public static HashSet < TypeDesc > GetRemovedAttributes ( Logger logger , TypeSystemContext context , Stream documentStream , ManifestResource resource , ModuleDesc resourceAssembly , string xmlDocumentLocation , IReadOnlyDictionary < string , bool > featureSwitchValues , bool globalAttributeRemoval )
1155
1175
{
1156
- var rdr = new LinkAttributesReader ( logger , context , documentStream , resource , resourceAssembly , xmlDocumentLocation , featureSwitchValues ) ;
1176
+ var rdr = new LinkAttributesReader ( logger , context , documentStream , resource , resourceAssembly , xmlDocumentLocation , featureSwitchValues , globalAttributeRemoval ) ;
1157
1177
rdr . ProcessXml ( false ) ;
1158
1178
return rdr . _removedAttributes ;
1159
1179
}
1160
1180
1181
+ protected override AllowedAssemblies AllowedAssemblySelector
1182
+ {
1183
+ get
1184
+ {
1185
+ if ( _owningModule ? . Assembly == null )
1186
+ return AllowedAssemblies . AllAssemblies ;
1187
+
1188
+ // Corelib XML may contain assembly wildcard to support compiler-injected attribute types
1189
+ if ( _owningModule ? . Assembly == _context . SystemModule )
1190
+ return AllowedAssemblies . AllAssemblies ;
1191
+
1192
+ return AllowedAssemblies . ContainingAssembly ;
1193
+ }
1194
+ }
1195
+
1161
1196
protected override void ProcessAssembly ( ModuleDesc assembly , XPathNavigator nav , bool warnOnUnresolvedTypes )
1162
1197
{
1163
1198
ProcessTypes ( assembly , nav , warnOnUnresolvedTypes ) ;
0 commit comments