internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder <SynthesizedAttributeData> attributes)
        {
            base.AddSynthesizedAttributes(moduleBuilder, ref attributes);

            AddSynthesizedAttribute(
                ref attributes,
                moduleBuilder.Compilation.TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_CompilerGeneratedAttribute__ctor));

            if (!DeclaringCompilation.GetWellKnownType(WellKnownType.Microsoft_CodeAnalysis_EmbeddedAttribute).IsErrorType())
            {
                AddSynthesizedAttribute(
                    ref attributes,
                    moduleBuilder.Compilation.TrySynthesizeAttribute(WellKnownMember.Microsoft_CodeAnalysis_EmbeddedAttribute__ctor));
            }
        }
        /// <summary>
        /// Adds an `[AttributeUsage(AttributeTargets.Class | ...)]` (if possible) and captures any diagnostics in the process.
        /// </summary>
        private ImmutableArray <CSharpAttributeData> MakeAttributes()
        {
            var ctor = (MethodSymbol)Binder.GetWellKnownTypeMember(DeclaringCompilation, WellKnownMember.System_AttributeUsageAttribute__ctor, _diagnostics, Location.None);

            if (ctor is null)
            {
                // member is missing
                return(ImmutableArray <CSharpAttributeData> .Empty);
            }

            NamedTypeSymbol attributeTargets = DeclaringCompilation.GetWellKnownType(WellKnownType.System_AttributeTargets);

            Binder.ReportUseSiteDiagnostics(attributeTargets, _diagnostics, Location.None);

            var usage = new SynthesizedAttributeData(ctor,
                                                     arguments: ImmutableArray.Create(new TypedConstant(attributeTargets, TypedConstantKind.Enum, attributeUsage)),
                                                     namedArguments: ImmutableArray <KeyValuePair <string, TypedConstant> > .Empty);

            return(ImmutableArray.Create <CSharpAttributeData>(usage));
        }
