Beispiel #1
0
        private DeclarationModifiers MakeModifiers(SyntaxTokenList modifiers, MethodKind methodKind, bool hasBody, Location location, DiagnosticBag diagnostics, out bool modifierErrors)
        {
            var defaultAccess = (methodKind == MethodKind.StaticConstructor) ? DeclarationModifiers.None : DeclarationModifiers.Private;

            // Check that the set of modifiers is allowed
            const DeclarationModifiers allowedModifiers =
                DeclarationModifiers.AccessibilityMask |
                DeclarationModifiers.Static |
                DeclarationModifiers.Extern |
                DeclarationModifiers.Unsafe;

            var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors);

            this.CheckUnsafeModifier(mods, diagnostics);

            if (methodKind == MethodKind.StaticConstructor)
            {
                if ((mods & DeclarationModifiers.AccessibilityMask) != 0)
                {
                    diagnostics.Add(ErrorCode.ERR_StaticConstructorWithAccessModifiers, location, this);
                    mods           = mods & ~DeclarationModifiers.AccessibilityMask;
                    modifierErrors = true;
                }

                mods |= DeclarationModifiers.Private; // we mark static constructors private in the symbol table

                if (this.ContainingType.IsInterface)
                {
                    ModifierUtils.ReportDefaultInterfaceImplementationModifiers(hasBody, mods,
                                                                                DeclarationModifiers.Extern,
                                                                                location, diagnostics);
                }
            }

            return(mods);
        }
        private DeclarationModifiers MakeModifiers(AccessorDeclarationSyntax syntax, Location location, DiagnosticBag diagnostics, out bool modifierErrors)
        {
            // No default accessibility. If unset, accessibility
            // will be inherited from the property.
            const DeclarationModifiers defaultAccess = DeclarationModifiers.None;

            // Check that the set of modifiers is allowed
            const DeclarationModifiers allowedModifiers = DeclarationModifiers.AccessibilityMask;
            var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(syntax.Modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors);

            // For interface, check there are no accessibility modifiers.
            // (This check is handled outside of MakeAndCheckModifiers
            // since a distinct error message is reported for interfaces.)
            if (this.ContainingType.IsInterface)
            {
                if ((mods & DeclarationModifiers.AccessibilityMask) != 0)
                {
                    diagnostics.Add(ErrorCode.ERR_PropertyAccessModInInterface, location, this);
                    mods = (mods & ~DeclarationModifiers.AccessibilityMask);
                }
            }

            return(mods);
        }
        private DeclarationModifiers MakeModifiers(SyntaxTokenList modifiers, MethodKind methodKind, Location location, DiagnosticBag diagnostics, out bool modifierErrors)
        {
            bool isInterface   = this.ContainingType.IsInterface;
            var  defaultAccess = isInterface ? DeclarationModifiers.Public : DeclarationModifiers.Private;

            // Check that the set of modifiers is allowed
            var allowedModifiers = DeclarationModifiers.Partial | DeclarationModifiers.Unsafe;

            if (methodKind != MethodKind.ExplicitInterfaceImplementation)
            {
                allowedModifiers |= DeclarationModifiers.New;

                if (!isInterface)
                {
                    allowedModifiers |=
                        DeclarationModifiers.AccessibilityMask |
                        DeclarationModifiers.Sealed |
                        DeclarationModifiers.Abstract |
                        DeclarationModifiers.Static |
                        DeclarationModifiers.Virtual |
                        DeclarationModifiers.Override;
                }
            }

            if (!isInterface)
            {
                allowedModifiers |= DeclarationModifiers.Extern | DeclarationModifiers.Async;
            }

            var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors);

            this.CheckUnsafeModifier(mods, diagnostics);

            mods = AddImpliedModifiers(mods, isInterface, methodKind);
            return(mods);
        }
        private DeclarationModifiers MakeModifiers(
            SyntaxTokenList modifiers,
            MethodKind methodKind,
            bool hasBody,
            Location location,
            BindingDiagnosticBag diagnostics,
            out bool modifierErrors
            )
        {
            var defaultAccess =
                (methodKind == MethodKind.StaticConstructor)
                    ? DeclarationModifiers.None
                    : DeclarationModifiers.Private;

            // Check that the set of modifiers is allowed
            const DeclarationModifiers allowedModifiers =
                DeclarationModifiers.AccessibilityMask
                | DeclarationModifiers.Static
                | DeclarationModifiers.Extern
                | DeclarationModifiers.Unsafe;

            var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(
                modifiers,
                defaultAccess,
                allowedModifiers,
                location,
                diagnostics,
                out modifierErrors
                );

            this.CheckUnsafeModifier(mods, diagnostics);

            if (methodKind == MethodKind.StaticConstructor)
            {
                // Don't report ERR_StaticConstructorWithAccessModifiers if the ctor symbol name doesn't match the containing type name.
                // This avoids extra unnecessary errors.
                // There will already be a diagnostic saying Method must have a return type.
                if (
                    (mods & DeclarationModifiers.AccessibilityMask) != 0 &&
                    ContainingType.Name
                    == ((ConstructorDeclarationSyntax)this.SyntaxNode).Identifier.ValueText
                    )
                {
                    diagnostics.Add(
                        ErrorCode.ERR_StaticConstructorWithAccessModifiers,
                        location,
                        this
                        );
                    mods           = mods & ~DeclarationModifiers.AccessibilityMask;
                    modifierErrors = true;
                }

                mods |= DeclarationModifiers.Private; // we mark static constructors private in the symbol table

                if (this.ContainingType.IsInterface)
                {
                    ModifierUtils.ReportDefaultInterfaceImplementationModifiers(
                        hasBody,
                        mods,
                        DeclarationModifiers.Extern,
                        location,
                        diagnostics
                        );
                }
            }

            return(mods);
        }
        internal static DeclarationModifiers MakeModifiers(NamedTypeSymbol containingType, SyntaxToken firstIdentifier, SyntaxTokenList modifiers, DiagnosticBag diagnostics, out bool modifierErrors)
        {
            DeclarationModifiers defaultAccess =
                (containingType.IsInterface) ? DeclarationModifiers.Public : DeclarationModifiers.Private;

            DeclarationModifiers allowedModifiers =
                DeclarationModifiers.AccessibilityMask |
                DeclarationModifiers.Const |
                DeclarationModifiers.New |
                DeclarationModifiers.ReadOnly |
                DeclarationModifiers.Static |
                DeclarationModifiers.Volatile |
                DeclarationModifiers.Fixed |
                DeclarationModifiers.Unsafe |
                DeclarationModifiers.Abstract; // filtered out later

            var errorLocation           = new SourceLocation(firstIdentifier);
            DeclarationModifiers result = ModifierUtils.MakeAndCheckNontypeMemberModifiers(
                modifiers, defaultAccess, allowedModifiers, errorLocation, diagnostics, out modifierErrors);

            if ((result & DeclarationModifiers.Abstract) != 0)
            {
                diagnostics.Add(ErrorCode.ERR_AbstractField, errorLocation);
                result &= ~DeclarationModifiers.Abstract;
            }

            if ((result & DeclarationModifiers.Fixed) != 0)
            {
                if ((result & DeclarationModifiers.Static) != 0)
                {
                    // The modifier 'static' is not valid for this item
                    diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.StaticKeyword));
                }

                if ((result & DeclarationModifiers.ReadOnly) != 0)
                {
                    // The modifier 'readonly' is not valid for this item
                    diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.ReadOnlyKeyword));
                }

                if ((result & DeclarationModifiers.Const) != 0)
                {
                    // The modifier 'const' is not valid for this item
                    diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.ConstKeyword));
                }

                if ((result & DeclarationModifiers.Volatile) != 0)
                {
                    // The modifier 'volatile' is not valid for this item
                    diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.VolatileKeyword));
                }

                result &= ~(DeclarationModifiers.Static | DeclarationModifiers.ReadOnly | DeclarationModifiers.Const | DeclarationModifiers.Volatile);
                Debug.Assert((result & ~(DeclarationModifiers.AccessibilityMask | DeclarationModifiers.Fixed | DeclarationModifiers.Unsafe | DeclarationModifiers.New)) == 0);
            }


            if ((result & DeclarationModifiers.Const) != 0)
            {
                if ((result & DeclarationModifiers.Static) != 0)
                {
                    // The constant '{0}' cannot be marked static
                    diagnostics.Add(ErrorCode.ERR_StaticConstant, errorLocation, firstIdentifier.ValueText);
                }

                if ((result & DeclarationModifiers.ReadOnly) != 0)
                {
                    // The modifier 'readonly' is not valid for this item
                    diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.ReadOnlyKeyword));
                }

                if ((result & DeclarationModifiers.Volatile) != 0)
                {
                    // The modifier 'volatile' is not valid for this item
                    diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.VolatileKeyword));
                }

                if ((result & DeclarationModifiers.Unsafe) != 0)
                {
                    // The modifier 'unsafe' is not valid for this item
                    diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.UnsafeKeyword));
                }

                result |= DeclarationModifiers.Static; // "constants are considered static members"
            }
            else
            {
                // NOTE: always cascading on a const, so suppress.
                // NOTE: we're being a bit sneaky here - we're using the containingType rather than this symbol
                // to determine whether or not unsafe is allowed.  Since this symbol and the containing type are
                // in the same compilation, it won't make a difference.  We do, however, have to pass the error
                // location explicitly.
                containingType.CheckUnsafeModifier(result, errorLocation, diagnostics);
            }

            return(result);
        }
