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 | DeclarationModifiers.Let; var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(true, 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); }
protected SourceUserDefinedOperatorSymbolBase( MethodKind methodKind, string name, SourceMemberContainerTypeSymbol containingType, Location location, BaseMethodDeclarationSyntax syntax, DiagnosticBag diagnostics) : base(containingType, syntax.GetReference(), location) { _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(true, 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) { // 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; } // 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); if (info != null) { diagnostics.Add(info, location); } }
private SourcePropertyAccessorSymbol( NamedTypeSymbol containingType, string name, SourcePropertySymbol property, DeclarationModifiers propertyModifiers, ImmutableArray <MethodSymbol> explicitInterfaceImplementations, Location location, AccessorDeclarationSyntax syntax, MethodKind methodKind, bool isAutoPropertyAccessor, DiagnosticBag diagnostics) : base(containingType, syntax.GetReference(), location) { _property = property; _explicitInterfaceImplementations = explicitInterfaceImplementations; _name = name; _isAutoPropertyAccessor = isAutoPropertyAccessor; Debug.Assert(!_property.IsExpressionBodied, "Cannot have accessors in expression bodied lightweight properties"); var hasBody = syntax.Body != null; var hasExpressionBody = syntax.ExpressionBody != null; _isExpressionBodied = !hasBody && hasExpressionBody; bool modifierErrors; var declarationModifiers = this.MakeModifiers(syntax, location, diagnostics, out modifierErrors); // Include modifiers from the containing property. propertyModifiers &= ~DeclarationModifiers.AccessibilityMask; if ((declarationModifiers & DeclarationModifiers.Private) != 0) { // Private accessors cannot be virtual. propertyModifiers &= ~DeclarationModifiers.Virtual; } declarationModifiers |= propertyModifiers & ~DeclarationModifiers.Indexer; // ReturnsVoid property is overridden in this class so // returnsVoid argument to MakeFlags is ignored. this.MakeFlags(methodKind, declarationModifiers, returnsVoid: false, isExtensionMethod: false, isMetadataVirtualIgnoringModifiers: explicitInterfaceImplementations.Any()); if (hasBody || hasExpressionBody) { CheckModifiersForBody(location, diagnostics); } var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers); if (info != null) { diagnostics.Add(info, location); } if (!modifierErrors) { this.CheckModifiers(location, hasBody || hasExpressionBody, isAutoPropertyAccessor, diagnostics); } if (this.IsOverride) { MethodSymbol overriddenMethod = this.OverriddenMethod; if ((object)overriddenMethod != null) { // If this accessor is overriding a method from metadata, it is possible that // the name of the overridden method doesn't follow the C# get_X/set_X pattern. // We should copy the name so that the runtime will recognize this as an override. _name = overriddenMethod.Name; } } CheckForBlockAndExpressionBody( syntax.Body, syntax.ExpressionBody, syntax, diagnostics); }
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.Static | DeclarationModifiers.Volatile | DeclarationModifiers.Fixed | DeclarationModifiers.Unsafe | DeclarationModifiers.Abstract; // filtered out later var errorLocation = new SourceLocation(firstIdentifier); DeclarationModifiers result = ModifierUtils.MakeAndCheckNontypeMemberModifiers(false, 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.Let) != 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.Let | 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.Let) != 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); }