| File: Symbols\Source\SourceNamedTypeSymbol_Enum.cs | Web Access |
| Project: src\roslyn\src\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj (Microsoft.CodeAnalysis.CSharp) |
// 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 disable using System.Diagnostics; using System.Threading; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; namespace Microsoft.CodeAnalysis.CSharp.Symbols { internal partial class SourceNamedTypeSymbol { private SynthesizedEnumValueFieldSymbol _lazyEnumValueField; private NamedTypeSymbol _lazyEnumUnderlyingType = ErrorTypeSymbol.UnknownResultType; /// <summary> /// For enum types, gets the underlying type. Returns null on all other /// kinds of types. /// </summary> public override NamedTypeSymbol EnumUnderlyingType { get { if (ReferenceEquals(_lazyEnumUnderlyingType, ErrorTypeSymbol.UnknownResultType)) { BindingDiagnosticBag diagnostics = BindingDiagnosticBag.GetInstance(); if ((object)Interlocked.CompareExchange(ref _lazyEnumUnderlyingType, this.GetEnumUnderlyingType(diagnostics), ErrorTypeSymbol.UnknownResultType) == (object)ErrorTypeSymbol.UnknownResultType) { AddDeclarationDiagnostics(diagnostics); this.state.NotePartComplete(CompletionPart.EnumUnderlyingType); } diagnostics.Free(); } return _lazyEnumUnderlyingType; } } private NamedTypeSymbol GetEnumUnderlyingType(BindingDiagnosticBag diagnostics) { if (this.TypeKind != TypeKind.Enum) { return null; } var compilation = this.DeclaringCompilation; var decl = this.declaration.Declarations[0]; var bases = GetBaseListOpt(decl); if (bases != null) { var types = bases.Types; if (types.Count > 0) { var typeSyntax = types[0].Type; var baseBinder = compilation.GetBinder(bases); var type = baseBinder.BindType(typeSyntax, diagnostics).Type; // Error types are not exposed to the caller. In those // cases, the underlying type is treated as int. if (!type.SpecialType.IsValidEnumUnderlyingType()) { diagnostics.Add(ErrorCode.ERR_IntegralTypeExpected, typeSyntax.Location); type = compilation.GetSpecialType(SpecialType.System_Int32); } return (NamedTypeSymbol)type; } } NamedTypeSymbol defaultUnderlyingType = compilation.GetSpecialType(SpecialType.System_Int32); Binder.ReportUseSite(defaultUnderlyingType, diagnostics, this.GetFirstLocation()); return defaultUnderlyingType; } /// <summary> /// For enum types, returns the synthesized instance field used /// for generating metadata. Returns null for non-enum types. /// </summary> internal FieldSymbol EnumValueField { get { if (this.TypeKind != TypeKind.Enum) { return null; } if ((object)_lazyEnumValueField == null) { Debug.Assert((object)this.EnumUnderlyingType != null); Interlocked.CompareExchange(ref _lazyEnumValueField, new SynthesizedEnumValueFieldSymbol(this), null); } return _lazyEnumValueField; } } } }