|
// 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;
using System.Collections.Generic;
using System.Collections.Immutable;
using Roslyn.Utilities;
using System.Diagnostics;
using Microsoft.CodeAnalysis.PooledObjects;
namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
/// <summary>
/// Represents a pointer type such as "int *". Pointer types
/// are used only in unsafe code.
/// </summary>
internal sealed partial class PointerTypeSymbol : TypeSymbol
{
private readonly TypeWithAnnotations _pointedAtType;
/// <summary>
/// Create a new PointerTypeSymbol.
/// </summary>
/// <param name="pointedAtType">The type being pointed at.</param>
internal PointerTypeSymbol(TypeWithAnnotations pointedAtType)
{
Debug.Assert(pointedAtType.HasType);
_pointedAtType = pointedAtType;
}
public override Accessibility DeclaredAccessibility
{
get { return Accessibility.NotApplicable; }
}
public override bool IsStatic
{
get
{
return false;
}
}
public override bool IsAbstract
{
get
{
return false;
}
}
public override bool IsSealed
{
get
{
return false;
}
}
/// <summary>
/// Gets the type of the storage location that an instance of the pointer type points to, along with its annotations.
/// </summary>
public TypeWithAnnotations PointedAtTypeWithAnnotations
{
get
{
return _pointedAtType;
}
}
/// <summary>
/// Gets the type of the storage location that an instance of the pointer type points to.
/// </summary>
public TypeSymbol PointedAtType => PointedAtTypeWithAnnotations.Type;
internal override NamedTypeSymbol? BaseTypeNoUseSiteDiagnostics
{
get
{
// Pointers do not support boxing, so they really have no base type.
return null;
}
}
internal override ImmutableArray<NamedTypeSymbol> InterfacesNoUseSiteDiagnostics(ConsList<TypeSymbol>? basesBeingResolved)
{
// Pointers do not support boxing, so they really have no interfaces
return ImmutableArray<NamedTypeSymbol>.Empty;
}
public override bool IsReferenceType
{
get
{
return false;
}
}
public override bool IsValueType
{
get
{
return true;
}
}
internal sealed override ManagedKind GetManagedKind(ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo) => ManagedKind.Unmanaged;
public sealed override bool IsRefLikeType
{
get
{
return false;
}
}
public sealed override bool IsReadOnly
{
get
{
return false;
}
}
internal sealed override ObsoleteAttributeData? ObsoleteAttributeData
{
get { return null; }
}
public override ImmutableArray<Symbol> GetMembers()
{
return ImmutableArray<Symbol>.Empty;
}
public override ImmutableArray<Symbol> GetMembers(string name)
{
return ImmutableArray<Symbol>.Empty;
}
public override ImmutableArray<NamedTypeSymbol> GetTypeMembers()
{
return ImmutableArray<NamedTypeSymbol>.Empty;
}
public override ImmutableArray<NamedTypeSymbol> GetTypeMembers(ReadOnlyMemory<char> name)
{
return ImmutableArray<NamedTypeSymbol>.Empty;
}
public override ImmutableArray<NamedTypeSymbol> GetTypeMembers(ReadOnlyMemory<char> name, int arity)
{
return ImmutableArray<NamedTypeSymbol>.Empty;
}
public override SymbolKind Kind
{
get
{
return SymbolKind.PointerType;
}
}
public override TypeKind TypeKind
{
get
{
return TypeKind.Pointer;
}
}
public override Symbol? ContainingSymbol
{
get
{
return null;
}
}
public override ImmutableArray<Location> Locations
{
get
{
return ImmutableArray<Location>.Empty;
}
}
public override ImmutableArray<SyntaxReference> DeclaringSyntaxReferences
{
get
{
return ImmutableArray<SyntaxReference>.Empty;
}
}
internal override TResult Accept<TArgument, TResult>(CSharpSymbolVisitor<TArgument, TResult> visitor, TArgument argument)
{
return visitor.VisitPointerType(this, argument);
}
public override void Accept(CSharpSymbolVisitor visitor)
{
visitor.VisitPointerType(this);
}
public override TResult Accept<TResult>(CSharpSymbolVisitor<TResult> visitor)
{
return visitor.VisitPointerType(this);
}
public override int GetHashCode()
{
// We don't want to blow the stack if we have a type like T***************...***,
// so we do not recurse until we have a non-array.
int indirections = 0;
TypeSymbol current = this;
while (current.TypeKind == TypeKind.Pointer)
{
indirections += 1;
current = ((PointerTypeSymbol)current).PointedAtType;
}
return Hash.Combine(current, indirections);
}
internal override bool Equals(TypeSymbol? t2, TypeCompareKind comparison)
{
return this.Equals(t2 as PointerTypeSymbol, comparison);
}
private bool Equals(PointerTypeSymbol? other, TypeCompareKind comparison)
{
if (ReferenceEquals(this, other))
{
return true;
}
if ((object?)other == null || !other._pointedAtType.Equals(_pointedAtType, comparison))
{
return false;
}
return true;
}
internal override void AddNullableTransforms(ArrayBuilder<byte> transforms)
{
PointedAtTypeWithAnnotations.AddNullableTransforms(transforms);
}
internal override bool ApplyNullableTransforms(byte defaultTransformFlag, ImmutableArray<byte> transforms, ref int position, out TypeSymbol result)
{
TypeWithAnnotations oldPointedAtType = PointedAtTypeWithAnnotations;
TypeWithAnnotations newPointedAtType;
if (!oldPointedAtType.ApplyNullableTransforms(defaultTransformFlag, transforms, ref position, out newPointedAtType))
{
result = this;
return false;
}
result = WithPointedAtType(newPointedAtType);
return true;
}
internal override TypeSymbol SetNullabilityForReferenceTypes(Func<TypeWithAnnotations, TypeWithAnnotations> transform)
{
return WithPointedAtType(transform(PointedAtTypeWithAnnotations));
}
internal override TypeSymbol MergeEquivalentTypes(TypeSymbol other, VarianceKind variance)
{
Debug.Assert(this.Equals(other, TypeCompareKind.IgnoreDynamicAndTupleNames | TypeCompareKind.IgnoreNullableModifiersForReferenceTypes));
TypeWithAnnotations pointedAtType = PointedAtTypeWithAnnotations.MergeEquivalentTypes(((PointerTypeSymbol)other).PointedAtTypeWithAnnotations, VarianceKind.None);
return WithPointedAtType(pointedAtType);
}
internal PointerTypeSymbol WithPointedAtType(TypeWithAnnotations newPointedAtType)
{
return PointedAtTypeWithAnnotations.IsSameAs(newPointedAtType) ? this : new PointerTypeSymbol(newPointedAtType);
}
internal override UseSiteInfo<AssemblySymbol> GetUseSiteInfo()
{
UseSiteInfo<AssemblySymbol> result = default;
// Check type, custom modifiers
DeriveUseSiteInfoFromType(ref result, this.PointedAtTypeWithAnnotations, AllowedRequiredModifierType.None);
return result;
}
internal override bool GetUnificationUseSiteDiagnosticRecursive(ref DiagnosticInfo result, Symbol owner, ref HashSet<TypeSymbol> checkedTypes)
{
return this.PointedAtTypeWithAnnotations.GetUnificationUseSiteDiagnosticRecursive(ref result, owner, ref checkedTypes);
}
protected override ISymbol CreateISymbol()
{
return new PublicModel.PointerTypeSymbol(this, DefaultNullableAnnotation);
}
protected override ITypeSymbol CreateITypeSymbol(CodeAnalysis.NullableAnnotation nullableAnnotation)
{
Debug.Assert(nullableAnnotation != DefaultNullableAnnotation);
return new PublicModel.PointerTypeSymbol(this, nullableAnnotation);
}
internal override bool IsRecord => false;
internal override bool IsRecordStruct => false;
internal sealed override IEnumerable<(MethodSymbol Body, MethodSymbol Implemented)> SynthesizedInterfaceMethodImpls()
{
return SpecializedCollections.EmptyEnumerable<(MethodSymbol Body, MethodSymbol Implemented)>();
}
internal sealed override bool HasInlineArrayAttribute(out int length)
{
length = 0;
return false;
}
}
}
|