Ejemplo n.º 3
0
        public override ImmutableArray <AttributeData> GetAttributes()
        {
            var builder = ImmutableArray.CreateBuilder <AttributeData>();

            if (IsPhpHidden)
            {
                // [PhpHiddenAttribute]
                builder.Add(new SynthesizedAttributeData(
                                DeclaringCompilation.CoreMethods.Ctors.PhpHiddenAttribute,
                                ImmutableArray <TypedConstant> .Empty,
                                ImmutableArray <KeyValuePair <string, TypedConstant> > .Empty));
            }

            if (IsEditorBrowsableHidden)
            {
                builder.Add(new SynthesizedAttributeData(
                                (MethodSymbol)DeclaringCompilation.GetWellKnownTypeMember(WellKnownMember.System_ComponentModel_EditorBrowsableAttribute__ctor),
                                ImmutableArray.Create(
                                    new TypedConstant(
                                        DeclaringCompilation.GetWellKnownType(WellKnownType.System_ComponentModel_EditorBrowsableState),
                                        TypedConstantKind.Enum,
                                        System.ComponentModel.EditorBrowsableState.Never)),
                                ImmutableArray <KeyValuePair <string, TypedConstant> > .Empty));
            }

            if (this is SynthesizedPhpCtorSymbol sctor && sctor.IsInitFieldsOnly) // we do it here to avoid allocating new ImmutableArray in derived class
            {
                // [PhpFieldsOnlyCtorAttribute]
                builder.Add(new SynthesizedAttributeData(
                                DeclaringCompilation.CoreMethods.Ctors.PhpFieldsOnlyCtorAttribute,
                                ImmutableArray <TypedConstant> .Empty,
                                ImmutableArray <KeyValuePair <string, TypedConstant> > .Empty));

                // [CompilerGeneratedAttribute]
                builder.Add(DeclaringCompilation.CreateCompilerGeneratedAttribute());
            }

            return(builder.ToImmutable());
        }
        internal override void GenerateMethodBody(TypeCompilationState compilationState, DiagnosticBag diagnostics)
        {
            var F = new SyntheticBoundNodeFactory(this, ContainingType.GetNonNullSyntaxNode(), compilationState, diagnostics);

            try
            {
                var             other = F.Parameter(Parameters[0]);
                BoundExpression?retExpr;

                // This method is the strongly-typed Equals method where the parameter type is
                // the containing type.

                if (ContainingType.BaseTypeNoUseSiteDiagnostics.IsObjectType())
                {
                    if (_equalityContract.GetMethod is null)
                    {
                        // The equality contract isn't usable, an error was reported elsewhere
                        F.CloseMethod(F.ThrowNull());
                        return;
                    }

                    if (_equalityContract.IsStatic || !_equalityContract.Type.Equals(DeclaringCompilation.GetWellKnownType(WellKnownType.System_Type), TypeCompareKind.AllIgnoreOptions))
                    {
                        // There is a signature mismatch, an error was reported elsewhere
                        F.CloseMethod(F.ThrowNull());
                        return;
                    }

                    // There are no base record types.
                    // The definition of the method is as follows
                    //
                    // virtual bool Equals(T other) =>
                    //     other != null &&
                    //     EqualityContract == other.EqualityContract &&
                    //     field1 == other.field1 && ... && fieldN == other.fieldN;

                    // other != null
                    Debug.Assert(!other.Type.IsStructType());
                    retExpr = F.ObjectNotEqual(other, F.Null(F.SpecialType(SpecialType.System_Object)));

                    // EqualityContract == other.EqualityContract
                    var contractsEqual = F.Call(receiver: null, F.WellKnownMethod(WellKnownMember.System_Type__op_Equality),
                                                F.Property(F.This(), _equalityContract),
                                                F.Property(other, _equalityContract));

                    retExpr = F.LogicalAnd(retExpr, contractsEqual);
                }
                else
                {
                    MethodSymbol?baseEquals = ContainingType.GetMembersUnordered().OfType <SynthesizedRecordBaseEquals>().Single().OverriddenMethod;

                    if (baseEquals is null || !baseEquals.ContainingType.Equals(ContainingType.BaseTypeNoUseSiteDiagnostics, TypeCompareKind.AllIgnoreOptions) ||
                        baseEquals.ReturnType.SpecialType != SpecialType.System_Boolean)
                    {
                        // There was a problem with overriding of base equals, an error was reported elsewhere
                        F.CloseMethod(F.ThrowNull());
                        return;
                    }

                    // There are base record types.
                    // The definition of the method is as follows, and baseEquals
                    // is the corresponding method on the nearest base record type to
                    // delegate to:
                    //
                    // virtual bool Equals(Derived other) =>
                    //     base.Equals((Base)other) &&
                    //     field1 == other.field1 && ... && fieldN == other.fieldN;
                    retExpr = F.Call(
                        F.Base(baseEquals.ContainingType),
                        baseEquals,
                        F.Convert(baseEquals.Parameters[0].Type, other));
                }

                // field1 == other.field1 && ... && fieldN == other.fieldN
                var fields = ArrayBuilder <FieldSymbol> .GetInstance();

                bool foundBadField = false;
                foreach (var f in ContainingType.GetFieldsToEmit())
                {
                    if (!f.IsStatic)
                    {
                        fields.Add(f);

                        var parameterType = f.Type;
                        if (parameterType.IsUnsafe())
                        {
                            diagnostics.Add(ErrorCode.ERR_BadFieldTypeInRecord, f.Locations.FirstOrNone(), parameterType);
                            foundBadField = true;
                        }
                        else if (parameterType.IsRestrictedType())
                        {
                            // We'll have reported a diagnostic elsewhere (SourceMemberFieldSymbol.TypeChecks)
                            foundBadField = true;
                        }
                    }
                }
                if (fields.Count > 0 && !foundBadField)
                {
                    retExpr = MethodBodySynthesizer.GenerateFieldEquals(
                        retExpr,
                        other,
                        fields,
                        F);
                }

                fields.Free();

                F.CloseMethod(F.Block(F.Return(retExpr)));
            }
            catch (SyntheticBoundNodeFactory.MissingPredefinedMember ex)
            {
                diagnostics.Add(ex.Diagnostic);
                F.CloseMethod(F.ThrowNull());
            }
        }
