예제 #1
0
        protected override void MethodChecks(DiagnosticBag diagnostics)
        {
            // These values may not be final, but we need to have something set here in the
            // event that we need to find the overridden accessor.
            _lazyParameters      = ComputeParameters(diagnostics);
            _lazyReturnType      = ComputeReturnType(diagnostics);
            _lazyCustomModifiers = CustomModifiersTuple.Empty;

            if (_explicitInterfaceImplementations.Length > 0)
            {
                Debug.Assert(_explicitInterfaceImplementations.Length == 1);
                MethodSymbol implementedMethod = _explicitInterfaceImplementations[0];
                CustomModifierUtils.CopyMethodCustomModifiers(implementedMethod, this, out _lazyReturnType,
                                                              out _lazyCustomModifiers,
                                                              out _lazyParameters, alsoCopyParamsModifier: false);
            }
            else if (this.IsOverride)
            {
                // This will cause another call to SourceMethodSymbol.LazyMethodChecks,
                // but that method already handles reentrancy for exactly this case.
                MethodSymbol overriddenMethod = this.OverriddenMethod;
                if ((object)overriddenMethod != null)
                {
                    CustomModifierUtils.CopyMethodCustomModifiers(overriddenMethod, this, out _lazyReturnType,
                                                                  out _lazyCustomModifiers,
                                                                  out _lazyParameters, alsoCopyParamsModifier: true);
                }
            }
            else if (_lazyReturnType.SpecialType != SpecialType.System_Void)
            {
                PropertySymbol associatedProperty = _property;
                _lazyReturnType      = CustomModifierUtils.CopyTypeCustomModifiers(associatedProperty.Type, _lazyReturnType, this.ContainingAssembly);
                _lazyCustomModifiers = CustomModifiersTuple.Create(associatedProperty.TypeCustomModifiers, associatedProperty.RefCustomModifiers);
            }
        }
예제 #2
0
        /// <remarks>
        /// Out params are updated by assignment.  If you require thread-safety, pass temps and then
        /// CompareExchange them back into shared memory.
        /// </remarks>
        internal static void CopyMethodCustomModifiers(
            MethodSymbol sourceMethod,
            MethodSymbol destinationMethod,
            out TypeSymbol returnType,
            out CustomModifiersTuple customModifiers,
            out ImmutableArray <ParameterSymbol> parameters,
            bool alsoCopyParamsModifier) // Last since always named.
        {
            Debug.Assert((object)sourceMethod != null);

            // Assert: none of the method's type parameters have been substituted
            Debug.Assert((object)sourceMethod == sourceMethod.ConstructedFrom);

            // For the most part, we will copy custom modifiers by copying types.
            // The only time when this fails is when the type refers to a type parameter
            // owned by the overridden method.  We need to replace all such references
            // with (equivalent) type parameters owned by this method.  We know that
            // we can perform this mapping positionally, because the method signatures
            // have already been compared.
            MethodSymbol constructedSourceMethod = sourceMethod.ConstructIfGeneric(destinationMethod.TypeArguments);

            customModifiers = CustomModifiersTuple.Create(
                constructedSourceMethod.ReturnTypeCustomModifiers,
                destinationMethod.RefKind != RefKind.None ? constructedSourceMethod.RefCustomModifiers : ImmutableArray <CustomModifier> .Empty);

            parameters = CopyParameterCustomModifiers(constructedSourceMethod.Parameters, destinationMethod.Parameters, alsoCopyParamsModifier);

            returnType = destinationMethod.ReturnType; // Default value - in case we don't copy the custom modifiers.

            // We do an extra check before copying the return type to handle the case where the overriding
            // method (incorrectly) has a different return type than the overridden method.  In such cases,
            // we want to retain the original (incorrect) return type to avoid hiding the return type
            // given in source.
            TypeSymbol returnTypeWithCustomModifiers = constructedSourceMethod.ReturnType;

            if (returnType.Equals(returnTypeWithCustomModifiers, TypeCompareKind.AllIgnoreOptions))
            {
                returnType = CopyTypeCustomModifiers(returnTypeWithCustomModifiers, returnType, destinationMethod.ContainingAssembly);
            }
        }
