376 lines
16 KiB
C#
376 lines
16 KiB
C#
using System;
|
|
using System.Collections.Immutable;
|
|
using System.Runtime.InteropServices;
|
|
using Microsoft.CodeAnalysis.CSharp.Emit;
|
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
|
using Microsoft.CodeAnalysis.PooledObjects;
|
|
using Roslyn.Utilities;
|
|
|
|
namespace Microsoft.CodeAnalysis.CSharp.Symbols;
|
|
|
|
internal abstract class FieldSymbolWithAttributesAndModifiers : FieldSymbol, IAttributeTargetSymbol
|
|
{
|
|
private CustomAttributesBag<CSharpAttributeData> _lazyCustomAttributesBag;
|
|
|
|
protected SymbolCompletionState state;
|
|
|
|
internal abstract Location ErrorLocation { get; }
|
|
|
|
protected abstract DeclarationModifiers Modifiers { get; }
|
|
|
|
protected abstract SyntaxList<AttributeListSyntax> AttributeDeclarationSyntaxList { get; }
|
|
|
|
protected abstract IAttributeTargetSymbol AttributeOwner { get; }
|
|
|
|
IAttributeTargetSymbol IAttributeTargetSymbol.AttributesOwner => AttributeOwner;
|
|
|
|
AttributeLocation IAttributeTargetSymbol.DefaultAttributeLocation => AttributeLocation.Field;
|
|
|
|
AttributeLocation IAttributeTargetSymbol.AllowedAttributeLocations => AttributeLocation.Field;
|
|
|
|
public sealed override bool IsStatic => (Modifiers & DeclarationModifiers.Static) != 0;
|
|
|
|
public sealed override bool IsReadOnly => (Modifiers & DeclarationModifiers.ReadOnly) != 0;
|
|
|
|
public sealed override Accessibility DeclaredAccessibility => ModifierUtils.EffectiveAccessibility(Modifiers);
|
|
|
|
public sealed override bool IsConst => (Modifiers & DeclarationModifiers.Const) != 0;
|
|
|
|
public sealed override bool IsVolatile => (Modifiers & DeclarationModifiers.Volatile) != 0;
|
|
|
|
public sealed override bool IsFixedSizeBuffer => (Modifiers & DeclarationModifiers.Fixed) != 0;
|
|
|
|
internal sealed override ObsoleteAttributeData ObsoleteAttributeData
|
|
{
|
|
get
|
|
{
|
|
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0032: Expected O, but got Unknown
|
|
if (!((SourceMemberContainerTypeSymbol)ContainingType).AnyMemberHasAttributes)
|
|
{
|
|
return null;
|
|
}
|
|
CustomAttributesBag<CSharpAttributeData> lazyCustomAttributesBag = _lazyCustomAttributesBag;
|
|
if (lazyCustomAttributesBag != null && lazyCustomAttributesBag.IsEarlyDecodedWellKnownAttributeDataComputed)
|
|
{
|
|
CommonFieldEarlyWellKnownAttributeData val = (CommonFieldEarlyWellKnownAttributeData)lazyCustomAttributesBag.EarlyDecodedWellKnownAttributeData;
|
|
if (val == null)
|
|
{
|
|
return null;
|
|
}
|
|
return val.ObsoleteAttributeData;
|
|
}
|
|
return ObsoleteAttributeData.Uninitialized;
|
|
}
|
|
}
|
|
|
|
public override FlowAnalysisAnnotations FlowAnalysisAnnotations => DecodeFlowAnalysisAttributes(GetDecodedWellKnownAttributeData());
|
|
|
|
internal sealed override bool HasSpecialName
|
|
{
|
|
get
|
|
{
|
|
if (HasRuntimeSpecialName)
|
|
{
|
|
return true;
|
|
}
|
|
FieldWellKnownAttributeData decodedWellKnownAttributeData = GetDecodedWellKnownAttributeData();
|
|
if (decodedWellKnownAttributeData != null)
|
|
{
|
|
return ((CommonFieldWellKnownAttributeData)decodedWellKnownAttributeData).HasSpecialNameAttribute;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
internal sealed override bool IsNotSerialized
|
|
{
|
|
get
|
|
{
|
|
FieldWellKnownAttributeData decodedWellKnownAttributeData = GetDecodedWellKnownAttributeData();
|
|
if (decodedWellKnownAttributeData != null)
|
|
{
|
|
return ((CommonFieldWellKnownAttributeData)decodedWellKnownAttributeData).HasNonSerializedAttribute;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
internal sealed override MarshalPseudoCustomAttributeData MarshallingInformation
|
|
{
|
|
get
|
|
{
|
|
FieldWellKnownAttributeData decodedWellKnownAttributeData = GetDecodedWellKnownAttributeData();
|
|
if (decodedWellKnownAttributeData == null)
|
|
{
|
|
return null;
|
|
}
|
|
return ((CommonFieldWellKnownAttributeData)decodedWellKnownAttributeData).MarshallingInformation;
|
|
}
|
|
}
|
|
|
|
internal sealed override int? TypeLayoutOffset
|
|
{
|
|
get
|
|
{
|
|
FieldWellKnownAttributeData decodedWellKnownAttributeData = GetDecodedWellKnownAttributeData();
|
|
if (decodedWellKnownAttributeData == null)
|
|
{
|
|
return null;
|
|
}
|
|
return ((CommonFieldWellKnownAttributeData)decodedWellKnownAttributeData).Offset;
|
|
}
|
|
}
|
|
|
|
internal sealed override bool HasComplete(CompletionPart part)
|
|
{
|
|
return state.HasComplete(part);
|
|
}
|
|
|
|
public sealed override ImmutableArray<CSharpAttributeData> GetAttributes()
|
|
{
|
|
return GetAttributesBag().Attributes;
|
|
}
|
|
|
|
private CustomAttributesBag<CSharpAttributeData> GetAttributesBag()
|
|
{
|
|
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
|
|
CustomAttributesBag<CSharpAttributeData> lazyCustomAttributesBag = _lazyCustomAttributesBag;
|
|
if (lazyCustomAttributesBag != null && lazyCustomAttributesBag.IsSealed)
|
|
{
|
|
return lazyCustomAttributesBag;
|
|
}
|
|
if (LoadAndValidateAttributes(OneOrMany.Create<SyntaxList<AttributeListSyntax>>(AttributeDeclarationSyntaxList), ref _lazyCustomAttributesBag))
|
|
{
|
|
state.NotePartComplete(CompletionPart.Attributes);
|
|
}
|
|
return _lazyCustomAttributesBag;
|
|
}
|
|
|
|
protected FieldWellKnownAttributeData GetDecodedWellKnownAttributeData()
|
|
{
|
|
CustomAttributesBag<CSharpAttributeData> val = _lazyCustomAttributesBag;
|
|
if (val == null || !val.IsDecodedWellKnownAttributeDataComputed)
|
|
{
|
|
val = GetAttributesBag();
|
|
}
|
|
return (FieldWellKnownAttributeData)(object)val.DecodedWellKnownAttributeData;
|
|
}
|
|
|
|
internal sealed override (CSharpAttributeData?, BoundAttribute?) EarlyDecodeWellKnownAttribute(ref EarlyDecodeWellKnownAttributeArguments<EarlyWellKnownAttributeBinder, NamedTypeSymbol, AttributeSyntax, AttributeLocation> arguments)
|
|
{
|
|
if (Symbol.EarlyDecodeDeprecatedOrExperimentalOrObsoleteAttribute(ref arguments, out CSharpAttributeData attributeData, out BoundAttribute boundAttribute, out ObsoleteAttributeData obsoleteData))
|
|
{
|
|
if (obsoleteData != null)
|
|
{
|
|
arguments.GetOrCreateData<CommonFieldEarlyWellKnownAttributeData>().ObsoleteAttributeData = obsoleteData;
|
|
}
|
|
return (attributeData, boundAttribute);
|
|
}
|
|
return base.EarlyDecodeWellKnownAttribute(ref arguments);
|
|
}
|
|
|
|
protected override void DecodeWellKnownAttributeImpl(ref DecodeWellKnownAttributeArguments<AttributeSyntax, CSharpAttributeData, AttributeLocation> arguments)
|
|
{
|
|
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_011d: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0139: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0155: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0170: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_018b: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
|
|
BindingDiagnosticBag bindingDiagnosticBag = (BindingDiagnosticBag)(object)arguments.Diagnostics;
|
|
CSharpAttributeData attribute = arguments.Attribute;
|
|
if (attribute.IsTargetAttribute(this, AttributeDescription.SpecialNameAttribute))
|
|
{
|
|
((CommonFieldWellKnownAttributeData)arguments.GetOrCreateData<FieldWellKnownAttributeData>()).HasSpecialNameAttribute = true;
|
|
}
|
|
else if (attribute.IsTargetAttribute(this, AttributeDescription.NonSerializedAttribute))
|
|
{
|
|
((CommonFieldWellKnownAttributeData)arguments.GetOrCreateData<FieldWellKnownAttributeData>()).HasNonSerializedAttribute = true;
|
|
}
|
|
else if (attribute.IsTargetAttribute(this, AttributeDescription.FieldOffsetAttribute))
|
|
{
|
|
if (IsStatic || IsConst)
|
|
{
|
|
bindingDiagnosticBag.Add(ErrorCode.ERR_StructOffsetOnBadField, ((SyntaxNode)arguments.AttributeSyntaxOpt.Name).Location);
|
|
return;
|
|
}
|
|
TypedConstant val = ((AttributeData)attribute).CommonConstructorArguments[0];
|
|
int num = ((TypedConstant)(ref val)).DecodeValue<int>((SpecialType)13);
|
|
if (num < 0)
|
|
{
|
|
CSharpSyntaxNode attributeArgumentSyntax = ((AttributeData)(object)attribute).GetAttributeArgumentSyntax(0, arguments.AttributeSyntaxOpt);
|
|
bindingDiagnosticBag.Add(ErrorCode.ERR_InvalidAttributeArgument, ((SyntaxNode)attributeArgumentSyntax).Location, arguments.AttributeSyntaxOpt.GetErrorDisplayName());
|
|
num = 0;
|
|
}
|
|
((CommonFieldWellKnownAttributeData)arguments.GetOrCreateData<FieldWellKnownAttributeData>()).SetFieldOffset(num);
|
|
}
|
|
else if (attribute.IsTargetAttribute(this, AttributeDescription.MarshalAsAttribute))
|
|
{
|
|
MarshalAsAttributeDecoder<FieldWellKnownAttributeData, AttributeSyntax, CSharpAttributeData, AttributeLocation>.Decode(ref arguments, AttributeTargets.Field, (CommonMessageProvider)(object)MessageProvider.Instance);
|
|
}
|
|
else if (!ReportExplicitUseOfReservedAttributes(in arguments, ReservedAttributes.DynamicAttribute | ReservedAttributes.IsReadOnlyAttribute | ReservedAttributes.IsUnmanagedAttribute | ReservedAttributes.IsByRefLikeAttribute | ReservedAttributes.TupleElementNamesAttribute | ReservedAttributes.NullableAttribute | ReservedAttributes.NativeIntegerAttribute | ReservedAttributes.RequiredMemberAttribute | ReservedAttributes.RequiresLocationAttribute))
|
|
{
|
|
if (attribute.IsTargetAttribute(this, AttributeDescription.DateTimeConstantAttribute))
|
|
{
|
|
VerifyConstantValueMatches(((AttributeData)attribute).DecodeDateTimeConstantValue(), ref arguments);
|
|
}
|
|
else if (attribute.IsTargetAttribute(this, AttributeDescription.DecimalConstantAttribute))
|
|
{
|
|
VerifyConstantValueMatches(((AttributeData)attribute).DecodeDecimalConstantValue(), ref arguments);
|
|
}
|
|
else if (attribute.IsTargetAttribute(this, AttributeDescription.AllowNullAttribute))
|
|
{
|
|
arguments.GetOrCreateData<FieldWellKnownAttributeData>().HasAllowNullAttribute = true;
|
|
}
|
|
else if (attribute.IsTargetAttribute(this, AttributeDescription.DisallowNullAttribute))
|
|
{
|
|
arguments.GetOrCreateData<FieldWellKnownAttributeData>().HasDisallowNullAttribute = true;
|
|
}
|
|
else if (attribute.IsTargetAttribute(this, AttributeDescription.MaybeNullAttribute))
|
|
{
|
|
arguments.GetOrCreateData<FieldWellKnownAttributeData>().HasMaybeNullAttribute = true;
|
|
}
|
|
else if (attribute.IsTargetAttribute(this, AttributeDescription.NotNullAttribute))
|
|
{
|
|
arguments.GetOrCreateData<FieldWellKnownAttributeData>().HasNotNullAttribute = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static FlowAnalysisAnnotations DecodeFlowAnalysisAttributes(FieldWellKnownAttributeData attributeData)
|
|
{
|
|
FlowAnalysisAnnotations flowAnalysisAnnotations = FlowAnalysisAnnotations.None;
|
|
if (attributeData != null)
|
|
{
|
|
if (attributeData.HasAllowNullAttribute)
|
|
{
|
|
flowAnalysisAnnotations |= FlowAnalysisAnnotations.AllowNull;
|
|
}
|
|
if (attributeData.HasDisallowNullAttribute)
|
|
{
|
|
flowAnalysisAnnotations |= FlowAnalysisAnnotations.DisallowNull;
|
|
}
|
|
if (attributeData.HasMaybeNullAttribute)
|
|
{
|
|
flowAnalysisAnnotations |= FlowAnalysisAnnotations.MaybeNull;
|
|
}
|
|
if (attributeData.HasNotNullAttribute)
|
|
{
|
|
flowAnalysisAnnotations |= FlowAnalysisAnnotations.NotNull;
|
|
}
|
|
}
|
|
return flowAnalysisAnnotations;
|
|
}
|
|
|
|
private void VerifyConstantValueMatches(ConstantValue attrValue, ref DecodeWellKnownAttributeArguments<AttributeSyntax, CSharpAttributeData, AttributeLocation> arguments)
|
|
{
|
|
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0033: Invalid comparison between Unknown and I4
|
|
if (attrValue.IsBad)
|
|
{
|
|
return;
|
|
}
|
|
FieldWellKnownAttributeData orCreateData = arguments.GetOrCreateData<FieldWellKnownAttributeData>();
|
|
BindingDiagnosticBag bindingDiagnosticBag = (BindingDiagnosticBag)(object)arguments.Diagnostics;
|
|
ConstantValue constantValue;
|
|
if (IsConst)
|
|
{
|
|
if ((int)base.Type.SpecialType == 17)
|
|
{
|
|
constantValue = GetConstantValue(ConstantFieldsInProgress.Empty, earlyDecodingWellKnownAttributes: false);
|
|
if (constantValue != null && !constantValue.IsBad && constantValue != attrValue)
|
|
{
|
|
bindingDiagnosticBag.Add(ErrorCode.ERR_FieldHasMultipleDistinctConstantValues, ((SyntaxNode)arguments.AttributeSyntaxOpt).Location);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bindingDiagnosticBag.Add(ErrorCode.ERR_FieldHasMultipleDistinctConstantValues, ((SyntaxNode)arguments.AttributeSyntaxOpt).Location);
|
|
}
|
|
if (((CommonFieldWellKnownAttributeData)orCreateData).ConstValue == ConstantValue.Unset)
|
|
{
|
|
((CommonFieldWellKnownAttributeData)orCreateData).ConstValue = attrValue;
|
|
}
|
|
return;
|
|
}
|
|
constantValue = ((CommonFieldWellKnownAttributeData)orCreateData).ConstValue;
|
|
if (constantValue != ConstantValue.Unset)
|
|
{
|
|
if (constantValue != attrValue)
|
|
{
|
|
bindingDiagnosticBag.Add(ErrorCode.ERR_FieldHasMultipleDistinctConstantValues, ((SyntaxNode)arguments.AttributeSyntaxOpt).Location);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
((CommonFieldWellKnownAttributeData)orCreateData).ConstValue = attrValue;
|
|
}
|
|
}
|
|
|
|
internal override void PostDecodeWellKnownAttributes(ImmutableArray<CSharpAttributeData> boundAttributes, ImmutableArray<AttributeSyntax> allAttributeSyntaxNodes, BindingDiagnosticBag diagnostics, AttributeLocation symbolPart, WellKnownAttributeData decodedData)
|
|
{
|
|
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
|
|
FieldWellKnownAttributeData fieldWellKnownAttributeData = (FieldWellKnownAttributeData)(object)decodedData;
|
|
TypeLayout layout;
|
|
if (((fieldWellKnownAttributeData != null) ? ((CommonFieldWellKnownAttributeData)fieldWellKnownAttributeData).Offset : ((int?)null)).HasValue)
|
|
{
|
|
layout = ContainingType.Layout;
|
|
if (((TypeLayout)(ref layout)).Kind != LayoutKind.Explicit)
|
|
{
|
|
int index = boundAttributes.IndexOfAttribute(this, AttributeDescription.FieldOffsetAttribute);
|
|
diagnostics.Add(ErrorCode.ERR_StructOffsetOnBadStruct, ((SyntaxNode)allAttributeSyntaxNodes[index].Name).Location);
|
|
}
|
|
}
|
|
else if (!IsStatic && !IsConst)
|
|
{
|
|
layout = ContainingType.Layout;
|
|
if (((TypeLayout)(ref layout)).Kind == LayoutKind.Explicit)
|
|
{
|
|
diagnostics.Add(ErrorCode.ERR_MissingStructOffset, ErrorLocation, AttributeOwner);
|
|
}
|
|
}
|
|
base.PostDecodeWellKnownAttributes(boundAttributes, allAttributeSyntaxNodes, diagnostics, symbolPart, decodedData);
|
|
}
|
|
|
|
internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder<SynthesizedAttributeData> attributes)
|
|
{
|
|
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_000f: Invalid comparison between Unknown and I4
|
|
base.AddSynthesizedAttributes(moduleBuilder, ref attributes);
|
|
if ((int)RefKind == 3)
|
|
{
|
|
Symbol.AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeIsReadOnlyAttribute(this));
|
|
}
|
|
CSharpCompilation declaringCompilation = DeclaringCompilation;
|
|
TypeWithAnnotations typeWithAnnotations = base.TypeWithAnnotations;
|
|
if (typeWithAnnotations.Type.ContainsDynamic())
|
|
{
|
|
Symbol.AddSynthesizedAttribute(ref attributes, declaringCompilation.SynthesizeDynamicAttribute(typeWithAnnotations.Type, typeWithAnnotations.CustomModifiers.Length, (RefKind)0));
|
|
}
|
|
if (declaringCompilation.ShouldEmitNativeIntegerAttributes(typeWithAnnotations.Type))
|
|
{
|
|
Symbol.AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeNativeIntegerAttribute(this, typeWithAnnotations.Type));
|
|
}
|
|
if (typeWithAnnotations.Type.ContainsTupleNames())
|
|
{
|
|
Symbol.AddSynthesizedAttribute(ref attributes, declaringCompilation.SynthesizeTupleNamesAttribute(typeWithAnnotations.Type));
|
|
}
|
|
if (declaringCompilation.ShouldEmitNullableAttributes(this))
|
|
{
|
|
Symbol.AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeNullableAttributeIfNecessary(this, ContainingType.GetNullableContextValue(), typeWithAnnotations));
|
|
}
|
|
}
|
|
}
|