Beispiel #6
0
        internal static DeclarationModifiers MakeModifiers(NamedTypeSymbol containingType, SyntaxToken firstIdentifier, SyntaxTokenList modifiers, bool isRefField, BindingDiagnosticBag diagnostics, out bool modifierErrors)
        {
            bool isInterface = containingType.IsInterface;
            DeclarationModifiers defaultAccess =
                isInterface ? DeclarationModifiers.Public : DeclarationModifiers.Private;

            DeclarationModifiers allowedModifiers =
                DeclarationModifiers.AccessibilityMask |
                DeclarationModifiers.Const |
                DeclarationModifiers.New |
                DeclarationModifiers.ReadOnly |
                DeclarationModifiers.Static |
                DeclarationModifiers.Volatile |
                DeclarationModifiers.Fixed |
                DeclarationModifiers.Unsafe |
                DeclarationModifiers.Abstract |
                DeclarationModifiers.Required; // Some of these are filtered out later, when illegal, for better error messages.

            var errorLocation           = new SourceLocation(firstIdentifier);
            DeclarationModifiers result = ModifierUtils.MakeAndCheckNontypeMemberModifiers(
                isOrdinaryMethod: false, isForInterfaceMember: isInterface,
                modifiers, defaultAccess, allowedModifiers, errorLocation, diagnostics, out modifierErrors);

            if ((result & DeclarationModifiers.Abstract) != 0)
            {
                diagnostics.Add(ErrorCode.ERR_AbstractField, errorLocation);
                result &= ~DeclarationModifiers.Abstract;
            }

            if ((result & DeclarationModifiers.Fixed) != 0)
            {
                reportBadMemberFlagIfAny(result, DeclarationModifiers.Static, diagnostics, errorLocation);
                reportBadMemberFlagIfAny(result, DeclarationModifiers.ReadOnly, diagnostics, errorLocation);
                reportBadMemberFlagIfAny(result, DeclarationModifiers.Const, diagnostics, errorLocation);
                reportBadMemberFlagIfAny(result, DeclarationModifiers.Volatile, diagnostics, errorLocation);
                reportBadMemberFlagIfAny(result, DeclarationModifiers.Required, diagnostics, errorLocation);

                result &= ~(DeclarationModifiers.Static | DeclarationModifiers.ReadOnly | DeclarationModifiers.Const | DeclarationModifiers.Volatile | DeclarationModifiers.Required);
                Debug.Assert((result & ~(DeclarationModifiers.AccessibilityMask | DeclarationModifiers.Fixed | DeclarationModifiers.Unsafe | DeclarationModifiers.New)) == 0);
            }

            if ((result & DeclarationModifiers.Const) != 0)
            {
                if ((result & DeclarationModifiers.Static) != 0)
                {
                    // The constant '{0}' cannot be marked static
                    diagnostics.Add(ErrorCode.ERR_StaticConstant, errorLocation, firstIdentifier.ValueText);
                }

                reportBadMemberFlagIfAny(result, DeclarationModifiers.ReadOnly, diagnostics, errorLocation);
                reportBadMemberFlagIfAny(result, DeclarationModifiers.Volatile, diagnostics, errorLocation);
                reportBadMemberFlagIfAny(result, DeclarationModifiers.Unsafe, diagnostics, errorLocation);

                if (reportBadMemberFlagIfAny(result, DeclarationModifiers.Required, diagnostics, errorLocation))
                {
                    result &= ~DeclarationModifiers.Required;
                }

                result |= DeclarationModifiers.Static; // "constants are considered static members"
            }
            else
            {
                if ((result & DeclarationModifiers.Static) != 0 && (result & DeclarationModifiers.Required) != 0)
                {
                    // The modifier 'required' is not valid for this item
                    diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.RequiredKeyword));
                    result &= ~DeclarationModifiers.Required;
                }

                // NOTE: always cascading on a const, so suppress.
                // NOTE: we're being a bit sneaky here - we're using the containingType rather than this symbol
                // to determine whether or not unsafe is allowed.  Since this symbol and the containing type are
                // in the same compilation, it won't make a difference.  We do, however, have to pass the error
                // location explicitly.
                containingType.CheckUnsafeModifier(result, errorLocation, diagnostics);
            }

            if (isRefField)
            {
                reportBadMemberFlagIfAny(result, DeclarationModifiers.Static, diagnostics, errorLocation);
                reportBadMemberFlagIfAny(result, DeclarationModifiers.Const, diagnostics, errorLocation);
                reportBadMemberFlagIfAny(result, DeclarationModifiers.Volatile, diagnostics, errorLocation);
            }

            return(result);
        protected SourceUserDefinedOperatorSymbolBase(
            MethodKind methodKind,
            string name,
            SourceMemberContainerTypeSymbol containingType,
            Location location,
            BaseMethodDeclarationSyntax syntax,
            DiagnosticBag diagnostics) :
            base(containingType, syntax.GetReference(), location, isIterator: SyntaxFacts.HasYieldOperations(syntax.Body))
        {
            _name = name;
            _isExpressionBodied = syntax.Body == null && syntax.ExpressionBody != null;

            var defaultAccess    = DeclarationModifiers.Private;
            var allowedModifiers =
                DeclarationModifiers.AccessibilityMask |
                DeclarationModifiers.Static |
                DeclarationModifiers.Extern |
                DeclarationModifiers.Unsafe;

            bool modifierErrors;
            var  declarationModifiers = ModifierUtils.MakeAndCheckNontypeMemberModifiers(
                syntax.Modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors);

            this.CheckUnsafeModifier(declarationModifiers, diagnostics);

            // We will bind the formal parameters and the return type lazily. For now,
            // assume that the return type is non-void; when we do the lazy initialization
            // of the parameters and return type we will update the flag if necessary.

            this.MakeFlags(methodKind, declarationModifiers, returnsVoid: false, isExtensionMethod: false);

            if (this.ContainingType.IsInterface &&
                (methodKind == MethodKind.Conversion || name == WellKnownMemberNames.EqualityOperatorName || name == WellKnownMemberNames.InequalityOperatorName))
            {
                // If we have a conversion or equality/inequality operator in an interface, we already have reported that fact as
                // an error. No need to cascade the error further.
                return;
            }

            if (this.ContainingType.IsStatic)
            {
                // Similarly if we're in a static class, though we have not reported it yet.

                // CS0715: '{0}': static classes cannot contain user-defined operators
                diagnostics.Add(ErrorCode.ERR_OperatorInStaticClass, location, this);
                return;
            }

            // SPEC: An operator declaration must include both a public and a
            // SPEC: static modifier
            if (this.DeclaredAccessibility != Accessibility.Public || !this.IsStatic)
            {
                // CS0558: User-defined operator '...' must be declared static and public
                diagnostics.Add(ErrorCode.ERR_OperatorsMustBeStatic, this.Locations[0], this);
            }

            // SPEC: Because an external operator provides no actual implementation,
            // SPEC: its operator body consists of a semicolon. For expression-bodied
            // SPEC: operators, the body is an expression. For all other operators,
            // SPEC: the operator body consists of a block...
            bool hasBody = syntax.HasAnyBody();

            if (hasBody && IsExtern)
            {
                diagnostics.Add(ErrorCode.ERR_ExternHasBody, location, this);
            }
            else if (!hasBody && !IsExtern && !IsAbstract && !IsPartial)
            {
                // Do not report that the body is missing if the operator is marked as
                // partial or abstract; we will already have given an error for that so
                // there's no need to "cascade" the error.
                diagnostics.Add(ErrorCode.ERR_ConcreteMissingBody, location, this);
            }

            // SPEC: It is an error for the same modifier to appear multiple times in an
            // SPEC: operator declaration.
            var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers, this, isExplicitInterfaceImplementation: false);

            if (info != null)
            {
                diagnostics.Add(info, location);
            }
        }
        private DeclarationModifiers MakeModifiers(SyntaxTokenList modifiers, bool explicitInterfaceImplementation,
                                                   bool isFieldLike, Location location,
                                                   DiagnosticBag diagnostics, out bool modifierErrors)
        {
            bool isInterface   = this.ContainingType.IsInterface;
            var  defaultAccess = isInterface && !explicitInterfaceImplementation ? DeclarationModifiers.Public : DeclarationModifiers.Private;
            var  defaultInterfaceImplementationModifiers = DeclarationModifiers.None;

            // Check that the set of modifiers is allowed
            var allowedModifiers = DeclarationModifiers.Unsafe;

            if (!explicitInterfaceImplementation)
            {
                allowedModifiers |= DeclarationModifiers.New |
                                    DeclarationModifiers.Sealed |
                                    DeclarationModifiers.Abstract |
                                    DeclarationModifiers.Static |
                                    DeclarationModifiers.Virtual |
                                    DeclarationModifiers.AccessibilityMask;

                if (!isInterface)
                {
                    allowedModifiers |= DeclarationModifiers.Override;
                }
                else
                {
                    // This is needed to make sure we can detect 'public' modifier specified explicitly and
                    // check it against language version below.
                    defaultAccess = DeclarationModifiers.None;

                    allowedModifiers |= DeclarationModifiers.Extern;
                    defaultInterfaceImplementationModifiers |= DeclarationModifiers.Sealed |
                                                               DeclarationModifiers.Abstract |
                                                               DeclarationModifiers.Static |
                                                               DeclarationModifiers.Virtual |
                                                               DeclarationModifiers.Extern |
                                                               DeclarationModifiers.AccessibilityMask;
                }
            }
            else if (isInterface)
            {
                Debug.Assert(explicitInterfaceImplementation);
                allowedModifiers |= DeclarationModifiers.Abstract;
            }

            if (this.ContainingType.IsStructType())
            {
                allowedModifiers |= DeclarationModifiers.ReadOnly;
            }

            if (!isInterface)
            {
                allowedModifiers |= DeclarationModifiers.Extern;
            }

            var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors);

            this.CheckUnsafeModifier(mods, diagnostics);

            ModifierUtils.ReportDefaultInterfaceImplementationModifiers(!isFieldLike, mods,
                                                                        defaultInterfaceImplementationModifiers,
                                                                        location, diagnostics);

            // Let's overwrite modifiers for interface events with what they are supposed to be.
            // Proper errors must have been reported by now.
            if (isInterface)
            {
                mods = ModifierUtils.AdjustModifiersForAnInterfaceMember(mods, !isFieldLike, explicitInterfaceImplementation);
            }

            return(mods);
        }
        protected SourceUserDefinedOperatorSymbolBase(
            MethodKind methodKind,
            string name,
            // @MattWindsor91 (Concept-C# 2017)
            //
            // Default structs can contain these, so I've relaxed the class
            // requirement on 'containingType' to allow for this.
            //
            // A more robust approach to this would be to make a new symbol
            // for default user-defined operators and set this back to
            // SourceMemberContainerTypeSymbol.
            NamedTypeSymbol containingType,
            Location location,
            SyntaxReference syntaxReference,
            SyntaxReference bodySyntaxReference,
            SyntaxTokenList modifiersSyntax,
            DiagnosticBag diagnostics,
            bool isExpressionBodied) :
            base(containingType, syntaxReference, bodySyntaxReference, location)
        {
            _name = name;
            _isExpressionBodied = isExpressionBodied;

            var isConceptOperator = ContainingType.IsInstance || ContainingType.IsConcept || ContainingType.IsDefaultStruct;

            // @t-mawind (is this a good idea?)
            var defaultAccess    = isConceptOperator ? DeclarationModifiers.Public : DeclarationModifiers.Private;
            var allowedModifiers =
                DeclarationModifiers.AccessibilityMask |
                DeclarationModifiers.Static |
                DeclarationModifiers.Extern |
                DeclarationModifiers.Unsafe;

            bool modifierErrors;
            var  declarationModifiers = ModifierUtils.MakeAndCheckNontypeMemberModifiers(
                modifiersSyntax, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors);

            this.CheckUnsafeModifier(declarationModifiers, diagnostics);

            if (ContainingType.IsConcept)
            {
                // @t-mawind Is there any easier way of doing this?
                declarationModifiers |= DeclarationModifiers.Abstract;
            }

            // We will bind the formal parameters and the return type lazily. For now,
            // assume that the return type is non-void; when we do the lazy initialization
            // of the parameters and return type we will update the flag if necessary.

            this.MakeFlags(methodKind, declarationModifiers, returnsVoid: false, isExtensionMethod: false);

            if (this.ContainingType.IsInterface && !this.ContainingType.IsConcept)
            {
                // If we have an operator in an interface, we already have reported that fact as
                // an error. No need to cascade the error further.
                return;
            }

            if (this.ContainingType.IsStatic)
            {
                // Similarly if we're in a static class, though we have not reported it yet.

                // CS0715: '{0}': static classes cannot contain user-defined operators
                diagnostics.Add(ErrorCode.ERR_OperatorInStaticClass, location, this);
                return;
            }

            // @t-mawind
            //   Concept operators must be public and _non_-static.
            if (isConceptOperator)
            {
                if (DeclaredAccessibility != Accessibility.Public || IsStatic)
                {
                    // CS4038: User-defined concept operator '...' must be declared non-static and public.
                    diagnostics.Add(ErrorCode.ERR_ConceptOperatorsMustBeNonStatic, Locations[0], this);
                }
            }
            else
            {
                // SPEC: An operator declaration must include both a public and a
                // SPEC: static modifier
                if (this.DeclaredAccessibility != Accessibility.Public || !this.IsStatic)
                {
                    // CS0558: User-defined operator '...' must be declared static and public
                    diagnostics.Add(ErrorCode.ERR_OperatorsMustBeStatic, this.Locations[0], this);
                }
            }

            // SPEC: Because an external operator provides no actual implementation,
            // SPEC: its operator body consists of a semicolon. For expression-bodied
            // SPEC: operators, the body is an expression. For all other operators,
            // SPEC: the operator body consists of a block...
            if (bodySyntaxReference != null && IsExtern)
            {
                diagnostics.Add(ErrorCode.ERR_ExternHasBody, location, this);
            }
            else if (bodySyntaxReference == null && !IsExtern && !IsAbstract && !IsPartial)
            {
                // Do not report that the body is missing if the operator is marked as
                // partial or abstract; we will already have given an error for that so
                // there's no need to "cascade" the error.
                diagnostics.Add(ErrorCode.ERR_ConcreteMissingBody, location, this);
            }

            // SPEC: It is an error for the same modifier to appear multiple times in an
            // SPEC: operator declaration.
            var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers);

            if (info != null)
            {
                diagnostics.Add(info, location);
            }
        }