예제 #3
0
        /// <remarks>
        /// Out params are updated by assignment.  If you require thread-safety, pass temps and then
        /// CompareExchange them back into shared memory.
        /// </remarks>
        internal static void CopyMethodCustomModifiers(
            MethodSymbol sourceMethod,
            MethodSymbol destinationMethod,
            out TypeSymbol returnType,
            out CustomModifiersTuple customModifiers,
            out ImmutableArray<ParameterSymbol> parameters,
            bool alsoCopyParamsModifier) // Last since always named.
        {
            Debug.Assert((object)sourceMethod != null);

            // Assert: none of the method's type parameters have been substituted
            Debug.Assert((object)sourceMethod == sourceMethod.ConstructedFrom);

            // For the most part, we will copy custom modifiers by copying types.
            // The only time when this fails is when the type refers to a type parameter
            // owned by the overridden method.  We need to replace all such references
            // with (equivalent) type parameters owned by this method.  We know that
            // we can perform this mapping positionally, because the method signatures
            // have already been compared.
            MethodSymbol constructedSourceMethod = sourceMethod.ConstructIfGeneric(destinationMethod.TypeArguments);

            customModifiers = CustomModifiersTuple.Create(constructedSourceMethod.ReturnTypeCustomModifiers,
                                                          destinationMethod.ReturnsByRef ? constructedSourceMethod.RefCustomModifiers : ImmutableArray<CustomModifier>.Empty);

            parameters = CopyParameterCustomModifiers(constructedSourceMethod.Parameters, destinationMethod.Parameters, alsoCopyParamsModifier);

            returnType = destinationMethod.ReturnType; // Default value - in case we don't copy the custom modifiers.

            // We do an extra check before copying the return type to handle the case where the overriding
            // method (incorrectly) has a different return type than the overridden method.  In such cases,
            // we want to retain the original (incorrect) return type to avoid hiding the return type
            // given in source.
            TypeSymbol returnTypeWithCustomModifiers = constructedSourceMethod.ReturnType;
            if (returnType.Equals(returnTypeWithCustomModifiers, TypeCompareKind.AllIgnoreOptions))
            {
                returnType = CopyTypeCustomModifiers(returnTypeWithCustomModifiers, returnType, destinationMethod.ContainingAssembly);
            }
        }
        protected override void MethodChecks(DiagnosticBag diagnostics)
        {
            // These values may not be final, but we need to have something set here in the
            // event that we need to find the overridden accessor.
            _lazyParameters = ComputeParameters(diagnostics);
            _lazyReturnType = ComputeReturnType(diagnostics);
            _lazyCustomModifiers = CustomModifiersTuple.Empty;

            if (_explicitInterfaceImplementations.Length > 0)
            {
                Debug.Assert(_explicitInterfaceImplementations.Length == 1);
                MethodSymbol implementedMethod = _explicitInterfaceImplementations[0];
                CustomModifierUtils.CopyMethodCustomModifiers(implementedMethod, this, out _lazyReturnType, 
                                                              out _lazyCustomModifiers, 
                                                              out _lazyParameters, alsoCopyParamsModifier: false);
            }
            else if (this.IsOverride)
            {
                // This will cause another call to SourceMethodSymbol.LazyMethodChecks, 
                // but that method already handles reentrancy for exactly this case.
                MethodSymbol overriddenMethod = this.OverriddenMethod;
                if ((object)overriddenMethod != null)
                {
                    CustomModifierUtils.CopyMethodCustomModifiers(overriddenMethod, this, out _lazyReturnType, 
                                                                  out _lazyCustomModifiers, 
                                                                  out _lazyParameters, alsoCopyParamsModifier: true);
                }
            }
            else if (_lazyReturnType.SpecialType != SpecialType.System_Void)
            {
                PropertySymbol associatedProperty = _property;
                _lazyReturnType = CustomModifierUtils.CopyTypeCustomModifiers(associatedProperty.Type, _lazyReturnType, this.ContainingAssembly);
                _lazyCustomModifiers = CustomModifiersTuple.Create(associatedProperty.TypeCustomModifiers, associatedProperty.RefCustomModifiers);
            }
        }
        private void MethodChecks(MethodDeclarationSyntax syntax, Binder withTypeParamsBinder, DiagnosticBag diagnostics)
        {
            Debug.Assert(this.MethodKind != MethodKind.UserDefinedOperator, "SourceUserDefinedOperatorSymbolBase overrides this");

            SyntaxToken arglistToken;

            // Constraint checking for parameter and return types must be delayed until
            // the method has been added to the containing type member list since
            // evaluating the constraints may depend on accessing this method from
            // the container (comparing this method to others to find overrides for
            // instance). Constraints are checked in AfterAddingTypeMembersChecks.
            var signatureBinder = withTypeParamsBinder.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.SuppressConstraintChecks, this);

            _lazyParameters = ParameterHelpers.MakeParameters(
                signatureBinder, this, syntax.ParameterList, out arglistToken,
                allowRefOrOut: true,
                allowThis: true,
                addRefReadOnlyModifier: IsVirtual || IsAbstract,
                diagnostics: diagnostics);

            _lazyIsVararg = (arglistToken.Kind() == SyntaxKind.ArgListKeyword);
            RefKind refKind;
            var     returnTypeSyntax = syntax.ReturnType.SkipRef(out refKind);

            _lazyReturnType = signatureBinder.BindType(returnTypeSyntax, diagnostics);

            // span-like types are returnable in general
            if (_lazyReturnType.IsRestrictedType(ignoreSpanLikeTypes: true))
            {
                if (_lazyReturnType.SpecialType == SpecialType.System_TypedReference &&
                    (this.ContainingType.SpecialType == SpecialType.System_TypedReference || this.ContainingType.SpecialType == SpecialType.System_ArgIterator))
                {
                    // Two special cases: methods in the special types TypedReference and ArgIterator are allowed to return TypedReference
                }
                else
                {
                    // Method or delegate cannot return type '{0}'
                    diagnostics.Add(ErrorCode.ERR_MethodReturnCantBeRefAny, syntax.ReturnType.Location, _lazyReturnType);
                }
            }

            var returnsVoid = _lazyReturnType.SpecialType == SpecialType.System_Void;

            if (this.RefKind != RefKind.None && returnsVoid)
            {
                Debug.Assert(returnTypeSyntax.HasErrors);
            }

            // set ReturnsVoid flag
            this.SetReturnsVoid(returnsVoid);

            var location = this.Locations[0];

            this.CheckEffectiveAccessibility(_lazyReturnType, _lazyParameters, diagnostics);

            // Checks taken from MemberDefiner::defineMethod
            if (this.Name == WellKnownMemberNames.DestructorName && this.ParameterCount == 0 && this.Arity == 0 && this.ReturnsVoid)
            {
                diagnostics.Add(ErrorCode.WRN_FinalizeMethod, location);
            }

            // errors relevant for extension methods
            if (IsExtensionMethod)
            {
                var parameter0Type    = this.Parameters[0].Type;
                var parameter0RefKind = this.Parameters[0].RefKind;
                if (!parameter0Type.IsValidExtensionParameterType())
                {
                    // Duplicate Dev10 behavior by selecting the parameter type.
                    var parameterSyntax = syntax.ParameterList.Parameters[0];
                    Debug.Assert(parameterSyntax.Type != null);
                    var loc = parameterSyntax.Type.Location;
                    diagnostics.Add(ErrorCode.ERR_BadTypeforThis, loc, parameter0Type);
                }
                else if (parameter0RefKind == RefKind.Ref && !parameter0Type.IsValueType)
                {
                    diagnostics.Add(ErrorCode.ERR_RefExtensionMustBeValueTypeOrConstrainedToOne, location, Name);
                }
                else if (parameter0RefKind == RefKind.In && parameter0Type.TypeKind != TypeKind.Struct)
                {
                    diagnostics.Add(ErrorCode.ERR_InExtensionMustBeValueType, location, Name);
                }
                else if ((object)ContainingType.ContainingType != null)
                {
                    diagnostics.Add(ErrorCode.ERR_ExtensionMethodsDecl, location, ContainingType.Name);
                }
                else if (!ContainingType.IsScriptClass && !(ContainingType.IsStatic && ContainingType.Arity == 0))
                {
                    // Duplicate Dev10 behavior by selecting the containing type identifier. However if there
                    // is no containing type (in the interactive case for instance), select the method identifier.
                    var typeDecl   = syntax.Parent as TypeDeclarationSyntax;
                    var identifier = (typeDecl != null) ? typeDecl.Identifier : syntax.Identifier;
                    var loc        = identifier.GetLocation();
                    diagnostics.Add(ErrorCode.ERR_BadExtensionAgg, loc);
                }
                else if (!IsStatic)
                {
                    diagnostics.Add(ErrorCode.ERR_BadExtensionMeth, location);
                }
                else
                {
                    // Verify ExtensionAttribute is available.
                    var attributeConstructor = withTypeParamsBinder.Compilation.GetWellKnownTypeMember(WellKnownMember.System_Runtime_CompilerServices_ExtensionAttribute__ctor);
                    if ((object)attributeConstructor == null)
                    {
                        var memberDescriptor = WellKnownMembers.GetDescriptor(WellKnownMember.System_Runtime_CompilerServices_ExtensionAttribute__ctor);
                        // do not use Binder.ReportUseSiteErrorForAttributeCtor in this case, because we'll need to report a special error id, not a generic use site error.
                        diagnostics.Add(
                            ErrorCode.ERR_ExtensionAttrNotFound,
                            syntax.ParameterList.Parameters[0].Modifiers.FirstOrDefault(SyntaxKind.ThisKeyword).GetLocation(),
                            memberDescriptor.DeclaringTypeMetadataName);
                    }
                }
            }

            if (IsPartial)
            {
                // check that there are no out parameters in a partial
                foreach (var p in this.Parameters)
                {
                    if (p.RefKind == RefKind.Out)
                    {
                        diagnostics.Add(ErrorCode.ERR_PartialMethodCannotHaveOutParameters, location);
                        break;
                    }
                }

                if (MethodKind == MethodKind.ExplicitInterfaceImplementation)
                {
                    diagnostics.Add(ErrorCode.ERR_PartialMethodNotExplicit, location);
                }

                if (!ContainingType.IsPartial() || ContainingType.IsInterface)
                {
                    diagnostics.Add(ErrorCode.ERR_PartialMethodOnlyInPartialClass, location);
                }
            }

            if (!IsPartial)
            {
                LazyAsyncMethodChecks(CancellationToken.None);
                Debug.Assert(state.HasComplete(CompletionPart.FinishAsyncMethodChecks));
            }

            // The runtime will not treat this method as an override or implementation of another
            // method unless both the signatures and the custom modifiers match.  Hence, in the
            // case of overrides and *explicit* implementations, we need to copy the custom modifiers
            // that are in the signature of the overridden/implemented method.  (From source, we know
            // that there can only be one such method, so there are no conflicts.)  This is
            // unnecessary for implicit implementations because, if the custom modifiers don't match,
            // we'll insert a bridge method (an explicit implementation that delegates to the implicit
            // implementation) with the correct custom modifiers
            // (see SourceNamedTypeSymbol.ImplementInterfaceMember).

            // This value may not be correct, but we need something while we compute overridden/implemented method.
            // May be re-assigned below.
            Debug.Assert(_lazyCustomModifiers == null);
            _lazyCustomModifiers = CustomModifiersTuple.Empty;

            // Note: we're checking if the syntax indicates explicit implementation rather,
            // than if explicitInterfaceType is null because we don't want to look for an
            // overridden property if this is supposed to be an explicit implementation.
            if (syntax.ExplicitInterfaceSpecifier == null)
            {
                Debug.Assert(_lazyExplicitInterfaceImplementations.IsDefault);
                _lazyExplicitInterfaceImplementations = ImmutableArray <MethodSymbol> .Empty;

                // If this method is an override, we may need to copy custom modifiers from
                // the overridden method (so that the runtime will recognize it as an override).
                // We check for this case here, while we can still modify the parameters and
                // return type without losing the appearance of immutability.
                if (this.IsOverride)
                {
                    // This computation will necessarily be performed with partially incomplete
                    // information.  There is no way we can determine the complete signature
                    // (i.e. including custom modifiers) until we have found the method that
                    // this method overrides.  To accommodate this, MethodSymbol.OverriddenOrHiddenMembers
                    // is written to allow relaxed matching of custom modifiers for source methods,
                    // on the assumption that they will be updated appropriately.
                    MethodSymbol overriddenMethod = this.OverriddenMethod;

                    if ((object)overriddenMethod != null)
                    {
                        CustomModifierUtils.CopyMethodCustomModifiers(overriddenMethod, this, out _lazyReturnType,
                                                                      out _lazyCustomModifiers,
                                                                      out _lazyParameters, alsoCopyParamsModifier: true);
                    }
                }
                else if (_refKind == RefKind.RefReadOnly)
                {
                    var modifierType = withTypeParamsBinder.GetWellKnownType(WellKnownType.System_Runtime_InteropServices_InAttribute, diagnostics, syntax.ReturnType);

                    _lazyCustomModifiers = CustomModifiersTuple.Create(
                        typeCustomModifiers: ImmutableArray <CustomModifier> .Empty,
                        refCustomModifiers: ImmutableArray.Create(CSharpCustomModifier.CreateRequired(modifierType)));
                }
            }
            else if ((object)_explicitInterfaceType != null)
            {
                //do this last so that it can assume the method symbol is constructed (except for ExplicitInterfaceImplementation)
                MethodSymbol implementedMethod = this.FindExplicitlyImplementedMethod(_explicitInterfaceType, syntax.Identifier.ValueText, syntax.ExplicitInterfaceSpecifier, diagnostics);

                if ((object)implementedMethod != null)
                {
                    Debug.Assert(_lazyExplicitInterfaceImplementations.IsDefault);
                    _lazyExplicitInterfaceImplementations = ImmutableArray.Create <MethodSymbol>(implementedMethod);

                    CustomModifierUtils.CopyMethodCustomModifiers(implementedMethod, this, out _lazyReturnType,
                                                                  out _lazyCustomModifiers,
                                                                  out _lazyParameters, alsoCopyParamsModifier: false);
                }
                else
                {
                    Debug.Assert(_lazyExplicitInterfaceImplementations.IsDefault);
                    _lazyExplicitInterfaceImplementations = ImmutableArray <MethodSymbol> .Empty;
                }
            }

            CheckModifiers(_hasAnyBody, location, diagnostics);

            foreach (var typeParameter in _typeParameters)
            {
                if (typeParameter.HasUnmanagedTypeConstraint)
                {
                    DeclaringCompilation.EnsureIsUnmanagedAttributeExists(diagnostics, typeParameter.GetNonNullSyntaxNode().Location, modifyCompilationForIsUnmanaged: true);
                }
            }
        }