Ejemplo n.º 5
0
        private Tuple <NamedTypeSymbol, ImmutableArray <NamedTypeSymbol> > MakeDeclaredBases(
            ConsList <TypeSymbol> basesBeingResolved,
            BindingDiagnosticBag diagnostics
            )
        {
            if (this.TypeKind == TypeKind.Enum)
            {
                // Handled by GetEnumUnderlyingType().
                return(new Tuple <NamedTypeSymbol, ImmutableArray <NamedTypeSymbol> >(
                           null,
                           ImmutableArray <NamedTypeSymbol> .Empty
                           ));
            }

            var reportedPartialConflict = false;

            Debug.Assert(
                basesBeingResolved == null ||
                !basesBeingResolved.ContainsReference(this.OriginalDefinition)
                );
            var newBasesBeingResolved = basesBeingResolved.Prepend(this.OriginalDefinition);
            var baseInterfaces        = ArrayBuilder <NamedTypeSymbol> .GetInstance();

            NamedTypeSymbol baseType         = null;
            SourceLocation  baseTypeLocation = null;

            var interfaceLocations = SpecializedSymbolCollections.GetPooledSymbolDictionaryInstance <
                NamedTypeSymbol,
                SourceLocation
                >();

            foreach (var decl in this.declaration.Declarations)
            {
                Tuple <NamedTypeSymbol, ImmutableArray <NamedTypeSymbol> > one = MakeOneDeclaredBases(
                    newBasesBeingResolved,
                    decl,
                    diagnostics
                    );
                if ((object)one == null)
                {
                    continue;
                }

                var partBase       = one.Item1;
                var partInterfaces = one.Item2;
                if (!reportedPartialConflict)
                {
                    if ((object)baseType == null)
                    {
                        baseType         = partBase;
                        baseTypeLocation = decl.NameLocation;
                    }
                    else if (baseType.TypeKind == TypeKind.Error && (object)partBase != null)
                    {
                        // if the old base was an error symbol, copy it to the interfaces list so it doesn't get lost
                        partInterfaces   = partInterfaces.Add(baseType);
                        baseType         = partBase;
                        baseTypeLocation = decl.NameLocation;
                    }
                    else if (
                        (object)partBase != null &&
                        !TypeSymbol.Equals(
                            partBase,
                            baseType,
                            TypeCompareKind.ConsiderEverything2
                            ) &&
                        partBase.TypeKind != TypeKind.Error
                        )
                    {
                        // the parts do not agree
                        var info = diagnostics.Add(
                            ErrorCode.ERR_PartialMultipleBases,
                            Locations[0],
                            this
                            );
                        baseType = new ExtendedErrorTypeSymbol(
                            baseType,
                            LookupResultKind.Ambiguous,
                            info
                            );
                        baseTypeLocation        = decl.NameLocation;
                        reportedPartialConflict = true;
                    }
                }

                foreach (var t in partInterfaces)
                {
                    if (!interfaceLocations.ContainsKey(t))
                    {
                        baseInterfaces.Add(t);
                        interfaceLocations.Add(t, decl.NameLocation);
                    }
                }
            }

            CompoundUseSiteInfo <AssemblySymbol> useSiteInfo =
                new CompoundUseSiteInfo <AssemblySymbol>(diagnostics, ContainingAssembly);

            if (declaration.Kind == DeclarationKind.Record)
            {
                var type = DeclaringCompilation
                           .GetWellKnownType(WellKnownType.System_IEquatable_T)
                           .Construct(this);
                if (baseInterfaces.IndexOf(type, SymbolEqualityComparer.AllIgnoreOptions) < 0)
                {
                    baseInterfaces.Add(type);
                    type.AddUseSiteInfo(ref useSiteInfo);
                }
            }

            if ((object)baseType != null)
            {
                Debug.Assert(baseTypeLocation != null);
                if (baseType.IsStatic)
                {
                    // '{1}': cannot derive from static class '{0}'
                    diagnostics.Add(
                        ErrorCode.ERR_StaticBaseClass,
                        baseTypeLocation,
                        baseType,
                        this
                        );
                }

                if (!this.IsNoMoreVisibleThan(baseType, ref useSiteInfo))
                {
                    // Inconsistent accessibility: base class '{1}' is less accessible than class '{0}'
                    diagnostics.Add(
                        ErrorCode.ERR_BadVisBaseClass,
                        baseTypeLocation,
                        this,
                        baseType
                        );
                }
            }

            var baseInterfacesRO = baseInterfaces.ToImmutableAndFree();

            if (DeclaredAccessibility != Accessibility.Private && IsInterface)
            {
                foreach (var i in baseInterfacesRO)
                {
                    if (!i.IsAtLeastAsVisibleAs(this, ref useSiteInfo))
                    {
                        // Inconsistent accessibility: base interface '{1}' is less accessible than interface '{0}'
                        diagnostics.Add(
                            ErrorCode.ERR_BadVisBaseInterface,
                            interfaceLocations[i],
                            this,
                            i
                            );
                    }
                }
            }

            interfaceLocations.Free();

            diagnostics.Add(Locations[0], useSiteInfo);

            return(new Tuple <NamedTypeSymbol, ImmutableArray <NamedTypeSymbol> >(
                       baseType,
                       baseInterfacesRO
                       ));
        }
Ejemplo n.º 6
0
 protected override TypeWithAnnotations ComputeType(Binder?binder, SyntaxNode syntax, DiagnosticBag diagnostics)
 {
     // No need to worry about reporting use-site diagnostics, we already did that in the constructor
     return(TypeWithAnnotations.Create(DeclaringCompilation.GetWellKnownType(WellKnownType.System_Type), NullableAnnotation.NotAnnotated));
 }