未验证 提交 77056b7e 编写于 作者: C Charles Stoner 提交者: GitHub

Emit NativeIntegerAttribute (#41160)

上级 60a892c9
......@@ -566,6 +566,11 @@ private BoundLambda ReallyBind(NamedTypeSymbol delegateType)
if (returnType.HasType)
{
if (returnType.Type.ContainsNativeInteger())
{
compilation.EnsureNativeIntegerAttributeExists(diagnostics, lambdaSymbol.DiagnosticLocation, modifyCompilation: false);
}
if (compilation.ShouldEmitNullableAttributes(lambdaSymbol) &&
returnType.NeedsNullableAttribute())
{
......@@ -574,6 +579,7 @@ private BoundLambda ReallyBind(NamedTypeSymbol delegateType)
}
}
ParameterHelpers.EnsureNativeIntegerAttributeExists(compilation, lambdaParameters, diagnostics, modifyCompilation: false);
ParameterHelpers.EnsureNullableAttributeExists(compilation, lambdaSymbol, lambdaParameters, diagnostics, modifyCompilation: false);
// Note: we don't need to warn on annotations used in #nullable disable context for lambdas, as this is handled in binding already
......
......@@ -37,6 +37,7 @@ internal abstract class PEAssemblyBuilderBase : PEModuleBuilder, Cci.IAssemblyRe
private SynthesizedEmbeddedNullableAttributeSymbol _lazyNullableAttribute;
private SynthesizedEmbeddedNullableContextAttributeSymbol _lazyNullableContextAttribute;
private SynthesizedEmbeddedNullablePublicOnlyAttributeSymbol _lazyNullablePublicOnlyAttribute;
private SynthesizedEmbeddedNativeIntegerAttributeSymbol _lazyNativeIntegerAttribute;
/// <summary>
/// The behavior of the C# command-line compiler is as follows:
......@@ -94,6 +95,7 @@ public sealed override ImmutableArray<NamedTypeSymbol> GetEmbeddedTypes(Diagnost
builder.AddIfNotNull(_lazyNullableAttribute);
builder.AddIfNotNull(_lazyNullableContextAttribute);
builder.AddIfNotNull(_lazyNullablePublicOnlyAttribute);
builder.AddIfNotNull(_lazyNativeIntegerAttribute);
return builder.ToImmutableAndFree();
}
......@@ -231,6 +233,20 @@ internal override SynthesizedAttributeData SynthesizeNullablePublicOnlyAttribute
return base.SynthesizeNullablePublicOnlyAttribute(arguments);
}
internal override SynthesizedAttributeData SynthesizeNativeIntegerAttribute(WellKnownMember member, ImmutableArray<TypedConstant> arguments)
{
if ((object)_lazyNativeIntegerAttribute != null)
{
var constructorIndex = (member == WellKnownMember.System_Runtime_CompilerServices_NativeIntegerAttribute__ctorTransformFlags) ? 1 : 0;
return new SynthesizedAttributeData(
_lazyNativeIntegerAttribute.Constructors[constructorIndex],
arguments,
ImmutableArray<KeyValuePair<string, TypedConstant>>.Empty);
}
return base.SynthesizeNativeIntegerAttribute(member, arguments);
}
protected override SynthesizedAttributeData TrySynthesizeIsReadOnlyAttribute()
{
if ((object)_lazyIsReadOnlyAttribute != null)
......@@ -345,6 +361,15 @@ private void CreateEmbeddedAttributesIfNeeded(DiagnosticBag diagnostics)
AttributeDescription.NullablePublicOnlyAttribute,
CreateNullablePublicOnlyAttributeSymbol);
}
if ((needsAttributes & EmbeddableAttributes.NativeIntegerAttribute) != 0)
{
CreateAttributeIfNeeded(
ref _lazyNativeIntegerAttribute,
diagnostics,
AttributeDescription.NativeIntegerAttribute,
CreateNativeIntegerAttributeSymbol);
}
}
private SynthesizedEmbeddedAttributeSymbol CreateParameterlessEmbeddedAttributeSymbol(string name, NamespaceSymbol containingNamespace, DiagnosticBag diagnostics)
......@@ -378,6 +403,14 @@ private SynthesizedEmbeddedNullablePublicOnlyAttributeSymbol CreateNullablePubli
GetWellKnownType(WellKnownType.System_Attribute, diagnostics),
GetSpecialType(SpecialType.System_Boolean, diagnostics));
private SynthesizedEmbeddedNativeIntegerAttributeSymbol CreateNativeIntegerAttributeSymbol(string name, NamespaceSymbol containingNamespace, DiagnosticBag diagnostics)
=> new SynthesizedEmbeddedNativeIntegerAttributeSymbol(
name,
containingNamespace,
SourceModule,
GetWellKnownType(WellKnownType.System_Attribute, diagnostics),
GetSpecialType(SpecialType.System_Boolean, diagnostics));
private void CreateAttributeIfNeeded<T>(
ref T symbol,
DiagnosticBag diagnostics,
......
......@@ -15,7 +15,6 @@
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Symbols;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.Emit
......@@ -1514,6 +1513,39 @@ internal virtual SynthesizedAttributeData SynthesizeNullableContextAttribute(Imm
return Compilation.TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_NullableContextAttribute__ctor, arguments, isOptionalUse: true);
}
internal SynthesizedAttributeData SynthesizeNativeIntegerAttribute(Symbol symbol, TypeSymbol type)
{
Debug.Assert((object)type != null);
Debug.Assert(type.ContainsNativeInteger());
if ((object)Compilation.SourceModule != symbol.ContainingModule)
{
// For symbols that are not defined in the same compilation (like NoPia), don't synthesize this attribute.
return null;
}
if ((type as NamedTypeSymbol)?.IsNativeInt == true)
{
return SynthesizeNativeIntegerAttribute(WellKnownMember.System_Runtime_CompilerServices_NativeIntegerAttribute__ctor, ImmutableArray<TypedConstant>.Empty);
}
else
{
NamedTypeSymbol booleanType = Compilation.GetSpecialType(SpecialType.System_Boolean);
Debug.Assert((object)booleanType != null);
var transformFlags = CSharpCompilation.NativeIntegerTransformsEncoder.Encode(type, booleanType);
var boolArray = ArrayTypeSymbol.CreateSZArray(booleanType.ContainingAssembly, TypeWithAnnotations.Create(booleanType));
var arguments = ImmutableArray.Create(new TypedConstant(boolArray, transformFlags));
return SynthesizeNativeIntegerAttribute(WellKnownMember.System_Runtime_CompilerServices_NativeIntegerAttribute__ctorTransformFlags, arguments);
}
}
internal virtual SynthesizedAttributeData SynthesizeNativeIntegerAttribute(WellKnownMember member, ImmutableArray<TypedConstant> arguments)
{
// For modules, this attribute should be present. Only assemblies generate and embed this type.
// https://github.com/dotnet/roslyn/issues/30062 Should not be optional.
return Compilation.TrySynthesizeAttribute(member, arguments, isOptionalUse: true);
}
internal bool ShouldEmitNullablePublicOnlyAttribute()
{
// No need to look at this.GetNeedsGeneratedAttributes() since those bits are
......@@ -1575,5 +1607,10 @@ internal void EnsureNullableAttributeExists()
{
EnsureEmbeddableAttributeExists(EmbeddableAttributes.NullableAttribute);
}
internal void EnsureNativeIntegerAttributeExists()
{
EnsureEmbeddableAttributeExists(EmbeddableAttributes.NativeIntegerAttribute);
}
}
}
......@@ -257,24 +257,33 @@ public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatemen
var localFunction = node.Symbol;
CheckRefReadOnlySymbols(localFunction);
var typeParameters = localFunction.TypeParameters;
if (typeParameters.Any(typeParameter => typeParameter.HasUnmanagedTypeConstraint))
if (_factory.CompilationState.ModuleBuilderOpt is { } moduleBuilder)
{
_factory.CompilationState.ModuleBuilderOpt?.EnsureIsUnmanagedAttributeExists();
}
if (_factory.CompilationState.Compilation.ShouldEmitNullableAttributes(localFunction))
{
bool constraintsNeedNullableAttribute = typeParameters.Any(
typeParameter => ((SourceTypeParameterSymbolBase)typeParameter).ConstraintsNeedNullableAttribute());
var typeParameters = localFunction.TypeParameters;
if (typeParameters.Any(typeParameter => typeParameter.HasUnmanagedTypeConstraint))
{
moduleBuilder.EnsureIsUnmanagedAttributeExists();
}
bool returnTypeNeedsNullableAttribute = localFunction.ReturnTypeWithAnnotations.NeedsNullableAttribute();
bool parametersNeedNullableAttribute = localFunction.ParameterTypesWithAnnotations.Any(parameter => parameter.NeedsNullableAttribute());
if (hasReturnTypeOrParameter(localFunction, t => t.ContainsNativeInteger()) ||
typeParameters.Any(t => t.ConstraintTypesNoUseSiteDiagnostics.Any(t => t.ContainsNativeInteger())))
{
moduleBuilder.EnsureNativeIntegerAttributeExists();
}
if (constraintsNeedNullableAttribute || returnTypeNeedsNullableAttribute || parametersNeedNullableAttribute)
if (_factory.CompilationState.Compilation.ShouldEmitNullableAttributes(localFunction))
{
_factory.CompilationState.ModuleBuilderOpt?.EnsureNullableAttributeExists();
bool constraintsNeedNullableAttribute = typeParameters.Any(
typeParameter => ((SourceTypeParameterSymbolBase)typeParameter).ConstraintsNeedNullableAttribute());
if (constraintsNeedNullableAttribute || hasReturnTypeOrParameter(localFunction, t => t.NeedsNullableAttribute()))
{
moduleBuilder.EnsureNullableAttributeExists();
}
}
static bool hasReturnTypeOrParameter(LocalFunctionSymbol localFunction, Func<TypeWithAnnotations, bool> predicate) =>
predicate(localFunction.ReturnTypeWithAnnotations) || localFunction.ParameterTypesWithAnnotations.Any(predicate);
}
var oldContainingSymbol = _factory.CurrentFunction;
......
......@@ -522,6 +522,11 @@ internal void EnsureNullableContextAttributeExists(DiagnosticBag? diagnostics, L
EnsureEmbeddableAttributeExists(EmbeddableAttributes.NullableContextAttribute, diagnostics, location, modifyCompilation);
}
internal void EnsureNativeIntegerAttributeExists(DiagnosticBag? diagnostics, Location location, bool modifyCompilation)
{
EnsureEmbeddableAttributeExists(EmbeddableAttributes.NativeIntegerAttribute, diagnostics, location, modifyCompilation);
}
internal bool CheckIfAttributeShouldBeEmbedded(EmbeddableAttributes attribute, DiagnosticBag? diagnosticsOpt, Location locationOpt)
{
switch (attribute)
......@@ -548,7 +553,7 @@ internal bool CheckIfAttributeShouldBeEmbedded(EmbeddableAttributes attribute, D
WellKnownMember.System_Runtime_CompilerServices_IsUnmanagedAttribute__ctor);
case EmbeddableAttributes.NullableAttribute:
// Note: if the type exists, we'll check both constructors, regardless of which one(s) we'll eventually need
// If the type exists, we'll check both constructors, regardless of which one(s) we'll eventually need.
return CheckIfAttributeShouldBeEmbedded(
diagnosticsOpt,
locationOpt,
......@@ -570,6 +575,15 @@ internal bool CheckIfAttributeShouldBeEmbedded(EmbeddableAttributes attribute, D
WellKnownType.System_Runtime_CompilerServices_NullablePublicOnlyAttribute,
WellKnownMember.System_Runtime_CompilerServices_NullablePublicOnlyAttribute__ctor);
case EmbeddableAttributes.NativeIntegerAttribute:
// If the type exists, we'll check both constructors, regardless of which one(s) we'll eventually need.
return CheckIfAttributeShouldBeEmbedded(
diagnosticsOpt,
locationOpt,
WellKnownType.System_Runtime_CompilerServices_NativeIntegerAttribute,
WellKnownMember.System_Runtime_CompilerServices_NativeIntegerAttribute__ctor,
WellKnownMember.System_Runtime_CompilerServices_NativeIntegerAttribute__ctorTransformFlags);
default:
throw ExceptionUtilities.UnexpectedValue(attribute);
}
......@@ -699,7 +713,7 @@ private bool CheckIfAttributeShouldBeEmbedded(DiagnosticBag? diagnosticsOpt, Loc
RoslynDebug.Assert((object)booleanType != null);
var transformFlags = DynamicTransformsEncoder.Encode(type, refKindOpt, customModifiersCount, booleanType);
var boolArray = ArrayTypeSymbol.CreateSZArray(booleanType.ContainingAssembly, TypeWithAnnotations.Create(booleanType));
var arguments = ImmutableArray.Create<TypedConstant>(new TypedConstant(boolArray, transformFlags));
var arguments = ImmutableArray.Create(new TypedConstant(boolArray, transformFlags));
return TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_DynamicAttribute__ctorTransformFlags, arguments);
}
}
......@@ -896,11 +910,53 @@ private static bool AddFlags(TypeSymbol type, ArrayBuilder<bool> transformFlagsB
private static void HandleCustomModifiers(int customModifiersCount, ArrayBuilder<bool> transformFlagsBuilder)
{
for (int i = 0; i < customModifiersCount; i++)
// Native compiler encodes an extra transforms flag, always false, for each custom modifier.
transformFlagsBuilder.AddMany(false, customModifiersCount);
}
}
internal static class NativeIntegerTransformsEncoder
{
internal static ImmutableArray<TypedConstant> Encode(TypeSymbol type, TypeSymbol booleanType)
{
var builder = ArrayBuilder<bool>.GetInstance();
type.VisitType((typeSymbol, builder, isNested) => AddFlags(typeSymbol, builder, isNested), builder);
Debug.Assert(builder.Any());
Debug.Assert(builder.Contains(true));
var result = builder.SelectAsArray((flag, constantType) => new TypedConstant(constantType, TypedConstantKind.Primitive, flag), booleanType);
builder.Free();
return result;
}
private static bool AddFlags(TypeSymbol type, ArrayBuilder<bool> builder, bool isNestedNamedType)
{
switch (type.TypeKind)
{
// Native compiler encodes an extra transforms flag, always false, for each custom modifier.
transformFlagsBuilder.Add(false);
case TypeKind.Array:
case TypeKind.Pointer:
case TypeKind.TypeParameter:
case TypeKind.Dynamic:
builder.Add(false);
break;
case TypeKind.Class:
case TypeKind.Struct:
case TypeKind.Interface:
case TypeKind.Delegate:
case TypeKind.Enum:
case TypeKind.Error:
// For nested named types, a single false is encoded for the entire type name, followed by flags for all of the type arguments.
if (!isNestedNamedType)
{
builder.Add(((NamedTypeSymbol)type).IsNativeInt);
}
break;
default:
throw ExceptionUtilities.UnexpectedValue(type.TypeKind);
}
// Continue walking types
return false;
}
}
......
......@@ -15,5 +15,6 @@ internal enum EmbeddableAttributes
NullableAttribute = 0x08,
NullableContextAttribute = 0x10,
NullablePublicOnlyAttribute = 0x20,
NativeIntegerAttribute = 0x40,
}
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Reflection.Metadata;
using Microsoft.CodeAnalysis.PooledObjects;
namespace Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE
{
internal struct NativeIntegerTypeDecoder
{
internal static TypeSymbol TransformType(TypeSymbol type, EntityHandle handle, PEModuleSymbol containingModule)
{
return containingModule.Module.HasNativeIntegerAttribute(handle, out var transformFlags) ?
TransformType(type, transformFlags) :
type;
}
private static TypeSymbol TransformType(TypeSymbol type, ImmutableArray<bool> transformFlags)
{
var decoder = new NativeIntegerTypeDecoder(transformFlags);
try
{
var result = decoder.TransformType(type);
if (decoder._index == transformFlags.Length)
{
return result;
}
}
catch (ArgumentException)
{
}
return type;
}
private readonly ImmutableArray<bool> _transformFlags;
private int _index;
private NativeIntegerTypeDecoder(ImmutableArray<bool> transformFlags)
{
_transformFlags = transformFlags;
_index = 0;
}
private TypeWithAnnotations TransformTypeWithAnnotations(TypeWithAnnotations type)
{
return type.WithTypeAndModifiers(TransformType(type.Type), type.CustomModifiers);
}
private TypeSymbol TransformType(TypeSymbol type)
{
switch (type.TypeKind)
{
case TypeKind.Array:
return TransformArrayType((ArrayTypeSymbol)type);
case TypeKind.Pointer:
return TransformPointerType((PointerTypeSymbol)type);
case TypeKind.TypeParameter:
case TypeKind.Dynamic:
return type;
case TypeKind.Class:
case TypeKind.Struct:
case TypeKind.Interface:
case TypeKind.Delegate:
case TypeKind.Enum:
return TransformNamedType((NamedTypeSymbol)type);
default:
Debug.Assert(type.TypeKind == TypeKind.Error);
throw new ArgumentException();
}
}
private NamedTypeSymbol TransformNamedType(NamedTypeSymbol type)
{
int index = Increment();
if (!type.IsGenericType)
{
return _transformFlags[index] ? TransformTypeDefinition(type) : type;
}
var allTypeArguments = ArrayBuilder<TypeWithAnnotations>.GetInstance();
type.GetAllTypeArgumentsNoUseSiteDiagnostics(allTypeArguments);
bool haveChanges = false;
for (int i = 0; i < allTypeArguments.Count; i++)
{
TypeWithAnnotations oldTypeArgument = allTypeArguments[i];
TypeWithAnnotations newTypeArgument = TransformTypeWithAnnotations(oldTypeArgument);
if (!oldTypeArgument.IsSameAs(newTypeArgument))
{
allTypeArguments[i] = newTypeArgument;
haveChanges = true;
}
}
NamedTypeSymbol result = haveChanges ? type.WithTypeArguments(allTypeArguments.ToImmutable()) : type;
allTypeArguments.Free();
return result;
}
private ArrayTypeSymbol TransformArrayType(ArrayTypeSymbol type)
{
Increment();
return type.WithElementType(TransformTypeWithAnnotations(type.ElementTypeWithAnnotations));
}
private PointerTypeSymbol TransformPointerType(PointerTypeSymbol type)
{
Increment();
return type.WithPointedAtType(TransformTypeWithAnnotations(type.PointedAtTypeWithAnnotations));
}
private int Increment()
{
if (_index < _transformFlags.Length)
{
return _index++;
}
throw new ArgumentException();
}
private static NamedTypeSymbol TransformTypeDefinition(NamedTypeSymbol type)
{
switch (type.SpecialType)
{
case SpecialType.System_IntPtr:
case SpecialType.System_UIntPtr:
return type.AsNativeInt(true);
default:
throw new ArgumentException();
}
}
}
}
......@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using Microsoft.CodeAnalysis.CSharp.DocumentationComments;
using Microsoft.CodeAnalysis.CSharp.Emit;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Utilities;
using System;
......@@ -13,7 +14,6 @@
using System.Reflection;
using System.Reflection.Metadata;
using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Emit;
namespace Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE
{
......@@ -98,6 +98,7 @@ private enum Flags : byte
const int targetSymbolCustomModifierCount = 0;
var typeSymbol = DynamicTypeDecoder.TransformType(originalEventType, targetSymbolCustomModifierCount, handle, moduleSymbol);
typeSymbol = NativeIntegerTypeDecoder.TransformType(typeSymbol, handle, moduleSymbol);
// We start without annotation (they will be decoded below)
var type = TypeWithAnnotations.Create(typeSymbol);
......
......@@ -258,6 +258,7 @@ private void EnsureSignatureIsLoaded()
ImmutableArray<CustomModifier> customModifiersArray = CSharpCustomModifier.Convert(customModifiers);
typeSymbol = DynamicTypeDecoder.TransformType(typeSymbol, customModifiersArray.Length, _handle, moduleSymbol);
typeSymbol = NativeIntegerTypeDecoder.TransformType(typeSymbol, _handle, moduleSymbol);
// We start without annotations
var type = TypeWithAnnotations.Create(typeSymbol, customModifiers: customModifiersArray);
......
......@@ -471,6 +471,7 @@ private NamedTypeSymbol GetDeclaredBaseType(bool skipTransformsIfNecessary)
var moduleSymbol = ContainingPEModule;
TypeSymbol decodedType = DynamicTypeDecoder.TransformType(baseType, 0, _handle, moduleSymbol);
decodedType = NativeIntegerTypeDecoder.TransformType(decodedType, _handle, moduleSymbol);
decodedType = TupleTypeDecoder.DecodeTupleTypesIfApplicable(decodedType, _handle, moduleSymbol);
baseType = (NamedTypeSymbol)NullableTypeDecoder.TransformType(TypeWithAnnotations.Create(decodedType), _handle, moduleSymbol, accessSymbol: this, nullableContext: this).Type;
}
......@@ -530,6 +531,7 @@ private ImmutableArray<NamedTypeSymbol> MakeDeclaredInterfaces()
EntityHandle interfaceHandle = moduleSymbol.Module.MetadataReader.GetInterfaceImplementation(interfaceImpl).Interface;
TypeSymbol typeSymbol = tokenDecoder.GetTypeOfToken(interfaceHandle);
typeSymbol = NativeIntegerTypeDecoder.TransformType(typeSymbol, interfaceImpl, moduleSymbol);
typeSymbol = TupleTypeDecoder.DecodeTupleTypesIfApplicable(typeSymbol, interfaceImpl, moduleSymbol);
typeSymbol = NullableTypeDecoder.TransformType(TypeWithAnnotations.Create(typeSymbol), interfaceImpl, moduleSymbol, accessSymbol: this, nullableContext: this).Type;
......
......@@ -259,6 +259,7 @@ public bool TryGetFlowAnalysisAnnotations(out FlowAnalysisAnnotations value)
}
var typeSymbol = DynamicTypeDecoder.TransformType(typeWithAnnotations.Type, countOfCustomModifiers, handle, moduleSymbol, refKind);
typeSymbol = NativeIntegerTypeDecoder.TransformType(typeSymbol, handle, moduleSymbol);
typeWithAnnotations = typeWithAnnotations.WithTypeAndModifiers(typeSymbol, typeWithAnnotations.CustomModifiers);
// Decode nullable before tuple types to avoid converting between
// NamedTypeSymbol and TupleTypeSymbol unnecessarily.
......
......@@ -7,14 +7,12 @@
using System.Collections.Immutable;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Threading;
using Microsoft.CodeAnalysis.CSharp.DocumentationComments;
using Microsoft.CodeAnalysis.CSharp.Emit;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE
{
......@@ -165,6 +163,7 @@ private enum Flags : byte
TypeSymbol originalPropertyType = returnInfo.Type;
originalPropertyType = DynamicTypeDecoder.TransformType(originalPropertyType, typeCustomModifiers.Length, handle, moduleSymbol, _refKind);
originalPropertyType = NativeIntegerTypeDecoder.TransformType(originalPropertyType, handle, moduleSymbol);
// Dynamify object type if necessary
originalPropertyType = originalPropertyType.AsDynamicIfNoPia(_containingType);
......
......@@ -1010,6 +1010,11 @@ internal virtual void AddSynthesizedReturnTypeAttributes(PEModuleBuilder moduleB
AddSynthesizedAttribute(ref attributes, compilation.SynthesizeDynamicAttribute(type.Type, type.CustomModifiers.Length + this.RefCustomModifiers.Length, this.RefKind));
}
if (type.Type.ContainsNativeInteger())
{
AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeNativeIntegerAttribute(this, type.Type));
}
if (type.Type.ContainsTupleNames() && compilation.HasTupleNamesAttributes)
{
AddSynthesizedAttribute(ref attributes, compilation.SynthesizeTupleNamesAttribute(type.Type));
......@@ -1021,7 +1026,6 @@ internal virtual void AddSynthesizedReturnTypeAttributes(PEModuleBuilder moduleB
}
}
/// <summary>
/// Returns true if locals are to be initialized
/// </summary>
......
......@@ -802,19 +802,8 @@ internal override bool ApplyNullableTransforms(byte defaultTransformFlag, Immuta
}
}
if (!haveChanges)
{
allTypeArguments.Free();
result = this;
}
else
{
TypeMap substitution = new TypeMap(this.OriginalDefinition.GetAllTypeParameters(),
allTypeArguments.ToImmutableAndFree());
result = substitution.SubstituteNamedType(this.OriginalDefinition).WithTupleDataFrom(this);
}
result = haveChanges ? this.WithTypeArguments(allTypeArguments.ToImmutable()) : this;
allTypeArguments.Free();
return true;
}
......@@ -840,18 +829,18 @@ internal override TypeSymbol SetNullabilityForReferenceTypes(Func<TypeWithAnnota
}
}
TypeSymbol result = this;
if (haveChanges)
{
var definition = this.OriginalDefinition;
TypeMap substitution = new TypeMap(definition.GetAllTypeParameters(), allTypeArguments.ToImmutable());
result = substitution.SubstituteNamedType(definition).WithTupleDataFrom(this);
}
NamedTypeSymbol result = haveChanges ? this.WithTypeArguments(allTypeArguments.ToImmutable()) : this;
allTypeArguments.Free();
return result;
}
internal NamedTypeSymbol WithTypeArguments(ImmutableArray<TypeWithAnnotations> allTypeArguments)
{
var definition = this.OriginalDefinition;
TypeMap substitution = new TypeMap(definition.GetAllTypeParameters(), allTypeArguments);
return substitution.SubstituteNamedType(definition).WithTupleDataFrom(this);
}
internal override TypeSymbol MergeEquivalentTypes(TypeSymbol other, VarianceKind variance)
{
Debug.Assert(this.Equals(other, TypeCompareKind.IgnoreDynamicAndTupleNames | TypeCompareKind.IgnoreNullableModifiersForReferenceTypes));
......
......@@ -277,7 +277,7 @@ internal override TypeSymbol MergeEquivalentTypes(TypeSymbol other, VarianceKind
return WithPointedAtType(pointedAtType);
}
private PointerTypeSymbol WithPointedAtType(TypeWithAnnotations newPointedAtType)
internal PointerTypeSymbol WithPointedAtType(TypeWithAnnotations newPointedAtType)
{
return PointedAtTypeWithAnnotations.IsSameAs(newPointedAtType) ? this : new PointerTypeSymbol(newPointedAtType);
}
......
......@@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE;
using Microsoft.CodeAnalysis.PooledObjects;
using System.Collections.Immutable;
......@@ -76,6 +75,7 @@ internal static TypeSymbol CopyTypeCustomModifiers(TypeSymbol sourceType, TypeSy
// NOTE: ref is irrelevant here since we are just encoding/decoding the type out of the signature context
ImmutableArray<bool> flags = CSharpCompilation.DynamicTransformsEncoder.EncodeWithoutCustomModifierFlags(destinationType, refKind);
TypeSymbol typeWithDynamic = DynamicTypeDecoder.TransformTypeWithoutCustomModifierFlags(sourceType, containingAssembly, refKind, flags);
// PROTOTYPE: Should we use NativeIntegerTypeDecoder here?
TypeSymbol resultType;
if (destinationType.ContainsTuple() && !sourceType.Equals(destinationType, TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds | TypeCompareKind.IgnoreNullableModifiersForReferenceTypes | TypeCompareKind.IgnoreDynamic))
......
......@@ -197,25 +197,9 @@ internal override void DecodeWellKnownAttribute(ref DecodeWellKnownAttributeArgu
{
MarshalAsAttributeDecoder<FieldWellKnownAttributeData, AttributeSyntax, CSharpAttributeData, AttributeLocation>.Decode(ref arguments, AttributeTargets.Field, MessageProvider.Instance);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.DynamicAttribute))
else if (ReportExplicitUseOfReservedAttributes(in arguments,
ReservedAttributes.DynamicAttribute | ReservedAttributes.IsReadOnlyAttribute | ReservedAttributes.IsUnmanagedAttribute | ReservedAttributes.IsByRefLikeAttribute | ReservedAttributes.TupleElementNamesAttribute | ReservedAttributes.NullableAttribute | ReservedAttributes.NativeIntegerAttribute))
{
// DynamicAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitDynamicAttr, arguments.AttributeSyntaxOpt.Location);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.IsReadOnlyAttribute))
{
// IsReadOnlyAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, AttributeDescription.IsReadOnlyAttribute.FullName);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.IsUnmanagedAttribute))
{
// IsUnmanagedAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, AttributeDescription.IsUnmanagedAttribute.FullName);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.IsByRefLikeAttribute))
{
// IsByRefLikeAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, AttributeDescription.IsByRefLikeAttribute.FullName);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.DateTimeConstantAttribute))
{
......@@ -225,15 +209,6 @@ internal override void DecodeWellKnownAttribute(ref DecodeWellKnownAttributeArgu
{
VerifyConstantValueMatches(attribute.DecodeDecimalConstantValue(), ref arguments);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.TupleElementNamesAttribute))
{
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitTupleElementNamesAttribute, arguments.AttributeSyntaxOpt.Location);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.NullableAttribute))
{
// NullableAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitNullableAttribute, arguments.AttributeSyntaxOpt.Location);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.AllowNullAttribute))
{
arguments.GetOrCreateData<FieldWellKnownAttributeData>().HasAllowNullAttribute = true;
......@@ -406,7 +381,12 @@ internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, r
if (type.Type.ContainsDynamic())
{
AddSynthesizedAttribute(ref attributes,
compilation.SynthesizeDynamicAttribute(type.Type, TypeWithAnnotations.CustomModifiers.Length));
compilation.SynthesizeDynamicAttribute(type.Type, type.CustomModifiers.Length));
}
if (type.Type.ContainsNativeInteger())
{
AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeNativeIntegerAttribute(this, type.Type));
}
if (type.Type.ContainsTupleNames())
......
......@@ -171,6 +171,7 @@ private void ComputeParameters()
var compilation = DeclaringCompilation;
ParameterHelpers.EnsureIsReadOnlyAttributeExists(compilation, parameters, diagnostics, modifyCompilation: false);
ParameterHelpers.EnsureNativeIntegerAttributeExists(compilation, parameters, diagnostics, modifyCompilation: false);
ParameterHelpers.EnsureNullableAttributeExists(compilation, this, parameters, diagnostics, modifyCompilation: false);
// Note: we don't need to warn on annotations used in #nullable disable context for local functions, as this is handled in binding already
......@@ -251,6 +252,11 @@ internal void ComputeReturnType()
compilation.EnsureIsReadOnlyAttributeExists(diagnostics, location, modifyCompilation: false);
}
if (returnType.Type.ContainsNativeInteger())
{
compilation.EnsureNativeIntegerAttributeExists(diagnostics, location, modifyCompilation: false);
}
if (compilation.ShouldEmitNullableAttributes(this) &&
returnType.NeedsNullableAttribute())
{
......
......@@ -137,7 +137,25 @@ internal static void EnsureIsReadOnlyAttributeExists(CSharpCompilation compilati
{
if (parameter.RefKind == RefKind.In)
{
compilation.EnsureIsReadOnlyAttributeExists(diagnostics, parameter.GetNonNullSyntaxNode().Location, modifyCompilation);
compilation.EnsureIsReadOnlyAttributeExists(diagnostics, GetParameterLocation(parameter), modifyCompilation);
}
}
}
internal static void EnsureNativeIntegerAttributeExists(CSharpCompilation compilation, ImmutableArray<ParameterSymbol> parameters, DiagnosticBag diagnostics, bool modifyCompilation)
{
// These parameters might not come from a compilation (example: lambdas evaluated in EE).
// During rewriting, lowering will take care of flagging the appropriate PEModuleBuilder instead.
if (compilation == null)
{
return;
}
foreach (var parameter in parameters)
{
if (parameter.TypeWithAnnotations.ContainsNativeInteger())
{
compilation.EnsureNativeIntegerAttributeExists(diagnostics, GetParameterLocation(parameter), modifyCompilation);
}
}
}
......@@ -157,12 +175,14 @@ internal static void EnsureNullableAttributeExists(CSharpCompilation compilation
{
if (parameter.TypeWithAnnotations.NeedsNullableAttribute())
{
compilation.EnsureNullableAttributeExists(diagnostics, parameter.GetNonNullSyntaxNode().Location, modifyCompilation);
compilation.EnsureNullableAttributeExists(diagnostics, GetParameterLocation(parameter), modifyCompilation);
}
}
}
}
private static Location GetParameterLocation(ParameterSymbol parameter) => parameter.GetNonNullSyntaxNode().Location;
private static void CheckParameterModifiers(
ParameterSyntax parameter, DiagnosticBag diagnostics)
{
......
......@@ -646,34 +646,9 @@ internal override void DecodeWellKnownAttribute(ref DecodeWellKnownAttributeArgu
{
ValidateCallerMemberNameAttribute(arguments.AttributeSyntaxOpt, arguments.Diagnostics);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.DynamicAttribute))
else if (ReportExplicitUseOfReservedAttributes(in arguments,
ReservedAttributes.DynamicAttribute | ReservedAttributes.IsReadOnlyAttribute | ReservedAttributes.IsUnmanagedAttribute | ReservedAttributes.IsByRefLikeAttribute | ReservedAttributes.TupleElementNamesAttribute | ReservedAttributes.NullableAttribute | ReservedAttributes.NativeIntegerAttribute))
{
// DynamicAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitDynamicAttr, arguments.AttributeSyntaxOpt.Location);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.IsReadOnlyAttribute))
{
// IsReadOnlyAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, AttributeDescription.IsReadOnlyAttribute.FullName);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.IsUnmanagedAttribute))
{
// IsUnmanagedAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, AttributeDescription.IsUnmanagedAttribute.FullName);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.IsByRefLikeAttribute))
{
// IsByRefLikeAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, AttributeDescription.IsByRefLikeAttribute.FullName);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.TupleElementNamesAttribute))
{
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitTupleElementNamesAttribute, arguments.AttributeSyntaxOpt.Location);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.NullableAttribute))
{
// NullableAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitNullableAttribute, arguments.AttributeSyntaxOpt.Location);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.AllowNullAttribute))
{
......
......@@ -130,6 +130,7 @@ internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions,
var compilation = DeclaringCompilation;
ParameterHelpers.EnsureIsReadOnlyAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true);
ParameterHelpers.EnsureNativeIntegerAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true);
ParameterHelpers.EnsureNullableAttributeExists(compilation, this, Parameters, diagnostics, modifyCompilation: true);
foreach (var parameter in this.Parameters)
......
......@@ -2,16 +2,12 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
using System.Collections.Generic;
using System;
namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
......@@ -320,6 +316,13 @@ internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions,
ParameterHelpers.EnsureIsReadOnlyAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true);
if (ReturnType.ContainsNativeInteger())
{
compilation.EnsureNativeIntegerAttributeExists(diagnostics, location, modifyCompilation: true);
}
ParameterHelpers.EnsureNativeIntegerAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true);
if (compilation.ShouldEmitNullableAttributes(this) &&
ReturnTypeWithAnnotations.NeedsNullableAttribute())
{
......
......@@ -291,19 +291,13 @@ internal sealed override void DecodeWellKnownAttribute(ref DecodeWellKnownAttrib
{
arguments.GetOrCreateData<CommonEventWellKnownAttributeData>().HasSpecialNameAttribute = true;
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.NullableAttribute))
else if (ReportExplicitUseOfReservedAttributes(in arguments, ReservedAttributes.NullableAttribute | ReservedAttributes.NativeIntegerAttribute | ReservedAttributes.TupleElementNamesAttribute))
{
// NullableAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitNullableAttribute, arguments.AttributeSyntaxOpt.Location);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.ExcludeFromCodeCoverageAttribute))
{
arguments.GetOrCreateData<CommonEventWellKnownAttributeData>().HasExcludeFromCodeCoverageAttribute = true;
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.TupleElementNamesAttribute))
{
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitTupleElementNamesAttribute, arguments.AttributeSyntaxOpt.Location);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.SkipLocalsInitAttribute))
{
attribute.DecodeSkipLocalsInitAttribute<CommonEventWellKnownAttributeData>(DeclaringCompilation, ref arguments);
......@@ -322,6 +316,11 @@ internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, r
AddSynthesizedAttribute(ref attributes, compilation.SynthesizeDynamicAttribute(type.Type, type.CustomModifiers.Length));
}
if (type.Type.ContainsNativeInteger())
{
AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeNativeIntegerAttribute(this, type.Type));
}
if (type.Type.ContainsTupleNames())
{
AddSynthesizedAttribute(ref attributes,
......@@ -734,6 +733,11 @@ internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions,
this.CheckModifiersAndType(diagnostics);
this.Type.CheckAllConstraints(compilation, conversions, location, diagnostics);
if (Type.ContainsNativeInteger())
{
compilation.EnsureNativeIntegerAttributeExists(diagnostics, location, modifyCompilation: true);
}
if (compilation.ShouldEmitNullableAttributes(this) &&
TypeWithAnnotations.NeedsNullableAttribute())
{
......
......@@ -132,6 +132,11 @@ internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions,
var compilation = DeclaringCompilation;
var location = ErrorLocation;
if (Type.ContainsNativeInteger())
{
compilation.EnsureNativeIntegerAttributeExists(diagnostics, location, modifyCompilation: true);
}
if (compilation.ShouldEmitNullableAttributes(this) &&
TypeWithAnnotations.NeedsNullableAttribute())
{
......
......@@ -1434,6 +1434,12 @@ protected void AfterMembersChecks(DiagnosticBag diagnostics)
compilation.EnsureIsReadOnlyAttributeExists(diagnostics, location, modifyCompilation: true);
}
// https://github.com/dotnet/roslyn/issues/30080: Report diagnostics for base type and interfaces at more specific locations.
if (hasBaseTypeOrInterface(t => t.ContainsNativeInteger()))
{
compilation.EnsureNativeIntegerAttributeExists(diagnostics, location, modifyCompilation: true);
}
if (compilation.ShouldEmitNullableAttributes(this))
{
if (ShouldEmitNullableContextValue(out _))
......@@ -1441,15 +1447,18 @@ protected void AfterMembersChecks(DiagnosticBag diagnostics)
compilation.EnsureNullableContextAttributeExists(diagnostics, location, modifyCompilation: true);
}
// https://github.com/dotnet/roslyn/issues/30080: Report diagnostics for base type and interfaces at more specific locations.
var baseType = BaseTypeNoUseSiteDiagnostics;
var interfaces = InterfacesNoUseSiteDiagnostics();
if (baseType?.NeedsNullableAttribute() == true ||
interfaces.Any(t => t.NeedsNullableAttribute()))
if (hasBaseTypeOrInterface(t => t.NeedsNullableAttribute()))
{
compilation.EnsureNullableAttributeExists(diagnostics, location, modifyCompilation: true);
}
}
bool hasBaseTypeOrInterface(Func<NamedTypeSymbol, bool> predicate)
{
var baseType = BaseTypeNoUseSiteDiagnostics;
return ((object)baseType != null && predicate(baseType)) ||
InterfacesNoUseSiteDiagnostics().Any(predicate);
}
}
private void CheckMemberNamesDistinctFromType(DiagnosticBag diagnostics)
......@@ -3389,6 +3398,11 @@ internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, r
AddSynthesizedAttribute(ref attributes, compilation.SynthesizeDynamicAttribute(baseType, customModifiersCount: 0));
}
if (baseType.ContainsNativeInteger())
{
AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeNativeIntegerAttribute(this, baseType));
}
if (baseType.ContainsTupleNames())
{
AddSynthesizedAttribute(ref attributes, compilation.SynthesizeTupleNamesAttribute(baseType));
......
......@@ -12,7 +12,6 @@
using System.Diagnostics;
using System.Threading;
using Microsoft.CodeAnalysis.Text;
using System.Runtime.CompilerServices;
namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
......
......@@ -1220,30 +1220,15 @@ private void DecodeWellKnownAttributeAppliedToMethod(ref DecodeWellKnownAttribut
else if (VerifyObsoleteAttributeAppliedToMethod(ref arguments, AttributeDescription.DeprecatedAttribute))
{
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.IsReadOnlyAttribute))
else if (ReportExplicitUseOfReservedAttributes(in arguments,
ReservedAttributes.IsReadOnlyAttribute | ReservedAttributes.IsUnmanagedAttribute | ReservedAttributes.IsByRefLikeAttribute | ReservedAttributes.NullableContextAttribute))
{
// IsReadOnlyAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, AttributeDescription.IsReadOnlyAttribute.FullName);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.IsUnmanagedAttribute))
{
// IsUnmanagedAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, AttributeDescription.IsUnmanagedAttribute.FullName);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.IsByRefLikeAttribute))
{
// IsByRefLikeAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, AttributeDescription.IsByRefLikeAttribute.FullName);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.CaseSensitiveExtensionAttribute))
{
// [Extension] attribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitExtension, arguments.AttributeSyntaxOpt.Location);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.NullableContextAttribute))
{
ReportExplicitUseOfNullabilityAttribute(in arguments, AttributeDescription.NullableContextAttribute);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.SecurityCriticalAttribute)
|| attribute.IsTargetAttribute(this, AttributeDescription.SecuritySafeCriticalAttribute))
{
......@@ -1380,34 +1365,9 @@ private void DecodeWellKnownAttributeAppliedToReturnValue(ref DecodeWellKnownAtt
// MarshalAs applied to the return value:
MarshalAsAttributeDecoder<ReturnTypeWellKnownAttributeData, AttributeSyntax, CSharpAttributeData, AttributeLocation>.Decode(ref arguments, AttributeTargets.ReturnValue, MessageProvider.Instance);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.DynamicAttribute))
{
// DynamicAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitDynamicAttr, arguments.AttributeSyntaxOpt.Location);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.IsUnmanagedAttribute))
{
// IsUnmanagedAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, AttributeDescription.IsUnmanagedAttribute.FullName);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.IsReadOnlyAttribute))
{
// IsReadOnlyAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, AttributeDescription.IsReadOnlyAttribute.FullName);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.IsByRefLikeAttribute))
{
// IsByRefLikeAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, AttributeDescription.IsByRefLikeAttribute.FullName);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.TupleElementNamesAttribute))
{
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitTupleElementNamesAttribute, arguments.AttributeSyntaxOpt.Location);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.NullableAttribute))
else if (ReportExplicitUseOfReservedAttributes(in arguments,
ReservedAttributes.DynamicAttribute | ReservedAttributes.IsReadOnlyAttribute | ReservedAttributes.IsUnmanagedAttribute | ReservedAttributes.IsByRefLikeAttribute | ReservedAttributes.TupleElementNamesAttribute | ReservedAttributes.NullableAttribute | ReservedAttributes.NativeIntegerAttribute))
{
// NullableAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitNullableAttribute, arguments.AttributeSyntaxOpt.Location);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.MaybeNullAttribute))
{
......
......@@ -513,13 +513,9 @@ internal override void DecodeWellKnownAttribute(ref DecodeWellKnownAttributeArgu
arguments.GetOrCreateData<ModuleWellKnownAttributeData>().DefaultCharacterSet = charSet;
}
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.NullableContextAttribute))
else if (ReportExplicitUseOfReservedAttributes(in arguments,
ReservedAttributes.NullableContextAttribute | ReservedAttributes.NullablePublicOnlyAttribute))
{
ReportExplicitUseOfNullabilityAttribute(in arguments, AttributeDescription.NullableContextAttribute);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.NullablePublicOnlyAttribute))
{
ReportExplicitUseOfNullabilityAttribute(in arguments, AttributeDescription.NullablePublicOnlyAttribute);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.SkipLocalsInitAttribute))
{
......
......@@ -889,29 +889,9 @@ internal sealed override void DecodeWellKnownAttribute(ref DecodeWellKnownAttrib
// ExtensionAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitExtension, arguments.AttributeSyntaxOpt.Location);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.DynamicAttribute))
else if (ReportExplicitUseOfReservedAttributes(in arguments,
ReservedAttributes.DynamicAttribute | ReservedAttributes.IsReadOnlyAttribute | ReservedAttributes.IsUnmanagedAttribute | ReservedAttributes.IsByRefLikeAttribute | ReservedAttributes.TupleElementNamesAttribute | ReservedAttributes.NullableAttribute | ReservedAttributes.NullableContextAttribute | ReservedAttributes.NativeIntegerAttribute))
{
// DynamicAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitDynamicAttr, arguments.AttributeSyntaxOpt.Location);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.IsReadOnlyAttribute))
{
// IsReadOnlyAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, AttributeDescription.IsReadOnlyAttribute.FullName);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.IsUnmanagedAttribute))
{
// IsUnmanagedAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, AttributeDescription.IsUnmanagedAttribute.FullName);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.IsByRefLikeAttribute))
{
// IsByRefLikeAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, AttributeDescription.IsByRefLikeAttribute.FullName);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.TupleElementNamesAttribute))
{
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitTupleElementNamesAttribute, arguments.AttributeSyntaxOpt.Location);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.SecurityCriticalAttribute)
|| attribute.IsTargetAttribute(this, AttributeDescription.SecuritySafeCriticalAttribute))
......@@ -926,15 +906,6 @@ internal sealed override void DecodeWellKnownAttribute(ref DecodeWellKnownAttrib
{
_lazyIsExplicitDefinitionOfNoPiaLocalType = ThreeState.True;
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.NullableAttribute))
{
// NullableAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitNullableAttribute, arguments.AttributeSyntaxOpt.Location);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.NullableContextAttribute))
{
ReportExplicitUseOfNullabilityAttribute(in arguments, AttributeDescription.NullableContextAttribute);
}
else
{
var compilation = this.DeclaringCompilation;
......
......@@ -1169,6 +1169,13 @@ internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions,
ParameterHelpers.EnsureIsReadOnlyAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true);
if (ReturnType.ContainsNativeInteger())
{
compilation.EnsureNativeIntegerAttributeExists(diagnostics, location, modifyCompilation: true);
}
ParameterHelpers.EnsureNativeIntegerAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true);
if (compilation.ShouldEmitNullableAttributes(this) && ReturnTypeWithAnnotations.NeedsNullableAttribute())
{
compilation.EnsureNullableAttributeExists(diagnostics, location, modifyCompilation: true);
......
......@@ -87,6 +87,11 @@ internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, r
AddSynthesizedAttribute(ref attributes, compilation.SynthesizeDynamicAttribute(type.Type, type.CustomModifiers.Length + this.RefCustomModifiers.Length, this.RefKind));
}
if (type.Type.ContainsNativeInteger())
{
AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeNativeIntegerAttribute(this, type.Type));
}
if (type.Type.ContainsTupleNames())
{
AddSynthesizedAttribute(ref attributes,
......
......@@ -823,6 +823,13 @@ internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions,
ParameterHelpers.EnsureIsReadOnlyAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true);
if (Type.ContainsNativeInteger())
{
compilation.EnsureNativeIntegerAttributeExists(diagnostics, location, modifyCompilation: true);
}
ParameterHelpers.EnsureNativeIntegerAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true);
if (compilation.ShouldEmitNullableAttributes(this) &&
this.TypeWithAnnotations.NeedsNullableAttribute())
{
......@@ -1257,6 +1264,11 @@ internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, r
compilation.SynthesizeDynamicAttribute(type.Type, type.CustomModifiers.Length + RefCustomModifiers.Length, _refKind));
}
if (type.Type.ContainsNativeInteger())
{
AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeNativeIntegerAttribute(this, type.Type));
}
if (type.Type.ContainsTupleNames())
{
AddSynthesizedAttribute(ref attributes,
......@@ -1378,29 +1390,9 @@ internal override void DecodeWellKnownAttribute(ref DecodeWellKnownAttributeArgu
// DynamicAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitDynamicAttr, arguments.AttributeSyntaxOpt.Location);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.IsReadOnlyAttribute))
{
// IsReadOnlyAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, AttributeDescription.IsReadOnlyAttribute.FullName);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.IsUnmanagedAttribute))
{
// IsUnmanagedAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, AttributeDescription.IsUnmanagedAttribute.FullName);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.IsByRefLikeAttribute))
{
// IsByRefLikeAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, AttributeDescription.IsByRefLikeAttribute.FullName);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.TupleElementNamesAttribute))
{
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitTupleElementNamesAttribute, arguments.AttributeSyntaxOpt.Location);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.NullableAttribute))
else if (ReportExplicitUseOfReservedAttributes(in arguments,
ReservedAttributes.DynamicAttribute | ReservedAttributes.IsReadOnlyAttribute | ReservedAttributes.IsUnmanagedAttribute | ReservedAttributes.IsByRefLikeAttribute | ReservedAttributes.TupleElementNamesAttribute | ReservedAttributes.NullableAttribute | ReservedAttributes.NativeIntegerAttribute))
{
// NullableAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitNullableAttribute, arguments.AttributeSyntaxOpt.Location);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.DisallowNullAttribute))
{
......
......@@ -229,7 +229,7 @@ private TypeParameterBounds GetBounds(ConsList<TypeParameterSymbol> inProgress)
{
this.CheckConstraintTypeConstraints(diagnostics);
this.CheckUnmanagedConstraint(diagnostics);
this.CheckNullableAnnotationsInConstraints(diagnostics);
this.EnsureAttributesFromConstraints(diagnostics);
this.AddDeclarationDiagnostics(diagnostics);
_state.NotePartComplete(CompletionPart.TypeParameterConstraints);
}
......@@ -300,12 +300,17 @@ private bool ModifyCompilationForAttributeEmbedding()
return modifyCompilation;
}
private void CheckNullableAnnotationsInConstraints(DiagnosticBag diagnostics)
private void EnsureAttributesFromConstraints(DiagnosticBag diagnostics)
{
if (ConstraintTypesNoUseSiteDiagnostics.Any(t => t.ContainsNativeInteger()))
{
DeclaringCompilation.EnsureNativeIntegerAttributeExists(diagnostics, getLocation(), ModifyCompilationForAttributeEmbedding());
}
if (ConstraintsNeedNullableAttribute())
{
DeclaringCompilation.EnsureNullableAttributeExists(diagnostics, this.GetNonNullSyntaxNode().Location, ModifyCompilationForAttributeEmbedding());
DeclaringCompilation.EnsureNullableAttributeExists(diagnostics, getLocation(), ModifyCompilationForAttributeEmbedding());
}
Location getLocation() => this.GetNonNullSyntaxNode().Location;
}
// See https://github.com/dotnet/roslyn/blob/master/docs/features/nullable-metadata.md
......
......@@ -666,6 +666,13 @@ internal sealed override void AfterAddingTypeMembersChecks(ConversionsBase conve
ParameterHelpers.EnsureIsReadOnlyAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true);
if (ReturnType.ContainsNativeInteger())
{
compilation.EnsureNativeIntegerAttributeExists(diagnostics, ReturnTypeSyntax.Location, modifyCompilation: true);
}
ParameterHelpers.EnsureNativeIntegerAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true);
if (compilation.ShouldEmitNullableAttributes(this) &&
ReturnTypeWithAnnotations.NeedsNullableAttribute())
{
......
......@@ -1129,7 +1129,6 @@ internal ObsoleteAttributeKind ObsoleteKind
}
}
/// <summary>
/// Returns data decoded from <see cref="ObsoleteAttribute"/> attribute or null if there is no <see cref="ObsoleteAttribute"/> attribute.
/// This property returns <see cref="Microsoft.CodeAnalysis.ObsoleteAttributeData.Uninitialized"/> if attribute arguments haven't been decoded yet.
......@@ -1207,10 +1206,80 @@ public ImmutableArray<SymbolDisplayPart> ToDisplayParts(SymbolDisplayFormat form
}
}
internal void ReportExplicitUseOfNullabilityAttribute(in DecodeWellKnownAttributeArguments<AttributeSyntax, CSharpAttributeData, AttributeLocation> arguments, AttributeDescription attributeDescription)
[Flags]
internal enum ReservedAttributes
{
// Attribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, attributeDescription.FullName);
DynamicAttribute = 1 << 1,
IsReadOnlyAttribute = 1 << 2,
IsUnmanagedAttribute = 1 << 3,
IsByRefLikeAttribute = 1 << 4,
TupleElementNamesAttribute = 1 << 5,
NullableAttribute = 1 << 6,
NullableContextAttribute = 1 << 7,
NullablePublicOnlyAttribute = 1 << 8,
NativeIntegerAttribute = 1 << 9,
}
internal bool ReportExplicitUseOfReservedAttributes(in DecodeWellKnownAttributeArguments<AttributeSyntax, CSharpAttributeData, AttributeLocation> arguments, ReservedAttributes reserved)
{
var attribute = arguments.Attribute;
if ((reserved & ReservedAttributes.DynamicAttribute) != 0 &&
attribute.IsTargetAttribute(this, AttributeDescription.DynamicAttribute))
{
// DynamicAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitDynamicAttr, arguments.AttributeSyntaxOpt.Location);
}
else if ((reserved & ReservedAttributes.IsReadOnlyAttribute) != 0 &&
reportExplicitUseOfReservedAttribute(attribute, arguments, AttributeDescription.IsReadOnlyAttribute))
{
}
else if ((reserved & ReservedAttributes.IsUnmanagedAttribute) != 0 &&
reportExplicitUseOfReservedAttribute(attribute, arguments, AttributeDescription.IsUnmanagedAttribute))
{
}
else if ((reserved & ReservedAttributes.IsByRefLikeAttribute) != 0 &&
reportExplicitUseOfReservedAttribute(attribute, arguments, AttributeDescription.IsByRefLikeAttribute))
{
}
else if ((reserved & ReservedAttributes.TupleElementNamesAttribute) != 0 &&
attribute.IsTargetAttribute(this, AttributeDescription.TupleElementNamesAttribute))
{
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitTupleElementNamesAttribute, arguments.AttributeSyntaxOpt.Location);
}
else if ((reserved & ReservedAttributes.NullableAttribute) != 0 &&
attribute.IsTargetAttribute(this, AttributeDescription.NullableAttribute))
{
// NullableAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitNullableAttribute, arguments.AttributeSyntaxOpt.Location);
}
else if ((reserved & ReservedAttributes.NullableContextAttribute) != 0 &&
reportExplicitUseOfReservedAttribute(attribute, arguments, AttributeDescription.NullableContextAttribute))
{
}
else if ((reserved & ReservedAttributes.NullablePublicOnlyAttribute) != 0 &&
reportExplicitUseOfReservedAttribute(attribute, arguments, AttributeDescription.NullablePublicOnlyAttribute))
{
}
else if ((reserved & ReservedAttributes.NativeIntegerAttribute) != 0 &&
reportExplicitUseOfReservedAttribute(attribute, arguments, AttributeDescription.NativeIntegerAttribute))
{
}
else
{
return false;
}
return true;
bool reportExplicitUseOfReservedAttribute(CSharpAttributeData attribute, in DecodeWellKnownAttributeArguments<AttributeSyntax, CSharpAttributeData, AttributeLocation> arguments, in AttributeDescription attributeDescription)
{
if (attribute.IsTargetAttribute(this, attributeDescription))
{
// Do not use '{FullName}'. This is reserved for compiler usage.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, attributeDescription.FullName);
return true;
}
return false;
}
}
internal virtual byte? GetNullableContextValue()
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using Microsoft.CodeAnalysis.PooledObjects;
namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
internal sealed class SynthesizedEmbeddedNativeIntegerAttributeSymbol : SynthesizedEmbeddedAttributeSymbolBase
{
private readonly ImmutableArray<FieldSymbol> _fields;
private readonly ImmutableArray<MethodSymbol> _constructors;
private readonly TypeSymbol _boolType;
private const string FieldName = "TransformFlags";
public SynthesizedEmbeddedNativeIntegerAttributeSymbol(
string name,
NamespaceSymbol containingNamespace,
ModuleSymbol containingModule,
NamedTypeSymbol systemAttributeType,
TypeSymbol boolType)
: base(name, containingNamespace, containingModule, baseType: systemAttributeType)
{
_boolType = boolType;
var boolArrayType = TypeWithAnnotations.Create(
ArrayTypeSymbol.CreateSZArray(
boolType.ContainingAssembly,
TypeWithAnnotations.Create(boolType)));
_fields = ImmutableArray.Create<FieldSymbol>(
new SynthesizedFieldSymbol(
this,
boolArrayType.Type,
FieldName,
isPublic: true,
isReadOnly: true,
isStatic: false));
_constructors = ImmutableArray.Create<MethodSymbol>(
new SynthesizedEmbeddedAttributeConstructorWithBodySymbol(
this,
m => ImmutableArray<ParameterSymbol>.Empty,
(f, s, p) => GenerateParameterlessConstructorBody(f, s)),
new SynthesizedEmbeddedAttributeConstructorWithBodySymbol(
this,
m => ImmutableArray.Create(SynthesizedParameterSymbol.Create(m, boolArrayType, 0, RefKind.None)),
(f, s, p) => GenerateBoolArrayConstructorBody(f, s, p)));
// Ensure we never get out of sync with the description
Debug.Assert(_constructors.Length == AttributeDescription.NativeIntegerAttribute.Signatures.Length);
}
internal override IEnumerable<FieldSymbol> GetFieldsToEmit() => _fields;
public override ImmutableArray<MethodSymbol> Constructors => _constructors;
internal override AttributeUsageInfo GetAttributeUsageInfo()
{
return new AttributeUsageInfo(
AttributeTargets.Class | AttributeTargets.Event | AttributeTargets.Field | AttributeTargets.GenericParameter | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue,
allowMultiple: false,
inherited: false);
}
private void GenerateParameterlessConstructorBody(SyntheticBoundNodeFactory factory, ArrayBuilder<BoundStatement> statements)
{
statements.Add(
factory.ExpressionStatement(
factory.AssignmentExpression(
factory.Field(
factory.This(),
_fields.Single()),
factory.Array(
_boolType,
ImmutableArray.Create<BoundExpression>(factory.Literal(true))
)
)
)
);
}
private void GenerateBoolArrayConstructorBody(SyntheticBoundNodeFactory factory, ArrayBuilder<BoundStatement> statements, ImmutableArray<ParameterSymbol> parameters)
{
statements.Add(
factory.ExpressionStatement(
factory.AssignmentExpression(
factory.Field(
factory.This(),
_fields.Single()),
factory.Parameter(parameters.Single())
)
)
);
}
}
}
......@@ -63,6 +63,11 @@ internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, r
AddSynthesizedAttribute(ref attributes, compilation.SynthesizeDynamicAttribute(type, typeWithAnnotations.CustomModifiers.Length));
}
if (type.ContainsNativeInteger())
{
AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeNativeIntegerAttribute(this, type));
}
if (type.ContainsTupleNames() &&
compilation.HasTupleNamesAttributes &&
compilation.CanEmitSpecialType(SpecialType.System_String))
......
......@@ -152,6 +152,11 @@ internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, r
AddSynthesizedAttribute(ref attributes, compilation.SynthesizeDynamicAttribute(type.Type, type.CustomModifiers.Length + this.RefCustomModifiers.Length, this.RefKind));
}
if (type.Type.ContainsNativeInteger())
{
AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeNativeIntegerAttribute(this, type.Type));
}
if (type.Type.ContainsTupleNames() &&
compilation.HasTupleNamesAttributes &&
compilation.CanEmitSpecialType(SpecialType.System_String))
......
......@@ -902,6 +902,17 @@ public static bool ContainsDynamic(this TypeSymbol type)
private static readonly Func<TypeSymbol, object?, bool, bool> s_containsDynamicPredicate = (type, unused1, unused2) => type.TypeKind == TypeKind.Dynamic;
internal static bool ContainsNativeInteger(this TypeSymbol type)
{
var result = type.VisitType((type, unused1, unused2) => (type as NamedTypeSymbol)?.IsNativeInt == true, (object?)null, canDigThroughNullable: true);
return result is object;
}
internal static bool ContainsNativeInteger(this TypeWithAnnotations type)
{
return type.Type?.ContainsNativeInteger() == true;
}
/// <summary>
/// Return true if the type contains any tuples.
/// </summary>
......@@ -1630,16 +1641,19 @@ private static bool NormalizeTaskTypesInPointer(CSharpCompilation compilation, r
{
if (type.Type.ContainsTupleNames())
{
SynthesizedAttributeData? attr = compilation.SynthesizeTupleNamesAttribute(type.Type);
if (attr != null)
{
builder.Add(attr);
}
addIfNotNull(builder, compilation.SynthesizeTupleNamesAttribute(type.Type));
}
if (type.Type.ContainsNativeInteger())
{
addIfNotNull(builder, moduleBuilder.SynthesizeNativeIntegerAttribute(declaringSymbol, type.Type));
}
if (compilation.ShouldEmitNullableAttributes(declaringSymbol))
{
SynthesizedAttributeData? attr = moduleBuilder.SynthesizeNullableAttributeIfNecessary(declaringSymbol, declaringSymbol.GetNullableContextValue(), type);
addIfNotNull(builder, moduleBuilder.SynthesizeNullableAttributeIfNecessary(declaringSymbol, declaringSymbol.GetNullableContextValue(), type));
}
static void addIfNotNull(ArrayBuilder<Cci.ICustomAttribute> builder, SynthesizedAttributeData? attr)
{
if (attr != null)
{
builder.Add(attr);
......
......@@ -156,6 +156,57 @@ class C
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "object?[] y").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(10, 30));
}
[Fact]
public void ExplicitAttribute_ReferencedInSource()
{
var sourceAttribute =
@"namespace System.Runtime.CompilerServices
{
internal class NullableAttribute : System.Attribute
{
internal NullableAttribute(byte b) { }
}
}";
var source =
@"#pragma warning disable 169
using System.Runtime.CompilerServices;
[assembly: Nullable(0)]
[module: Nullable(0)]
[Nullable(0)]
class Program
{
[Nullable(0)]object F;
[Nullable(0)]static object M1() => throw null;
[return: Nullable(0)]static object M2() => throw null;
static void M3([Nullable(0)]object arg) { }
}";
// C#7
var comp = CreateCompilation(new[] { sourceAttribute, source }, parseOptions: TestOptions.Regular7);
verifyDiagnostics(comp);
// C#8
comp = CreateCompilation(new[] { sourceAttribute, source });
verifyDiagnostics(comp);
static void verifyDiagnostics(CSharpCompilation comp)
{
comp.VerifyDiagnostics(
// (5,2): error CS8623: Explicit application of 'System.Runtime.CompilerServices.NullableAttribute' is not allowed.
// [Nullable(0)]
Diagnostic(ErrorCode.ERR_ExplicitNullableAttribute, "Nullable(0)").WithLocation(5, 2),
// (8,6): error CS8623: Explicit application of 'System.Runtime.CompilerServices.NullableAttribute' is not allowed.
// [Nullable(0)]object F;
Diagnostic(ErrorCode.ERR_ExplicitNullableAttribute, "Nullable(0)").WithLocation(8, 6),
// (10,14): error CS8623: Explicit application of 'System.Runtime.CompilerServices.NullableAttribute' is not allowed.
// [return: Nullable(0)]static object M2() => throw null;
Diagnostic(ErrorCode.ERR_ExplicitNullableAttribute, "Nullable(0)").WithLocation(10, 14),
// (11,21): error CS8623: Explicit application of 'System.Runtime.CompilerServices.NullableAttribute' is not allowed.
// static void M3([Nullable(0)]object arg) { }
Diagnostic(ErrorCode.ERR_ExplicitNullableAttribute, "Nullable(0)").WithLocation(11, 21));
}
}
[Fact]
public void AttributeFromInternalsVisibleTo_01()
{
......
......@@ -599,6 +599,7 @@ public void AllWellKnownTypes()
case WellKnownType.System_Runtime_CompilerServices_AsyncIteratorMethodBuilder:
case WellKnownType.System_Threading_CancellationToken:
case WellKnownType.System_Runtime_CompilerServices_SwitchExpressionException:
case WellKnownType.System_Runtime_CompilerServices_NativeIntegerAttribute:
// Not yet in the platform.
continue;
case WellKnownType.Microsoft_CodeAnalysis_Runtime_Instrumentation:
......@@ -950,6 +951,8 @@ public void AllWellKnownTypeMembers()
case WellKnownMember.System_Runtime_CompilerServices_AsyncStateMachineAttribute__ctor:
case WellKnownMember.System_Runtime_CompilerServices_SwitchExpressionException__ctor:
case WellKnownMember.System_Runtime_CompilerServices_SwitchExpressionException__ctorObject:
case WellKnownMember.System_Runtime_CompilerServices_NativeIntegerAttribute__ctor:
case WellKnownMember.System_Runtime_CompilerServices_NativeIntegerAttribute__ctorTransformFlags:
// Not yet in the platform.
continue;
case WellKnownMember.Microsoft_CodeAnalysis_Runtime_Instrumentation__CreatePayloadForMethodsSpanningSingleFile:
......
......@@ -1009,26 +1009,46 @@ internal CustomAttributeHandle GetAttributeHandle(EntityHandle token, AttributeD
return FindTargetAttribute(token, description).Handle;
}
private static readonly ImmutableArray<bool> s_simpleDynamicTransforms = ImmutableArray.Create(true);
private static readonly ImmutableArray<bool> s_simpleTransformFlags = ImmutableArray.Create(true);
internal bool HasDynamicAttribute(EntityHandle token, out ImmutableArray<bool> dynamicTransforms)
internal bool HasDynamicAttribute(EntityHandle token, out ImmutableArray<bool> transformFlags)
{
AttributeInfo info = FindTargetAttribute(token, AttributeDescription.DynamicAttribute);
Debug.Assert(!info.HasValue || info.SignatureIndex == 0 || info.SignatureIndex == 1);
if (!info.HasValue)
{
dynamicTransforms = default(ImmutableArray<bool>);
transformFlags = default;
return false;
}
if (info.SignatureIndex == 0)
{
dynamicTransforms = s_simpleDynamicTransforms;
transformFlags = s_simpleTransformFlags;
return true;
}
return TryExtractBoolArrayValueFromAttribute(info.Handle, out dynamicTransforms);
return TryExtractBoolArrayValueFromAttribute(info.Handle, out transformFlags);
}
internal bool HasNativeIntegerAttribute(EntityHandle token, out ImmutableArray<bool> transformFlags)
{
AttributeInfo info = FindTargetAttribute(token, AttributeDescription.NativeIntegerAttribute);
Debug.Assert(!info.HasValue || info.SignatureIndex == 0 || info.SignatureIndex == 1);
if (!info.HasValue)
{
transformFlags = default;
return false;
}
if (info.SignatureIndex == 0)
{
transformFlags = s_simpleTransformFlags;
return true;
}
return TryExtractBoolArrayValueFromAttribute(info.Handle, out transformFlags);
}
internal bool HasTupleElementNamesAttribute(EntityHandle token, out ImmutableArray<string> tupleElementNames)
......
......@@ -5,7 +5,6 @@
#nullable enable
using System.Diagnostics;
using Microsoft.CodeAnalysis.Text;
using System.Reflection.Metadata;
using System.Collections.Immutable;
using Roslyn.Utilities;
......@@ -419,12 +418,11 @@ static AttributeDescription()
private static readonly byte[][] s_signaturesOfNullableAttribute = { s_signature_HasThis_Void_Byte, s_signature_HasThis_Void_SzArray_Byte };
private static readonly byte[][] s_signaturesOfNullableContextAttribute = { s_signature_HasThis_Void_Byte };
private static readonly byte[][] s_signaturesOfNullablePublicOnlyAttribute = { s_signature_HasThis_Void_Boolean };
private static readonly byte[][] s_signaturesOfExperimentalAttribute = { s_signature_HasThis_Void };
private static readonly byte[][] s_signaturesOfExcludeFromCodeCoverageAttribute = { s_signature_HasThis_Void };
private static readonly byte[][] s_signaturesOfSkipLocalsInitAttribute = { s_signature_HasThis_Void };
private static readonly byte[][] s_signaturesOfEnumeratorCancellationAttribute = { s_signature_HasThis_Void };
private static readonly byte[][] s_signaturesOfNativeIntegerAttribute = { s_signature_HasThis_Void, s_signature_HasThis_Void_SzArray_Boolean };
// early decoded attributes:
internal static readonly AttributeDescription OptionalAttribute = new AttributeDescription("System.Runtime.InteropServices", "OptionalAttribute", s_signaturesOfOptionalAttribute);
......@@ -554,5 +552,6 @@ static AttributeDescription()
internal static readonly AttributeDescription ExcludeFromCodeCoverageAttribute = new AttributeDescription("System.Diagnostics.CodeAnalysis", "ExcludeFromCodeCoverageAttribute", s_signaturesOfExcludeFromCodeCoverageAttribute);
internal static readonly AttributeDescription EnumeratorCancellationAttribute = new AttributeDescription("System.Runtime.CompilerServices", "EnumeratorCancellationAttribute", s_signaturesOfEnumeratorCancellationAttribute);
internal static readonly AttributeDescription SkipLocalsInitAttribute = new AttributeDescription("System.Runtime.CompilerServices", "SkipLocalsInitAttribute", s_signaturesOfSkipLocalsInitAttribute);
internal static readonly AttributeDescription NativeIntegerAttribute = new AttributeDescription("System.Runtime.CompilerServices", "NativeIntegerAttribute", s_signaturesOfNativeIntegerAttribute);
}
}
......@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis
{
......@@ -39,7 +38,7 @@ public T GetOrCreateData<T>() where T : WellKnownAttributeData, new()
/// <summary>
/// Returns true if some decoded data has been stored into <see cref="_lazyDecodeData"/>.
/// </summary>
public bool HasDecodedData
public readonly bool HasDecodedData
{
get
{
......@@ -59,7 +58,7 @@ public bool HasDecodedData
/// <remarks>
/// Assumes <see cref="HasDecodedData"/> is true.
/// </remarks>
public WellKnownAttributeData DecodedData
public readonly WellKnownAttributeData DecodedData
{
get
{
......
......@@ -4,9 +4,6 @@
#nullable enable
using System;
using System.ComponentModel;
namespace Microsoft.CodeAnalysis
{
/// <summary>
......
......@@ -505,6 +505,9 @@ internal enum WellKnownMember
System_Threading_CancellationTokenSource__Token,
System_Threading_CancellationTokenSource__Dispose,
System_Runtime_CompilerServices_NativeIntegerAttribute__ctor,
System_Runtime_CompilerServices_NativeIntegerAttribute__ctorTransformFlags,
Count
// Remember to update the AllWellKnownTypeMembers tests when making changes here
......
......@@ -3459,6 +3459,21 @@ static WellKnownMembers()
0, // Arity
0, // Method Signature
(byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Void, // Return Type
// System_Runtime_CompilerServices_NativeIntegerAttribute__ctor
(byte)MemberFlags.Constructor, // Flags
(byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Runtime_CompilerServices_NativeIntegerAttribute - WellKnownType.ExtSentinel), // DeclaringTypeId
0, // Arity
0, // Method Signature
(byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Void, // Return Type
// System_Runtime_CompilerServices_NativeIntegerAttribute__ctorTransformFlags
(byte)MemberFlags.Constructor, // Flags
(byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Runtime_CompilerServices_NativeIntegerAttribute - WellKnownType.ExtSentinel), // DeclaringTypeId
0, // Arity
1, // Method Signature
(byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Void, // Return Type
(byte)SignatureTypeCode.SZArray, (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Boolean,
};
string[] allNames = new string[(int)WellKnownMember.Count]
......@@ -3893,6 +3908,8 @@ static WellKnownMembers()
"CreateLinkedTokenSource", // System_Threading_CancellationTokenSource__CreateLinkedTokenSource
"Token", // System_Threading_CancellationTokenSource__Token
"Dispose", // System_Threading_CancellationTokenSource__Dispose
".ctor", // System_Runtime_CompilerServices_NativeIntegerAttribute__ctor
".ctor", // System_Runtime_CompilerServices_NativeIntegerAttribute__ctorTransformFlags
};
s_descriptors = MemberDescriptor.InitializeFromStream(new System.IO.MemoryStream(initializationBytes, writable: false), allNames);
......
......@@ -309,6 +309,7 @@ internal enum WellKnownType
System_InvalidOperationException,
System_Runtime_CompilerServices_SwitchExpressionException,
System_Collections_Generic_IEqualityComparer_T,
System_Runtime_CompilerServices_NativeIntegerAttribute,
NextAvailable,
......@@ -611,6 +612,7 @@ internal static class WellKnownTypes
"System.InvalidOperationException",
"System.Runtime.CompilerServices.SwitchExpressionException",
"System.Collections.Generic.IEqualityComparer`1",
"System.Runtime.CompilerServices.NativeIntegerAttribute",
};
private readonly static Dictionary<string, WellKnownType> s_nameToTypeIdMap = new Dictionary<string, WellKnownType>((int)Count);
......
......@@ -504,6 +504,34 @@ public class EnumeratorCancellationAttribute : Attribute
}
";
protected const string NativeIntegerAttributeDefinition =
@"using System.Collections.Generic;
namespace System.Runtime.CompilerServices
{
[System.AttributeUsage(
AttributeTargets.Class |
AttributeTargets.Event |
AttributeTargets.Field |
AttributeTargets.GenericParameter |
AttributeTargets.Parameter |
AttributeTargets.Property |
AttributeTargets.ReturnValue,
AllowMultiple = false,
Inherited = false)]
public sealed class NativeIntegerAttribute : Attribute
{
public NativeIntegerAttribute()
{
TransformFlags = new[] { true };
}
public NativeIntegerAttribute(bool[] flags)
{
TransformFlags = flags;
}
public readonly IList<bool> TransformFlags;
}
}";
protected static CSharpCompilationOptions WithNonNullTypesTrue(CSharpCompilationOptions options = null)
{
return WithNonNullTypes(options, NullableContextOptions.Enable);
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Text;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE;
namespace Microsoft.CodeAnalysis.CSharp.Test.Utilities
{
/// <summary>
/// Returns a string with all symbols containing NativeIntegerAttributes.
/// </summary>
internal sealed class NativeIntegerAttributesVisitor : CSharpSymbolVisitor
{
internal static string GetString(PEModuleSymbol module)
{
var builder = new StringBuilder();
var visitor = new NativeIntegerAttributesVisitor(builder);
visitor.Visit(module);
return builder.ToString();
}
private readonly StringBuilder _builder;
private readonly HashSet<Symbol> _reported;
private NativeIntegerAttributesVisitor(StringBuilder builder)
{
_builder = builder;
_reported = new HashSet<Symbol>();
}
public override void DefaultVisit(Symbol symbol)
{
ReportSymbol(symbol);
}
public override void VisitModule(ModuleSymbol module)
{
Visit(module.GlobalNamespace);
}
public override void VisitNamespace(NamespaceSymbol @namespace)
{
VisitList(@namespace.GetMembers());
}
public override void VisitNamedType(NamedTypeSymbol type)
{
ReportSymbol(type);
VisitList(type.TypeParameters);
foreach (var member in type.GetMembers())
{
// Skip accessors since those are covered by associated symbol.
if (member.IsAccessor()) continue;
Visit(member);
}
}
public override void VisitMethod(MethodSymbol method)
{
ReportSymbol(method);
VisitList(method.TypeParameters);
VisitList(method.Parameters);
}
public override void VisitEvent(EventSymbol @event)
{
ReportSymbol(@event);
Visit(@event.AddMethod);
Visit(@event.RemoveMethod);
}
public override void VisitProperty(PropertySymbol property)
{
ReportSymbol(property);
VisitList(property.Parameters);
Visit(property.GetMethod);
Visit(property.SetMethod);
}
public override void VisitTypeParameter(TypeParameterSymbol typeParameter)
{
ReportSymbol(typeParameter);
}
private void VisitList<TSymbol>(ImmutableArray<TSymbol> symbols) where TSymbol : Symbol
{
foreach (var symbol in symbols)
{
Visit(symbol);
}
}
/// <summary>
/// Return the containing symbol used in the hierarchy here. Specifically, the
/// hierarchy contains types, members, and parameters only, and accessors are
/// considered members of the associated symbol rather than the type.
/// </summary>
private static Symbol GetContainingSymbol(Symbol symbol)
{
if (symbol.IsAccessor())
{
return ((MethodSymbol)symbol).AssociatedSymbol;
}
var containingSymbol = symbol.ContainingSymbol;
return containingSymbol?.Kind == SymbolKind.Namespace ? null : containingSymbol;
}
private static string GetIndentString(Symbol symbol)
{
int level = 0;
while (true)
{
symbol = GetContainingSymbol(symbol);
if (symbol is null)
{
break;
}
level++;
}
return new string(' ', level * 4);
}
private static readonly SymbolDisplayFormat _displayFormat = SymbolDisplayFormat.TestFormatWithConstraints.
WithMemberOptions(
SymbolDisplayMemberOptions.IncludeParameters |
SymbolDisplayMemberOptions.IncludeType |
SymbolDisplayMemberOptions.IncludeRef |
SymbolDisplayMemberOptions.IncludeExplicitInterface);
private void ReportContainingSymbols(Symbol symbol)
{
symbol = GetContainingSymbol(symbol);
if (symbol is null)
{
return;
}
if (_reported.Contains(symbol))
{
return;
}
ReportContainingSymbols(symbol);
_builder.Append(GetIndentString(symbol));
_builder.AppendLine(symbol.ToDisplayString(_displayFormat));
_reported.Add(symbol);
}
private void ReportSymbol(Symbol symbol)
{
var type = (symbol as TypeSymbol) ?? symbol.GetTypeOrReturnType().Type;
var attribute = GetNativeIntegerAttribute((symbol is MethodSymbol method) ? method.GetReturnTypeAttributes() : symbol.GetAttributes());
Debug.Assert((type?.ContainsNativeInteger() != true) || (attribute != null));
if (attribute == null)
{
return;
}
ReportContainingSymbols(symbol);
_builder.Append(GetIndentString(symbol));
_builder.Append($"{ReportAttribute(attribute)} ");
_builder.AppendLine(symbol.ToDisplayString(_displayFormat));
_reported.Add(symbol);
}
private static Symbol GetAccessSymbol(Symbol symbol)
{
while (true)
{
switch (symbol.Kind)
{
case SymbolKind.Parameter:
case SymbolKind.TypeParameter:
symbol = symbol.ContainingSymbol;
break;
default:
return symbol;
}
}
}
private static string ReportAttribute(CSharpAttributeData attribute)
{
var builder = new StringBuilder();
builder.Append("[");
var name = attribute.AttributeClass.Name;
if (name.EndsWith("Attribute")) name = name.Substring(0, name.Length - 9);
builder.Append(name);
var arguments = attribute.ConstructorArguments.ToImmutableArray();
if (arguments.Length > 0)
{
builder.Append("(");
printValues(builder, arguments);
builder.Append(")");
}
builder.Append("]");
return builder.ToString();
static void printValues(StringBuilder builder, ImmutableArray<TypedConstant> values)
{
for (int i = 0; i < values.Length; i++)
{
if (i > 0)
{
builder.Append(", ");
}
printValue(builder, values[i]);
}
}
static void printValue(StringBuilder builder, TypedConstant value)
{
if (value.Kind == TypedConstantKind.Array)
{
builder.Append("{ ");
printValues(builder, value.Values);
builder.Append(" }");
}
else
{
builder.Append(value.Value);
}
}
}
private static CSharpAttributeData GetNativeIntegerAttribute(ImmutableArray<CSharpAttributeData> attributes) =>
GetAttribute(attributes, "System.Runtime.CompilerServices", "NativeIntegerAttribute");
private static CSharpAttributeData GetAttribute(ImmutableArray<CSharpAttributeData> attributes, string namespaceName, string name)
{
foreach (var attribute in attributes)
{
var containingType = attribute.AttributeConstructor.ContainingType;
if (containingType.Name == name && containingType.ContainingNamespace.QualifiedName == namespaceName)
{
return attribute;
}
}
return null;
}
}
}
......@@ -536,7 +536,8 @@ End Namespace
WellKnownType.System_Threading_CancellationToken,
WellKnownType.System_Runtime_CompilerServices_NonNullTypesAttribute,
WellKnownType.Microsoft_CodeAnalysis_EmbeddedAttribute,
WellKnownType.System_Runtime_CompilerServices_SwitchExpressionException
WellKnownType.System_Runtime_CompilerServices_SwitchExpressionException,
WellKnownType.System_Runtime_CompilerServices_NativeIntegerAttribute
' Not available on all platforms.
Continue For
Case WellKnownType.ExtSentinel
......@@ -599,7 +600,8 @@ End Namespace
WellKnownType.System_Threading_CancellationToken,
WellKnownType.System_Runtime_CompilerServices_NonNullTypesAttribute,
WellKnownType.Microsoft_CodeAnalysis_EmbeddedAttribute,
WellKnownType.System_Runtime_CompilerServices_SwitchExpressionException
WellKnownType.System_Runtime_CompilerServices_SwitchExpressionException,
WellKnownType.System_Runtime_CompilerServices_NativeIntegerAttribute
' Not available on all platforms.
Continue For
Case WellKnownType.ExtSentinel
......@@ -682,7 +684,9 @@ End Namespace
WellKnownMember.System_Runtime_CompilerServices_AsyncIteratorMethodBuilder__Create,
WellKnownMember.System_Runtime_CompilerServices_AsyncIteratorMethodBuilder__MoveNext_T,
WellKnownMember.System_Runtime_CompilerServices_AsyncStateMachineAttribute__ctor,
WellKnownMember.System_Runtime_CompilerServices_RuntimeHelpers__GetSubArray_T
WellKnownMember.System_Runtime_CompilerServices_RuntimeHelpers__GetSubArray_T,
WellKnownMember.System_Runtime_CompilerServices_NativeIntegerAttribute__ctor,
WellKnownMember.System_Runtime_CompilerServices_NativeIntegerAttribute__ctorTransformFlags
' Not available yet, but will be in upcoming release.
Continue For
Case WellKnownMember.Microsoft_CodeAnalysis_Runtime_Instrumentation__CreatePayloadForMethodsSpanningSingleFile,
......@@ -821,7 +825,9 @@ End Namespace
WellKnownMember.System_Runtime_CompilerServices_AsyncIteratorMethodBuilder__Create,
WellKnownMember.System_Runtime_CompilerServices_AsyncIteratorMethodBuilder__MoveNext_T,
WellKnownMember.System_Runtime_CompilerServices_AsyncStateMachineAttribute__ctor,
WellKnownMember.System_Runtime_CompilerServices_RuntimeHelpers__GetSubArray_T
WellKnownMember.System_Runtime_CompilerServices_RuntimeHelpers__GetSubArray_T,
WellKnownMember.System_Runtime_CompilerServices_NativeIntegerAttribute__ctor,
WellKnownMember.System_Runtime_CompilerServices_NativeIntegerAttribute__ctorTransformFlags
' Not available yet, but will be in upcoming release.
Continue For
Case WellKnownMember.Microsoft_CodeAnalysis_Runtime_Instrumentation__CreatePayloadForMethodsSpanningSingleFile,
......
......@@ -193,6 +193,11 @@ public static ImmutableArray<byte> ReadByteArray(this MetadataReader reader, Blo
return ReadArray(reader, blobHandle, (ref BlobReader blobReader) => blobReader.ReadByte());
}
public static ImmutableArray<bool> ReadBoolArray(this MetadataReader reader, BlobHandle blobHandle)
{
return ReadArray(reader, blobHandle, (ref BlobReader blobReader) => blobReader.ReadBoolean());
}
public static IEnumerable<CustomAttributeRow> GetCustomAttributeRows(this MetadataReader reader)
{
foreach (var handle in reader.CustomAttributes)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册