예제 #6
0
        // CONSIDER: if the parameters were computed lazily, ParameterCount could be overridden to fall back on the syntax (as in SourceMemberMethodSymbol).

        private SourcePropertySymbol(
            SourceMemberContainerTypeSymbol containingType,
            Binder bodyBinder,
            BasePropertyDeclarationSyntax syntax,
            string name,
            Location location,
            DiagnosticBag diagnostics)
        {
            // This has the value that IsIndexer will ultimately have, once we've populated the fields of this object.
            bool isIndexer = syntax.Kind() == SyntaxKind.IndexerDeclaration;
            var interfaceSpecifier = GetExplicitInterfaceSpecifier(syntax);
            bool isExplicitInterfaceImplementation = (interfaceSpecifier != null);

            _location = location;
            _containingType = containingType;
            _syntaxRef = syntax.GetReference();
            syntax.Type.SkipRef(out _refKind);

            SyntaxTokenList modifiers = syntax.Modifiers;
            bodyBinder = bodyBinder.WithUnsafeRegionIfNecessary(modifiers);
            bodyBinder = bodyBinder.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.SuppressConstraintChecks, this);

            bool modifierErrors;
            _modifiers = MakeModifiers(modifiers, isExplicitInterfaceImplementation, isIndexer, location, diagnostics, out modifierErrors);
            this.CheckAccessibility(location, diagnostics);

            this.CheckModifiers(location, isIndexer, diagnostics);

            if (isIndexer && !isExplicitInterfaceImplementation)
            {
                // Evaluate the attributes immediately in case the IndexerNameAttribute has been applied.
                // NOTE: we want IsExplicitInterfaceImplementation, IsOverride, Locations, and the syntax reference
                // to be initialized before we pass this symbol to LoadCustomAttributes.

                // CONSIDER: none of the information from this early binding pass is cached.  Everything will
                // be re-bound when someone calls GetAttributes.  If this gets to be a problem, we could
                // always use the real attribute bag of this symbol and modify LoadAndValidateAttributes to
                // handle partially filled bags.
                CustomAttributesBag<CSharpAttributeData> temp = null;
                LoadAndValidateAttributes(OneOrMany.Create(this.CSharpSyntaxNode.AttributeLists), ref temp, earlyDecodingOnly: true);
                if (temp != null)
                {
                    Debug.Assert(temp.IsEarlyDecodedWellKnownAttributeDataComputed);
                    var propertyData = (PropertyEarlyWellKnownAttributeData)temp.EarlyDecodedWellKnownAttributeData;
                    if (propertyData != null)
                    {
                        _sourceName = propertyData.IndexerName;
                    }
                }
            }

            string aliasQualifierOpt;
            string memberName = ExplicitInterfaceHelpers.GetMemberNameAndInterfaceSymbol(bodyBinder, interfaceSpecifier, name, diagnostics, out _explicitInterfaceType, out aliasQualifierOpt);
            _sourceName = _sourceName ?? memberName; //sourceName may have been set while loading attributes
            _name = isIndexer ? ExplicitInterfaceHelpers.GetMemberName(WellKnownMemberNames.Indexer, _explicitInterfaceType, aliasQualifierOpt) : _sourceName;
            _isExpressionBodied = false;

            bool hasAccessorList = syntax.AccessorList != null;
            var propertySyntax = syntax as PropertyDeclarationSyntax;
            var arrowExpression = propertySyntax != null
                ? propertySyntax.ExpressionBody
                : ((IndexerDeclarationSyntax)syntax).ExpressionBody;
            bool hasExpressionBody = arrowExpression != null;
            bool hasInitializer = !isIndexer && propertySyntax.Initializer != null;

            bool notRegularProperty = (!IsAbstract && !IsExtern && !isIndexer && hasAccessorList);
            AccessorDeclarationSyntax getSyntax = null;
            AccessorDeclarationSyntax setSyntax = null;
            if (hasAccessorList)
            {
                foreach (var accessor in syntax.AccessorList.Accessors)
                {
                    if (accessor.Kind() == SyntaxKind.GetAccessorDeclaration &&
                        (getSyntax == null || getSyntax.Keyword.Span.IsEmpty))
                    {
                        getSyntax = accessor;
                    }
                    else if (accessor.Kind() == SyntaxKind.SetAccessorDeclaration &&
                        (setSyntax == null || setSyntax.Keyword.Span.IsEmpty))
                    {
                        setSyntax = accessor;
                    }
                    else
                    {
                        continue;
                    }

                    if (accessor.Body != null || accessor.ExpressionBody != null)
                    {
                        notRegularProperty = false;
                    }
                }
            }
            else
            {
                notRegularProperty = false;
            }

            if (hasInitializer)
            {
                CheckInitializer(notRegularProperty, location, diagnostics);
            }

            if (notRegularProperty || hasInitializer)
            {
                var hasGetSyntax = getSyntax != null;
                _isAutoProperty = notRegularProperty && hasGetSyntax;
                bool isReadOnly = hasGetSyntax && setSyntax == null;

                if (_isAutoProperty || hasInitializer)
                {
                    if (_isAutoProperty)
                    {
                        //issue a diagnostic if the compiler generated attribute ctor is not found.
                        Binder.ReportUseSiteDiagnosticForSynthesizedAttribute(bodyBinder.Compilation,
                        WellKnownMember.System_Runtime_CompilerServices_CompilerGeneratedAttribute__ctor, diagnostics, syntax: syntax);

                        if (this._refKind != RefKind.None && !_containingType.IsInterface)
                        {
                            diagnostics.Add(ErrorCode.ERR_AutoPropertyCannotBeRefReturning, location, this);
                        }
                    }

                    string fieldName = GeneratedNames.MakeBackingFieldName(_sourceName);
                    _backingField = new SynthesizedBackingFieldSymbol(this,
                                                                          fieldName,
                                                                          isReadOnly,
                                                                          this.IsStatic,
                                                                          hasInitializer);
                }

                if (notRegularProperty)
                {
                    Binder.CheckFeatureAvailability(location,
                                                    isReadOnly ? MessageID.IDS_FeatureReadonlyAutoImplementedProperties :
                                                                 MessageID.IDS_FeatureAutoImplementedProperties,
                                                    diagnostics);
                }
            }

            PropertySymbol explicitlyImplementedProperty = null;
            _customModifiers = CustomModifiersTuple.Empty;

            // The runtime will not treat the accessors of this property as overrides or implementations
            // of those of another property unless both the signatures and the custom modifiers match.
            // Hence, in the case of overrides and *explicit* implementations, we need to copy the custom
            // modifiers that are in the signatures of the overridden/implemented property accessors.
            // (From source, we know that there can only be one overridden/implemented property, so there
            // are no conflicts.)  This is unnecessary for implicit implementations because, if the custom
            // modifiers don't match, we'll insert bridge methods for the accessors (explicit implementations 
            // that delegate to the implicit implementations) with the correct custom modifiers
            // (see SourceNamedTypeSymbol.ImplementInterfaceMember).

            // Note: we're checking if the syntax indicates explicit implementation rather,
            // than if explicitInterfaceType is null because we don't want to look for an
            // overridden property if this is supposed to be an explicit implementation.
            if (isExplicitInterfaceImplementation || this.IsOverride)
            {
                // Type and parameters for overrides and explicit implementations cannot be bound
                // lazily since the property name depends on the metadata name of the base property,
                // and the property name is required to add the property to the containing type, and
                // the type and parameters are required to determine the override or implementation.
                _lazyType = this.ComputeType(bodyBinder, syntax, diagnostics);
                _lazyParameters = this.ComputeParameters(bodyBinder, syntax, diagnostics);

                bool isOverride = false;
                PropertySymbol overriddenOrImplementedProperty = null;

                if (!isExplicitInterfaceImplementation)
                {
                    // If this property is an override, we may need to copy custom modifiers from
                    // the overridden property (so that the runtime will recognize it as an override).
                    // We check for this case here, while we can still modify the parameters and
                    // return type without losing the appearance of immutability.
                    isOverride = true;
                    overriddenOrImplementedProperty = this.OverriddenProperty;
                }
                else
                {
                    string interfacePropertyName = isIndexer ? WellKnownMemberNames.Indexer : name;
                    explicitlyImplementedProperty = this.FindExplicitlyImplementedProperty(_explicitInterfaceType, interfacePropertyName, interfaceSpecifier, diagnostics);
                    overriddenOrImplementedProperty = explicitlyImplementedProperty;
                }

                if ((object)overriddenOrImplementedProperty != null)
                {
                    _customModifiers = CustomModifiersTuple.Create(overriddenOrImplementedProperty.TypeCustomModifiers,
                                                                   _refKind != RefKind.None ? overriddenOrImplementedProperty.RefCustomModifiers : ImmutableArray<CustomModifier>.Empty);

                    TypeSymbol overriddenPropertyType = overriddenOrImplementedProperty.Type;

                    // We do an extra check before copying the type to handle the case where the overriding
                    // property (incorrectly) has a different type than the overridden property.  In such cases,
                    // we want to retain the original (incorrect) type to avoid hiding the type given in source.
                    if (_lazyType.Equals(overriddenPropertyType, TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds | TypeCompareKind.IgnoreDynamic))
                    {
                        _lazyType = CustomModifierUtils.CopyTypeCustomModifiers(overriddenPropertyType, _lazyType, this.ContainingAssembly);
                    }

                    _lazyParameters = CustomModifierUtils.CopyParameterCustomModifiers(overriddenOrImplementedProperty.Parameters, _lazyParameters, alsoCopyParamsModifier: isOverride);
                }
            }

            if (!hasAccessorList)
            {
                if (hasExpressionBody)
                {
                    _isExpressionBodied = true;
                    _getMethod = SourcePropertyAccessorSymbol.CreateAccessorSymbol(
                        containingType,
                        this,
                        _modifiers,
                        _sourceName,
                        arrowExpression,
                        explicitlyImplementedProperty,
                        aliasQualifierOpt,
                        diagnostics);
                }
                else
                {
                    _getMethod = null;
                }
                _setMethod = null;
            }
            else
            {
                _getMethod = CreateAccessorSymbol(getSyntax, explicitlyImplementedProperty, aliasQualifierOpt, notRegularProperty, diagnostics);
                _setMethod = CreateAccessorSymbol(setSyntax, explicitlyImplementedProperty, aliasQualifierOpt, notRegularProperty, diagnostics);

                if ((getSyntax == null) || (setSyntax == null))
                {
                    if ((getSyntax == null) && (setSyntax == null))
                    {
                        diagnostics.Add(ErrorCode.ERR_PropertyWithNoAccessors, location, this);
                    }
                    else if (_refKind != RefKind.None)
                    {
                        if (getSyntax == null)
                        {
                            diagnostics.Add(ErrorCode.ERR_RefPropertyMustHaveGetAccessor, location, this);
                        }
                    }
                    else if (notRegularProperty)
                    {
                        var accessor = _getMethod ?? _setMethod;
                        if (getSyntax == null)
                        {
                            diagnostics.Add(ErrorCode.ERR_AutoPropertyMustHaveGetAccessor, accessor.Locations[0], accessor);
                        }
                    }
                }

                // Check accessor accessibility is more restrictive than property accessibility.
                CheckAccessibilityMoreRestrictive(_getMethod, diagnostics);
                CheckAccessibilityMoreRestrictive(_setMethod, diagnostics);

                if (((object)_getMethod != null) && ((object)_setMethod != null))
                {
                    if (_refKind != RefKind.None)
                    {
                        diagnostics.Add(ErrorCode.ERR_RefPropertyCannotHaveSetAccessor, _setMethod.Locations[0], _setMethod);
                    }
                    else if ((_getMethod.LocalAccessibility != Accessibility.NotApplicable) &&
                             (_setMethod.LocalAccessibility != Accessibility.NotApplicable))
                    {
                        // Check accessibility is set on at most one accessor.
                        diagnostics.Add(ErrorCode.ERR_DuplicatePropertyAccessMods, location, this);
                    }
                    else if (this.IsAbstract)
                    {
                        // Check abstract property accessors are not private.
                        CheckAbstractPropertyAccessorNotPrivate(_getMethod, diagnostics);
                        CheckAbstractPropertyAccessorNotPrivate(_setMethod, diagnostics);
                    }
                }
                else
                {
                    if (!this.IsOverride)
                    {
                        var accessor = _getMethod ?? _setMethod;
                        if ((object)accessor != null)
                        {
                            // Check accessibility is not set on the one accessor.
                            if (accessor.LocalAccessibility != Accessibility.NotApplicable)
                            {
                                diagnostics.Add(ErrorCode.ERR_AccessModMissingAccessor, location, this);
                            }
                        }
                    }
                }
            }

            if ((object)explicitlyImplementedProperty != null)
            {
                CheckExplicitImplementationAccessor(this.GetMethod, explicitlyImplementedProperty.GetMethod, explicitlyImplementedProperty, diagnostics);
                CheckExplicitImplementationAccessor(this.SetMethod, explicitlyImplementedProperty.SetMethod, explicitlyImplementedProperty, diagnostics);
            }

            _explicitInterfaceImplementations =
                (object)explicitlyImplementedProperty == null ?
                    ImmutableArray<PropertySymbol>.Empty :
                    ImmutableArray.Create(explicitlyImplementedProperty);

            // get-only auto property should not override settable properties
            if (_isAutoProperty && (object)_setMethod == null && !this.IsReadOnly)
            {
                diagnostics.Add(ErrorCode.ERR_AutoPropertyMustOverrideSet, location, this);
            }
        }